diff --git a/app/models/poll/question/option.rb b/app/models/poll/question/option.rb index 4b59ec04b..c6b8a3f4d 100644 --- a/app/models/poll/question/option.rb +++ b/app/models/poll/question/option.rb @@ -40,8 +40,7 @@ class Poll::Question::Option < ApplicationRecord end def total_votes - Poll::Answer.where(question_id: question, answer: title).count + - ::Poll::PartialResult.where(question: question).where(answer: title).sum(:amount) + answers.count + partial_results.sum(:amount) end def total_votes_percentage diff --git a/spec/models/poll/question/option_spec.rb b/spec/models/poll/question/option_spec.rb index f719064ff..41096c31e 100644 --- a/spec/models/poll/question/option_spec.rb +++ b/spec/models/poll/question/option_spec.rb @@ -60,4 +60,83 @@ describe Poll::Question::Option do expect(option.with_read_more?).to be_truthy end end + + describe "#total_votes" do + let!(:question) { create(:poll_question) } + + context "with translated options" do + let(:option_yes) { create(:poll_question_option, question: question, title_en: "Yes", title_es: "Sí") } + + it "group votes from different locales for the same option" do + create(:poll_answer, question: question, option: option_yes, answer: "Sí") + create(:poll_answer, question: question, option: option_yes, answer: "Yes") + + expect(option_yes.total_votes).to eq 2 + end + end + + context "with options whose titles collide across locales" do + let!(:option_a) do + create(:poll_question_option, question: question, title_en: "Lead", title_es: "Plomo") + end + let!(:option_b) do + create(:poll_question_option, question: question, title_en: "Plomo", title_es: "Lead") + end + + it "keeps votes isolated to the correct option" do + create(:poll_answer, question: question, option: option_a, answer: "Plomo") + create(:poll_answer, question: question, option: option_a, answer: "Lead") + + expect(option_b.total_votes).to eq 0 + end + end + + context "with partial results" do + it "sums amounts by option_id" do + option = create(:poll_question_option, question: question, title_en: "Yes", title_es: "Sí") + booth_assignment = create(:poll_booth_assignment, poll: question.poll) + + create(:poll_partial_result, + booth_assignment: booth_assignment, + question: question, + option: option, + answer: "Yes", + amount: 2) + + create(:poll_partial_result, + booth_assignment: create(:poll_booth_assignment, poll: question.poll), + question: question, + option: option, + answer: "Sí", + amount: 3) + + expect(option.total_votes).to eq 5 + end + end + + context "with both answers and partial results" do + it "sums poll answers and partial results amounts" do + option = create(:poll_question_option, question: question, title_en: "Yes", title_es: "Sí") + + create(:poll_answer, question: question, option: option, answer: "Yes") + create(:poll_answer, question: question, option: option, answer: "Sí") + + create(:poll_partial_result, + booth_assignment: create(:poll_booth_assignment, poll: question.poll), + question: question, + option: option, + answer: "Yes", + amount: 2) + + create(:poll_partial_result, + booth_assignment: create(:poll_booth_assignment, poll: question.poll), + question: question, + option: option, + answer: "Sí", + amount: 3) + + expect(option.total_votes).to eq 7 + end + end + end end diff --git a/spec/models/poll/question_spec.rb b/spec/models/poll/question_spec.rb index f5bd37735..ddd57aa58 100644 --- a/spec/models/poll/question_spec.rb +++ b/spec/models/poll/question_spec.rb @@ -46,4 +46,44 @@ RSpec.describe Poll::Question do end end end + + describe "#options_total_votes" do + let!(:question) { create(:poll_question) } + let!(:option_yes) { create(:poll_question_option, question: question, title_en: "Yes", title_es: "Sí") } + let!(:option_no) { create(:poll_question_option, question: question, title_en: "No", title_es: "No") } + + before do + create(:poll_answer, question: question, option: option_yes, answer: "Sí") + create(:poll_answer, question: question, option: option_yes, answer: "Yes") + create(:poll_answer, question: question, option: option_no, answer: "No") + end + + it "includes answers in every language" do + expect(question.options_total_votes).to eq 3 + end + + it "includes partial results counted by option_id" do + booth_assignment = create(:poll_booth_assignment, poll: question.poll) + create(:poll_partial_result, + booth_assignment: booth_assignment, + question: question, + option: option_yes, + amount: 4) + + expect(question.options_total_votes).to eq 7 + end + + it "does not include votes from other questions even with same answer text" do + other_question = create(:poll_question, poll: question.poll) + other_option_yes = create(:poll_question_option, + question: other_question, + title_en: "Yes", + title_es: "Sí") + + create(:poll_partial_result, question: other_question, option: other_option_yes, amount: 4) + create(:poll_answer, question: other_question, option: other_option_yes, answer: "Yes") + + expect(question.options_total_votes).to eq 3 + end + end end