Enable voting for open-ended questions in public section

This commit is contained in:
taitus
2025-08-08 15:30:46 +02:00
parent 62e1c13e7e
commit 83b206f0b7
9 changed files with 201 additions and 57 deletions

View File

@@ -69,5 +69,26 @@ describe Polls::Questions::QuestionComponent do
expect(page).to have_field "Yes", type: :radio, checked: true
expect(page).to have_field "No", type: :radio, checked: false
end
context "Open-ended question" do
let(:question) { create(:poll_question_open, poll: poll, title: "What do you want?") }
before { create(:poll_answer, author: user, question: question, answer: "I don't know") }
it "renders text area with persisted answer" do
render_inline Polls::Questions::QuestionComponent.new(question, form: form)
expect(page).to have_field "What do you want?", type: :textarea, with: "I don't know"
end
it "renders unsaved form text over the persisted value" do
web_vote.answers[question.id] = [
build(:poll_answer, question: question, author: user, answer: "Typed (unsaved)")
]
render_inline Polls::Questions::QuestionComponent.new(question, form: form)
expect(page).to have_field "What do you want?", type: :textarea, with: "Typed (unsaved)"
end
end
end
end

View File

@@ -100,7 +100,7 @@ RSpec.describe Poll::Question do
existing_answer = create(:poll_answer, question: question, author: user, option: answer_a)
create(:poll_answer, question: question, author: other_user, option: answer_b)
answer = question.find_or_initialize_user_answer(user, answer_b.id)
answer = question.find_or_initialize_user_answer(user, option_id: answer_b.id)
expect(answer).to eq existing_answer
expect(answer.author).to eq user
@@ -111,13 +111,25 @@ RSpec.describe Poll::Question do
it "initializes a new answer when only another user has answered" do
create(:poll_answer, question: question, author: other_user, option: answer_a)
answer = question.find_or_initialize_user_answer(user, answer_a.id)
answer = question.find_or_initialize_user_answer(user, option_id: answer_a.id)
expect(answer).to be_new_record
expect(answer.author).to eq user
expect(answer.option).to eq answer_a
expect(answer.answer).to eq "Answer A"
end
it "raises when option_id is invalid" do
expect do
question.find_or_initialize_user_answer(user, option_id: 999999)
end.to raise_error(ActiveRecord::RecordNotFound)
end
it "raises when option_id is nil" do
expect do
question.find_or_initialize_user_answer(user, answer_text: "ignored")
end.to raise_error(ActiveRecord::RecordNotFound)
end
end
context "multiple question" do
@@ -129,7 +141,7 @@ RSpec.describe Poll::Question do
existing_answer = create(:poll_answer, question: question, author: user, option: answer_a)
create(:poll_answer, question: question, author: other_user, option: answer_a)
answer = question.find_or_initialize_user_answer(user, answer_a.id)
answer = question.find_or_initialize_user_answer(user, option_id: answer_a.id)
expect(answer).to eq existing_answer
expect(answer.author).to eq user
@@ -141,7 +153,7 @@ RSpec.describe Poll::Question do
create(:poll_answer, question: question, author: user, option: answer_a)
create(:poll_answer, question: question, author: other_user, option: answer_b)
answer = question.find_or_initialize_user_answer(user, answer_b.id)
answer = question.find_or_initialize_user_answer(user, option_id: answer_b.id)
expect(answer).to be_new_record
expect(answer.author).to eq user
@@ -149,5 +161,31 @@ RSpec.describe Poll::Question do
expect(answer.answer).to eq "Answer B"
end
end
context "Open-ended question" do
let(:question) { create(:poll_question_open) }
it "ignores invalid option_id and uses answer_text" do
answer = question.find_or_initialize_user_answer(user, option_id: 999999, answer_text: "Hi")
expect(answer.option).to be nil
expect(answer.answer).to eq "Hi"
end
it "ignores option_id when nil and assigns answer with option set to nil" do
answer = question.find_or_initialize_user_answer(user, answer_text: "Hi")
expect(answer.option).to be nil
expect(answer.answer).to eq "Hi"
end
it "reuses the existing poll answer for the user and updates answer" do
existing = create(:poll_answer, question: question, author: user, answer: "Before")
answer = question.find_or_initialize_user_answer(user, answer_text: "After")
expect(answer).to eq existing
expect(answer.author).to eq user
expect(answer.answer).to eq "After"
end
end
end
end

View File

@@ -156,5 +156,47 @@ describe Poll::WebVote do
expect(Poll::Answer.count).to be 2
end
end
context "Open-ended questions" do
let!(:open_ended_question) { create(:poll_question_open, poll: poll) }
it "creates one answer when text is present" do
web_vote.update(open_ended_question.id.to_s => { answer: " Hi " })
expect(poll.reload.voters.size).to eq 1
open_answer = open_ended_question.reload.answers.find_by(author: user)
expect(open_answer.answer).to eq "Hi"
expect(open_answer.option_id).to be nil
end
it "does not create an answer but create voters when text is blank or only spaces" do
web_vote.update(open_ended_question.id.to_s => { answer: " " })
expect(poll.reload.voters.size).to eq 1
expect(open_ended_question.reload.answers.where(author: user)).to be_empty
end
it "deletes existing answer but keeps voters when leaving open-ended blank" do
create(:poll_answer, question: open_ended_question, author: user, answer: "Old answer")
web_vote.update(open_ended_question.id.to_s => { answer: " " })
expect(poll.reload.voters.size).to eq 1
expect(open_ended_question.reload.answers.where(author: user)).to be_empty
end
it "updates existing open answer without creating duplicates" do
existing = create(:poll_answer, question: open_ended_question, author: user, answer: "Old text")
web_vote.update(open_ended_question.id.to_s => { answer: " New text " })
updated = open_ended_question.reload.answers.find_by(author: user)
expect(updated.id).to eq existing.id
expect(updated.answer).to eq "New text"
expect(updated.option_id).to be nil
expect(poll.reload.voters.size).to eq 1
end
end
end
end

View File

@@ -8,9 +8,10 @@ describe "Poll Votation Type" do
login_as(author)
end
scenario "Unique and multiple 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_multiple, :abcde, poll: poll, max_votes: 3, title: "Which ones do you prefer?")
create(:poll_question_open, poll: poll, title: "What do you think?")
visit poll_path(poll)
@@ -21,6 +22,10 @@ describe "Poll Votation Type" do
check "Answer C"
end
within(".poll-question-open-ended") do
fill_in "What do you think?", with: "I believe it's great"
end
click_button "Vote"
expect(page).to have_content "Thank you for voting!"
@@ -39,6 +44,10 @@ describe "Poll Votation Type" do
expect(page).to have_field "Answer E", type: :checkbox, checked: false
end
within(".poll-question-open-ended") do
expect(page).to have_field "What do you think?", with: "I believe it's great"
end
expect(page).to have_button "Vote"
end