From 3dfd2653e134bf5b1c523e35b5738f0639363eec Mon Sep 17 00:00:00 2001 From: Nate Date: Thu, 7 Jan 2016 18:07:58 -0500 Subject: [PATCH 1/4] GroupsController#create red specs --- app/controllers/groups_controller.rb | 4 + app/interactors/create_group.rb | 2 + app/serializers/group_serializer.rb | 3 + config/routes.rb | 1 + spec/controllers/groups_controller_spec.rb | 118 +++++++++++++++++++++ 5 files changed, 128 insertions(+) create mode 100644 app/controllers/groups_controller.rb create mode 100644 app/interactors/create_group.rb create mode 100644 app/serializers/group_serializer.rb create mode 100644 spec/controllers/groups_controller_spec.rb diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb new file mode 100644 index 0000000..f27895e --- /dev/null +++ b/app/controllers/groups_controller.rb @@ -0,0 +1,4 @@ +class GroupsController < AuthenticationController + def create + end +end diff --git a/app/interactors/create_group.rb b/app/interactors/create_group.rb new file mode 100644 index 0000000..47d91c5 --- /dev/null +++ b/app/interactors/create_group.rb @@ -0,0 +1,2 @@ +class CreateGroup < StandardInteraction +end diff --git a/app/serializers/group_serializer.rb b/app/serializers/group_serializer.rb new file mode 100644 index 0000000..3606eb1 --- /dev/null +++ b/app/serializers/group_serializer.rb @@ -0,0 +1,3 @@ +class GroupSerializer < ActiveModel::Serializer + attributes :id, :name, :city, :state, :country, :facebook, :twitter +end diff --git a/config/routes.rb b/config/routes.rb index 1b228b8..6574383 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,4 +3,5 @@ resources :users, except: [:new, :edit] resources :password_resets, only: [:create, :update] + resources :groups, except: [:new, :edit] end diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb new file mode 100644 index 0000000..8c1ec7d --- /dev/null +++ b/spec/controllers/groups_controller_spec.rb @@ -0,0 +1,118 @@ +include Helpers + +RSpec.describe GroupsController do + let(:group) { create(:group) } + + describe "POST #create" do + let(:params) { { group: create_group_input.fetch(:group_params) } } + + let(:create_group_input) do + { group_params: { + name: group.name } + } + end + + let(:create_group_context) do + Interactor::Context.new(errors: :val, group: group) + end + + before do + allow(CreateGroup).to receive(:call).with(create_group_input). + and_return(create_group_context) + end + + context "when called" do + it "calls the CreateGroup interactor" do + expect(CreateGroup).to receive(:call) + post :create, params + end + end + + context "when CreateGroup is a success" do + let(:serializer) { GroupSerializer.new(group) } + + let(:serialization) do + ActiveModel::Serializer::Adapter.create(serializer) + end + + it "returns HTTP status 201" do + post :create, params + expect(response).to have_http_status(201) + end + + it "renders the group as JSON" do + post :create, params + expect(serialization.to_json).to eq(response.body) + end + end + + context "when CreateGroup is a failure" do + let(:create_group_context) do + double(:context, success?: false, group: group) + end + + it "returns HTTP status 422" do + post :create, params + expect(response).to have_http_status(422) + end + + it "returns an error" do + group.errors.add("error") + post :create, params + expect(JSON.parse(response.body)).to eq("error") + end + end + end + + describe "GET #show" do + context "when called" do + it "calls the ShowGroup Interactor" do + end + end + + context "when ShowGroup is successful" do + it "returns HTTP status 201" do + end + + it "renders the group as JSON" do + end + end + + context "when ShowGroup fails" do + it "returns HTTP status xxx" do + end + + it "renders an error" do + end + end + end + + describe "PATCH #update" do + context "when called" do + it "calls the UpdateGroup Interactor" do + end + end + + context "when UpdateGroup is successful" do + it "returns HTTP status 201" do + end + + it "renders the group as JSON" do + end + end + + context "when UpdateGroup fails" do + it "returns HTTP status xxx" do + end + + it "renders an error" do + end + end + end + + describe "DELETE #delete" do + end + + describe "GET #index" do + end +end From 248f9b39b7a5e3836ab1a8f178c5ca5a4367dbf6 Mon Sep 17 00:00:00 2001 From: Nate Date: Fri, 8 Jan 2016 10:50:05 -0500 Subject: [PATCH 2/4] add serialization to #create specs and start #show specs --- spec/controllers/groups_controller_spec.rb | 34 +++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index 8c1ec7d..21f64a2 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -2,6 +2,15 @@ RSpec.describe GroupsController do let(:group) { create(:group) } + let(:serializer) { GroupSerializer.new(group) } + + let(:serialization) do + ActiveModel::Serializer::Adapter.create(serializer) + end + + before do + authenticate + end describe "POST #create" do let(:params) { { group: create_group_input.fetch(:group_params) } } @@ -65,24 +74,47 @@ end describe "GET #show" do + let(:group) { create(:group) } + let(:params) { { id: group.id } } + let(:show_group_input) { { id: params.fetch(:id).to_s } } + + let(:show_group_context) do + Interactor::Context.new(errors: :val, group: group) + end + + before do + allow(ShowGroup).to receive(:call).with(show_group_input). + and_return(show_group_context) + end + context "when called" do it "calls the ShowGroup Interactor" do + expect(ShowGroup).to receive(:call) + get :show, params end end context "when ShowGroup is successful" do it "returns HTTP status 201" do + get :show, params + expect(response).to have_http_status(200) end it "renders the group as JSON" do + get :show, params + expect(serialization.to_json).to eq(response.body) end end context "when ShowGroup fails" do - it "returns HTTP status xxx" do + it "returns HTTP status 404" do + get :show, params + expect(response).to have_http_status(404) end it "renders an error" do + get :show, params + expect(response.body).to eq("invalid") end end end From a986e567eae1e1d1de975a8cd6b7ac37f4f8c5bb Mon Sep 17 00:00:00 2001 From: Nate Date: Sat, 9 Jan 2016 20:08:10 -0500 Subject: [PATCH 3/4] complete GroupsController specs -- red --- app/controllers/groups_controller.rb | 9 ++ app/interactors/delete_group.rb | 3 + app/interactors/show_group.rb | 3 + app/interactors/update_group.rb | 3 + spec/controllers/groups_controller_spec.rb | 96 ++++++++++++++++++++-- spec/interactors/update_password_spec.rb | 2 +- 6 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 app/interactors/delete_group.rb create mode 100644 app/interactors/show_group.rb create mode 100644 app/interactors/update_group.rb diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index f27895e..96e32b5 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -1,4 +1,13 @@ class GroupsController < AuthenticationController def create end + + def show + end + + def update + end + + def delete + end end diff --git a/app/interactors/delete_group.rb b/app/interactors/delete_group.rb new file mode 100644 index 0000000..b23d647 --- /dev/null +++ b/app/interactors/delete_group.rb @@ -0,0 +1,3 @@ +class DeleteGroup + include Interactor +end diff --git a/app/interactors/show_group.rb b/app/interactors/show_group.rb new file mode 100644 index 0000000..ee600a6 --- /dev/null +++ b/app/interactors/show_group.rb @@ -0,0 +1,3 @@ +class ShowGroup + include Interactor +end diff --git a/app/interactors/update_group.rb b/app/interactors/update_group.rb new file mode 100644 index 0000000..78db6e3 --- /dev/null +++ b/app/interactors/update_group.rb @@ -0,0 +1,3 @@ +class UpdateGroup + include Interactor +end diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index 21f64a2..deba61a 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -1,6 +1,7 @@ include Helpers RSpec.describe GroupsController do + let(:user) { create(:confirmed_user) } let(:group) { create(:group) } let(:serializer) { GroupSerializer.new(group) } @@ -95,7 +96,7 @@ end context "when ShowGroup is successful" do - it "returns HTTP status 201" do + it "returns HTTP status 200" do get :show, params expect(response).to have_http_status(200) end @@ -106,7 +107,11 @@ end end - context "when ShowGroup fails" do + context "when ShowGroup is a failure" do + let(:show_group_context) do + double(:context, success?: false, group: group) + end + it "returns HTTP status 404" do get :show, params expect(response).to have_http_status(404) @@ -120,31 +125,108 @@ end describe "PATCH #update" do + let(:params) { { group: update_group_input.fetch(:group_params) } } + + let(:update_group_input) do + { group_params: { + name: group.name } + } + end + + let(:update_group_context) do + Interactor::Context.new(errors: :val, group: group) + end + + let(:serializer) { GroupSerializer.new(group) } + + let(:serialization) do + ActiveModel::Serializer::Adapter.create(serializer) + end + + before do + allow(UpdateGroup).to receive(:call).with(update_group_input). + and_return(update_group_context) + end + context "when called" do it "calls the UpdateGroup Interactor" do + expect(UpdateGroup).to receive(:call) + patch :update, params end end context "when UpdateGroup is successful" do - it "returns HTTP status 201" do + it "returns HTTP status 200" do + patch :update, params + expect(response).to have_http_status(200) end it "renders the group as JSON" do + patch :update, params + expect(serialization.to_json).to eq(response.body) end end - context "when UpdateGroup fails" do - it "returns HTTP status xxx" do + context "when UpdateGroup is a failure" do + let(:update_group_context) do + double(:context, success?: false, group: group) + end + + it "returns HTTP status 404" do + patch :update, params + expect(response).to have_http_status(404) end it "renders an error" do + group.errors.add("error") + patch :update, params + expect(JSON.parse(response.body)).to eq("error") end end end describe "DELETE #delete" do - end + let(:params) { { group: delete_group_input.fetch(:group_params) } } + + let(:delete_group_input) do + { group_params: { + name: group.name } + } + end + + let(:delete_group_context) do + Interactor::Context.new(errors: :val, group: group) + end + + context "when called" do + it "calls the DeleteGroup Interactor" do + expect(DeleteGroup).to receive(:call) + delete :delete, params + end + end - describe "GET #index" do + context "when DeleteGroup is successful" do + it "returns HTTP status 200" do + delete :delete, params + expect(response).to have_http_status(200) + end + end + + context "when DeleteGroup is a failure" do + let(:delete_group_context) do + double(:context, success?: false, group: group) + end + + it "returns HTTP status 500" do + delete :delete, params + expect(response).to have_http_status(500) + end + + it "renders an error" do + group.errors.add("error") + patch :update, params + expect(JSON.parse(response.body)).to eq("error") + end + end end end diff --git a/spec/interactors/update_password_spec.rb b/spec/interactors/update_password_spec.rb index 1fb4b88..7c1e4f1 100644 --- a/spec/interactors/update_password_spec.rb +++ b/spec/interactors/update_password_spec.rb @@ -35,7 +35,7 @@ end end - context "when user password not provided" do + context "when user password not provided" do subject do described_class.call(user: user) end From fa56511f05c24b7994210b4bfa93acc7312bd369 Mon Sep 17 00:00:00 2001 From: Nate Date: Thu, 14 Jan 2016 15:07:21 -0500 Subject: [PATCH 4/4] GroupsController green specs --- app/controllers/groups_controller.rb | 38 +++++++++- spec/controllers/groups_controller_spec.rb | 81 ++++++++++------------ 2 files changed, 74 insertions(+), 45 deletions(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 96e32b5..9b9b955 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -1,13 +1,49 @@ class GroupsController < AuthenticationController def create + result = CreateGroup.call(group_params) + + if result.success? + render json: result.group, status: :created + else + render json: result.group.errors, status: :unprocessable_entity + end end def show + result = ShowGroup.call(id: params[:id]) + + if result.success? + render json: result.group, status: :ok + else + render json: result.errors, status: :not_found + end end def update + result = UpdateGroup.call(group_params) + + if result.success? + render json: result.group, status: :ok + else + render json: result.group.errors, status: :unprocessable_entity + end end - def delete + def destroy + result = DeleteGroup.call(id: params[:id]) + unless result.success? + render json: result.errors, status: :internal_server_error + end + end + + private + + def group_params + params.require(:group).permit(:name, + :city, + :state, + :country, + :facebook, + :twitter) end end diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index deba61a..e698f30 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -1,25 +1,16 @@ -include Helpers - RSpec.describe GroupsController do let(:user) { create(:confirmed_user) } let(:group) { create(:group) } - let(:serializer) { GroupSerializer.new(group) } - - let(:serialization) do - ActiveModel::Serializer::Adapter.create(serializer) - end before do authenticate end describe "POST #create" do - let(:params) { { group: create_group_input.fetch(:group_params) } } + let(:params) { { group: create_group_input } } let(:create_group_input) do - { group_params: { - name: group.name } - } + { name: group.name } end let(:create_group_context) do @@ -52,7 +43,7 @@ it "renders the group as JSON" do post :create, params - expect(serialization.to_json).to eq(response.body) + expect(serialize(group)).to eq(response.body) end end @@ -67,9 +58,9 @@ end it "returns an error" do - group.errors.add("error") + group.errors.add(:name, "error") post :create, params - expect(JSON.parse(response.body)).to eq("error") + expect(json["name"]).to eq(["error"]) end end end @@ -103,13 +94,16 @@ it "renders the group as JSON" do get :show, params - expect(serialization.to_json).to eq(response.body) + expect(serialize(group)).to eq(response.body) end end context "when ShowGroup is a failure" do let(:show_group_context) do - double(:context, success?: false, group: group) + double(:context, + errors: { name: ["invalid"] }, + success?: false, + group: group) end it "returns HTTP status 404" do @@ -119,30 +113,22 @@ it "renders an error" do get :show, params - expect(response.body).to eq("invalid") + expect(json["name"]).to eq(["invalid"]) end end end describe "PATCH #update" do - let(:params) { { group: update_group_input.fetch(:group_params) } } + let(:params) { { id: group.id, group: update_group_input } } let(:update_group_input) do - { group_params: { - name: group.name } - } + { name: group.name } end let(:update_group_context) do Interactor::Context.new(errors: :val, group: group) end - let(:serializer) { GroupSerializer.new(group) } - - let(:serialization) do - ActiveModel::Serializer::Adapter.create(serializer) - end - before do allow(UpdateGroup).to receive(:call).with(update_group_input). and_return(update_group_context) @@ -163,7 +149,7 @@ it "renders the group as JSON" do patch :update, params - expect(serialization.to_json).to eq(response.body) + expect(serialize(group)).to eq(response.body) end end @@ -172,60 +158,67 @@ double(:context, success?: false, group: group) end - it "returns HTTP status 404" do + it "returns HTTP status 422" do patch :update, params - expect(response).to have_http_status(404) + expect(response).to have_http_status(422) end it "renders an error" do - group.errors.add("error") + group.errors.add(:name, "error") patch :update, params - expect(JSON.parse(response.body)).to eq("error") + expect(json["name"]).to eq(["error"]) end end end - describe "DELETE #delete" do - let(:params) { { group: delete_group_input.fetch(:group_params) } } + describe "DELETE #destroy" do + let(:params) do + { id: group.id } + end let(:delete_group_input) do - { group_params: { - name: group.name } - } + { id: params.fetch(:id).to_s } end let(:delete_group_context) do Interactor::Context.new(errors: :val, group: group) end + before do + allow(DeleteGroup).to receive(:call).with(delete_group_input). + and_return(delete_group_context) + end + context "when called" do it "calls the DeleteGroup Interactor" do expect(DeleteGroup).to receive(:call) - delete :delete, params + delete :destroy, params end end context "when DeleteGroup is successful" do it "returns HTTP status 200" do - delete :delete, params + delete :destroy, params expect(response).to have_http_status(200) end end context "when DeleteGroup is a failure" do let(:delete_group_context) do - double(:context, success?: false, group: group) + double(:context, + errors: { id: ["invalid"] }, + success?: false, + group: group) end it "returns HTTP status 500" do - delete :delete, params + delete :destroy, params expect(response).to have_http_status(500) end it "renders an error" do - group.errors.add("error") - patch :update, params - expect(JSON.parse(response.body)).to eq("error") + delete :destroy, params + expect(json["id"]).to eq(["invalid"]) end end end