diff --git a/app/assets/stylesheets/in_favor_against.scss b/app/assets/stylesheets/in_favor_against.scss index f3c6988e7..6e8d48481 100644 --- a/app/assets/stylesheets/in_favor_against.scss +++ b/app/assets/stylesheets/in_favor_against.scss @@ -25,10 +25,10 @@ &:not([disabled]) { &:hover, - &:active { + &:active, + &[aria-pressed=true] { color: #fff; cursor: pointer; - opacity: 1 !important; } } } @@ -38,7 +38,8 @@ &:not([disabled]) { &:hover, - &:active { + &:active, + &[aria-pressed=true] { background: $like; border: 2px solid $like; } @@ -50,19 +51,14 @@ &:not([disabled]) { &:hover, - &:active { + &:active, + &[aria-pressed=true] { background: $unlike; border: 2px solid $unlike; } } } - .like, - .unlike { - vertical-align: super; - text-decoration: none; - } - .percentage { display: inline-block; font-size: $small-font-size; @@ -76,22 +72,4 @@ padding-right: 0; } } - - .voted { - color: #fff; - } - - .in-favor .voted { - background: $like; - border: 2px solid $like; - } - - .against .voted { - background: $unlike; - border: 2px solid $unlike; - } - - .no-voted { - opacity: 0.3; - } } diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss index a557f582f..fcda6b480 100644 --- a/app/assets/stylesheets/layout.scss +++ b/app/assets/stylesheets/layout.scss @@ -1705,7 +1705,8 @@ table { .in-favor button { @include has-fa-icon(thumbs-up, solid); - &:hover { + &:hover, + &[aria-pressed=true] { color: $like; } } @@ -1713,7 +1714,8 @@ table { .against button { @include has-fa-icon(thumbs-down, solid); - &:hover { + &:hover, + &[aria-pressed=true] { color: $unlike; } } diff --git a/app/components/comments/votes_component.html.erb b/app/components/comments/votes_component.html.erb index 9e3deae86..8ef3a8293 100644 --- a/app/components/comments/votes_component.html.erb +++ b/app/components/comments/votes_component.html.erb @@ -3,22 +3,16 @@  |  - <%= button_to vote_comment_path(comment, value: "yes"), - method: "post", - remote: can?(:vote, comment), - title: t("votes.agree") do %> - <%= t("votes.agree") %> - <% end %> + <%= render Shared::VoteButtonComponent.new(comment, + value: "yes", + title: t("votes.agree")) %> <%= comment.total_likes %> - <%= button_to vote_comment_path(comment, value: "no"), - method: "post", - remote: can?(:vote, comment), - title: t("votes.disagree") do %> - <%= t("votes.disagree") %> - <% end %> + <%= render Shared::VoteButtonComponent.new(comment, + value: "no", + title: t("votes.disagree")) %> <%= comment.total_dislikes %> diff --git a/app/components/comments/votes_component.rb b/app/components/comments/votes_component.rb index d93a24b0f..50cf56a86 100644 --- a/app/components/comments/votes_component.rb +++ b/app/components/comments/votes_component.rb @@ -1,6 +1,5 @@ class Comments::VotesComponent < ApplicationComponent attr_reader :comment - delegate :can?, to: :helpers def initialize(comment) @comment = comment diff --git a/app/components/legislation/proposals/votes_component.rb b/app/components/legislation/proposals/votes_component.rb index 96495800f..10d16e74f 100644 --- a/app/components/legislation/proposals/votes_component.rb +++ b/app/components/legislation/proposals/votes_component.rb @@ -1,6 +1,6 @@ class Legislation::Proposals::VotesComponent < ApplicationComponent attr_reader :proposal - delegate :current_user, :link_to_verify_account, to: :helpers + delegate :current_user, :link_to_verify_account, :can?, to: :helpers def initialize(proposal) @proposal = proposal @@ -9,7 +9,7 @@ class Legislation::Proposals::VotesComponent < ApplicationComponent private def can_vote? - proposal.votable_by?(current_user) + can?(:create, proposal.votes_for.new(voter: current_user)) end def cannot_vote_text diff --git a/app/components/shared/in_favor_against_component.html.erb b/app/components/shared/in_favor_against_component.html.erb index b78e245f2..fbe2fb611 100644 --- a/app/components/shared/in_favor_against_component.html.erb +++ b/app/components/shared/in_favor_against_component.html.erb @@ -1,25 +1,17 @@
- <%= button_to polymorphic_path(votable, action: :vote, value: "yes"), - class: "like #{voted_classes[:in_favor]}", - title: t("votes.agree"), - "aria-label": agree_aria_label, - method: "post", - remote: true do %> - <%= t("votes.agree") %> - <% end %> + <%= render Shared::VoteButtonComponent.new(votable, + value: "yes", + "aria-label": agree_aria_label, + title: t("votes.agree")) %> <%= votes_percentage("likes", votable) %>
- <%= button_to polymorphic_path(votable, action: :vote, value: "no"), - class: "unlike #{voted_classes[:against]}", - title: t("votes.disagree"), - "aria-label": disagree_aria_label, - method: "post", - remote: true do %> - <%= t("votes.disagree") %> - <% end %> + <%= render Shared::VoteButtonComponent.new(votable, + value: "no", + "aria-label": disagree_aria_label, + title: t("votes.disagree")) %> <%= votes_percentage("dislikes", votable) %>
diff --git a/app/components/shared/in_favor_against_component.rb b/app/components/shared/in_favor_against_component.rb index 8806057c6..ee490ecd6 100644 --- a/app/components/shared/in_favor_against_component.rb +++ b/app/components/shared/in_favor_against_component.rb @@ -1,6 +1,6 @@ class Shared::InFavorAgainstComponent < ApplicationComponent attr_reader :votable - delegate :current_user, :votes_percentage, to: :helpers + delegate :votes_percentage, to: :helpers def initialize(votable) @votable = votable @@ -8,21 +8,6 @@ class Shared::InFavorAgainstComponent < ApplicationComponent private - def voted_classes - @voted_classes ||= css_classes_for_vote - end - - def css_classes_for_vote - case current_user&.voted_as_when_voted_for(votable) - when true - { in_favor: "voted", against: "no-voted" } - when false - { in_favor: "no-voted", against: "voted" } - else - { in_favor: "", against: "" } - end - end - def agree_aria_label t("votes.agree_label", title: votable.title) end diff --git a/app/components/shared/vote_button_component.html.erb b/app/components/shared/vote_button_component.html.erb new file mode 100644 index 000000000..19b35fc06 --- /dev/null +++ b/app/components/shared/vote_button_component.html.erb @@ -0,0 +1,3 @@ +<%= button_to path, default_options.merge(options) do %> + <%= options[:title] %> +<% end %> diff --git a/app/components/shared/vote_button_component.rb b/app/components/shared/vote_button_component.rb new file mode 100644 index 000000000..f71e3e93c --- /dev/null +++ b/app/components/shared/vote_button_component.rb @@ -0,0 +1,48 @@ +class Shared::VoteButtonComponent < ApplicationComponent + attr_reader :votable, :value, :options + delegate :current_user, :can?, to: :helpers + + def initialize(votable, value:, **options) + @votable = votable + @value = value + @options = options + end + + private + + def path + if already_voted? + polymorphic_path(vote) + else + polymorphic_path(vote, value: value) + end + end + + def default_options + if already_voted? + { + "aria-pressed": true, + method: :delete, + remote: can?(:destroy, vote) + } + else + { + "aria-pressed": false, + method: :post, + remote: can?(:create, vote) + } + end + end + + def vote + @vote ||= Vote.find_or_initialize_by(votable: votable, voter: current_user, vote_flag: parsed_value) + end + + def already_voted? + vote.persisted? + end + + def parsed_value + value == "yes" + end +end diff --git a/app/controllers/comments/votes_controller.rb b/app/controllers/comments/votes_controller.rb new file mode 100644 index 000000000..d8289f9cf --- /dev/null +++ b/app/controllers/comments/votes_controller.rb @@ -0,0 +1,35 @@ +module Comments + class VotesController < ApplicationController + before_action :authenticate_user! + load_and_authorize_resource :comment + load_and_authorize_resource through: :comment, through_association: :votes_for, only: :destroy + before_action :verify_comments_open! + + def create + authorize! :create, Vote.new(voter: current_user, votable: @comment) + @comment.vote_by(voter: current_user, vote: params[:value]) + + respond_to do |format| + format.js { render :show } + end + end + + def destroy + @comment.unvote_by(current_user) + + respond_to do |format| + format.js { render :show } + end + end + + private + + def verify_comments_open! + return if current_user.administrator? || current_user.moderator? + + if @comment.commentable.respond_to?(:comments_closed?) && @comment.commentable.comments_closed? + redirect_to polymorphic_path(@comment.commentable), alert: t("comments.comments_closed") + end + end + end +end diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 8f54125ae..cc60c3fc2 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -1,8 +1,8 @@ class CommentsController < ApplicationController - before_action :authenticate_user!, only: [:create, :hide, :vote] + before_action :authenticate_user!, only: [:create, :hide] before_action :load_commentable, only: :create before_action :verify_resident_for_commentable!, only: :create - before_action :verify_comments_open!, only: [:create, :vote] + before_action :verify_comments_open!, only: [:create] before_action :build_comment, only: :create load_and_authorize_resource @@ -27,11 +27,6 @@ class CommentsController < ApplicationController end end - def vote - @comment.vote_by(voter: current_user, vote: params[:value]) - respond_with @comment - end - def flag Flag.flag(current_user, @comment) set_comment_flags(@comment) diff --git a/app/controllers/debates/votes_controller.rb b/app/controllers/debates/votes_controller.rb new file mode 100644 index 000000000..ae0cf33d5 --- /dev/null +++ b/app/controllers/debates/votes_controller.rb @@ -0,0 +1,24 @@ +module Debates + class VotesController < ApplicationController + before_action :authenticate_user! + load_and_authorize_resource :debate + load_and_authorize_resource through: :debate, through_association: :votes_for, only: :destroy + + def create + authorize! :create, Vote.new(voter: current_user, votable: @debate) + @debate.register_vote(current_user, params[:value]) + + respond_to do |format| + format.js { render :show } + end + end + + def destroy + @debate.unvote_by(current_user) + + respond_to do |format| + format.js { render :show } + end + end + end +end diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb index c08963a6c..33c7fd899 100644 --- a/app/controllers/debates_controller.rb +++ b/app/controllers/debates_controller.rb @@ -28,10 +28,6 @@ class DebatesController < ApplicationController redirect_to debate_path(@debate), status: :moved_permanently if request.path != debate_path(@debate) end - def vote - @debate.register_vote(current_user, params[:value]) - end - def unmark_featured @debate.update!(featured_at: nil) redirect_to debates_path diff --git a/app/controllers/legislation/proposals/votes_controller.rb b/app/controllers/legislation/proposals/votes_controller.rb new file mode 100644 index 000000000..5f70a5b95 --- /dev/null +++ b/app/controllers/legislation/proposals/votes_controller.rb @@ -0,0 +1,29 @@ +module Legislation + module Proposals + class VotesController < ApplicationController + before_action :authenticate_user! + load_and_authorize_resource :process, class: "Legislation::Process" + load_and_authorize_resource :proposal, class: "Legislation::Proposal", + through: :process, + id_param: "legislation_proposal_id" + load_and_authorize_resource through: :proposal, through_association: :votes_for, only: :destroy + + def create + authorize! :create, Vote.new(voter: current_user, votable: @proposal) + @proposal.vote_by(voter: current_user, vote: params[:value]) + + respond_to do |format| + format.js { render :show } + end + end + + def destroy + @proposal.unvote_by(current_user) + + respond_to do |format| + format.js { render :show } + end + end + end + end +end diff --git a/app/controllers/legislation/proposals_controller.rb b/app/controllers/legislation/proposals_controller.rb index 86b34bce0..d9adb14e3 100644 --- a/app/controllers/legislation/proposals_controller.rb +++ b/app/controllers/legislation/proposals_controller.rb @@ -37,10 +37,6 @@ class Legislation::ProposalsController < Legislation::BaseController end end - def vote - @proposal.register_vote(current_user, params[:value]) - end - private def proposal_params diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb index fe96be60b..e14469539 100644 --- a/app/models/abilities/common.rb +++ b/app/models/abilities/common.rb @@ -81,14 +81,15 @@ module Abilities can [:create, :destroy], DirectUpload unless user.organization? - can :vote, Debate - can :vote, Comment + can [:create, :destroy], ActsAsVotable::Vote, voter_id: user.id, votable_type: "Debate" + can [:create, :destroy], ActsAsVotable::Vote, voter_id: user.id, votable_type: "Comment" end if user.level_two_or_three_verified? can :vote, Proposal, &:published? - can :vote, Legislation::Proposal + can [:create, :destroy], ActsAsVotable::Vote, voter_id: user.id, votable_type: "Legislation::Proposal" + can :create, Legislation::Answer can :create, Budget::Investment, budget: { phase: "accepting" } diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index 086a4265b..1808d8033 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -286,7 +286,7 @@ class Budget def permission_problem(user) return :not_logged_in unless user return :organization if user.organization? - return :not_verified unless user.can?(:create, ActsAsVotable::Vote) + return :not_verified unless user.level_two_or_three_verified? nil end diff --git a/app/models/legislation/proposal.rb b/app/models/legislation/proposal.rb index ec653d4c3..497cea5db 100644 --- a/app/models/legislation/proposal.rb +++ b/app/models/legislation/proposal.rb @@ -108,14 +108,6 @@ class Legislation::Proposal < ApplicationRecord author_id == user.id && editable? end - def votable_by?(user) - user&.level_two_or_three_verified? - end - - def register_vote(user, vote_value) - vote_by(voter: user, vote: vote_value) if votable_by?(user) - end - def code "#{Setting["proposal_code_prefix"]}-#{created_at.strftime("%Y-%m")}-#{id}" end diff --git a/app/views/comments/_comment.html.erb b/app/views/comments/_comment.html.erb index 75d3887ca..549bab2d1 100644 --- a/app/views/comments/_comment.html.erb +++ b/app/views/comments/_comment.html.erb @@ -81,7 +81,7 @@
<% unless valuation %>
- <%= render "comments/votes", comment: comment %> + <%= render Comments::VotesComponent.new(comment) %>
<% end %> diff --git a/app/views/comments/_votes.html.erb b/app/views/comments/_votes.html.erb deleted file mode 100644 index e45be3c2c..000000000 --- a/app/views/comments/_votes.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render Comments::VotesComponent.new(comment) %> diff --git a/app/views/comments/vote.js.erb b/app/views/comments/vote.js.erb deleted file mode 100644 index 2fe859cbd..000000000 --- a/app/views/comments/vote.js.erb +++ /dev/null @@ -1 +0,0 @@ -$("#<%= dom_id(@comment) %>_votes").html("<%= j render("comments/votes", comment: @comment) %>"); diff --git a/app/views/comments/votes/show.js.erb b/app/views/comments/votes/show.js.erb new file mode 100644 index 000000000..f26291e73 --- /dev/null +++ b/app/views/comments/votes/show.js.erb @@ -0,0 +1 @@ +$("#<%= dom_id(@comment) %>_votes").html("<%= j render Comments::VotesComponent.new(@comment) %>"); diff --git a/app/views/debates/_debate.html.erb b/app/views/debates/_debate.html.erb index 905c3ec79..68de5a60d 100644 --- a/app/views/debates/_debate.html.erb +++ b/app/views/debates/_debate.html.erb @@ -49,7 +49,7 @@
- <%= render "debates/votes", debate: debate %> + <%= render Debates::VotesComponent.new(debate) %>
diff --git a/app/views/debates/_votes.html.erb b/app/views/debates/_votes.html.erb deleted file mode 100644 index 01a1f2b3f..000000000 --- a/app/views/debates/_votes.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render Debates::VotesComponent.new(debate) %> diff --git a/app/views/debates/show.html.erb b/app/views/debates/show.html.erb index 52146ee68..38fc11825 100644 --- a/app/views/debates/show.html.erb +++ b/app/views/debates/show.html.erb @@ -57,7 +57,7 @@

<%= t("votes.supports") %>

- <%= render "debates/votes", debate: @debate %> + <%= render Debates::VotesComponent.new(@debate) %>
<%= render "shared/social_share", share_title: t("debates.show.share"), diff --git a/app/views/debates/vote.js.erb b/app/views/debates/vote.js.erb deleted file mode 100644 index aae060dbd..000000000 --- a/app/views/debates/vote.js.erb +++ /dev/null @@ -1 +0,0 @@ -$("#<%= dom_id(@debate) %>_votes").html("<%= j render("debates/votes", debate: @debate) %>"); diff --git a/app/views/debates/votes/show.js.erb b/app/views/debates/votes/show.js.erb new file mode 100644 index 000000000..bee28fcc7 --- /dev/null +++ b/app/views/debates/votes/show.js.erb @@ -0,0 +1 @@ +$("#<%= dom_id(@debate) %>_votes").html("<%= j render Debates::VotesComponent.new(@debate) %>"); diff --git a/app/views/legislation/annotations/_comments.html.erb b/app/views/legislation/annotations/_comments.html.erb index aad5a4248..c8c1bd29d 100644 --- a/app/views/legislation/annotations/_comments.html.erb +++ b/app/views/legislation/annotations/_comments.html.erb @@ -24,7 +24,7 @@
- <%= render "comments/votes", comment: comment %> + <%= render Comments::VotesComponent.new(comment) %>
diff --git a/app/views/legislation/proposals/vote.js.erb b/app/views/legislation/proposals/votes/show.js.erb similarity index 100% rename from app/views/legislation/proposals/vote.js.erb rename to app/views/legislation/proposals/votes/show.js.erb diff --git a/config/routes/comment.rb b/config/routes/comment.rb index c973446e2..d461be5fb 100644 --- a/config/routes/comment.rb +++ b/config/routes/comment.rb @@ -1,8 +1,9 @@ -resources :comments, only: [:create, :show], shallow: true do +resources :comments, only: [:create, :show] do member do - post :vote put :flag put :unflag put :hide end + + resources :votes, controller: "comments/votes", only: [:create, :destroy] end diff --git a/config/routes/debate.rb b/config/routes/debate.rb index 58f1f9215..03735cc15 100644 --- a/config/routes/debate.rb +++ b/config/routes/debate.rb @@ -1,6 +1,5 @@ resources :debates do member do - post :vote put :flag put :unflag put :mark_featured @@ -11,4 +10,6 @@ resources :debates do get :suggest put "recommendations/disable", only: :index, controller: "debates", action: :disable_recommendations end + + resources :votes, controller: "debates/votes", only: [:create, :destroy] end diff --git a/config/routes/legislation.rb b/config/routes/legislation.rb index 4a18ef1cd..ae37f818b 100644 --- a/config/routes/legislation.rb +++ b/config/routes/legislation.rb @@ -16,7 +16,6 @@ namespace :legislation do resources :proposals, except: [:index] do member do - post :vote put :flag put :unflag end @@ -25,6 +24,10 @@ namespace :legislation do end end + resources :legislation_proposals, path: "proposals", only: [] do + resources :votes, controller: "proposals/votes", only: [:create, :destroy] + end + resources :draft_versions, only: [:show] do get :go_to_version, on: :collection get :changes @@ -41,6 +44,10 @@ resolve "Legislation::Proposal" do |proposal, options| [proposal.process, :proposal, options.merge(id: proposal)] end +resolve "Vote" do |vote, options| + [*resource_hierarchy_for(vote.votable), vote, options] +end + resolve "Legislation::Question" do |question, options| [question.process, :question, options.merge(id: question)] end diff --git a/spec/components/comments/votes_component_spec.rb b/spec/components/comments/votes_component_spec.rb new file mode 100644 index 000000000..59708d71a --- /dev/null +++ b/spec/components/comments/votes_component_spec.rb @@ -0,0 +1,65 @@ +require "rails_helper" + +describe Comments::VotesComponent do + let(:user) { create(:user) } + let(:comment) { create(:comment, user: user) } + let(:component) { Comments::VotesComponent.new(comment) } + + describe "aria-pressed and method attributes" do + it "have expected values when the in-favor button is pressed" do + comment.vote_by(voter: user, vote: "yes") + sign_in(user) + + render_inline component + + page.find(".in-favor") do |in_favor_block| + expect(in_favor_block).to have_css "button[aria-pressed='true']" + expect(in_favor_block).to have_css "form[action*='votes'][method='post']" + expect(in_favor_block).to have_css "input[name='_method'][value='delete']", visible: :hidden + end + + page.find(".against") do |against_block| + expect(against_block).to have_css "button[aria-pressed='false']" + expect(against_block).to have_css "form[action*='votes'][method='post']" + expect(against_block).not_to have_css "input[name='_method']", visible: :all + end + end + + it "have expected values when the against button is pressed" do + comment.vote_by(voter: user, vote: "no") + sign_in(user) + + render_inline component + + page.find(".in-favor") do |in_favor_block| + expect(in_favor_block).to have_css "button[aria-pressed='false']" + expect(in_favor_block).to have_css "form[action*='votes'][method='post']" + expect(in_favor_block).not_to have_css "input[name='_method']", visible: :all + end + + page.find(".against") do |against_block| + expect(against_block).to have_css "button[aria-pressed='true']" + expect(against_block).to have_css "form[action*='votes'][method='post']" + expect(against_block).to have_css "input[name='_method'][value='delete']", visible: :hidden + end + end + + it "have expected values when neither the 'in-favor' button nor the 'against' button are pressed" do + sign_in(user) + + render_inline component + + page.find(".in-favor") do |in_favor_block| + expect(in_favor_block).to have_css "button[aria-pressed='false']" + expect(in_favor_block).to have_css "form[action*='votes'][method='post']" + expect(in_favor_block).not_to have_css "input[name='_method']", visible: :all + end + + page.find(".against") do |against_block| + expect(against_block).to have_css "button[aria-pressed='false']" + expect(against_block).to have_css "form[action*='votes'][method='post']" + expect(against_block).not_to have_css "input[name='_method']", visible: :all + end + end + end +end diff --git a/spec/components/debates/votes_component_spec.rb b/spec/components/debates/votes_component_spec.rb index 6d1c973aa..b859f58ed 100644 --- a/spec/components/debates/votes_component_spec.rb +++ b/spec/components/debates/votes_component_spec.rb @@ -25,19 +25,5 @@ describe Debates::VotesComponent do expect(page).to have_button "I don't agree with What about the 2030 agenda?" expect(page).not_to have_content "You must sign in or sign up to continue." end - - it "does not include result percentages" do - create(:vote, votable: debate) - sign_in(create(:user)) - - render_inline component - - expect(page).to have_button count: 2 - expect(page).to have_button "I agree" - expect(page).to have_button "I disagree" - expect(page).not_to have_button text: "%" - expect(page).not_to have_button text: "100" - expect(page).not_to have_button text: "0" - end end end diff --git a/spec/components/legislation/proposals/votes_component_spec.rb b/spec/components/legislation/proposals/votes_component_spec.rb index 81649bf9f..65418b001 100644 --- a/spec/components/legislation/proposals/votes_component_spec.rb +++ b/spec/components/legislation/proposals/votes_component_spec.rb @@ -38,19 +38,5 @@ describe Legislation::Proposals::VotesComponent do expect(page).to have_button "I don't agree with Require wearing masks at home" expect(page).not_to have_content "You must sign in or sign up to continue." end - - it "does not include result percentages" do - create(:vote, votable: proposal) - sign_in(create(:user)) - - render_inline component - - expect(page).to have_button count: 2 - expect(page).to have_button "I agree" - expect(page).to have_button "I disagree" - expect(page).not_to have_button text: "%" - expect(page).not_to have_button text: "100" - expect(page).not_to have_button text: "0" - end end end diff --git a/spec/components/shared/in_favor_against_component_spec.rb b/spec/components/shared/in_favor_against_component_spec.rb new file mode 100644 index 000000000..f3ade0ec9 --- /dev/null +++ b/spec/components/shared/in_favor_against_component_spec.rb @@ -0,0 +1,88 @@ +require "rails_helper" + +describe Shared::InFavorAgainstComponent do + let(:debate) { create(:debate) } + let(:component) { Shared::InFavorAgainstComponent.new(debate) } + let(:user) { create(:user) } + + describe "Agree and disagree buttons" do + it "can create a vote when the user has not yet voted" do + sign_in user + + render_inline component + + page.find(".in-favor") do |in_favor_block| + expect(in_favor_block).to have_css "form[action*='votes'][method='post']" + expect(in_favor_block).not_to have_css "input[name='_method']", visible: :all + end + + page.find(".against") do |against_block| + expect(against_block).to have_css "form[action*='votes'][method='post']" + expect(against_block).not_to have_css "input[name='_method']", visible: :all + end + end + + it "can undo vote when the user has already voted" do + create(:vote, votable: debate, voter: user) + + sign_in user + + render_inline component + + page.find(".in-favor") do |in_favor_block| + expect(in_favor_block).to have_css "form[action*='votes'][method='post']" + expect(in_favor_block).to have_css "input[name='_method'][value='delete']", visible: :hidden + end + + page.find(".against") do |against_block| + expect(against_block).to have_css "form[action*='votes'][method='post']" + expect(against_block).not_to have_css "input[name='_method']", visible: :all + end + end + + it "does not include result percentages" do + create(:vote, votable: debate) + sign_in(user) + + render_inline component + + expect(page).to have_button count: 2 + expect(page).to have_button "I agree" + expect(page).to have_button "I disagree" + expect(page).not_to have_button text: "%" + expect(page).not_to have_button text: "100" + expect(page).not_to have_button text: "0" + end + + describe "aria-pressed attribute" do + it "is true when the in-favor button is pressed" do + debate.register_vote(user, "yes") + sign_in(user) + + render_inline component + + expect(page.find(".in-favor")).to have_css "button[aria-pressed='true']" + expect(page.find(".against")).to have_css "button[aria-pressed='false']" + end + + it "is true when the against button is pressed" do + debate.register_vote(user, "no") + sign_in(user) + + render_inline component + + expect(page.find(".in-favor")).to have_css "button[aria-pressed='false']" + expect(page.find(".against")).to have_css "button[aria-pressed='true']" + end + + it "is false when neither the 'in-favor' button nor the 'against' button are pressed" do + sign_in(user) + + render_inline component + + expect(page.find(".in-favor")).to have_css "button[aria-pressed='false']" + expect(page.find(".against")).to have_css "button[aria-pressed='false']" + end + end + end +end diff --git a/spec/controllers/comments/votes_controller_spec.rb b/spec/controllers/comments/votes_controller_spec.rb new file mode 100644 index 000000000..cc164423f --- /dev/null +++ b/spec/controllers/comments/votes_controller_spec.rb @@ -0,0 +1,34 @@ +require "rails_helper" + +describe Comments::VotesController do + let(:comment) { create(:comment) } + + describe "POST create" do + it "allows voting" do + sign_in create(:user) + + expect do + post :create, xhr: true, params: { comment_id: comment.id, value: "yes" } + end.to change { comment.reload.votes_for.size }.by(1) + end + end + + describe "DELETE destroy" do + let(:user) { create(:user) } + let!(:vote) { create(:vote, votable: comment, voter: user) } + + it "redirects unidentified users to the sign in page" do + delete :destroy, params: { comment_id: comment.id, id: vote } + + expect(response).to redirect_to new_user_session_path + end + + it "allows undoing a vote" do + sign_in user + + expect do + delete :destroy, xhr: true, params: { comment_id: comment.id, id: vote } + end.to change { comment.reload.votes_for.size }.by(-1) + end + end +end diff --git a/spec/controllers/debates/votes_controller_spec.rb b/spec/controllers/debates/votes_controller_spec.rb new file mode 100644 index 000000000..74bd009d2 --- /dev/null +++ b/spec/controllers/debates/votes_controller_spec.rb @@ -0,0 +1,56 @@ +require "rails_helper" + +describe Debates::VotesController do + describe "POST create" do + it "does not authorize unauthenticated users" do + debate = create(:debate) + + post :create, xhr: true, params: { debate_id: debate.id, value: "yes" } + + expect(response).to be_unauthorized + end + + it "redirects unauthenticated users without JavaScript to the sign in page" do + debate = create(:debate) + + post :create, params: { debate_id: debate.id, value: "yes" } + + expect(response).to redirect_to new_user_session_path + end + + describe "Vote with too many anonymous votes" do + it "allows vote if user is allowed" do + Setting["max_ratio_anon_votes_on_debates"] = 100 + debate = create(:debate) + sign_in create(:user) + + expect do + post :create, xhr: true, params: { debate_id: debate.id, value: "yes" } + end.to change { debate.reload.votes_for.size }.by(1) + end + + it "does not allow voting if user is not allowed" do + Setting["max_ratio_anon_votes_on_debates"] = 0 + debate = create(:debate, cached_votes_total: 1000) + sign_in create(:user) + + expect do + post :create, xhr: true, params: { debate_id: debate.id, value: "yes" } + end.not_to change { debate.reload.votes_for.size } + end + end + end + + describe "DELETE destroy" do + let(:user) { create(:user) } + let(:debate) { create(:debate) } + let!(:vote) { create(:vote, votable: debate, voter: user) } + before { sign_in user } + + it "allows undoing a vote if user is allowed" do + expect do + delete :destroy, xhr: true, params: { debate_id: debate.id, id: vote } + end.to change { debate.reload.votes_for.size }.by(-1) + end + end +end diff --git a/spec/controllers/debates_controller_spec.rb b/spec/controllers/debates_controller_spec.rb index 01af1db82..c3d96dcea 100644 --- a/spec/controllers/debates_controller_spec.rb +++ b/spec/controllers/debates_controller_spec.rb @@ -37,28 +37,6 @@ describe DebatesController do end end - describe "Vote with too many anonymous votes" do - it "allows vote if user is allowed" do - Setting["max_ratio_anon_votes_on_debates"] = 100 - debate = create(:debate) - sign_in create(:user) - - expect do - post :vote, xhr: true, params: { id: debate.id, value: "yes" } - end.to change { debate.reload.votes_for.size }.by(1) - end - - it "does not allow vote if user is not allowed" do - Setting["max_ratio_anon_votes_on_debates"] = 0 - debate = create(:debate, cached_votes_total: 1000) - sign_in create(:user) - - expect do - post :vote, xhr: true, params: { id: debate.id, value: "yes" } - end.not_to change { debate.reload.votes_for.size } - end - end - describe "PUT mark_featured" do it "ignores query parameters" do debate = create(:debate) diff --git a/spec/controllers/legislation/proposals/votes_controller_spec.rb b/spec/controllers/legislation/proposals/votes_controller_spec.rb new file mode 100644 index 000000000..f618277b1 --- /dev/null +++ b/spec/controllers/legislation/proposals/votes_controller_spec.rb @@ -0,0 +1,56 @@ +require "rails_helper" + +describe Legislation::Proposals::VotesController do + let(:legislation_process) { create(:legislation_process) } + let(:proposal) { create(:legislation_proposal, process: legislation_process) } + + describe "POST create" do + let(:vote_params) do + { process_id: legislation_process.id, legislation_proposal_id: proposal.id, value: "yes" } + end + + it "does not authorize unauthenticated users" do + post :create, xhr: true, params: vote_params + + expect(response).to be_unauthorized + end + + it "redirects unauthenticated users without JavaScript to the sign in page" do + post :create, params: vote_params + + expect(response).to redirect_to new_user_session_path + end + + it "allows vote if user is level_two_or_three_verified" do + sign_in create(:user, :level_two) + + expect do + post :create, xhr: true, params: vote_params + end.to change { proposal.reload.votes_for.size }.by(1) + end + + it "does not allow voting if user is not level_two_or_three_verified" do + sign_in create(:user) + + expect do + post :create, xhr: true, params: vote_params + end.not_to change { proposal.reload.votes_for.size } + end + end + + describe "DELETE destroy" do + let(:user) { create(:user, :level_two) } + let!(:vote) { create(:vote, votable: proposal, voter: user) } + let(:vote_params) do + { process_id: legislation_process.id, legislation_proposal_id: proposal.id, id: vote } + end + + it "allows undoing a vote" do + sign_in user + + expect do + delete :destroy, xhr: true, params: vote_params + end.to change { proposal.reload.votes_for.size }.by(-1) + end + end +end diff --git a/spec/models/abilities/administrator_spec.rb b/spec/models/abilities/administrator_spec.rb index 39a42dbd6..7fb48b225 100644 --- a/spec/models/abilities/administrator_spec.rb +++ b/spec/models/abilities/administrator_spec.rb @@ -48,7 +48,6 @@ describe Abilities::Administrator do it { should be_able_to(:index, Debate) } it { should be_able_to(:show, debate) } - it { should be_able_to(:vote, debate) } it { should be_able_to(:index, Proposal) } it { should be_able_to(:show, proposal) } diff --git a/spec/models/abilities/common_spec.rb b/spec/models/abilities/common_spec.rb index 6c3918ec8..392d4367b 100644 --- a/spec/models/abilities/common_spec.rb +++ b/spec/models/abilities/common_spec.rb @@ -7,6 +7,7 @@ describe Abilities::Common do let(:geozone) { create(:geozone) } let(:user) { create(:user, geozone: geozone) } + let(:another_user) { create(:user) } let(:debate) { create(:debate) } let(:comment) { create(:comment) } @@ -15,6 +16,7 @@ describe Abilities::Common do let(:own_comment) { create(:comment, author: user) } let(:own_proposal) { create(:proposal, author: user) } let(:own_legislation_proposal) { create(:legislation_proposal, author: user) } + let(:legislation_proposal) { create(:legislation_proposal) } let(:accepting_budget) { create(:budget, :accepting) } let(:reviewing_budget) { create(:budget, :reviewing) } @@ -73,7 +75,10 @@ describe Abilities::Common do it { should be_able_to(:index, Debate) } it { should be_able_to(:show, debate) } - it { should be_able_to(:vote, debate) } + it { should be_able_to(:create, user.votes.build(votable: debate)) } + it { should_not be_able_to(:create, another_user.votes.build(votable: debate)) } + it { should be_able_to(:destroy, user.votes.build(votable: debate)) } + it { should_not be_able_to(:destroy, another_user.votes.build(votable: debate)) } it { should be_able_to(:show, user) } it { should be_able_to(:edit, user) } @@ -108,7 +113,10 @@ describe Abilities::Common do describe "Comment" do it { should be_able_to(:create, Comment) } - it { should be_able_to(:vote, Comment) } + it { should be_able_to(:create, user.votes.build(votable: comment)) } + it { should_not be_able_to(:create, another_user.votes.build(votable: comment)) } + it { should be_able_to(:destroy, user.votes.build(votable: comment)) } + it { should_not be_able_to(:destroy, another_user.votes.build(votable: comment)) } it { should be_able_to(:hide, own_comment) } it { should_not be_able_to(:hide, comment) } @@ -137,20 +145,16 @@ describe Abilities::Common do end describe "follows" do - let(:other_user) { create(:user) } - it { should be_able_to(:create, build(:follow, :followed_proposal, user: user)) } - it { should_not be_able_to(:create, build(:follow, :followed_proposal, user: other_user)) } + it { should_not be_able_to(:create, build(:follow, :followed_proposal, user: another_user)) } it { should be_able_to(:destroy, create(:follow, :followed_proposal, user: user)) } - it { should_not be_able_to(:destroy, create(:follow, :followed_proposal, user: other_user)) } + it { should_not be_able_to(:destroy, create(:follow, :followed_proposal, user: another_user)) } end describe "other users" do - let(:other_user) { create(:user) } - - it { should be_able_to(:show, other_user) } - it { should_not be_able_to(:edit, other_user) } + it { should be_able_to(:show, another_user) } + it { should_not be_able_to(:edit, another_user) } end describe "editing debates" do @@ -182,6 +186,21 @@ describe Abilities::Common do it { should_not be_able_to(:edit, own_legislation_proposal) } it { should_not be_able_to(:update, own_legislation_proposal) } + describe "vote legislation proposal" do + context "when user is not level_two_or_three_verified" do + it { should_not be_able_to(:create, user.votes.build(votable: legislation_proposal)) } + it { should_not be_able_to(:destroy, user.votes.build(votable: legislation_proposal)) } + end + + context "when user is level_two_or_three_verified" do + before { user.update(level_two_verified_at: Date.current) } + it { should be_able_to(:create, user.votes.build(votable: legislation_proposal)) } + it { should_not be_able_to(:create, another_user.votes.build(votable: legislation_proposal)) } + it { should be_able_to(:destroy, user.votes.build(votable: legislation_proposal)) } + it { should_not be_able_to(:destroy, another_user.votes.build(votable: legislation_proposal)) } + end + end + describe "proposals dashboard" do it { should be_able_to(:dashboard, own_proposal) } it { should_not be_able_to(:dashboard, proposal) } diff --git a/spec/models/abilities/moderator_spec.rb b/spec/models/abilities/moderator_spec.rb index b9df69067..9dd4f4c0c 100644 --- a/spec/models/abilities/moderator_spec.rb +++ b/spec/models/abilities/moderator_spec.rb @@ -25,7 +25,6 @@ describe Abilities::Moderator do it { should be_able_to(:index, Debate) } it { should be_able_to(:show, debate) } - it { should be_able_to(:vote, debate) } it { should be_able_to(:index, Proposal) } it { should be_able_to(:show, proposal) } diff --git a/spec/models/abilities/organization_spec.rb b/spec/models/abilities/organization_spec.rb index 874a5ce40..f38c60b14 100644 --- a/spec/models/abilities/organization_spec.rb +++ b/spec/models/abilities/organization_spec.rb @@ -8,20 +8,23 @@ describe "Abilities::Organization" do let(:organization) { create(:organization) } let(:debate) { create(:debate) } let(:proposal) { create(:proposal) } + let(:comment) { create(:comment) } it { should be_able_to(:show, user) } it { should be_able_to(:edit, user) } it { should be_able_to(:index, Debate) } it { should be_able_to(:show, debate) } - it { should_not be_able_to(:vote, debate) } + it { should_not be_able_to(:create, user.votes.build(votable: debate)) } + it { should_not be_able_to(:destroy, user.votes.build(votable: debate)) } it { should be_able_to(:index, Proposal) } it { should be_able_to(:show, proposal) } it { should_not be_able_to(:vote, Proposal) } it { should be_able_to(:create, Comment) } - it { should_not be_able_to(:vote, Comment) } + it { should_not be_able_to(:create, user.votes.build(votable: comment)) } + it { should_not be_able_to(:destroy, user.votes.build(votable: comment)) } it { should_not be_able_to(:read, SDG::Target) } diff --git a/spec/routing/polymorphic_routes_spec.rb b/spec/routing/polymorphic_routes_spec.rb index 5ff9bef09..9810cfcda 100644 --- a/spec/routing/polymorphic_routes_spec.rb +++ b/spec/routing/polymorphic_routes_spec.rb @@ -16,6 +16,26 @@ describe "Polymorphic routes" do expect(polymorphic_path(proposal)).to eq legislation_process_proposal_path(process, proposal) end + it "routes legislation proposals vote" do + process = create(:legislation_process) + proposal = create(:legislation_proposal, process: process) + path = polymorphic_path(Vote.new(votable: proposal), value: true) + + expect(path).to eq legislation_process_legislation_proposal_votes_path(process, proposal, value: true) + end + + it "routes legislation proposals remove vote" do + process = create(:legislation_process) + proposal = create(:legislation_proposal, process: process) + vote = create(:vote, votable: proposal) + path = polymorphic_path(vote, value: true) + + expect(path).to eq legislation_process_legislation_proposal_vote_path(process, + proposal, + vote, + value: true) + end + it "routes legislation questions" do process = create(:legislation_process) question = create(:legislation_question, process: process) diff --git a/spec/system/comments/budget_investments_spec.rb b/spec/system/comments/budget_investments_spec.rb index f0c39c266..f7f643a6c 100644 --- a/spec/system/comments/budget_investments_spec.rb +++ b/spec/system/comments/budget_investments_spec.rb @@ -578,7 +578,7 @@ describe "Commenting Budget::Investments" do end end - scenario "Trying to vote multiple times" do + scenario "Allow undoing votes" do visit budget_investment_path(budget, investment) within("#comment_#{comment.id}_votes") do @@ -591,14 +591,14 @@ describe "Commenting Budget::Investments" do click_button "I agree" within(".in-favor") do - expect(page).to have_content "1" + expect(page).to have_content "0" end within(".against") do expect(page).to have_content "0" end - expect(page).to have_content "1 vote" + expect(page).to have_content "No votes" end end end diff --git a/spec/system/comments/debates_spec.rb b/spec/system/comments/debates_spec.rb index b6550b3d9..3242b8943 100644 --- a/spec/system/comments/debates_spec.rb +++ b/spec/system/comments/debates_spec.rb @@ -614,7 +614,7 @@ describe "Commenting debates" do end end - scenario "Trying to vote multiple times" do + scenario "Allow undoing votes" do visit debate_path(debate) within("#comment_#{comment.id}_votes") do @@ -626,14 +626,14 @@ describe "Commenting debates" do click_button "I agree" within(".in-favor") do expect(page).not_to have_content "2" - expect(page).to have_content "1" + expect(page).to have_content "0" end within(".against") do expect(page).to have_content "0" end - expect(page).to have_content "1 vote" + expect(page).to have_content "No votes" end end end diff --git a/spec/system/comments/legislation_annotations_spec.rb b/spec/system/comments/legislation_annotations_spec.rb index aae580f14..63b89850b 100644 --- a/spec/system/comments/legislation_annotations_spec.rb +++ b/spec/system/comments/legislation_annotations_spec.rb @@ -550,7 +550,7 @@ describe "Commenting legislation questions" do end end - scenario "Trying to vote multiple times" do + scenario "Allow undoing votes" do visit polymorphic_path(annotation) within("#comment_#{comment.id}_votes") do @@ -562,14 +562,14 @@ describe "Commenting legislation questions" do click_button "I agree" within(".in-favor") do expect(page).not_to have_content "2" - expect(page).to have_content "1" + expect(page).to have_content "0" end within(".against") do expect(page).to have_content "0" end - expect(page).to have_content "1 vote" + expect(page).to have_content "No votes" end end end diff --git a/spec/system/comments/legislation_questions_spec.rb b/spec/system/comments/legislation_questions_spec.rb index 6cc9c3685..bc50f7610 100644 --- a/spec/system/comments/legislation_questions_spec.rb +++ b/spec/system/comments/legislation_questions_spec.rb @@ -534,7 +534,7 @@ describe "Commenting legislation questions" do end end - scenario "Trying to vote multiple times" do + scenario "Allow undoing votes" do visit legislation_process_question_path(question.process, question) within("#comment_#{comment.id}_votes") do @@ -546,14 +546,14 @@ describe "Commenting legislation questions" do click_button "I agree" within(".in-favor") do expect(page).not_to have_content "2" - expect(page).to have_content "1" + expect(page).to have_content "0" end within(".against") do expect(page).to have_content "0" end - expect(page).to have_content "1 vote" + expect(page).to have_content "No votes" end end end diff --git a/spec/system/comments/polls_spec.rb b/spec/system/comments/polls_spec.rb index ca0708398..8f3d00759 100644 --- a/spec/system/comments/polls_spec.rb +++ b/spec/system/comments/polls_spec.rb @@ -495,7 +495,7 @@ describe "Commenting polls" do end end - scenario "Trying to vote multiple times" do + scenario "Allow undoing votes" do visit poll_path(poll) within("#comment_#{comment.id}_votes") do @@ -508,14 +508,14 @@ describe "Commenting polls" do click_button "I agree" within(".in-favor") do - expect(page).to have_content "1" + expect(page).to have_content "0" end within(".against") do expect(page).to have_content "0" end - expect(page).to have_content "1 vote" + expect(page).to have_content "No votes" end end end diff --git a/spec/system/comments/proposals_spec.rb b/spec/system/comments/proposals_spec.rb index 5d2f42329..a2da45137 100644 --- a/spec/system/comments/proposals_spec.rb +++ b/spec/system/comments/proposals_spec.rb @@ -500,7 +500,7 @@ describe "Commenting proposals" do end end - scenario "Trying to vote multiple times" do + scenario "Allow undoing votes" do visit proposal_path(proposal) within("#comment_#{comment.id}_votes") do @@ -513,14 +513,14 @@ describe "Commenting proposals" do click_button "I agree" within(".in-favor") do - expect(page).to have_content "1" + expect(page).to have_content "0" end within(".against") do expect(page).to have_content "0" end - expect(page).to have_content "1 vote" + expect(page).to have_content "No votes" end end end diff --git a/spec/system/comments/topics_spec.rb b/spec/system/comments/topics_spec.rb index e4a603bc7..c41ef234a 100644 --- a/spec/system/comments/topics_spec.rb +++ b/spec/system/comments/topics_spec.rb @@ -547,7 +547,7 @@ describe "Commenting topics from proposals" do end end - scenario "Trying to vote multiple times" do + scenario "Allow undoing votes" do visit community_topic_path(proposal.community, topic) within("#comment_#{comment.id}_votes") do @@ -560,14 +560,14 @@ describe "Commenting topics from proposals" do click_button "I agree" within(".in-favor") do - expect(page).to have_content "1" + expect(page).to have_content "0" end within(".against") do expect(page).to have_content "0" end - expect(page).to have_content "1 vote" + expect(page).to have_content "No votes" end end end @@ -1060,7 +1060,7 @@ describe "Commenting topics from budget investments" do end end - scenario "Trying to vote multiple times" do + scenario "Allow undoing votes" do visit community_topic_path(investment.community, topic) within("#comment_#{comment.id}_votes") do @@ -1073,14 +1073,14 @@ describe "Commenting topics from budget investments" do click_button "I agree" within(".in-favor") do - expect(page).to have_content "1" + expect(page).to have_content "0" end within(".against") do expect(page).to have_content "0" end - expect(page).to have_content "1 vote" + expect(page).to have_content "No votes" end end end diff --git a/spec/system/votes_spec.rb b/spec/system/votes_spec.rb index 294d91bc7..96eaf11e5 100644 --- a/spec/system/votes_spec.rb +++ b/spec/system/votes_spec.rb @@ -19,37 +19,31 @@ describe "Votes" do within("#debates") do within("#debate_#{debate1.id}_votes") do within(".in-favor") do - expect(page).to have_button class: "voted" - expect(page).not_to have_button class: "no-voted" + expect(page).to have_css "button[aria-pressed='true']" end within(".against") do - expect(page).to have_button class: "no-voted" - expect(page).not_to have_button class: "voted" + expect(page).to have_css "button[aria-pressed='false']" end end within("#debate_#{debate2.id}_votes") do within(".in-favor") do - expect(page).not_to have_button class: "voted" - expect(page).not_to have_button class: "no-voted" + expect(page).to have_css "button[aria-pressed='false']" end within(".against") do - expect(page).not_to have_button class: "no-voted" - expect(page).not_to have_button class: "voted" + expect(page).to have_css "button[aria-pressed='false']" end end within("#debate_#{debate3.id}_votes") do within(".in-favor") do - expect(page).to have_button class: "no-voted" - expect(page).not_to have_button class: "voted" + expect(page).to have_css "button[aria-pressed='false']" end within(".against") do - expect(page).to have_button class: "voted" - expect(page).not_to have_button class: "no-voted" + expect(page).to have_css "button[aria-pressed='true']" end end end @@ -63,56 +57,70 @@ describe "Votes" do within(".in-favor") do expect(page).to have_content "0%" - expect(page).not_to have_button class: "voted" - expect(page).not_to have_button class: "no-voted" + expect(page).to have_css "button[aria-pressed='false']" end within(".against") do expect(page).to have_content "0%" - expect(page).not_to have_button class: "voted" - expect(page).not_to have_button class: "no-voted" + expect(page).to have_css "button[aria-pressed='false']" end end - scenario "Update" do + scenario "Create and update from debate show" do visit debate_path(create(:debate)) + expect(page).to have_content "No votes" + click_button "I agree" within(".in-favor") do expect(page).to have_content "100%" - expect(page).to have_button class: "voted" + expect(page).to have_css "button[aria-pressed='true']" end + within(".against") do + expect(page).to have_content "0%" + expect(page).to have_css "button[aria-pressed='false']" + end + + expect(page).to have_content "1 vote" + click_button "I disagree" within(".in-favor") do expect(page).to have_content "0%" - expect(page).to have_button class: "no-voted" + expect(page).to have_css "button[aria-pressed='false']" end within(".against") do expect(page).to have_content "100%" - expect(page).to have_button class: "voted" + expect(page).to have_css "button[aria-pressed='true']" end expect(page).to have_content "1 vote" end - scenario "Trying to vote multiple times" do + scenario "Allow undoing votes" do visit debate_path(create(:debate)) click_button "I agree" + expect(page).to have_content "1 vote" + expect(page).not_to have_content "No votes" + click_button "I agree" + + expect(page).to have_content "No votes" expect(page).not_to have_content "2 votes" within(".in-favor") do - expect(page).to have_content "100%" + expect(page).to have_content "0%" + expect(page).to have_css "button[aria-pressed='false']" end within(".against") do expect(page).to have_content "0%" + expect(page).to have_css "button[aria-pressed='false']" end end @@ -127,33 +135,15 @@ describe "Votes" do within(".in-favor") do expect(page).to have_content "50%" - expect(page).to have_button class: "voted" + expect(page).to have_css "button[aria-pressed='true']" end within(".against") do expect(page).to have_content "50%" - expect(page).to have_button class: "no-voted" + expect(page).to have_css "button[aria-pressed='false']" end end - scenario "Create from debate show" do - visit debate_path(create(:debate)) - - click_button "I agree" - - within(".in-favor") do - expect(page).to have_content "100%" - expect(page).to have_button class: "voted" - end - - within(".against") do - expect(page).to have_content "0%" - expect(page).to have_button class: "no-voted" - end - - expect(page).to have_content "1 vote" - end - scenario "Create in index" do create(:debate) visit debates_path @@ -163,12 +153,12 @@ describe "Votes" do within(".in-favor") do expect(page).to have_content "100%" - expect(page).to have_button class: "voted" + expect(page).to have_css "button[aria-pressed='true']" end within(".against") do expect(page).to have_content "0%" - expect(page).to have_button class: "no-voted" + expect(page).to have_css "button[aria-pressed='false']" end expect(page).to have_content "1 vote" @@ -354,4 +344,31 @@ describe "Votes" do expect(page).not_to have_button "Support", disabled: :all end end + + describe "Legislation Proposals" do + let(:proposal) { create(:legislation_proposal) } + + scenario "Allow undoing votes" do + login_as verified + visit legislation_process_proposal_path(proposal.process, proposal) + + click_button "I agree" + + expect(page).to have_content "1 vote" + expect(page).not_to have_content "No votes" + + click_button "I agree" + + expect(page).to have_content "No votes" + expect(page).not_to have_content "2 votes" + + within(".in-favor") do + expect(page).to have_content "0%" + end + + within(".against") do + expect(page).to have_content "0%" + end + end + end end