From b1cb6f83729a75375190647e522b33e88b435793 Mon Sep 17 00:00:00 2001 From: taitus Date: Fri, 22 Aug 2025 14:26:25 +0200 Subject: [PATCH] Exclude open-ended questions from managing physical votes Also make the :yes_no factory trait create a votation_type_unique by default, since yes/no questions should always be unique. --- .../officing/results/form_component.html.erb | 2 +- .../officing/results/index_component.html.erb | 2 +- app/models/poll/question.rb | 1 + app/models/votation_type.rb | 2 ++ .../officing/results/form_component_spec.rb | 9 +++++++++ spec/factories/polls.rb | 1 + spec/models/poll/question_spec.rb | 15 +++++++++++++++ spec/models/votation_type_spec.rb | 16 ++++++++++++++++ spec/system/officing/results_spec.rb | 10 ++++++++-- spec/system/polls/votation_types_spec.rb | 2 +- 10 files changed, 55 insertions(+), 5 deletions(-) diff --git a/app/components/officing/results/form_component.html.erb b/app/components/officing/results/form_component.html.erb index d1c7870ec..3572ac33b 100644 --- a/app/components/officing/results/form_component.html.erb +++ b/app/components/officing/results/form_component.html.erb @@ -8,7 +8,7 @@ - <% poll.questions.each do |question| %> + <% poll.questions.for_physical_votes.each do |question| %>
<%= question.title %> <% question.question_options.each_with_index do |option, i| %> diff --git a/app/components/officing/results/index_component.html.erb b/app/components/officing/results/index_component.html.erb index 046f2319d..98f667ce3 100644 --- a/app/components/officing/results/index_component.html.erb +++ b/app/components/officing/results/index_component.html.erb @@ -29,7 +29,7 @@ - <% @poll.questions.each do |question| %> + <% @poll.questions.for_physical_votes.each do |question| %> <%= render Admin::Poll::Results::QuestionComponent.new(question, @partial_results) %> <% end %> diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb index d6c9fc763..ce719493a 100644 --- a/app/models/poll/question.rb +++ b/app/models/poll/question.rb @@ -31,6 +31,7 @@ class Poll::Question < ApplicationRecord scope :sort_for_list, -> { order(Arel.sql("poll_questions.proposal_id IS NULL"), :created_at) } scope :for_render, -> { includes(:author, :proposal) } + scope :for_physical_votes, -> { left_joins(:votation_type).merge(VotationType.accepts_options) } def copy_attributes_from_proposal(proposal) if proposal.present? diff --git a/app/models/votation_type.rb b/app/models/votation_type.rb index af2758527..2302760c4 100644 --- a/app/models/votation_type.rb +++ b/app/models/votation_type.rb @@ -11,6 +11,8 @@ class VotationType < ApplicationRecord validates :questionable_type, inclusion: { in: ->(*) { QUESTIONABLE_TYPES }} validates :max_votes, presence: true, if: :max_votes_required? + scope :accepts_options, -> { where.not(vote_type: "open") } + def accepts_options? !open? end diff --git a/spec/components/officing/results/form_component_spec.rb b/spec/components/officing/results/form_component_spec.rb index 81f19e38e..b0e46dc2b 100644 --- a/spec/components/officing/results/form_component_spec.rb +++ b/spec/components/officing/results/form_component_spec.rb @@ -16,4 +16,13 @@ describe Officing::Results::FormComponent do expect(page).to have_field "Invalid ballots", with: 0, type: :number expect(page).to have_field "Valid ballots", with: 0, type: :number end + + it "does not render open-ended questions" do + create(:poll_question_open, poll: poll, title: "What do you want?") + + render_inline Officing::Results::FormComponent.new(poll, Poll::OfficerAssignment.none) + + expect(page).not_to have_content "What do you want?" + expect(page).to have_css "fieldset", text: "Agreed?" + end end diff --git a/spec/factories/polls.rb b/spec/factories/polls.rb index 155066fd6..a97df79d5 100644 --- a/spec/factories/polls.rb +++ b/spec/factories/polls.rb @@ -60,6 +60,7 @@ FactoryBot.define do trait :yes_no do after(:create) do |question| + create(:votation_type_unique, questionable: question) create(:poll_question_option, question: question, title: "Yes") create(:poll_question_option, question: question, title: "No") end diff --git a/spec/models/poll/question_spec.rb b/spec/models/poll/question_spec.rb index f882b0503..36945c8c8 100644 --- a/spec/models/poll/question_spec.rb +++ b/spec/models/poll/question_spec.rb @@ -189,6 +189,21 @@ RSpec.describe Poll::Question do end end + describe "scopes" do + describe ".for_physical_votes" do + it "returns unique and multiple, but not open_ended" do + question_unique = create(:poll_question_unique) + question_multiple = create(:poll_question_multiple) + question_open_ended = create(:poll_question_open) + + result = Poll::Question.for_physical_votes + + expect(result).to match_array [question_unique, question_multiple] + expect(result).not_to include question_open_ended + end + end + end + context "open-ended results" do let(:poll) { create(:poll) } let!(:question_open) { create(:poll_question_open, poll: poll) } diff --git a/spec/models/votation_type_spec.rb b/spec/models/votation_type_spec.rb index b31090a6f..3bae901bd 100644 --- a/spec/models/votation_type_spec.rb +++ b/spec/models/votation_type_spec.rb @@ -58,4 +58,20 @@ describe VotationType do "because you've already defined possible valid answers for this question" end end + + describe "scopes" do + describe ".accepts_options" do + it "includes unique and multiple, excludes open_ended" do + question_unique = create(:poll_question_unique) + question_multiple = create(:poll_question_multiple) + question_open_ended = create(:poll_question_open) + + accepts_options = VotationType.accepts_options + + expect(accepts_options).to match_array [question_unique.votation_type, + question_multiple.votation_type] + expect(accepts_options).not_to include question_open_ended.votation_type + end + end + end end diff --git a/spec/system/officing/results_spec.rb b/spec/system/officing/results_spec.rb index e17da5857..35348b95c 100644 --- a/spec/system/officing/results_spec.rb +++ b/spec/system/officing/results_spec.rb @@ -4,8 +4,8 @@ describe "Officing Results", :with_frozen_time do let(:poll) { create(:poll, ends_at: 1.day.ago) } let(:booth) { create(:poll_booth, polls: [poll]) } let(:poll_officer) { create(:poll_officer) } - let(:question_1) { create(:poll_question, poll: poll) } - let(:question_2) { create(:poll_question, poll: poll) } + let(:question_1) { create(:poll_question_unique, poll: poll) } + let(:question_2) { create(:poll_question_unique, poll: poll) } before do create(:poll_shift, :recount_scrutiny_task, officer: poll_officer, booth: booth, date: Date.current) @@ -15,6 +15,8 @@ describe "Officing Results", :with_frozen_time do create(:poll_question_option, title: "Today", question: question_2, given_order: 1) create(:poll_question_option, title: "Tomorrow", question: question_2, given_order: 2) + create(:poll_question_open, poll: poll, title: "What do you want?") + login_as(poll_officer.user) set_officing_booth(booth) end @@ -69,6 +71,8 @@ describe "Officing Results", :with_frozen_time do fill_in "Tomorrow", with: "444" end + expect(page).not_to have_css "fieldset", text: "What do you want?" + fill_in "Totally blank ballots", with: "66" fill_in "Invalid ballots", with: "77" fill_in "Valid ballots", with: "88" @@ -100,6 +104,7 @@ describe "Officing Results", :with_frozen_time do booth_assignment_id: partial_result.booth_assignment_id) within("#question_#{question_1.id}_0_result") { expect(page).to have_content("7777") } + expect(page).not_to have_content "What do you want?" visit new_officing_poll_result_path(poll) @@ -136,5 +141,6 @@ describe "Officing Results", :with_frozen_time do within("#total_results") { expect(page).to have_content("8") } within("#question_#{question_1.id}_0_result") { expect(page).to have_content("5555") } within("#question_#{question_1.id}_1_result") { expect(page).to have_content("200") } + expect(page).not_to have_content "What do you want?" end end diff --git a/spec/system/polls/votation_types_spec.rb b/spec/system/polls/votation_types_spec.rb index 444c785de..9d5de41b5 100644 --- a/spec/system/polls/votation_types_spec.rb +++ b/spec/system/polls/votation_types_spec.rb @@ -9,7 +9,7 @@ describe "Poll Votation Type" do end scenario "Unique, multiple and open answers" do - create(:poll_question_unique, :yes_no, poll: poll, title: "Is it that bad?") + create(:poll_question, :yes_no, poll: poll, title: "Is it that bad?") create(:poll_question_multiple, :abcde, poll: poll, max_votes: 3, title: "Which ones do you prefer?") create(:poll_question_open, poll: poll, title: "What do you think?")