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.
This commit is contained in:
taitus
2025-08-22 14:26:25 +02:00
parent f3050a1aa5
commit b1cb6f8372
10 changed files with 55 additions and 5 deletions

View File

@@ -8,7 +8,7 @@
</div> </div>
</div> </div>
<% poll.questions.each do |question| %> <% poll.questions.for_physical_votes.each do |question| %>
<fieldset class="row"> <fieldset class="row">
<legend class="column"><%= question.title %></legend> <legend class="column"><%= question.title %></legend>
<% question.question_options.each_with_index do |option, i| %> <% question.question_options.each_with_index do |option, i| %>

View File

@@ -29,7 +29,7 @@
</tbody> </tbody>
</table> </table>
<% @poll.questions.each do |question| %> <% @poll.questions.for_physical_votes.each do |question| %>
<%= render Admin::Poll::Results::QuestionComponent.new(question, @partial_results) %> <%= render Admin::Poll::Results::QuestionComponent.new(question, @partial_results) %>
<% end %> <% end %>
</div> </div>

View File

@@ -31,6 +31,7 @@ class Poll::Question < ApplicationRecord
scope :sort_for_list, -> { order(Arel.sql("poll_questions.proposal_id IS NULL"), :created_at) } scope :sort_for_list, -> { order(Arel.sql("poll_questions.proposal_id IS NULL"), :created_at) }
scope :for_render, -> { includes(:author, :proposal) } scope :for_render, -> { includes(:author, :proposal) }
scope :for_physical_votes, -> { left_joins(:votation_type).merge(VotationType.accepts_options) }
def copy_attributes_from_proposal(proposal) def copy_attributes_from_proposal(proposal)
if proposal.present? if proposal.present?

View File

@@ -11,6 +11,8 @@ class VotationType < ApplicationRecord
validates :questionable_type, inclusion: { in: ->(*) { QUESTIONABLE_TYPES }} validates :questionable_type, inclusion: { in: ->(*) { QUESTIONABLE_TYPES }}
validates :max_votes, presence: true, if: :max_votes_required? validates :max_votes, presence: true, if: :max_votes_required?
scope :accepts_options, -> { where.not(vote_type: "open") }
def accepts_options? def accepts_options?
!open? !open?
end end

View File

@@ -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 "Invalid ballots", with: 0, type: :number
expect(page).to have_field "Valid ballots", with: 0, type: :number expect(page).to have_field "Valid ballots", with: 0, type: :number
end 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 end

View File

@@ -60,6 +60,7 @@ FactoryBot.define do
trait :yes_no do trait :yes_no do
after(:create) do |question| 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: "Yes")
create(:poll_question_option, question: question, title: "No") create(:poll_question_option, question: question, title: "No")
end end

View File

@@ -189,6 +189,21 @@ RSpec.describe Poll::Question do
end end
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 context "open-ended results" do
let(:poll) { create(:poll) } let(:poll) { create(:poll) }
let!(:question_open) { create(:poll_question_open, poll: poll) } let!(:question_open) { create(:poll_question_open, poll: poll) }

View File

@@ -58,4 +58,20 @@ describe VotationType do
"because you've already defined possible valid answers for this question" "because you've already defined possible valid answers for this question"
end end
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 end

View File

@@ -4,8 +4,8 @@ describe "Officing Results", :with_frozen_time do
let(:poll) { create(:poll, ends_at: 1.day.ago) } let(:poll) { create(:poll, ends_at: 1.day.ago) }
let(:booth) { create(:poll_booth, polls: [poll]) } let(:booth) { create(:poll_booth, polls: [poll]) }
let(:poll_officer) { create(:poll_officer) } let(:poll_officer) { create(:poll_officer) }
let(:question_1) { create(:poll_question, poll: poll) } let(:question_1) { create(:poll_question_unique, poll: poll) }
let(:question_2) { create(:poll_question, poll: poll) } let(:question_2) { create(:poll_question_unique, poll: poll) }
before do before do
create(:poll_shift, :recount_scrutiny_task, officer: poll_officer, booth: booth, date: Date.current) 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: "Today", question: question_2, given_order: 1)
create(:poll_question_option, title: "Tomorrow", question: question_2, given_order: 2) 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) login_as(poll_officer.user)
set_officing_booth(booth) set_officing_booth(booth)
end end
@@ -69,6 +71,8 @@ describe "Officing Results", :with_frozen_time do
fill_in "Tomorrow", with: "444" fill_in "Tomorrow", with: "444"
end end
expect(page).not_to have_css "fieldset", text: "What do you want?"
fill_in "Totally blank ballots", with: "66" fill_in "Totally blank ballots", with: "66"
fill_in "Invalid ballots", with: "77" fill_in "Invalid ballots", with: "77"
fill_in "Valid ballots", with: "88" 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) booth_assignment_id: partial_result.booth_assignment_id)
within("#question_#{question_1.id}_0_result") { expect(page).to have_content("7777") } 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) 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("#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}_0_result") { expect(page).to have_content("5555") }
within("#question_#{question_1.id}_1_result") { expect(page).to have_content("200") } 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
end end

View File

@@ -9,7 +9,7 @@ describe "Poll Votation Type" do
end end
scenario "Unique, multiple and open answers" do 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_multiple, :abcde, poll: poll, max_votes: 3, title: "Which ones do you prefer?")
create(:poll_question_open, poll: poll, title: "What do you think?") create(:poll_question_open, poll: poll, title: "What do you think?")