Allow undo votes in comments votes component
This commit is contained in:
@@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
<span class="in-favor">
|
<span class="in-favor">
|
||||||
<%= button_to vote_in_favor_against_path("yes"),
|
<%= button_to vote_in_favor_against_path("yes"),
|
||||||
method: "post",
|
method: user_already_voted_with("yes") ? "delete" : "post",
|
||||||
remote: can?(:create, comment.votes_for.new(voter: current_user)),
|
remote: remote_submit("yes"),
|
||||||
"aria-pressed": pressed?("yes"),
|
"aria-pressed": pressed?("yes"),
|
||||||
title: t("votes.agree") do %>
|
title: t("votes.agree") do %>
|
||||||
<span class="show-for-sr"><%= t("votes.agree") %></span>
|
<span class="show-for-sr"><%= t("votes.agree") %></span>
|
||||||
@@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
<span class="against">
|
<span class="against">
|
||||||
<%= button_to vote_in_favor_against_path("no"),
|
<%= button_to vote_in_favor_against_path("no"),
|
||||||
method: "post",
|
method: user_already_voted_with("no") ? "delete" : "post",
|
||||||
remote: can?(:create, comment.votes_for.new(voter: current_user)),
|
remote: remote_submit("no"),
|
||||||
"aria-pressed": pressed?("no"),
|
"aria-pressed": pressed?("no"),
|
||||||
title: t("votes.disagree") do %>
|
title: t("votes.disagree") do %>
|
||||||
<span class="show-for-sr"><%= t("votes.disagree") %></span>
|
<span class="show-for-sr"><%= t("votes.disagree") %></span>
|
||||||
|
|||||||
@@ -18,6 +18,28 @@ class Comments::VotesComponent < ApplicationComponent
|
|||||||
end
|
end
|
||||||
|
|
||||||
def vote_in_favor_against_path(value)
|
def vote_in_favor_against_path(value)
|
||||||
|
if user_already_voted_with(value)
|
||||||
|
vote = comment.votes_for.find_by!(voter: current_user)
|
||||||
|
|
||||||
|
comment_vote_path(comment, vote, value: value)
|
||||||
|
else
|
||||||
comment_votes_path(comment, value: value)
|
comment_votes_path(comment, value: value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def user_already_voted_with(value)
|
||||||
|
current_user&.voted_as_when_voted_for(comment) == parse_vote(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_vote(value)
|
||||||
|
value == "yes" ? true : false
|
||||||
|
end
|
||||||
|
|
||||||
|
def remote_submit(value)
|
||||||
|
if user_already_voted_with(value)
|
||||||
|
can?(:destroy, comment.votes_for.new(voter: current_user))
|
||||||
|
else
|
||||||
|
can?(:create, comment.votes_for.new(voter: current_user))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
module Comments
|
module Comments
|
||||||
class VotesController < ApplicationController
|
class VotesController < ApplicationController
|
||||||
load_and_authorize_resource :comment
|
|
||||||
before_action :authenticate_user!
|
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!
|
before_action :verify_comments_open!
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@@ -13,6 +14,14 @@ module Comments
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@comment.unvote_by(current_user)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.js { render :show }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def verify_comments_open!
|
def verify_comments_open!
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ module Abilities
|
|||||||
|
|
||||||
unless user.organization?
|
unless user.organization?
|
||||||
can [:create, :destroy], ActsAsVotable::Vote, voter_id: user.id, votable_type: "Debate"
|
can [:create, :destroy], ActsAsVotable::Vote, voter_id: user.id, votable_type: "Debate"
|
||||||
can :create, ActsAsVotable::Vote, voter_id: user.id, votable_type: "Comment"
|
can [:create, :destroy], ActsAsVotable::Vote, voter_id: user.id, votable_type: "Comment"
|
||||||
end
|
end
|
||||||
|
|
||||||
if user.level_two_or_three_verified?
|
if user.level_two_or_three_verified?
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ resources :comments, only: [:create, :show] do
|
|||||||
put :hide
|
put :hide
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :votes, controller: "comments/votes", only: :create
|
resources :votes, controller: "comments/votes", only: [:create, :destroy]
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ describe Comments::VotesComponent do
|
|||||||
let(:comment) { create(:comment, user: user) }
|
let(:comment) { create(:comment, user: user) }
|
||||||
let(:component) { Comments::VotesComponent.new(comment) }
|
let(:component) { Comments::VotesComponent.new(comment) }
|
||||||
|
|
||||||
describe "aria-pressed attribute" do
|
describe "aria-pressed and method attributes" do
|
||||||
it "is true when the in-favor button is pressed" do
|
it "have expected values when the in-favor button is pressed" do
|
||||||
comment.vote_by(voter: user, vote: "yes")
|
comment.vote_by(voter: user, vote: "yes")
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
|
|
||||||
@@ -14,14 +14,18 @@ describe Comments::VotesComponent do
|
|||||||
|
|
||||||
page.find(".in-favor") do |in_favor_block|
|
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 "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
|
end
|
||||||
|
|
||||||
page.find(".against") do |against_block|
|
page.find(".against") do |against_block|
|
||||||
expect(against_block).to have_css "button[aria-pressed='false']"
|
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
|
||||||
|
|
||||||
it "is true when the against button is pressed" do
|
it "have expected values when the against button is pressed" do
|
||||||
comment.vote_by(voter: user, vote: "no")
|
comment.vote_by(voter: user, vote: "no")
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
|
|
||||||
@@ -29,24 +33,32 @@ describe Comments::VotesComponent do
|
|||||||
|
|
||||||
page.find(".in-favor") do |in_favor_block|
|
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 "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
|
end
|
||||||
|
|
||||||
page.find(".against") do |against_block|
|
page.find(".against") do |against_block|
|
||||||
expect(against_block).to have_css "button[aria-pressed='true']"
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is false when neither the 'in-favor' button nor the 'against' button are pressed" do
|
it "have expected values when neither the 'in-favor' button nor the 'against' button are pressed" do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
|
|
||||||
render_inline component
|
render_inline component
|
||||||
|
|
||||||
page.find(".in-favor") do |in_favor_block|
|
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 "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
|
end
|
||||||
|
|
||||||
page.find(".against") do |against_block|
|
page.find(".against") do |against_block|
|
||||||
expect(against_block).to have_css "button[aria-pressed='false']"
|
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
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -12,4 +12,23 @@ describe Comments::VotesController do
|
|||||||
end.to change { comment.reload.votes_for.size }.by(1)
|
end.to change { comment.reload.votes_for.size }.by(1)
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|||||||
@@ -115,6 +115,8 @@ describe Abilities::Common do
|
|||||||
it { should be_able_to(:create, Comment) }
|
it { should be_able_to(:create, Comment) }
|
||||||
it { should be_able_to(:create, user.votes.build(votable: 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_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 be_able_to(:hide, own_comment) }
|
||||||
it { should_not be_able_to(:hide, comment) }
|
it { should_not be_able_to(:hide, comment) }
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ describe "Abilities::Organization" do
|
|||||||
|
|
||||||
it { should be_able_to(:create, Comment) }
|
it { should be_able_to(:create, Comment) }
|
||||||
it { should_not be_able_to(:create, user.votes.build(votable: 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) }
|
it { should_not be_able_to(:read, SDG::Target) }
|
||||||
|
|
||||||
|
|||||||
@@ -578,7 +578,7 @@ describe "Commenting Budget::Investments" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Trying to vote multiple times" do
|
scenario "Allow undoing votes" do
|
||||||
visit budget_investment_path(budget, investment)
|
visit budget_investment_path(budget, investment)
|
||||||
|
|
||||||
within("#comment_#{comment.id}_votes") do
|
within("#comment_#{comment.id}_votes") do
|
||||||
@@ -591,14 +591,14 @@ describe "Commenting Budget::Investments" do
|
|||||||
click_button "I agree"
|
click_button "I agree"
|
||||||
|
|
||||||
within(".in-favor") do
|
within(".in-favor") do
|
||||||
expect(page).to have_content "1"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
within(".against") do
|
within(".against") do
|
||||||
expect(page).to have_content "0"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page).to have_content "1 vote"
|
expect(page).to have_content "No votes"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -614,7 +614,7 @@ describe "Commenting debates" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Trying to vote multiple times" do
|
scenario "Allow undoing votes" do
|
||||||
visit debate_path(debate)
|
visit debate_path(debate)
|
||||||
|
|
||||||
within("#comment_#{comment.id}_votes") do
|
within("#comment_#{comment.id}_votes") do
|
||||||
@@ -626,14 +626,14 @@ describe "Commenting debates" do
|
|||||||
click_button "I agree"
|
click_button "I agree"
|
||||||
within(".in-favor") do
|
within(".in-favor") do
|
||||||
expect(page).not_to have_content "2"
|
expect(page).not_to have_content "2"
|
||||||
expect(page).to have_content "1"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
within(".against") do
|
within(".against") do
|
||||||
expect(page).to have_content "0"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page).to have_content "1 vote"
|
expect(page).to have_content "No votes"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -550,7 +550,7 @@ describe "Commenting legislation questions" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Trying to vote multiple times" do
|
scenario "Allow undoing votes" do
|
||||||
visit polymorphic_path(annotation)
|
visit polymorphic_path(annotation)
|
||||||
|
|
||||||
within("#comment_#{comment.id}_votes") do
|
within("#comment_#{comment.id}_votes") do
|
||||||
@@ -562,14 +562,14 @@ describe "Commenting legislation questions" do
|
|||||||
click_button "I agree"
|
click_button "I agree"
|
||||||
within(".in-favor") do
|
within(".in-favor") do
|
||||||
expect(page).not_to have_content "2"
|
expect(page).not_to have_content "2"
|
||||||
expect(page).to have_content "1"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
within(".against") do
|
within(".against") do
|
||||||
expect(page).to have_content "0"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page).to have_content "1 vote"
|
expect(page).to have_content "No votes"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -534,7 +534,7 @@ describe "Commenting legislation questions" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Trying to vote multiple times" do
|
scenario "Allow undoing votes" do
|
||||||
visit legislation_process_question_path(question.process, question)
|
visit legislation_process_question_path(question.process, question)
|
||||||
|
|
||||||
within("#comment_#{comment.id}_votes") do
|
within("#comment_#{comment.id}_votes") do
|
||||||
@@ -546,14 +546,14 @@ describe "Commenting legislation questions" do
|
|||||||
click_button "I agree"
|
click_button "I agree"
|
||||||
within(".in-favor") do
|
within(".in-favor") do
|
||||||
expect(page).not_to have_content "2"
|
expect(page).not_to have_content "2"
|
||||||
expect(page).to have_content "1"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
within(".against") do
|
within(".against") do
|
||||||
expect(page).to have_content "0"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page).to have_content "1 vote"
|
expect(page).to have_content "No votes"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -495,7 +495,7 @@ describe "Commenting polls" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Trying to vote multiple times" do
|
scenario "Allow undoing votes" do
|
||||||
visit poll_path(poll)
|
visit poll_path(poll)
|
||||||
|
|
||||||
within("#comment_#{comment.id}_votes") do
|
within("#comment_#{comment.id}_votes") do
|
||||||
@@ -508,14 +508,14 @@ describe "Commenting polls" do
|
|||||||
click_button "I agree"
|
click_button "I agree"
|
||||||
|
|
||||||
within(".in-favor") do
|
within(".in-favor") do
|
||||||
expect(page).to have_content "1"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
within(".against") do
|
within(".against") do
|
||||||
expect(page).to have_content "0"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page).to have_content "1 vote"
|
expect(page).to have_content "No votes"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -500,7 +500,7 @@ describe "Commenting proposals" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Trying to vote multiple times" do
|
scenario "Allow undoing votes" do
|
||||||
visit proposal_path(proposal)
|
visit proposal_path(proposal)
|
||||||
|
|
||||||
within("#comment_#{comment.id}_votes") do
|
within("#comment_#{comment.id}_votes") do
|
||||||
@@ -513,14 +513,14 @@ describe "Commenting proposals" do
|
|||||||
click_button "I agree"
|
click_button "I agree"
|
||||||
|
|
||||||
within(".in-favor") do
|
within(".in-favor") do
|
||||||
expect(page).to have_content "1"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
within(".against") do
|
within(".against") do
|
||||||
expect(page).to have_content "0"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page).to have_content "1 vote"
|
expect(page).to have_content "No votes"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -547,7 +547,7 @@ describe "Commenting topics from proposals" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Trying to vote multiple times" do
|
scenario "Allow undoing votes" do
|
||||||
visit community_topic_path(proposal.community, topic)
|
visit community_topic_path(proposal.community, topic)
|
||||||
|
|
||||||
within("#comment_#{comment.id}_votes") do
|
within("#comment_#{comment.id}_votes") do
|
||||||
@@ -560,14 +560,14 @@ describe "Commenting topics from proposals" do
|
|||||||
click_button "I agree"
|
click_button "I agree"
|
||||||
|
|
||||||
within(".in-favor") do
|
within(".in-favor") do
|
||||||
expect(page).to have_content "1"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
within(".against") do
|
within(".against") do
|
||||||
expect(page).to have_content "0"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page).to have_content "1 vote"
|
expect(page).to have_content "No votes"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1060,7 +1060,7 @@ describe "Commenting topics from budget investments" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Trying to vote multiple times" do
|
scenario "Allow undoing votes" do
|
||||||
visit community_topic_path(investment.community, topic)
|
visit community_topic_path(investment.community, topic)
|
||||||
|
|
||||||
within("#comment_#{comment.id}_votes") do
|
within("#comment_#{comment.id}_votes") do
|
||||||
@@ -1073,14 +1073,14 @@ describe "Commenting topics from budget investments" do
|
|||||||
click_button "I agree"
|
click_button "I agree"
|
||||||
|
|
||||||
within(".in-favor") do
|
within(".in-favor") do
|
||||||
expect(page).to have_content "1"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
within(".against") do
|
within(".against") do
|
||||||
expect(page).to have_content "0"
|
expect(page).to have_content "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page).to have_content "1 vote"
|
expect(page).to have_content "No votes"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user