From 64676be2462416fb80d2a831effc56dd575fc2ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?=
<15726+Senen@users.noreply.github.com>
Date: Thu, 15 Sep 2022 18:45:28 +0200
Subject: [PATCH 1/8] Remove `token` column from `poll_voters` table
As it is no longer used as originally pretended [1][2].
[1] Check consul/consul pull request 1994
[2] Check consul/consul pull request 3539
---
app/assets/javascripts/polls.js | 21 -------------------
app/controllers/polls/questions_controller.rb | 3 +--
app/controllers/polls_controller.rb | 2 --
app/helpers/polls_helper.rb | 4 ----
app/models/poll/answer.rb | 4 ++--
app/views/polls/questions/_answers.html.erb | 4 ++--
app/views/polls/questions/_question.html.erb | 2 +-
app/views/polls/questions/answer.js.erb | 3 +--
app/views/polls/show.html.erb | 2 +-
db/dev_seeds/polls.rb | 3 +--
...0915154808_remove_token_from_poll_voter.rb | 5 +++++
db/schema.rb | 3 +--
spec/factories/polls.rb | 1 -
spec/models/poll/answer_spec.rb | 8 +++----
spec/models/poll/voter_spec.rb | 8 +++----
spec/system/polls/voter_spec.rb | 4 ++--
16 files changed, 24 insertions(+), 53 deletions(-)
create mode 100644 db/migrate/20220915154808_remove_token_from_poll_voter.rb
diff --git a/app/assets/javascripts/polls.js b/app/assets/javascripts/polls.js
index 6a9f50079..fa0495e27 100644
--- a/app/assets/javascripts/polls.js
+++ b/app/assets/javascripts/polls.js
@@ -1,28 +1,7 @@
(function() {
"use strict";
App.Polls = {
- generateToken: function() {
- var strings;
- strings = Array.apply(null, {
- length: 6
- }).map(function() {
- return Math.random().toString(36).substr(2); // remove `0.`
- });
- return strings.join("").substring(0, 64);
- },
- replaceToken: function(token) {
- $(".js-question-answer").each(function() {
- var token_param;
- token_param = this.search.slice(-6);
- if (token_param === "token=") {
- this.href = this.href + token;
- }
- });
- },
initialize: function() {
- var token;
- token = App.Polls.generateToken();
- App.Polls.replaceToken(token);
$(".zoom-link").on("click", function(event) {
var answer;
answer = $(event.target).closest("div.answer");
diff --git a/app/controllers/polls/questions_controller.rb b/app/controllers/polls/questions_controller.rb
index 3f2809b75..4f76fc672 100644
--- a/app/controllers/polls/questions_controller.rb
+++ b/app/controllers/polls/questions_controller.rb
@@ -6,10 +6,9 @@ class Polls::QuestionsController < ApplicationController
def answer
answer = @question.answers.find_or_initialize_by(author: current_user)
- token = params[:token]
answer.answer = params[:answer]
- answer.save_and_record_voter_participation(token)
+ answer.save_and_record_voter_participation
@answers_by_question_id = { @question.id => params[:answer] }
end
diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb
index 154961a6b..f96298914 100644
--- a/app/controllers/polls_controller.rb
+++ b/app/controllers/polls_controller.rb
@@ -1,6 +1,5 @@
class PollsController < ApplicationController
include FeatureFlags
- include PollsHelper
feature_flag :polls
@@ -20,7 +19,6 @@ class PollsController < ApplicationController
def show
@questions = @poll.questions.for_render.sort_for_list
- @token = poll_voter_token(@poll, current_user)
@poll_questions_answers = Poll::Question::Answer.where(question: @poll.questions)
.with_content.order(:given_order)
diff --git a/app/helpers/polls_helper.rb b/app/helpers/polls_helper.rb
index 08a2d3ab2..ee4ddb375 100644
--- a/app/helpers/polls_helper.rb
+++ b/app/helpers/polls_helper.rb
@@ -12,10 +12,6 @@ module PollsHelper
booth.name + location
end
- def poll_voter_token(poll, user)
- Poll::Voter.find_by(poll: poll, user: user, origin: "web")&.token || ""
- end
-
def voted_before_sign_in(question)
question.answers.where(author: current_user).any? { |vote| current_user.current_sign_in_at > vote.updated_at }
end
diff --git a/app/models/poll/answer.rb b/app/models/poll/answer.rb
index 8742b7d64..685830201 100644
--- a/app/models/poll/answer.rb
+++ b/app/models/poll/answer.rb
@@ -14,11 +14,11 @@ class Poll::Answer < ApplicationRecord
scope :by_author, ->(author_id) { where(author_id: author_id) }
scope :by_question, ->(question_id) { where(question_id: question_id) }
- def save_and_record_voter_participation(token)
+ def save_and_record_voter_participation
transaction do
touch if persisted?
save!
- Poll::Voter.find_or_create_by!(user: author, poll: poll, origin: "web", token: token)
+ Poll::Voter.find_or_create_by!(user: author, poll: poll, origin: "web")
end
end
end
diff --git a/app/views/polls/questions/_answers.html.erb b/app/views/polls/questions/_answers.html.erb
index 02088ab7a..4c521107f 100644
--- a/app/views/polls/questions/_answers.html.erb
+++ b/app/views/polls/questions/_answers.html.erb
@@ -10,11 +10,11 @@
<% else %>
<%= link_to answer.title,
- answer_question_path(question, answer: answer.title, token: token),
+ answer_question_path(question, answer: answer.title),
method: :post,
remote: true,
title: t("poll_questions.show.vote_answer", answer: answer.title),
- class: "button secondary hollow js-question-answer" %>
+ class: "button secondary hollow" %>
<% end %>
<% end %>
<% elsif !user_signed_in? %>
diff --git a/app/views/polls/questions/_question.html.erb b/app/views/polls/questions/_question.html.erb
index 016c0fa95..ade9c5910 100644
--- a/app/views/polls/questions/_question.html.erb
+++ b/app/views/polls/questions/_question.html.erb
@@ -4,6 +4,6 @@
- <%= render "polls/questions/answers", question: question, token: token %>
+ <%= render "polls/questions/answers", question: question %>
diff --git a/app/views/polls/questions/answer.js.erb b/app/views/polls/questions/answer.js.erb
index 79978e2c1..f98441d0f 100644
--- a/app/views/polls/questions/answer.js.erb
+++ b/app/views/polls/questions/answer.js.erb
@@ -1,2 +1 @@
-<% token = poll_voter_token(@question.poll, current_user) %>
-$("#<%= dom_id(@question) %>_answers").html("<%= j render("polls/questions/answers", question: @question, token: token) %>");
+$("#<%= dom_id(@question) %>_answers").html("<%= j render("polls/questions/answers", question: @question) %>");
diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb
index 1aa0e89ec..ee4449124 100644
--- a/app/views/polls/show.html.erb
+++ b/app/views/polls/show.html.erb
@@ -32,7 +32,7 @@
<% end %>
<% @questions.each do |question| %>
- <%= render "polls/questions/question", question: question, token: @token %>
+ <%= render "polls/questions/question", question: question %>
<% end %>
diff --git a/db/dev_seeds/polls.rb b/db/dev_seeds/polls.rb
index a4bd79fba..cf9e97fbe 100644
--- a/db/dev_seeds/polls.rb
+++ b/db/dev_seeds/polls.rb
@@ -146,8 +146,7 @@ section "Creating Poll Voters" do
document_number: user.document_number,
user: user,
poll: poll,
- origin: "web",
- token: SecureRandom.hex(32))
+ origin: "web")
end
def randomly_answer_questions(poll, user)
diff --git a/db/migrate/20220915154808_remove_token_from_poll_voter.rb b/db/migrate/20220915154808_remove_token_from_poll_voter.rb
new file mode 100644
index 000000000..068307c64
--- /dev/null
+++ b/db/migrate/20220915154808_remove_token_from_poll_voter.rb
@@ -0,0 +1,5 @@
+class RemoveTokenFromPollVoter < ActiveRecord::Migration[6.0]
+ def change
+ remove_column :poll_voters, :token, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index b3cac4d02..cb93e1c07 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2021_11_03_112944) do
+ActiveRecord::Schema.define(version: 2022_09_15_154808) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm"
@@ -1210,7 +1210,6 @@ ActiveRecord::Schema.define(version: 2021_11_03_112944) do
t.integer "user_id"
t.string "origin"
t.integer "officer_id"
- t.string "token"
t.index ["booth_assignment_id"], name: "index_poll_voters_on_booth_assignment_id"
t.index ["document_number"], name: "index_poll_voters_on_document_number"
t.index ["officer_assignment_id"], name: "index_poll_voters_on_officer_assignment_id"
diff --git a/spec/factories/polls.rb b/spec/factories/polls.rb
index 03ad24670..212e7998b 100644
--- a/spec/factories/polls.rb
+++ b/spec/factories/polls.rb
@@ -144,7 +144,6 @@ FactoryBot.define do
poll { budget&.poll || association(:poll, budget: budget) }
trait :from_web do
origin { "web" }
- token { SecureRandom.hex(32) }
end
trait :from_booth do
diff --git a/spec/models/poll/answer_spec.rb b/spec/models/poll/answer_spec.rb
index 8c0598734..d420e367e 100644
--- a/spec/models/poll/answer_spec.rb
+++ b/spec/models/poll/answer_spec.rb
@@ -46,7 +46,7 @@ describe Poll::Answer do
answer = create(:poll_answer, question: question, author: author, answer: "Yes")
expect(answer.poll.voters).to be_blank
- answer.save_and_record_voter_participation("token")
+ answer.save_and_record_voter_participation
expect(poll.reload.voters.size).to eq(1)
voter = poll.voters.first
@@ -57,12 +57,12 @@ describe Poll::Answer do
it "updates a poll_voter with user and poll data" do
answer = create(:poll_answer, question: question, author: author, answer: "Yes")
- answer.save_and_record_voter_participation("token")
+ answer.save_and_record_voter_participation
expect(poll.reload.voters.size).to eq(1)
answer = create(:poll_answer, question: question, author: author, answer: "No")
- answer.save_and_record_voter_participation("token")
+ answer.save_and_record_voter_participation
expect(poll.reload.voters.size).to eq(1)
@@ -76,7 +76,7 @@ describe Poll::Answer do
answer = build(:poll_answer)
expect do
- answer.save_and_record_voter_participation("token")
+ answer.save_and_record_voter_participation
end.to raise_error(ActiveRecord::RecordInvalid)
expect(answer).not_to be_persisted
diff --git a/spec/models/poll/voter_spec.rb b/spec/models/poll/voter_spec.rb
index b30c7428e..e33711ff1 100644
--- a/spec/models/poll/voter_spec.rb
+++ b/spec/models/poll/voter_spec.rb
@@ -196,21 +196,19 @@ describe Poll::Voter do
it "sets user info" do
user = create(:user, document_number: "1234A", document_type: "1")
- voter = build(:poll_voter, user: user, token: "1234abcd")
+ voter = build(:poll_voter, user: user)
voter.save!
expect(voter.document_number).to eq("1234A")
expect(voter.document_type).to eq("1")
- expect(voter.token).to eq("1234abcd")
end
it "sets user info with skip verification enabled" do
Setting["feature.user.skip_verification"] = true
user = create(:user)
- voter = build(:poll_voter, user: user, token: "1234abcd")
- voter.save!
+ voter = build(:poll_voter, user: user)
- expect(voter.token).to eq("1234abcd")
+ expect { voter.save! }.not_to raise_exception
end
end
end
diff --git a/spec/system/polls/voter_spec.rb b/spec/system/polls/voter_spec.rb
index 46305ce4a..336c2db0b 100644
--- a/spec/system/polls/voter_spec.rb
+++ b/spec/system/polls/voter_spec.rb
@@ -38,8 +38,8 @@ describe "Voter" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- expect(page).not_to have_link(answer_yes.title, href: "/questions/#{question.id}/answer?answer=#{answer_yes.title}&token=")
- expect(page).not_to have_link(answer_no.title, href: "/questions/#{question.id}/answer?answer=#{answer_no.title}&token=")
+ expect(page).not_to have_link(answer_yes.title, href: "/questions/#{question.id}/answer?answer=#{answer_yes.title}")
+ expect(page).not_to have_link(answer_no.title, href: "/questions/#{question.id}/answer?answer=#{answer_no.title}")
end
expect(page).to have_content("You must verify your account in order to answer")
From 527d5691f7f962b30ef483efd437564648dc1e09 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?=
<15726+Senen@users.noreply.github.com>
Date: Thu, 15 Sep 2022 19:13:14 +0200
Subject: [PATCH 2/8] Make poll feature work in browsers with javascript
disabled
By using the Rails `button_to` helper (which generates a form), and adapting the
response to `html` and `js` formats, the feature works with or without javascript
enabled.
---
app/assets/stylesheets/participation.scss | 3 +-
app/controllers/polls/questions_controller.rb | 9 +++
app/views/polls/questions/_answers.html.erb | 12 +--
spec/support/common_actions/polls.rb | 6 +-
spec/system/polls/polls_spec.rb | 74 +++++++++++--------
spec/system/polls/voter_spec.rb | 18 ++---
6 files changed, 74 insertions(+), 48 deletions(-)
diff --git a/app/assets/stylesheets/participation.scss b/app/assets/stylesheets/participation.scss
index 7efc0f1e8..8b254d440 100644
--- a/app/assets/stylesheets/participation.scss
+++ b/app/assets/stylesheets/participation.scss
@@ -1634,9 +1634,10 @@
}
.poll-question-answers {
+ @include flex-with-gap($line-height / 4);
+ flex-wrap: wrap;
.button {
- margin-right: $line-height / 4;
min-width: rem-calc(168);
@include breakpoint(medium down) {
diff --git a/app/controllers/polls/questions_controller.rb b/app/controllers/polls/questions_controller.rb
index 4f76fc672..51269cff1 100644
--- a/app/controllers/polls/questions_controller.rb
+++ b/app/controllers/polls/questions_controller.rb
@@ -11,5 +11,14 @@ class Polls::QuestionsController < ApplicationController
answer.save_and_record_voter_participation
@answers_by_question_id = { @question.id => params[:answer] }
+
+ respond_to do |format|
+ format.html do
+ redirect_to request.referer
+ end
+ format.js do
+ render :answer
+ end
+ end
end
end
diff --git a/app/views/polls/questions/_answers.html.erb b/app/views/polls/questions/_answers.html.erb
index 4c521107f..08030bc0e 100644
--- a/app/views/polls/questions/_answers.html.erb
+++ b/app/views/polls/questions/_answers.html.erb
@@ -9,12 +9,12 @@
<%= answer.title %>
<% else %>
- <%= link_to answer.title,
- answer_question_path(question, answer: answer.title),
- method: :post,
- remote: true,
- title: t("poll_questions.show.vote_answer", answer: answer.title),
- class: "button secondary hollow" %>
+ <%= button_to answer_question_path(question, answer: answer.title),
+ remote: true,
+ title: t("poll_questions.show.vote_answer", answer: answer.title),
+ class: "button secondary hollow" do %>
+ <%= answer.title %>
+ <% end %>
<% end %>
<% end %>
<% elsif !user_signed_in? %>
diff --git a/spec/support/common_actions/polls.rb b/spec/support/common_actions/polls.rb
index b097c4355..b571472c4 100644
--- a/spec/support/common_actions/polls.rb
+++ b/spec/support/common_actions/polls.rb
@@ -3,8 +3,10 @@ module Polls
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- click_link answer.to_s
- expect(page).not_to have_link(answer.to_s)
+ click_button answer
+
+ expect(page).to have_css("span.answered", text: answer)
+ expect(page).not_to have_button(answer)
end
end
diff --git a/spec/system/polls/polls_spec.rb b/spec/system/polls/polls_spec.rb
index d2631c873..c4ec85e99 100644
--- a/spec/system/polls/polls_spec.rb
+++ b/spec/system/polls/polls_spec.rb
@@ -283,8 +283,8 @@ describe "Polls" do
within("#poll_question_#{question.id}_answers") do
expect(page).to have_content("Yes")
expect(page).to have_content("No")
- expect(page).not_to have_link("Yes")
- expect(page).not_to have_link("No")
+ expect(page).not_to have_button "Yes"
+ expect(page).not_to have_button "No"
end
expect(page).to have_content("This poll has finished")
end
@@ -302,8 +302,8 @@ describe "Polls" do
within("#poll_question_#{question.id}_answers") do
expect(page).to have_content("Yes")
expect(page).to have_content("No")
- expect(page).not_to have_link("Yes")
- expect(page).not_to have_link("No")
+ expect(page).not_to have_button "Yes"
+ expect(page).not_to have_button "No"
end
end
@@ -317,8 +317,8 @@ describe "Polls" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- expect(page).to have_link("Yes")
- expect(page).to have_link("No")
+ expect(page).to have_button "Yes"
+ expect(page).to have_button "No"
end
end
@@ -329,8 +329,8 @@ describe "Polls" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- expect(page).to have_link("Yes")
- expect(page).to have_link("No")
+ expect(page).to have_button "Yes"
+ expect(page).to have_button "No"
end
end
@@ -343,8 +343,8 @@ describe "Polls" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- expect(page).to have_link("Yes")
- expect(page).to have_link("No")
+ expect(page).to have_button "Yes"
+ expect(page).to have_button "No"
end
end
@@ -359,10 +359,10 @@ describe "Polls" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- click_link "Yes"
+ click_button "Yes"
- expect(page).not_to have_link("Yes")
- expect(page).to have_link("No")
+ expect(page).not_to have_button "Yes"
+ expect(page).to have_button "No"
end
end
@@ -377,15 +377,15 @@ describe "Polls" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- click_link "Yes"
+ click_button "Yes"
- expect(page).not_to have_link("Yes")
- expect(page).to have_link("No")
+ expect(page).not_to have_button "Yes"
+ expect(page).to have_button "No"
- click_link "No"
+ click_button "No"
- expect(page).not_to have_link("No")
- expect(page).to have_link("Yes")
+ expect(page).not_to have_button "No"
+ expect(page).to have_button "Yes"
end
end
@@ -400,30 +400,30 @@ describe "Polls" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- click_link "Yes"
+ click_button "Yes"
- expect(page).not_to have_link("Yes")
- expect(page).to have_link("No")
+ expect(page).not_to have_button "Yes"
+ expect(page).to have_button "No"
end
click_link "Sign out"
login_as user
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- click_link "Yes"
+ click_button "Yes"
- expect(page).not_to have_link("Yes")
- expect(page).to have_link("No")
+ expect(page).not_to have_button "Yes"
+ expect(page).to have_button "No"
end
click_link "Sign out"
login_as user
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- click_link "No"
+ click_button "No"
- expect(page).not_to have_link("No")
- expect(page).to have_link("Yes")
+ expect(page).not_to have_button "No"
+ expect(page).to have_button "Yes"
end
end
@@ -450,6 +450,20 @@ describe "Polls" do
expect("Not restricted").to appear_before("Geozone Poll")
expect("Geozone Poll").to appear_before("A Poll")
end
+
+ scenario "Level 2 users answering in a browser without javascript", :no_js do
+ question = create(:poll_question, :yes_no, poll: poll)
+ user = create(:user, :level_two)
+ login_as user
+ visit poll_path(poll)
+
+ within("#poll_question_#{question.id}_answers") do
+ click_button "Yes"
+
+ expect(page).not_to have_button "Yes"
+ expect(page).to have_button "No"
+ end
+ end
end
context "Booth & Website", :with_frozen_time do
@@ -481,8 +495,8 @@ describe "Polls" do
expect(page).to have_content("Yes")
expect(page).to have_content("No")
- expect(page).not_to have_link("Yes")
- expect(page).not_to have_link("No")
+ expect(page).not_to have_button "Yes"
+ expect(page).not_to have_button "No"
end
end
end
diff --git a/spec/system/polls/voter_spec.rb b/spec/system/polls/voter_spec.rb
index 336c2db0b..a629dcdf6 100644
--- a/spec/system/polls/voter_spec.rb
+++ b/spec/system/polls/voter_spec.rb
@@ -23,8 +23,8 @@ describe "Voter" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- click_link answer_yes.title
- expect(page).not_to have_link(answer_yes.title)
+ click_button answer_yes.title
+ expect(page).not_to have_button(answer_yes.title)
end
expect(Poll::Voter.count).to eq(1)
@@ -38,8 +38,8 @@ describe "Voter" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- expect(page).not_to have_link(answer_yes.title, href: "/questions/#{question.id}/answer?answer=#{answer_yes.title}")
- expect(page).not_to have_link(answer_no.title, href: "/questions/#{question.id}/answer?answer=#{answer_no.title}")
+ expect(page).to have_link(answer_yes.title, href: verification_path)
+ expect(page).to have_link(answer_no.title, href: verification_path)
end
expect(page).to have_content("You must verify your account in order to answer")
@@ -145,7 +145,7 @@ describe "Voter" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- expect(page).not_to have_link(answer_yes.title)
+ expect(page).not_to have_button(answer_yes.title)
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)
@@ -173,7 +173,7 @@ describe "Voter" do
expect(page).to have_content "You have already participated in this poll. If you vote again it will be overwritten."
within("#poll_question_#{question.id}_answers") do
- expect(page).not_to have_link(answer_yes.title)
+ expect(page).not_to have_button(answer_yes.title)
end
unfreeze_time
@@ -184,8 +184,8 @@ describe "Voter" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- expect(page).to have_link(answer_yes.title)
- expect(page).to have_link(answer_no.title)
+ expect(page).to have_button(answer_yes.title)
+ expect(page).to have_button(answer_no.title)
end
end
end
@@ -209,7 +209,7 @@ describe "Voter" do
visit poll_path(poll)
within("#poll_question_#{question.id}_answers") do
- expect(page).not_to have_link(answer_yes.title)
+ expect(page).not_to have_button(answer_yes.title)
end
expect(page).to have_content "You have already participated in a physical booth. You can not participate again."
From bd58023a8a9070c22c68f6181b4ae2bf49ace4fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?=
<15726+Senen@users.noreply.github.com>
Date: Wed, 31 Aug 2022 13:35:00 +0200
Subject: [PATCH 3/8] Extract `polls questions answers partial` into a
component
---
.../questions/answers_component.html.erb} | 4 +-
.../polls/questions/answers_component.rb | 31 +++++
app/controllers/polls/questions_controller.rb | 2 -
app/controllers/polls_controller.rb | 7 --
app/helpers/polls_helper.rb | 4 -
app/views/polls/questions/_question.html.erb | 2 +-
app/views/polls/questions/answer.js.erb | 2 +-
.../polls/questions/answers_component_spec.rb | 110 ++++++++++++++++++
spec/system/polls/polls_spec.rb | 88 +-------------
9 files changed, 147 insertions(+), 103 deletions(-)
rename app/{views/polls/questions/_answers.html.erb => components/polls/questions/answers_component.html.erb} (92%)
create mode 100644 app/components/polls/questions/answers_component.rb
create mode 100644 spec/components/polls/questions/answers_component_spec.rb
diff --git a/app/views/polls/questions/_answers.html.erb b/app/components/polls/questions/answers_component.html.erb
similarity index 92%
rename from app/views/polls/questions/_answers.html.erb
rename to app/components/polls/questions/answers_component.html.erb
index 08030bc0e..4e61ee767 100644
--- a/app/views/polls/questions/_answers.html.erb
+++ b/app/components/polls/questions/answers_component.html.erb
@@ -1,8 +1,8 @@
<% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %>
<% question.question_answers.each do |answer| %>
- <% if @answers_by_question_id[question.id] == answer.title &&
- (!voted_before_sign_in(question) ||
+ <% if answers_by_question_id[question.id] == answer.title &&
+ (!voted_before_sign_in? ||
question.poll.voted_in_booth?(current_user)) %>
">
diff --git a/app/components/polls/questions/answers_component.rb b/app/components/polls/questions/answers_component.rb
new file mode 100644
index 000000000..1d64198a4
--- /dev/null
+++ b/app/components/polls/questions/answers_component.rb
@@ -0,0 +1,31 @@
+class Polls::Questions::AnswersComponent < ApplicationComponent
+ attr_reader :question
+ delegate :can?, :current_user, :user_signed_in?, to: :helpers
+
+ def initialize(question)
+ @question = question
+ end
+
+ def answers_by_question_id
+ if params[:answer]
+ { question.id => params[:answer] }
+ else
+ stored_answers_by_question_id
+ end
+ end
+
+ def voted_before_sign_in?
+ question.answers.where(author: current_user).any? do |vote|
+ vote.updated_at < current_user.current_sign_in_at
+ end
+ end
+
+ private
+
+ def stored_answers_by_question_id
+ poll_answers = ::Poll::Answer.by_question(question.poll.question_ids).by_author(current_user&.id)
+ poll_answers.each_with_object({}) do |answer, answers_by_question_id|
+ answers_by_question_id[answer.question_id] = answer.answer
+ end
+ end
+end
diff --git a/app/controllers/polls/questions_controller.rb b/app/controllers/polls/questions_controller.rb
index 51269cff1..3731aa2f9 100644
--- a/app/controllers/polls/questions_controller.rb
+++ b/app/controllers/polls/questions_controller.rb
@@ -10,8 +10,6 @@ class Polls::QuestionsController < ApplicationController
answer.answer = params[:answer]
answer.save_and_record_voter_participation
- @answers_by_question_id = { @question.id => params[:answer] }
-
respond_to do |format|
format.html do
redirect_to request.referer
diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb
index f96298914..af2dc563a 100644
--- a/app/controllers/polls_controller.rb
+++ b/app/controllers/polls_controller.rb
@@ -21,13 +21,6 @@ class PollsController < ApplicationController
@questions = @poll.questions.for_render.sort_for_list
@poll_questions_answers = Poll::Question::Answer.where(question: @poll.questions)
.with_content.order(:given_order)
-
- @answers_by_question_id = {}
- poll_answers = ::Poll::Answer.by_question(@poll.question_ids).by_author(current_user&.id)
- poll_answers.each do |answer|
- @answers_by_question_id[answer.question_id] = answer.answer
- end
-
@commentable = @poll
@comment_tree = CommentTree.new(@commentable, params[:page], @current_order)
end
diff --git a/app/helpers/polls_helper.rb b/app/helpers/polls_helper.rb
index ee4ddb375..5a27d25db 100644
--- a/app/helpers/polls_helper.rb
+++ b/app/helpers/polls_helper.rb
@@ -12,10 +12,6 @@ module PollsHelper
booth.name + location
end
- def voted_before_sign_in(question)
- question.answers.where(author: current_user).any? { |vote| current_user.current_sign_in_at > vote.updated_at }
- end
-
def link_to_poll(text, poll)
if can?(:results, poll)
link_to text, results_poll_path(id: poll.slug || poll.id)
diff --git a/app/views/polls/questions/_question.html.erb b/app/views/polls/questions/_question.html.erb
index ade9c5910..5fd7eeb8b 100644
--- a/app/views/polls/questions/_question.html.erb
+++ b/app/views/polls/questions/_question.html.erb
@@ -4,6 +4,6 @@
- <%= render "polls/questions/answers", question: question %>
+ <%= render Polls::Questions::AnswersComponent.new(question) %>
diff --git a/app/views/polls/questions/answer.js.erb b/app/views/polls/questions/answer.js.erb
index f98441d0f..2c4380238 100644
--- a/app/views/polls/questions/answer.js.erb
+++ b/app/views/polls/questions/answer.js.erb
@@ -1 +1 @@
-$("#<%= dom_id(@question) %>_answers").html("<%= j render("polls/questions/answers", question: @question) %>");
+$("#<%= dom_id(@question) %>_answers").html("<%= j render Polls::Questions::AnswersComponent.new(@question) %>");
diff --git a/spec/components/polls/questions/answers_component_spec.rb b/spec/components/polls/questions/answers_component_spec.rb
new file mode 100644
index 000000000..e0a543a16
--- /dev/null
+++ b/spec/components/polls/questions/answers_component_spec.rb
@@ -0,0 +1,110 @@
+require "rails_helper"
+
+describe Polls::Questions::AnswersComponent do
+ include Rails.application.routes.url_helpers
+ let(:poll) { create(:poll) }
+ let(:question) { create(:poll_question, :yes_no, poll: poll) }
+
+ it "renders answers in given order" do
+ render_inline Polls::Questions::AnswersComponent.new(question)
+
+ expect("Yes").to appear_before("No")
+ end
+
+ it "renders buttons to vote question answers" do
+ sign_in(create(:user, :verified))
+
+ render_inline Polls::Questions::AnswersComponent.new(question)
+
+ expect(page).to have_button "Yes"
+ expect(page).to have_button "No"
+ end
+
+ it "renders a span instead of a button for existing user answers" do
+ user = create(:user, :verified)
+ allow(user).to receive(:current_sign_in_at).and_return(user.created_at)
+ create(:poll_answer, author: user, question: question, answer: "Yes")
+ sign_in(user)
+
+ render_inline Polls::Questions::AnswersComponent.new(question)
+
+ expect(page).to have_selector "span", text: "Yes"
+ expect(page).not_to have_button "Yes"
+ expect(page).to have_button "No"
+ end
+
+ it "hides current answer and shows buttons in successive sessions" do
+ user = create(:user, :verified)
+ create(:poll_answer, author: user, question: question, answer: "Yes")
+ allow(user).to receive(:current_sign_in_at).and_return(Time.current)
+ sign_in(user)
+
+ render_inline Polls::Questions::AnswersComponent.new(question)
+
+ expect(page).to have_button "Yes"
+ expect(page).to have_button "No"
+ end
+
+ it "when user is not signed in, renders answers links pointing to user sign in path" do
+ render_inline Polls::Questions::AnswersComponent.new(question)
+
+ expect(page).to have_link "Yes", href: new_user_session_path
+ expect(page).to have_link "No", href: new_user_session_path
+ end
+
+ it "when user is not verified, renders answers links pointing to user verification in path" do
+ sign_in(create(:user))
+
+ render_inline Polls::Questions::AnswersComponent.new(question)
+
+ expect(page).to have_link "Yes", href: verification_path
+ expect(page).to have_link "No", href: verification_path
+ end
+
+ it "when user already voted in booth it renders disabled answers" do
+ user = create(:user, :level_two)
+ create(:poll_voter, :from_booth, poll: poll, user: user)
+ sign_in(user)
+
+ render_inline Polls::Questions::AnswersComponent.new(question)
+
+ expect(page).to have_selector "span.disabled", text: "Yes"
+ expect(page).to have_selector "span.disabled", text: "No"
+ end
+
+ it "user cannot vote when poll expired it renders disabled answers" do
+ question = create(:poll_question, :yes_no, poll: create(:poll, :expired))
+ sign_in(create(:user, :level_two))
+
+ render_inline Polls::Questions::AnswersComponent.new(question)
+
+ expect(page).to have_selector "span.disabled", text: "Yes"
+ expect(page).to have_selector "span.disabled", text: "No"
+ end
+
+ describe "geozone" do
+ let(:poll) { create(:poll, geozone_restricted: true) }
+ let(:geozone) { create(:geozone) }
+ let(:question) { create(:poll_question, :yes_no, poll: poll) }
+
+ it "when geozone which is not theirs it renders disabled answers" do
+ poll.geozones << geozone
+ sign_in(create(:user, :level_two))
+
+ render_inline Polls::Questions::AnswersComponent.new(question)
+
+ expect(page).to have_selector "span.disabled", text: "Yes"
+ expect(page).to have_selector "span.disabled", text: "No"
+ end
+
+ it "reading a same-geozone poll it renders buttons to vote question answers" do
+ poll.geozones << geozone
+ sign_in(create(:user, :level_two, geozone: geozone))
+
+ render_inline Polls::Questions::AnswersComponent.new(question)
+
+ expect(page).to have_button "Yes"
+ expect(page).to have_button "No"
+ end
+ end
+end
diff --git a/spec/system/polls/polls_spec.rb b/spec/system/polls/polls_spec.rb
index c4ec85e99..220d832da 100644
--- a/spec/system/polls/polls_spec.rb
+++ b/spec/system/polls/polls_spec.rb
@@ -191,18 +191,6 @@ describe "Polls" do
expect("Second question").to appear_before("Third question")
end
- scenario "Question answers appear in the given order" do
- question = create(:poll_question, poll: poll)
- answer1 = create(:poll_question_answer, title: "First", question: question, given_order: 2)
- answer2 = create(:poll_question_answer, title: "Second", question: question, given_order: 1)
-
- visit poll_path(poll)
-
- within("div#poll_question_#{question.id}") do
- expect(answer2.title).to appear_before(answer1.title)
- end
- end
-
scenario "More info answers appear in the given order" do
question = create(:poll_question, poll: poll)
answer1 = create(:poll_question_answer, title: "First", question: question, given_order: 2)
@@ -248,8 +236,6 @@ describe "Polls" do
visit poll_path(poll)
expect(page).to have_content("You must sign in or sign up to participate")
- expect(page).to have_link("Yes", href: new_user_session_path)
- expect(page).to have_link("No", href: new_user_session_path)
end
scenario "Level 1 users" do
@@ -265,89 +251,19 @@ describe "Polls" do
visit poll_path(poll)
expect(page).to have_content("You must verify your account in order to answer")
-
- expect(page).to have_link("Yes", href: verification_path)
- expect(page).to have_link("No", href: verification_path)
end
scenario "Level 2 users in an expired poll" do
- expired_poll = create(:poll, :expired, geozone_restricted: true)
- expired_poll.geozones << geozone
-
- question = create(:poll_question, :yes_no, poll: expired_poll)
+ expired_poll = create(:poll, :expired)
+ create(:poll_question, :yes_no, poll: expired_poll)
login_as(create(:user, :level_two, geozone: geozone))
visit poll_path(expired_poll)
- within("#poll_question_#{question.id}_answers") do
- expect(page).to have_content("Yes")
- expect(page).to have_content("No")
- expect(page).not_to have_button "Yes"
- expect(page).not_to have_button "No"
- end
expect(page).to have_content("This poll has finished")
end
- scenario "Level 2 users in a poll with questions for a geozone which is not theirs" do
- poll.update!(geozone_restricted: true)
- poll.geozones << create(:geozone)
-
- question = create(:poll_question, :yes_no, poll: poll)
-
- login_as(create(:user, :level_two))
-
- visit poll_path(poll)
-
- within("#poll_question_#{question.id}_answers") do
- expect(page).to have_content("Yes")
- expect(page).to have_content("No")
- expect(page).not_to have_button "Yes"
- expect(page).not_to have_button "No"
- end
- end
-
- scenario "Level 2 users reading a same-geozone poll" do
- poll.update!(geozone_restricted: true)
- poll.geozones << geozone
-
- question = create(:poll_question, :yes_no, poll: poll)
-
- login_as(create(:user, :level_two, geozone: geozone))
- visit poll_path(poll)
-
- within("#poll_question_#{question.id}_answers") do
- expect(page).to have_button "Yes"
- expect(page).to have_button "No"
- end
- end
-
- scenario "Level 2 users reading a all-geozones poll" do
- question = create(:poll_question, :yes_no, poll: poll)
-
- login_as(create(:user, :level_two))
- visit poll_path(poll)
-
- within("#poll_question_#{question.id}_answers") do
- expect(page).to have_button "Yes"
- expect(page).to have_button "No"
- end
- end
-
- scenario "Level 2 users who have already answered" do
- question = create(:poll_question, :yes_no, poll: poll)
- user = create(:user, :level_two)
- create(:poll_answer, question: question, author: user, answer: "No")
-
- login_as user
- visit poll_path(poll)
-
- within("#poll_question_#{question.id}_answers") do
- expect(page).to have_button "Yes"
- expect(page).to have_button "No"
- end
- end
-
scenario "Level 2 users answering" do
poll.update!(geozone_restricted: true)
poll.geozones << geozone
From 0ec4d52ed146f72fece701b3e6feae7123742299 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?=
<15726+Senen@users.noreply.github.com>
Date: Thu, 1 Sep 2022 09:48:48 +0200
Subject: [PATCH 4/8] Simplify `Polls::Questions::AnswersComponent` view
---
.../questions/answers_component.html.erb | 28 +++++++++----------
.../polls/questions/answers_component.rb | 21 ++++++--------
2 files changed, 22 insertions(+), 27 deletions(-)
diff --git a/app/components/polls/questions/answers_component.html.erb b/app/components/polls/questions/answers_component.html.erb
index 4e61ee767..4c746951c 100644
--- a/app/components/polls/questions/answers_component.html.erb
+++ b/app/components/polls/questions/answers_component.html.erb
@@ -1,33 +1,31 @@
<% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %>
- <% question.question_answers.each do |answer| %>
- <% if answers_by_question_id[question.id] == answer.title &&
- (!voted_before_sign_in? ||
- question.poll.voted_in_booth?(current_user)) %>
+ <% question_answers.each do |question_answer| %>
+ <% if already_answered?(question_answer) && !voted_before_sign_in? %>
">
- <%= answer.title %>
+ title="<%= t("poll_questions.show.voted", answer: question_answer.title) %>">
+ <%= question_answer.title %>
<% else %>
- <%= button_to answer_question_path(question, answer: answer.title),
+ <%= button_to answer_question_path(question, answer: question_answer.title),
remote: true,
- title: t("poll_questions.show.vote_answer", answer: answer.title),
+ title: t("poll_questions.show.vote_answer", answer: question_answer.title),
class: "button secondary hollow" do %>
- <%= answer.title %>
+ <%= question_answer.title %>
<% end %>
<% end %>
<% end %>
<% elsif !user_signed_in? %>
- <% question.question_answers.order(id: :desc).each do |answer| %>
- <%= link_to answer.title, new_user_session_path, class: "button secondary hollow" %>
+ <% question_answers.order(id: :desc).each do |question_answer| %>
+ <%= link_to question_answer.title, new_user_session_path, class: "button secondary hollow" %>
<% end %>
<% elsif !current_user.level_two_or_three_verified? %>
- <% question.question_answers.order(id: :desc).each do |answer| %>
- <%= link_to answer.title, verification_path, class: "button secondary hollow" %>
+ <% question_answers.order(id: :desc).each do |question_answer| %>
+ <%= link_to question_answer.title, verification_path, class: "button secondary hollow" %>
<% end %>
<% else %>
- <% question.question_answers.order(id: :desc).each do |answer| %>
- <%= answer.title %>
+ <% question_answers.order(id: :desc).each do |question_answer| %>
+ <%= question_answer.title %>
<% end %>
<% end %>
diff --git a/app/components/polls/questions/answers_component.rb b/app/components/polls/questions/answers_component.rb
index 1d64198a4..f51ad4e7f 100644
--- a/app/components/polls/questions/answers_component.rb
+++ b/app/components/polls/questions/answers_component.rb
@@ -6,26 +6,23 @@ class Polls::Questions::AnswersComponent < ApplicationComponent
@question = question
end
- def answers_by_question_id
- if params[:answer]
- { question.id => params[:answer] }
- else
- stored_answers_by_question_id
- end
+ def already_answered?(question_answer)
+ user_answers.find_by(answer: question_answer.title).present?
end
def voted_before_sign_in?
- question.answers.where(author: current_user).any? do |vote|
+ user_answers.any? do |vote|
vote.updated_at < current_user.current_sign_in_at
end
end
+ def question_answers
+ question.question_answers
+ end
+
private
- def stored_answers_by_question_id
- poll_answers = ::Poll::Answer.by_question(question.poll.question_ids).by_author(current_user&.id)
- poll_answers.each_with_object({}) do |answer, answers_by_question_id|
- answers_by_question_id[answer.question_id] = answer.answer
- end
+ def user_answers
+ @user_answers ||= question.answers.by_author(current_user)
end
end
From df65ba57cc157f31130af6e5c9cabc0204a55c4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?=
<15726+Senen@users.noreply.github.com>
Date: Thu, 22 Sep 2022 18:24:47 +0200
Subject: [PATCH 5/8] Use the same order criteria always
The relation of question with its questions answers is ordered by default by
`given_order`.
---
app/components/polls/questions/answers_component.html.erb | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/components/polls/questions/answers_component.html.erb b/app/components/polls/questions/answers_component.html.erb
index 4c746951c..91be9ab15 100644
--- a/app/components/polls/questions/answers_component.html.erb
+++ b/app/components/polls/questions/answers_component.html.erb
@@ -16,15 +16,15 @@
<% end %>
<% end %>
<% elsif !user_signed_in? %>
- <% question_answers.order(id: :desc).each do |question_answer| %>
+ <% question_answers.each do |question_answer| %>
<%= link_to question_answer.title, new_user_session_path, class: "button secondary hollow" %>
<% end %>
<% elsif !current_user.level_two_or_three_verified? %>
- <% question_answers.order(id: :desc).each do |question_answer| %>
+ <% question_answers.each do |question_answer| %>
<%= link_to question_answer.title, verification_path, class: "button secondary hollow" %>
<% end %>
<% else %>
- <% question_answers.order(id: :desc).each do |question_answer| %>
+ <% question_answers.each do |question_answer| %>
<%= question_answer.title %>
<% end %>
<% end %>
From 7efd7c89ef68e984cf890dfd23552d85877af66e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?=
<15726+Senen@users.noreply.github.com>
Date: Wed, 31 Aug 2022 17:28:33 +0200
Subject: [PATCH 6/8] Extract `Polls::QuestionComponent`
---
.../polls/questions/question_component.html.erb} | 0
app/components/polls/questions/question_component.rb | 7 +++++++
app/views/polls/show.html.erb | 4 +---
3 files changed, 8 insertions(+), 3 deletions(-)
rename app/{views/polls/questions/_question.html.erb => components/polls/questions/question_component.html.erb} (100%)
create mode 100644 app/components/polls/questions/question_component.rb
diff --git a/app/views/polls/questions/_question.html.erb b/app/components/polls/questions/question_component.html.erb
similarity index 100%
rename from app/views/polls/questions/_question.html.erb
rename to app/components/polls/questions/question_component.html.erb
diff --git a/app/components/polls/questions/question_component.rb b/app/components/polls/questions/question_component.rb
new file mode 100644
index 000000000..d1a4edf27
--- /dev/null
+++ b/app/components/polls/questions/question_component.rb
@@ -0,0 +1,7 @@
+class Polls::Questions::QuestionComponent < ApplicationComponent
+ attr_reader :question
+
+ def initialize(question:)
+ @question = question
+ end
+end
diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb
index ee4449124..29904041c 100644
--- a/app/views/polls/show.html.erb
+++ b/app/views/polls/show.html.erb
@@ -31,9 +31,7 @@
<% end %>
<% end %>
- <% @questions.each do |question| %>
- <%= render "polls/questions/question", question: question %>
- <% end %>
+ <%= render Polls::Questions::QuestionComponent.with_collection(@questions) %>
From ed7968349ddc825c9dfd5bee5213890b0e77396c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?=
<15726+Senen@users.noreply.github.com>
Date: Wed, 31 Aug 2022 13:59:23 +0200
Subject: [PATCH 7/8] Extract `Poll::Results::Question` component to render
question results
---
.../polls/results/question_component.html.erb | 25 ++++++++++++++++
.../polls/results/question_component.rb | 15 ++++++++++
app/views/polls/results.html.erb | 29 +------------------
3 files changed, 41 insertions(+), 28 deletions(-)
create mode 100644 app/components/polls/results/question_component.html.erb
create mode 100644 app/components/polls/results/question_component.rb
diff --git a/app/components/polls/results/question_component.html.erb b/app/components/polls/results/question_component.html.erb
new file mode 100644
index 000000000..f11a56898
--- /dev/null
+++ b/app/components/polls/results/question_component.html.erb
@@ -0,0 +1,25 @@
+<%= question.title %>
+
+
+
+ <%- question.question_answers.each do |answer| %>
+ |
+ <% if most_voted_answer?(answer) %>
+ <%= t("polls.show.results.most_voted_answer") %>
+ <% end %>
+ <%= answer.title %>
+ |
+ <% end %>
+
+
+
+
+ <%- question.question_answers.each do |answer| %>
+ |
+ <%= answer.total_votes %>
+ (<%= answer.total_votes_percentage.round(2) %>%)
+ |
+ <% end %>
+
+
+
diff --git a/app/components/polls/results/question_component.rb b/app/components/polls/results/question_component.rb
new file mode 100644
index 000000000..f62a6b69d
--- /dev/null
+++ b/app/components/polls/results/question_component.rb
@@ -0,0 +1,15 @@
+class Polls::Results::QuestionComponent < ApplicationComponent
+ attr_reader :question
+
+ def initialize(question:)
+ @question = question
+ end
+
+ def answer_styles(answer)
+ "win" if most_voted_answer?(answer)
+ end
+
+ def most_voted_answer?(answer)
+ answer.id == question.most_voted_answer_id
+ end
+end
diff --git a/app/views/polls/results.html.erb b/app/views/polls/results.html.erb
index 745b31914..eaaaaae5b 100644
--- a/app/views/polls/results.html.erb
+++ b/app/views/polls/results.html.erb
@@ -16,34 +16,7 @@
- <%- @poll.questions.each do |question| %>
- <% most_voted_answer_id = question.most_voted_answer_id %>
-
<%= question.title %>
-
-
-
- <%- question.question_answers.each do |answer| %>
- | >
- <% if answer.id == most_voted_answer_id %>
- <%= t("polls.show.results.most_voted_answer") %>
- <% end %>
- <%= answer.title %>
- |
- <% end %>
-
-
-
-
- <%- question.question_answers.each do |answer| %>
- | >
- <%= answer.total_votes %>
- (<%= answer.total_votes_percentage.round(2) %>%)
- |
- <% end %>
-
-
-
- <% end %>
+ <%= render Polls::Results::QuestionComponent.with_collection(@poll.questions) %>
From 8311e7e6b843cfadaa64d0e632eb0e98cfa0dd0b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?=
<15726+Senen@users.noreply.github.com>
Date: Wed, 31 Aug 2022 16:32:18 +0200
Subject: [PATCH 8/8] Extract component to render answers additional
information
---
.../read_more_answer_component.html.erb | 60 ++++++++++++++++++
.../questions/read_more_answer_component.rb | 9 +++
app/views/polls/show.html.erb | 63 +------------------
.../read_more_answer_component_spec.rb | 32 ++++++++++
spec/system/polls/polls_spec.rb | 17 -----
5 files changed, 102 insertions(+), 79 deletions(-)
create mode 100644 app/components/polls/questions/read_more_answer_component.html.erb
create mode 100644 app/components/polls/questions/read_more_answer_component.rb
create mode 100644 spec/components/polls/questions/read_more_answer_component_spec.rb
diff --git a/app/components/polls/questions/read_more_answer_component.html.erb b/app/components/polls/questions/read_more_answer_component.html.erb
new file mode 100644
index 000000000..becece5a7
--- /dev/null
+++ b/app/components/polls/questions/read_more_answer_component.html.erb
@@ -0,0 +1,60 @@
+" id="answer_<%= answer.id %>">
+
<%= answer.title %>
+
+ <% if answer.images.any? %>
+ <%= render "polls/gallery", answer: answer %>
+ <% end %>
+
+ <% if answer.description.present? %>
+
+
+ <%= wysiwyg(answer.description) %>
+
+
+
+
+
+
+ <% end %>
+
+ <% if answer.documents.present? %>
+
+
+
+ <%= t("polls.show.documents") %>
+
+
+ <% answer.documents.each do |document| %>
+ <%= link_to document.title,
+ document.attachment,
+ target: "_blank",
+ rel: "nofollow" %>
+ <% end %>
+
+ <% end %>
+
+ <% if answer.videos.present? %>
+
+
+
+ <%= t("polls.show.videos") %>
+
+
+ <% answer.videos.each do |video| %>
+ <%= link_to video.title,
+ video.url,
+ target: "_blank",
+ rel: "nofollow" %>
+ <% end %>
+
+ <% end %>
+
diff --git a/app/components/polls/questions/read_more_answer_component.rb b/app/components/polls/questions/read_more_answer_component.rb
new file mode 100644
index 000000000..edb34180c
--- /dev/null
+++ b/app/components/polls/questions/read_more_answer_component.rb
@@ -0,0 +1,9 @@
+class Polls::Questions::ReadMoreAnswerComponent < ApplicationComponent
+ with_collection_parameter :answer
+ attr_reader :answer
+ delegate :wysiwyg, to: :helpers
+
+ def initialize(answer:)
+ @answer = answer
+ end
+end
diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb
index 29904041c..906595616 100644
--- a/app/views/polls/show.html.erb
+++ b/app/views/polls/show.html.erb
@@ -46,68 +46,7 @@
- <% @poll_questions_answers.each do |answer| %>
-
" id="answer_<%= answer.id %>">
-
<%= answer.title %>
-
- <% if answer.images.any? %>
- <%= render "gallery", answer: answer %>
- <% end %>
-
- <% if answer.description.present? %>
-
-
- <%= wysiwyg(answer.description) %>
-
-
-
-
-
-
- <% end %>
-
- <% if answer.documents.present? %>
-
-
-
- <%= t("polls.show.documents") %>
-
-
- <% answer.documents.each do |document| %>
- <%= link_to document.title,
- document.attachment,
- target: "_blank",
- rel: "nofollow" %>
- <% end %>
-
- <% end %>
-
- <% if answer.videos.present? %>
-
-
-
- <%= t("polls.show.videos") %>
-
-
- <% answer.videos.each do |video| %>
- <%= link_to video.title,
- video.url,
- target: "_blank",
- rel: "nofollow" %>
- <% end %>
-
- <% end %>
-
- <% end %>
+ <%= render Polls::Questions::ReadMoreAnswerComponent.with_collection(@poll_questions_answers) %>
diff --git a/spec/components/polls/questions/read_more_answer_component_spec.rb b/spec/components/polls/questions/read_more_answer_component_spec.rb
new file mode 100644
index 000000000..4e4902a81
--- /dev/null
+++ b/spec/components/polls/questions/read_more_answer_component_spec.rb
@@ -0,0 +1,32 @@
+require "rails_helper"
+
+describe Polls::Questions::ReadMoreAnswerComponent do
+ include Rails.application.routes.url_helpers
+ let(:poll) { create(:poll) }
+ let(:question) { create(:poll_question, poll: poll) }
+ let(:answer) { create(:poll_question_answer, question: question) }
+
+ it "renders answers with videos" do
+ create(:poll_answer_video, answer: answer, title: "Awesome video", url: "youtube.com/watch?v=123")
+
+ render_inline Polls::Questions::ReadMoreAnswerComponent.new(answer: answer)
+
+ expect(page).to have_link("Awesome video", href: "youtube.com/watch?v=123")
+ end
+
+ it "renders answers with images" do
+ create(:image, imageable: answer, title: "The yes movement")
+
+ render_inline Polls::Questions::ReadMoreAnswerComponent.new(answer: answer)
+
+ expect(page).to have_css "img[alt='The yes movement']"
+ end
+
+ it "renders answers with documents" do
+ create(:document, documentable: answer, title: "The yes movement")
+
+ render_inline Polls::Questions::ReadMoreAnswerComponent.new(answer: answer)
+
+ expect(page).to have_link("The yes movement")
+ end
+end
diff --git a/spec/system/polls/polls_spec.rb b/spec/system/polls/polls_spec.rb
index 220d832da..78cfae471 100644
--- a/spec/system/polls/polls_spec.rb
+++ b/spec/system/polls/polls_spec.rb
@@ -152,14 +152,6 @@ describe "Polls" do
expect(page).to have_current_path(poll_path(poll.slug))
end
- scenario "Show answers with videos" do
- create(:poll_answer_video, poll: poll, title: "Awesome video", url: "youtube.com/watch?v=123")
-
- visit poll_path(poll)
-
- expect(page).to have_link("Awesome video", href: "youtube.com/watch?v=123")
- end
-
scenario "Lists questions from proposals as well as regular ones" do
normal_question = create(:poll_question, poll: poll)
proposal_question = create(:poll_question, poll: poll, proposal: create(:proposal))
@@ -203,15 +195,6 @@ describe "Polls" do
end
end
- scenario "Answer images are shown" do
- question = create(:poll_question, :yes_no, poll: poll)
- create(:image, imageable: question.question_answers.first, title: "The yes movement")
-
- visit poll_path(poll)
-
- expect(page).to have_css "img[alt='The yes movement']"
- end
-
scenario "Buttons to slide through images work back and forth" do
question = create(:poll_question, :yes_no, poll: poll)
create(:image, imageable: question.question_answers.last, title: "The no movement")