diff --git a/app/components/admin/poll/questions/answers/videos/table_actions_component.html.erb b/app/components/admin/poll/questions/answers/videos/table_actions_component.html.erb new file mode 100644 index 000000000..f799eae21 --- /dev/null +++ b/app/components/admin/poll/questions/answers/videos/table_actions_component.html.erb @@ -0,0 +1 @@ +<%= render Admin::TableActionsComponent.new(video, actions: actions) %> diff --git a/app/components/admin/poll/questions/answers/videos/table_actions_component.rb b/app/components/admin/poll/questions/answers/videos/table_actions_component.rb new file mode 100644 index 000000000..935cd5c80 --- /dev/null +++ b/app/components/admin/poll/questions/answers/videos/table_actions_component.rb @@ -0,0 +1,14 @@ +class Admin::Poll::Questions::Answers::Videos::TableActionsComponent < ApplicationComponent + attr_reader :video + delegate :can?, to: :helpers + + def initialize(video) + @video = video + end + + private + + def actions + [:edit, :destroy].select { |action| can?(action, video) } + end +end diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index 07f26a649..ee323ef80 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -99,7 +99,10 @@ module Abilities can [:create, :update, :destroy], Poll::Question::Answer do |answer| can?(:update, answer.question) end - can :manage, Poll::Question::Answer::Video + can :read, Poll::Question::Answer::Video + can [:create, :update, :destroy], Poll::Question::Answer::Video do |video| + can?(:update, video.answer) + end can [:create, :destroy], Image do |image| image.imageable_type == "Poll::Question::Answer" end diff --git a/app/views/admin/poll/questions/answers/videos/index.html.erb b/app/views/admin/poll/questions/answers/videos/index.html.erb index bd436d88a..c9e82498a 100644 --- a/app/views/admin/poll/questions/answers/videos/index.html.erb +++ b/app/views/admin/poll/questions/answers/videos/index.html.erb @@ -6,9 +6,15 @@ <%= t("admin.answers.videos.index.title") %> -<%= link_to t("admin.answers.videos.index.add_video"), - new_admin_answer_video_path(@answer), - class: "button success float-right" %> +<% if can?(:create, Poll::Question::Answer.new(question: @answer.question)) %> + <%= link_to t("admin.answers.videos.index.add_video"), + new_admin_answer_video_path(@answer), + class: "button success float-right" %> +<% else %> +
+ <%= t("admin.questions.no_edit") %> +
+<% end %>
@@ -27,7 +33,7 @@ <%= video.title %> <%= link_to video.url, video.url %> - <%= render Admin::TableActionsComponent.new(video) %> + <%= render Admin::Poll::Questions::Answers::Videos::TableActionsComponent.new(video) %> <% end %> diff --git a/spec/components/admin/poll/questions/answers/videos/table_actions_component_spec.rb b/spec/components/admin/poll/questions/answers/videos/table_actions_component_spec.rb new file mode 100644 index 000000000..e8449103d --- /dev/null +++ b/spec/components/admin/poll/questions/answers/videos/table_actions_component_spec.rb @@ -0,0 +1,23 @@ +require "rails_helper" + +describe Admin::Poll::Questions::Answers::Videos::TableActionsComponent, controller: Admin::BaseController do + before { sign_in(create(:administrator).user) } + + it "displays the edit and destroy actions when the poll has not started" do + video = create(:poll_answer_video, poll: create(:poll, :future)) + + render_inline Admin::Poll::Questions::Answers::Videos::TableActionsComponent.new(video) + + expect(page).to have_link "Edit" + expect(page).to have_button "Delete" + end + + it "does not display the edit and destroy actions when the poll has started" do + video = create(:poll_answer_video, poll: create(:poll)) + + render_inline Admin::Poll::Questions::Answers::Videos::TableActionsComponent.new(video) + + expect(page).not_to have_link "Edit" + expect(page).not_to have_button "Delete" + end +end diff --git a/spec/controllers/admin/poll/questions/answers/videos_controller_spec.rb b/spec/controllers/admin/poll/questions/answers/videos_controller_spec.rb new file mode 100644 index 000000000..65c5dc1f8 --- /dev/null +++ b/spec/controllers/admin/poll/questions/answers/videos_controller_spec.rb @@ -0,0 +1,87 @@ +require "rails_helper" + +describe Admin::Poll::Questions::Answers::VideosController, :admin do + let(:current_answer) { create(:poll_question_answer, poll: create(:poll)) } + let(:future_answer) { create(:poll_question_answer, poll: create(:poll, :future)) } + + describe "POST create" do + it "is not possible for an already started poll" do + post :create, params: { + poll_question_answer_video: { + title: "Video from started poll", + url: "https://www.youtube.com/watch?v=-JMf43st-1A" + }, + answer_id: current_answer + } + + expect(flash[:alert]).to eq "You do not have permission to carry out the action 'create' on Video." + expect(Poll::Question::Answer::Video.count).to eq 0 + end + + it "is possible for a not started poll" do + post :create, params: { + poll_question_answer_video: { + title: "Video from not started poll", + url: "https://www.youtube.com/watch?v=-JMf43st-1A" + }, + answer_id: future_answer + } + + expect(response).to redirect_to admin_answer_videos_path(future_answer) + expect(flash[:notice]).to eq "Video created successfully" + expect(Poll::Question::Answer::Video.count).to eq 1 + end + end + + describe "PATCH update" do + it "is not possible for an already started poll" do + current_video = create(:poll_answer_video, answer: current_answer, title: "Sample title") + + patch :update, params: { + poll_question_answer_video: { + title: "New title" + }, + id: current_video, + answer_id: current_answer + } + + expect(flash[:alert]).to eq "You do not have permission to carry out the action 'update' on Video." + expect(current_video.reload.title).to eq "Sample title" + end + + it "is possible for a not started poll" do + future_video = create(:poll_answer_video, answer: future_answer) + + patch :update, params: { + poll_question_answer_video: { + title: "New title" + }, + id: future_video, + answer_id: future_answer + } + + expect(response).to redirect_to admin_answer_videos_path(future_answer) + expect(flash[:notice]).to eq "Changes saved" + expect(future_video.reload.title).to eq "New title" + end + end + + describe "DELETE destroy" do + it "is not possible for an already started poll" do + current_video = create(:poll_answer_video, answer: current_answer) + delete :destroy, params: { answer_id: current_answer, id: current_video } + + expect(flash[:alert]).to eq "You do not have permission to carry out the action 'destroy' on Video." + expect(Poll::Question::Answer::Video.count).to eq 1 + end + + it "is possible for a not started poll" do + future_video = create(:poll_answer_video, answer: future_answer) + delete :destroy, params: { answer_id: future_answer, id: future_video } + + expect(response).to redirect_to admin_answer_videos_path(future_answer) + expect(flash[:notice]).to eq "Answer video deleted successfully." + expect(Poll::Question::Answer::Video.count).to eq 0 + end + end +end diff --git a/spec/models/abilities/administrator_spec.rb b/spec/models/abilities/administrator_spec.rb index 853fcee82..289407fd4 100644 --- a/spec/models/abilities/administrator_spec.rb +++ b/spec/models/abilities/administrator_spec.rb @@ -22,6 +22,8 @@ describe Abilities::Administrator do let(:future_poll_question) { create(:poll_question, poll: future_poll) } let(:current_poll_question_answer) { create(:poll_question_answer) } let(:future_poll_question_answer) { create(:poll_question_answer, poll: future_poll) } + let(:current_poll_answer_video) { create(:poll_answer_video, answer: current_poll_question_answer) } + let(:future_poll_answer_video) { create(:poll_answer_video, answer: future_poll_question_answer) } let(:answer_image) { build(:image, imageable: current_poll_question_answer) } let(:past_process) { create(:legislation_process, :past) } @@ -132,7 +134,12 @@ describe Abilities::Administrator do it { should_not be_able_to(:update, current_poll_question_answer) } it { should_not be_able_to(:destroy, current_poll_question_answer) } - it { should be_able_to(:manage, Poll::Question::Answer::Video) } + it { should be_able_to(:create, future_poll_answer_video) } + it { should be_able_to(:update, future_poll_answer_video) } + it { should be_able_to(:destroy, future_poll_answer_video) } + it { should_not be_able_to(:create, current_poll_answer_video) } + it { should_not be_able_to(:update, current_poll_answer_video) } + it { should_not be_able_to(:destroy, current_poll_answer_video) } it { should be_able_to(:create, answer_image) } it { should be_able_to(:destroy, answer_image) } diff --git a/spec/system/admin/poll/questions/answers/videos/videos_spec.rb b/spec/system/admin/poll/questions/answers/videos/videos_spec.rb index b4d2cdfab..67278fbdd 100644 --- a/spec/system/admin/poll/questions/answers/videos/videos_spec.rb +++ b/spec/system/admin/poll/questions/answers/videos/videos_spec.rb @@ -1,55 +1,72 @@ require "rails_helper" describe "Videos", :admin do - let!(:question) { create(:poll_question) } - let!(:answer) { create(:poll_question_answer, question: question) } + let(:future_poll) { create(:poll, :future) } + let(:current_poll) { create(:poll) } let(:title) { "'Magical' by Junko Ohashi" } let(:url) { "https://www.youtube.com/watch?v=-JMf43st-1A" } - scenario "Create" do - visit admin_question_path(question) + describe "Create" do + scenario "Is possible for a not started poll" do + question = create(:poll_question, poll: future_poll) + answer = create(:poll_question_answer, question: question) - within("#poll_question_answer_#{answer.id}") do - click_link "Video list" + visit admin_question_path(question) + + within("#poll_question_answer_#{answer.id}") do + click_link "Video list" + end + click_link "Add video" + + fill_in "Title", with: title + fill_in "External video", with: url + + click_button "Save" + + expect(page).to have_content "Video created successfully" + expect(page).to have_content title + expect(page).to have_content url end - click_link "Add video" - fill_in "Title", with: title - fill_in "External video", with: url + scenario "Is not possible for an already started poll" do + answer = create(:poll_question_answer, poll: current_poll) - click_button "Save" + visit admin_answer_videos_path(answer) - expect(page).to have_content title - expect(page).to have_content url + expect(page).not_to have_link "Add video" + expect(page).to have_content "Once the poll has started it will not be possible to create, edit or" + end end scenario "Update" do - video = create(:poll_answer_video, answer: answer) + video = create(:poll_answer_video, poll: future_poll) - visit edit_admin_answer_video_path(answer, video) + visit edit_admin_answer_video_path(video.answer, video) - expect(page).to have_link "Go back", href: admin_answer_videos_path(answer) + expect(page).to have_link "Go back", href: admin_answer_videos_path(video.answer) fill_in "Title", with: title fill_in "External video", with: url click_button "Save" + expect(page).to have_content "Changes saved" expect(page).to have_content title expect(page).to have_content url end scenario "Destroy" do - video = create(:poll_answer_video, answer: answer) + video = create(:poll_answer_video, poll: future_poll) - visit admin_answer_videos_path(answer) + visit admin_answer_videos_path(video.answer) - within("#poll_question_answer_video_#{video.id}") do + within("tr", text: video.title) do accept_confirm("Are you sure? This action will delete \"#{video.title}\" and can't be undone.") do click_button "Delete" end end expect(page).to have_content "Answer video deleted successfully." + expect(page).not_to have_content video.title end end