diff --git a/app/components/admin/poll/questions/answers/table_actions_component.html.erb b/app/components/admin/poll/questions/answers/table_actions_component.html.erb new file mode 100644 index 000000000..a9fc5cd8a --- /dev/null +++ b/app/components/admin/poll/questions/answers/table_actions_component.html.erb @@ -0,0 +1 @@ +<%= render Admin::TableActionsComponent.new(answer, actions: actions) %> diff --git a/app/components/admin/poll/questions/answers/table_actions_component.rb b/app/components/admin/poll/questions/answers/table_actions_component.rb new file mode 100644 index 000000000..fcec11fce --- /dev/null +++ b/app/components/admin/poll/questions/answers/table_actions_component.rb @@ -0,0 +1,14 @@ +class Admin::Poll::Questions::Answers::TableActionsComponent < ApplicationComponent + attr_reader :answer + delegate :can?, to: :helpers + + def initialize(answer) + @answer = answer + end + + private + + def actions + [:edit].select { |action| can?(action, answer) } + end +end diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index 437b678a1..96f4b581a 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -95,7 +95,10 @@ module Abilities can [:update, :destroy], Poll::Question do |question| !question.poll.started? end - can :manage, Poll::Question::Answer + can [:read, :order_answers], Poll::Question::Answer + can [:create, :update], Poll::Question::Answer do |answer| + can?(:update, answer.question) + end can :manage, Poll::Question::Answer::Video can [:create, :destroy], Image do |image| image.imageable_type == "Poll::Question::Answer" diff --git a/app/views/admin/poll/questions/show.html.erb b/app/views/admin/poll/questions/show.html.erb index bfeff9f6d..ec4e9cecc 100644 --- a/app/views/admin/poll/questions/show.html.erb +++ b/app/views/admin/poll/questions/show.html.erb @@ -32,8 +32,14 @@
- <%= link_to t("admin.questions.show.add_answer"), new_admin_question_answer_path(@question), - class: "button float-right" %> + <% if can?(:create, Poll::Question::Answer.new(question: @question)) %> + <%= link_to t("admin.questions.show.add_answer"), new_admin_question_answer_path(@question), + class: "button float-right" %> + <% else %> +
+ <%= t("admin.questions.no_edit") %> +
+ <% end %>
@@ -73,7 +79,7 @@ admin_answer_videos_path(answer) %> <% end %> diff --git a/spec/components/admin/poll/questions/answers/table_actions_component_spec.rb b/spec/components/admin/poll/questions/answers/table_actions_component_spec.rb new file mode 100644 index 000000000..3ed96b8da --- /dev/null +++ b/spec/components/admin/poll/questions/answers/table_actions_component_spec.rb @@ -0,0 +1,21 @@ +require "rails_helper" + +describe Admin::Poll::Questions::Answers::TableActionsComponent, controller: Admin::BaseController do + before { sign_in(create(:administrator).user) } + + it "displays the edit action when the poll has not started" do + answer = create(:poll_question_answer, poll: create(:poll, :future)) + + render_inline Admin::Poll::Questions::Answers::TableActionsComponent.new(answer) + + expect(page).to have_link "Edit" + end + + it "does not display the edit action when the poll has started" do + answer = create(:poll_question_answer, poll: create(:poll)) + + render_inline Admin::Poll::Questions::Answers::TableActionsComponent.new(answer) + + expect(page).not_to have_link "Edit" + end +end diff --git a/spec/controllers/admin/poll/questions/answers_controller_spec.rb b/spec/controllers/admin/poll/questions/answers_controller_spec.rb new file mode 100644 index 000000000..6ecccf37b --- /dev/null +++ b/spec/controllers/admin/poll/questions/answers_controller_spec.rb @@ -0,0 +1,88 @@ +require "rails_helper" + +describe Admin::Poll::Questions::AnswersController, :admin do + let(:current_question) { create(:poll_question, poll: create(:poll)) } + let(:future_question) { create(:poll_question, poll: create(:poll, :future)) } + + describe "POST create" do + it "is not possible for an already started poll" do + post :create, params: { + poll_question_answer: { + translations_attributes: { + "0" => { + locale: "en", + title: "Answer from started poll" + } + } + }, + question_id: current_question + } + + expect(flash[:alert]).to eq "You do not have permission to carry out the action 'create' on Answer." + expect(Poll::Question::Answer.count).to eq 0 + end + + it "is possible for a not started poll" do + post :create, params: { + poll_question_answer: { + translations_attributes: { + "0" => { + locale: "en", + title: "Answer from future poll" + } + } + }, + question_id: future_question + } + + expect(response).to redirect_to admin_question_path(future_question) + expect(Poll::Question::Answer.last.title).to eq "Answer from future poll" + expect(Poll::Question::Answer.count).to eq 1 + end + end + + describe "PATCH update" do + it "is not possible for an already started poll" do + current_answer = create(:poll_question_answer, question: current_question, title: "Sample title") + + patch :update, params: { + poll_question_answer: { + translations_attributes: { + "0" => { + locale: "en", + title: "New title", + id: current_answer.translations.first.id + } + } + }, + question_id: current_question, + id: current_answer + } + + expect(flash[:alert]).to eq "You do not have permission to carry out the action 'update' on Answer." + expect(current_answer.reload.title).to eq "Sample title" + end + + it "is possible for a not started poll" do + future_answer = create(:poll_question_answer, question: future_question) + + patch :update, params: { + poll_question_answer: { + translations_attributes: { + "0" => { + locale: "en", + title: "New title", + id: future_answer.translations.first.id + } + } + }, + question_id: future_question, + id: future_answer + } + + expect(response).to redirect_to admin_question_path(future_question) + expect(flash[:notice]).to eq "Changes saved" + expect(future_answer.reload.title).to eq "New title" + end + end +end diff --git a/spec/models/abilities/administrator_spec.rb b/spec/models/abilities/administrator_spec.rb index f9a6da74f..dfd1a76f0 100644 --- a/spec/models/abilities/administrator_spec.rb +++ b/spec/models/abilities/administrator_spec.rb @@ -20,8 +20,9 @@ describe Abilities::Administrator do let(:future_poll) { create(:poll, :future) } let(:current_poll_question) { create(:poll_question) } let(:future_poll_question) { create(:poll_question, poll: future_poll) } - let(:poll_question_answer) { create(:poll_question_answer) } - let(:answer_image) { build(:image, imageable: poll_question_answer) } + let(:current_poll_question_answer) { create(:poll_question_answer) } + let(:future_poll_question_answer) { create(:poll_question_answer, poll: future_poll) } + let(:answer_image) { build(:image, imageable: current_poll_question_answer) } let(:past_process) { create(:legislation_process, :past) } let(:past_draft_process) { create(:legislation_process, :past, :not_published) } @@ -122,7 +123,12 @@ describe Abilities::Administrator do it { should_not be_able_to(:update, current_poll_question) } it { should_not be_able_to(:destroy, current_poll_question) } - it { should be_able_to(:manage, Poll::Question::Answer) } + it { should be_able_to(:read, Poll::Question::Answer) } + it { should be_able_to(:order_answers, Poll::Question::Answer) } + it { should be_able_to(:create, future_poll_question_answer) } + it { should be_able_to(:update, future_poll_question_answer) } + it { should_not be_able_to(:create, current_poll_question_answer) } + it { should_not be_able_to(:update, current_poll_question_answer) } it { should be_able_to(:manage, Poll::Question::Answer::Video) } diff --git a/spec/system/admin/poll/questions/answers/answers_spec.rb b/spec/system/admin/poll/questions/answers/answers_spec.rb index 3b12ce770..9e3ac1a4f 100644 --- a/spec/system/admin/poll/questions/answers/answers_spec.rb +++ b/spec/system/admin/poll/questions/answers/answers_spec.rb @@ -1,40 +1,55 @@ require "rails_helper" describe "Answers", :admin do - scenario "Create" do - question = create(:poll_question) + let(:future_poll) { create(:poll, :future) } + let(:current_poll) { create(:poll) } - visit admin_question_path(question) - click_link "Add answer" + describe "Create" do + scenario "Is possible for a not started poll" do + question = create(:poll_question, poll: future_poll) - expect(page).to have_link "Go back", href: admin_question_path(question) + visit admin_question_path(question) + click_link "Add answer" - fill_in "Answer", with: "The answer is always 42" - fill_in_ckeditor "Description", with: "The Hitchhiker's Guide To The Universe" + expect(page).to have_link "Go back", href: admin_question_path(question) - click_button "Save" + fill_in "Answer", with: "The answer is always 42" + fill_in_ckeditor "Description", with: "The Hitchhiker's Guide To The Universe" - expect(page).to have_content "The answer is always 42" - expect(page).to have_content "The Hitchhiker's Guide To The Universe" - end + click_button "Save" - scenario "Create second answer and place after the first one" do - question = create(:poll_question) - create(:poll_question_answer, title: "First", question: question, given_order: 1) + expect(page).to have_content "Answer created successfully" + expect(page).to have_content "The answer is always 42" + expect(page).to have_content "The Hitchhiker's Guide To The Universe" + end - visit admin_question_path(question) - click_link "Add answer" + scenario "Is not possible for an already started poll" do + question = create(:poll_question, poll: current_poll) - fill_in "Answer", with: "Second" - fill_in_ckeditor "Description", with: "Description" + visit admin_question_path(question) - click_button "Save" + expect(page).not_to have_link "Add answer" + expect(page).to have_content "Once the poll has started it will not be possible to create, edit or" + end - expect("First").to appear_before("Second") + scenario "Create second answer and place after the first one" do + question = create(:poll_question, poll: future_poll) + create(:poll_question_answer, title: "First", question: question, given_order: 1) + + visit admin_question_path(question) + click_link "Add answer" + + fill_in "Answer", with: "Second" + fill_in_ckeditor "Description", with: "Description" + + click_button "Save" + + expect("First").to appear_before("Second") + end end scenario "Update" do - question = create(:poll_question) + question = create(:poll_question, poll: future_poll) create(:poll_question_answer, question: question, title: "Answer title", given_order: 2) create(:poll_question_answer, question: question, title: "Another title", given_order: 1) diff --git a/spec/system/admin/translatable_spec.rb b/spec/system/admin/translatable_spec.rb index 42cbefafd..ca81e8e39 100644 --- a/spec/system/admin/translatable_spec.rb +++ b/spec/system/admin/translatable_spec.rb @@ -215,7 +215,7 @@ describe "Admin edit translatable records", :admin do end context "CKEditor fields" do - let(:translatable) { create(:poll_question_answer) } + let(:translatable) { create(:poll_question_answer, poll: create(:poll, :future)) } let(:path) { edit_admin_question_answer_path(translatable.question, translatable) } scenario "Changes the existing translation" do
- <%= render Admin::TableActionsComponent.new(answer, actions: [:edit]) %> + <%= render Admin::Poll::Questions::Answers::TableActionsComponent.new(answer) %>