diff --git a/app/controllers/polls/answers_controller.rb b/app/controllers/polls/answers_controller.rb index 46a40185d..9e4988c05 100644 --- a/app/controllers/polls/answers_controller.rb +++ b/app/controllers/polls/answers_controller.rb @@ -5,7 +5,7 @@ class Polls::AnswersController < ApplicationController through_association: :answers def destroy - @answer.destroy! + @answer.destroy_and_remove_voter_participation respond_to do |format| format.html do diff --git a/app/models/poll/answer.rb b/app/models/poll/answer.rb index 904216355..41d76e925 100644 --- a/app/models/poll/answer.rb +++ b/app/models/poll/answer.rb @@ -23,6 +23,16 @@ class Poll::Answer < ApplicationRecord end end + def destroy_and_remove_voter_participation + transaction do + destroy! + + if author.poll_answers.where(question_id: poll.question_ids).none? + Poll::Voter.find_by(user: author, poll: poll, origin: "web").destroy! + end + end + end + private def max_votes diff --git a/spec/models/poll/answer_spec.rb b/spec/models/poll/answer_spec.rb index b2b419c23..691a09943 100644 --- a/spec/models/poll/answer_spec.rb +++ b/spec/models/poll/answer_spec.rb @@ -106,4 +106,32 @@ describe Poll::Answer do expect(answer).not_to be_persisted end end + + describe "#destroy_and_remove_voter_participation" do + let(:poll) { create(:poll) } + let(:question) { create(:poll_question, :yes_no, poll: poll) } + + it "destroys voter record and answer when it was the only user's answer" do + answer = build(:poll_answer, question: question) + answer.save_and_record_voter_participation + + expect { answer.destroy_and_remove_voter_participation } + .to change { Poll::Answer.count }.by(-1) + .and change { Poll::Voter.count }.by(-1) + end + + it "destroys the answer but does not destroy the voter record when the user + has answered other poll questions" do + answer = build(:poll_answer, question: question) + answer.save_and_record_voter_participation + other_question = create(:poll_question, :yes_no, poll: poll) + other_answer = build(:poll_answer, question: other_question, author: answer.author) + other_answer.save_and_record_voter_participation + + expect(other_answer).to be_persisted + expect { answer.destroy_and_remove_voter_participation } + .to change { Poll::Answer.count }.by(-1) + .and change { Poll::Voter.count }.by(0) + end + end end diff --git a/spec/system/polls/voter_spec.rb b/spec/system/polls/voter_spec.rb index 30cc577fd..46086b2e5 100644 --- a/spec/system/polls/voter_spec.rb +++ b/spec/system/polls/voter_spec.rb @@ -3,12 +3,10 @@ require "rails_helper" describe "Voter" do context "Origin", :with_frozen_time do let(:poll) { create(:poll) } - let(:question) { create(:poll_question, poll: poll) } + let!(:question) { create(:poll_question, :yes_no, poll: poll) } let(:booth) { create(:poll_booth) } let(:officer) { create(:poll_officer) } let(:admin) { create(:administrator) } - let!(:answer_yes) { create(:poll_question_answer, question: question, title: "Yes") } - let!(:answer_no) { create(:poll_question_answer, question: question, title: "No") } before do create(:geozone, :in_census) @@ -29,8 +27,34 @@ describe "Voter" do expect(page).not_to have_button("Vote Yes") end - expect(Poll::Voter.count).to eq(1) - expect(Poll::Voter.first.origin).to eq("web") + visit poll_path(poll) + + expect(page).to have_content("You have already participated in this poll.") + expect(page).to have_content("If you vote again it will be overwritten") + end + + scenario "Remove vote via web - Standard" do + user = create(:user, :level_two) + create(:poll_answer, question: question, author: user, answer: "Yes") + create(:poll_voter, poll: poll, user: user) + + login_as user + visit poll_path(poll) + + expect(page).to have_content("You have already participated in this poll.") + expect(page).to have_content("If you vote again it will be overwritten") + + within("#poll_question_#{question.id}_answers") do + click_button "You have voted Yes" + + expect(page).to have_button("Vote Yes") + expect(page).to have_button("Vote No") + end + + visit poll_path(poll) + + expect(page).not_to have_content("You have already participated in this poll.") + expect(page).not_to have_content("If you vote again it will be overwritten") end scenario "Voting via web as unverified user" do @@ -40,8 +64,8 @@ describe "Voter" do visit poll_path(poll) within("#poll_question_#{question.id}_answers") do - expect(page).to have_link(answer_yes.title, href: verification_path) - expect(page).to have_link(answer_no.title, href: verification_path) + expect(page).to have_link("Yes", href: verification_path) + expect(page).to have_link("No", href: verification_path) end expect(page).to have_content("You must verify your account in order to answer") @@ -120,7 +144,7 @@ describe "Voter" do scenario "Trying to vote in web and then in booth" do login_as user - vote_for_poll_via_web(poll, question, answer_yes.title) + vote_for_poll_via_web(poll, question, "Yes") expect(Poll::Voter.count).to eq(1) click_link "Sign out" @@ -147,7 +171,7 @@ describe "Voter" do visit poll_path(poll) within("#poll_question_#{question.id}_answers") do - expect(page).not_to have_button(answer_yes.title) + expect(page).not_to have_button("Yes") end expect(page).to have_content "You have already participated in a physical booth. You can not participate again." expect(Poll::Voter.count).to eq(1) @@ -186,7 +210,7 @@ describe "Voter" do visit poll_path(poll) within("#poll_question_#{question.id}_answers") do - expect(page).not_to have_button(answer_yes.title) + expect(page).not_to have_button("Yes") end expect(page).to have_content "You have already participated in a physical booth. You can not participate again."