diff --git a/test/app/controllers/api/demo/marbles_controller.rb b/test/app/controllers/api/demo/marbles_controller.rb deleted file mode 100644 index 3704bfe..0000000 --- a/test/app/controllers/api/demo/marbles_controller.rb +++ /dev/null @@ -1,16 +0,0 @@ -class Api::Demo::MarblesController < Api::DemoController - include RESTFramework::BulkModelControllerMixin - - self.extra_member_actions = {adjust_price: :patch, toggle_is_discounted: :patch} - - def adjust_price - self.get_record.update!(price: params[:price]) - return api_response({message: "Price updated to #{params[:price]}."}) - end - - def toggle_is_discounted - marble = self.get_record - marble.update!(is_discounted: !marble.is_discounted) - return api_response({message: "Is discounted toggled to #{marble.is_discounted}."}) - end -end diff --git a/test/app/controllers/api/demo/users/marbles_controller.rb b/test/app/controllers/api/demo/users/marbles_controller.rb deleted file mode 100644 index 72f1a0b..0000000 --- a/test/app/controllers/api/demo/users/marbles_controller.rb +++ /dev/null @@ -1,7 +0,0 @@ -class Api::Demo::Users::MarblesController < Api::DemoController - include RESTFramework::BulkModelControllerMixin - - def get_recordset - return User.find(params[:user_id]).marbles - end -end diff --git a/test/app/controllers/api/plain/marbles_controller.rb b/test/app/controllers/api/plain/marbles_controller.rb deleted file mode 100644 index b5f5d88..0000000 --- a/test/app/controllers/api/plain/marbles_controller.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Api::Plain::MarblesController < Api::PlainController - include RESTFramework::ModelControllerMixin -end diff --git a/test/app/models/movie.rb b/test/app/models/movie.rb index a4737a3..905ddd7 100644 --- a/test/app/models/movie.rb +++ b/test/app/models/movie.rb @@ -8,6 +8,8 @@ class Movie < ApplicationRecord has_one_attached :cover has_many_attached :pictures + validates_presence_of :name + validates_uniqueness_of :name validates_numericality_of :price, greater_than: 0, allow_nil: true def self.ransackable_attributes(*args) @@ -17,4 +19,11 @@ def self.ransackable_attributes(*args) def self.ransackable_associations(*args) return [] end + + before_destroy do + if self.name == "Undestroyable" + errors.add(:base, "This record is undestroyable.") + throw(:abort) + end + end end diff --git a/test/config/routes.rb b/test/config/routes.rb index 020042b..78ecb41 100644 --- a/test/config/routes.rb +++ b/test/config/routes.rb @@ -24,7 +24,6 @@ rest_root rest_resources :emails rest_resources :genres - rest_resources :marbles rest_resources :movies rest_resources :phone_numbers rest_resources :users @@ -34,11 +33,9 @@ rest_root rest_resources :emails rest_resources :genres - rest_resources :marbles rest_resources :movies rest_resources :phone_numbers rest_resources :users do - rest_resources :marbles rest_resources :movies end end diff --git a/test/test/controllers/api/demo/marbles_controller_test.rb b/test/test/controllers/api/demo/marbles_controller_test.rb deleted file mode 100644 index 7a596c1..0000000 --- a/test/test/controllers/api/demo/marbles_controller_test.rb +++ /dev/null @@ -1,96 +0,0 @@ -require_relative "base" - -class Api::Demo::MarblesControllerTest < ActionController::TestCase - include Api::Demo::Base - - self.create_params = {name: "mutation_test"} - self.update_params = {name: "mutation_test"} - - def test_bulk_create - post( - :create, - as: :json, - params: {_json: [{name: "test_bulk_marble_1"}, {name: "test_bulk_marble_2"}]}, - ) - assert_response(:success) - assert(@response.parsed_body.all? { |r| Marble.find(r["id"]) }) - end - - def test_bulk_create_with_error - post( - :create, - as: :json, - params: {_json: [{name: "test_bulk_marble_1"}, {name: "test_bulk_marble_1"}]}, - ) - assert_response(:success) - parsed_body = @response.parsed_body - assert(Marble.find(parsed_body[0]["id"])) - assert_nil(parsed_body[0]["errors"]) - assert_nil(parsed_body[1]["id"]) - assert(parsed_body[1]["errors"]) - end - - def test_bulk_update - marble1 = Marble.create!(name: "test_bulk_marble_1", radius_mm: 4) - marble2 = Marble.create!(name: "test_bulk_marble_2", radius_mm: 23) - old_count = Marble.count - - patch( - :update_all, - as: :json, - params: {_json: [{id: marble1.id, radius_mm: 5}, {id: marble2.id, radius_mm: 24}]}, - ) - assert_response(:success) - - marble1.reload - marble2.reload - assert_equal(5, marble1.radius_mm) - assert_equal(24, marble2.radius_mm) - assert_equal(old_count, Marble.count) - end - - def test_bulk_update_with_error - marble1 = Marble.create!(name: "test_bulk_marble_1", radius_mm: 4) - marble2 = Marble.create!(name: "test_bulk_marble_2", radius_mm: 23) - old_count = Marble.count - - patch( - :update_all, - as: :json, - params: {_json: [{id: marble1.id, radius_mm: 5}, {id: marble2.id, radius_mm: 24, name: nil}]}, - ) - assert_response(:success) - parsed_body = @response.parsed_body - assert_nil(parsed_body[0]["errors"]) - assert(parsed_body[1]["errors"]) - - marble1.reload - marble2.reload - assert_equal(5, marble1.radius_mm) - assert_equal(23, marble2.radius_mm) - assert_equal(old_count, Marble.count) - end - - def test_bulk_destroy - marble_names = ["Example Marble 1", "Example Marble 2"] - marbles = Marble.where(name: marble_names) - assert_equal(2, marbles.count) - delete(:destroy_all, as: :json, params: {_json: marbles.pluck(:id)}) - assert_response(:success) - assert_equal(0, marbles.count) - end - - def test_bulk_destroy_validation_error - Marble.create!(name: "Undestroyable") - marble_names = ["Example Marble 1", "Undestroyable"] - marbles = Marble.where(name: marble_names) - assert_equal(2, marbles.count) - delete(:destroy_all, as: :json, params: {_json: marbles.pluck(:id)}) - assert_response(:success) - parsed_body = @response.parsed_body - assert_equal(2, parsed_body.count) - assert_nil(parsed_body[0]["errors"]) - assert(parsed_body[1]["errors"]) - assert_equal(1, marbles.count) - end -end diff --git a/test/test/controllers/api/demo/movies_controller_test.rb b/test/test/controllers/api/demo/movies_controller_test.rb index e86265e..e0962ed 100644 --- a/test/test/controllers/api/demo/movies_controller_test.rb +++ b/test/test/controllers/api/demo/movies_controller_test.rb @@ -13,4 +13,93 @@ def test_ransack_simple assert_equal(1, @response.parsed_body["results"].length) end end + + def test_bulk_create + post( + :create, + as: :json, + params: {_json: [{name: "test_bulk_1"}, {name: "test_bulk_2"}]}, + ) + assert_response(:success) + assert(@response.parsed_body.all? { |r| Movie.find(r["id"]) }) + end + + def test_bulk_create_with_error + post( + :create, + as: :json, + params: {_json: [{name: "test_bulk_1"}, {name: "test_bulk_1"}]}, + ) + assert_response(:success) + parsed_body = @response.parsed_body + assert(Movie.find(parsed_body[0]["id"])) + assert_nil(parsed_body[0]["errors"]) + assert_nil(parsed_body[1]["id"]) + assert(parsed_body[1]["errors"]) + end + + def test_bulk_update + movie1 = Movie.create!(name: "test_bulk_1", price: 4) + movie2 = Movie.create!(name: "test_bulk_2", price: 23) + old_count = Movie.count + + patch( + :update_all, + as: :json, + params: {_json: [{id: movie1.id, price: 5}, {id: movie2.id, price: 24}]}, + ) + assert_response(:success) + + movie1.reload + movie2.reload + assert_equal(5, movie1.price) + assert_equal(24, movie2.price) + assert_equal(old_count, Movie.count) + end + + def test_bulk_update_with_error + movie1 = Movie.create!(name: "test_bulk_1", price: 4) + movie2 = Movie.create!(name: "test_bulk_2", price: 23) + old_count = Movie.count + + patch( + :update_all, + as: :json, + params: {_json: [{id: movie1.id, price: 5}, {id: movie2.id, price: 24, name: nil}]}, + ) + assert_response(:success) + parsed_body = @response.parsed_body + assert_nil(parsed_body[0]["errors"]) + assert(parsed_body[1]["errors"]) + + movie1.reload + movie2.reload + assert_equal(5, movie1.price) + assert_equal(23, movie2.price) + assert_equal(old_count, Movie.count) + end + + def test_bulk_destroy + movie_names = ["Test Movie 1", "Test Movie 2"] + movie_names.each { |n| Movie.create!(name: n) } + movies = Movie.where(name: movie_names) + assert_equal(2, movies.count) + delete(:destroy_all, as: :json, params: {_json: movies.pluck(:id)}) + assert_response(:success) + assert_equal(0, movies.count) + end + + def test_bulk_destroy_validation_error + movie_names = ["Test Movie 1", "Undestroyable"] + movie_names.each { |n| Movie.create!(name: n) } + movies = Movie.where(name: movie_names) + assert_equal(2, movies.count) + delete(:destroy_all, as: :json, params: {_json: movies.pluck(:id)}) + assert_response(:success) + parsed_body = @response.parsed_body + assert_equal(2, parsed_body.count) + assert_nil(parsed_body[0]["errors"]) + assert(parsed_body[1]["errors"]) + assert_equal(1, movies.count) + end end diff --git a/test/test/controllers/api/plain/marbles_controller_test.rb b/test/test/controllers/api/plain/marbles_controller_test.rb deleted file mode 100644 index af6cc3d..0000000 --- a/test/test/controllers/api/plain/marbles_controller_test.rb +++ /dev/null @@ -1,92 +0,0 @@ -require_relative "base" - -class Api::Plain::MarblesControllerTest < ActionController::TestCase - include Api::Plain::Base - - self.create_params = {name: "mutation_test"} - self.update_params = {name: "mutation_test"} - - def test_destroy_aborted - t = Marble.create!(name: "Undestroyable") - delete(:destroy, as: :json, params: {id: t.id}) - assert_response(400) - end - - def test_update_validation_failed - t = Marble.create!(name: "test") - patch(:update, as: :json, params: {id: t.id}, body: {price: -1}.to_json) - assert_response(400) - end - - def test_create_failed - post(:create, as: :json, body: {some_column: "should fail"}.to_json) - assert_response(400) - assert(@response.parsed_body.key?("message")) - end - - def test_except_columns - # Test to make sure this controller normally has a `name` field. - get(:index, as: :json) - assert_response(:success) - assert(@response.parsed_body[0].key?("name")) - - # Adding `name` to `except` param should remove the attribute. - get(:index, as: :json, params: {except: "name"}) - assert_response(:success) - refute(@response.parsed_body[0].key?("name")) - end - - def test_only_columns - # Test to make sure this controller normally has a `name` field. - get(:index, as: :json) - assert_response(:success) - assert(@response.parsed_body[0].keys.length > 2) - - # Adding `name` to `except` param should remove the attribute. - get(:index, as: :json, params: {only: "id,name"}) - assert_response(:success) - assert_equal(["id", "name"].sort, @response.parsed_body[0].keys.sort) - end - - if Rails::VERSION::MAJOR >= 7 - def test_filter_by_user_id - get(:index, as: :json, params: {"user.id": 1}) - assert_response(:success) - assert(@response.parsed_body.all? { |t| t["user"]["id"] == 1 }) - end - - def test_filter_by_user_login - get(:index, as: :json, params: {"user.login": "admin"}) - assert_response(:success) - assert(@response.parsed_body.all? { |t| t["user"]["login"] == "admin" }) - end - - def test_order_by_user_id - get(:index, as: :json, params: {ordering: "user.id"}) - assert_response(:success) - ids = @response.parsed_body.select { |t| - t["user"] - }.map { |t| t["user"]["id"] }.compact.uniq - assert_equal(ids, ids.sort) - - get(:index, as: :json, params: {ordering: "-user.id"}) - assert_response(:success) - ids = @response.parsed_body.select { |t| - t["user"] - }.map { |t| t["user"]["id"] }.compact.uniq - assert_equal(ids.sort.reverse, ids) - end - - def test_order_by_name - get(:index, as: :json, params: {ordering: "name"}) - assert_response(:success) - names = @response.parsed_body.map { |t| t["name"] }.compact.uniq - assert_equal(names, names.sort) - - get(:index, as: :json, params: {ordering: "-name"}) - assert_response(:success) - names = @response.parsed_body.map { |t| t["name"] }.compact.uniq - assert_equal(names, names.sort.reverse) - end - end -end diff --git a/test/test/integration/api/demo_routing_test.rb b/test/test/integration/api/demo_routing_test.rb index b2c5311..7077a33 100644 --- a/test/test/integration/api/demo_routing_test.rb +++ b/test/test/integration/api/demo_routing_test.rb @@ -1,6 +1,6 @@ require "test_helper" -# The goal of this test is to ensure that the proper routes are defined for API1. +# The goal of this test is to ensure that the proper routes are defined for the demo API. class Api::DemoRoutingTest < ActionDispatch::IntegrationTest def test_can_get_root get("/api/demo") @@ -9,10 +9,10 @@ def test_can_get_root assert_response(:success) end - def test_can_get_marbles - get("/api/demo/marbles") + def test_can_get_users + get("/api/demo/users") assert_response(:success) - get("/api/demo/marbles.json") + get("/api/demo/users.json") assert_response(:success) end