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/assets/stylesheets/participation.scss b/app/assets/stylesheets/participation.scss index 74ab2e1e9..2b8ceffac 100644 --- a/app/assets/stylesheets/participation.scss +++ b/app/assets/stylesheets/participation.scss @@ -1633,9 +1633,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/components/polls/questions/answers_component.html.erb b/app/components/polls/questions/answers_component.html.erb new file mode 100644 index 000000000..91be9ab15 --- /dev/null +++ b/app/components/polls/questions/answers_component.html.erb @@ -0,0 +1,31 @@ +
+ <% if can?(:answer, question) && !question.poll.voted_in_booth?(current_user) %> + <% question_answers.each do |question_answer| %> + <% if already_answered?(question_answer) && !voted_before_sign_in? %> + "> + <%= question_answer.title %> + + <% else %> + <%= button_to answer_question_path(question, answer: question_answer.title), + remote: true, + title: t("poll_questions.show.vote_answer", answer: question_answer.title), + class: "button secondary hollow" do %> + <%= question_answer.title %> + <% end %> + <% end %> + <% end %> + <% elsif !user_signed_in? %> + <% 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.each do |question_answer| %> + <%= link_to question_answer.title, verification_path, class: "button secondary hollow" %> + <% end %> + <% else %> + <% question_answers.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 new file mode 100644 index 000000000..f51ad4e7f --- /dev/null +++ b/app/components/polls/questions/answers_component.rb @@ -0,0 +1,28 @@ +class Polls::Questions::AnswersComponent < ApplicationComponent + attr_reader :question + delegate :can?, :current_user, :user_signed_in?, to: :helpers + + def initialize(question) + @question = question + end + + def already_answered?(question_answer) + user_answers.find_by(answer: question_answer.title).present? + end + + def voted_before_sign_in? + 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 user_answers + @user_answers ||= question.answers.by_author(current_user) + end +end diff --git a/app/views/polls/questions/_question.html.erb b/app/components/polls/questions/question_component.html.erb similarity index 69% rename from app/views/polls/questions/_question.html.erb rename to app/components/polls/questions/question_component.html.erb index 016c0fa95..5fd7eeb8b 100644 --- a/app/views/polls/questions/_question.html.erb +++ b/app/components/polls/questions/question_component.html.erb @@ -4,6 +4,6 @@
- <%= render "polls/questions/answers", question: question, token: token %> + <%= render Polls::Questions::AnswersComponent.new(question) %>
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/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? %> + + <% end %> + + <% if answer.videos.present? %> + + <% 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/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| %> + + <% end %> + + + + + <%- question.question_answers.each do |answer| %> + + <% end %> + + +
+ <% if most_voted_answer?(answer) %> + <%= t("polls.show.results.most_voted_answer") %> + <% end %> + <%= answer.title %> +
+ <%= answer.total_votes %> + (<%= answer.total_votes_percentage.round(2) %>%) +
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/controllers/polls/questions_controller.rb b/app/controllers/polls/questions_controller.rb index 3f2809b75..3731aa2f9 100644 --- a/app/controllers/polls/questions_controller.rb +++ b/app/controllers/polls/questions_controller.rb @@ -6,11 +6,17 @@ 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] } + 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/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index 154961a6b..af2dc563a 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,16 +19,8 @@ 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) - - @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 08a2d3ab2..5a27d25db 100644 --- a/app/helpers/polls_helper.rb +++ b/app/helpers/polls_helper.rb @@ -12,14 +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 - 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/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 deleted file mode 100644 index 02088ab7a..000000000 --- a/app/views/polls/questions/_answers.html.erb +++ /dev/null @@ -1,33 +0,0 @@ -
- <% 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) || - question.poll.voted_in_booth?(current_user)) %> - "> - <%= answer.title %> - - <% else %> - <%= link_to answer.title, - answer_question_path(question, answer: answer.title, token: token), - method: :post, - remote: true, - title: t("poll_questions.show.vote_answer", answer: answer.title), - class: "button secondary hollow js-question-answer" %> - <% 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" %> - <% 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" %> - <% end %> - <% else %> - <% question.question_answers.order(id: :desc).each do |answer| %> - <%= answer.title %> - <% end %> - <% end %> -
diff --git a/app/views/polls/questions/answer.js.erb b/app/views/polls/questions/answer.js.erb index 79978e2c1..2c4380238 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::AnswersComponent.new(@question) %>"); 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| %> - - <% end %> - - - - - <%- question.question_answers.each do |answer| %> - - <% end %> - - -
> - <% if answer.id == most_voted_answer_id %> - <%= t("polls.show.results.most_voted_answer") %> - <% end %> - <%= answer.title %> -
> - <%= answer.total_votes %> - (<%= answer.total_votes_percentage.round(2) %>%) -
- <% end %> + <%= render Polls::Results::QuestionComponent.with_collection(@poll.questions) %>
diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb index 1aa0e89ec..906595616 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, token: @token %> - <% end %> + <%= render Polls::Questions::QuestionComponent.with_collection(@questions) %> @@ -48,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? %> - - <% end %> - - <% if answer.videos.present? %> - - <% end %> -
- <% end %> + <%= render Polls::Questions::ReadMoreAnswerComponent.with_collection(@poll_questions_answers) %>
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/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/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/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/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..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)) @@ -191,18 +183,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) @@ -215,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") @@ -248,8 +219,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 +234,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_link("Yes") - expect(page).not_to have_link("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_link("Yes") - expect(page).not_to have_link("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_link("Yes") - expect(page).to have_link("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_link("Yes") - expect(page).to have_link("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_link("Yes") - expect(page).to have_link("No") - end - end - scenario "Level 2 users answering" do poll.update!(geozone_restricted: true) poll.geozones << geozone @@ -359,10 +258,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 +276,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 +299,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 +349,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 +394,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 46305ce4a..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}&token=") - expect(page).not_to have_link(answer_no.title, href: "/questions/#{question.id}/answer?answer=#{answer_no.title}&token=") + 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."