Extract methods in votes components
This way we can make the view code a bit easier to read. We're also changing the order of the conditions a little bit so we only check for the presence of a current user once. To make sure we aren't breaking anything with these changes, we're adding some tests. We're also replacing one system test checking content with a component test, since component tests are much faster.
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
<% reason = investment.reason_for_not_being_ballotable_by(current_user, ballot) %>
|
||||
<div class="js-participation supports ballot">
|
||||
<% if ballot.has_investment?(investment) %>
|
||||
<% if voted? %>
|
||||
<div class="remove supported">
|
||||
<span class="icon-check-circle"
|
||||
title="<%= t("budgets.investments.investment.already_added") %>">
|
||||
@@ -36,20 +35,14 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if reason.present? && !ballot.has_investment?(investment) %>
|
||||
<% if reason.present? && !voted? %>
|
||||
<div class="js-participation-not-allowed participation-not-allowed" style="display:none">
|
||||
<% my_heading = link_to(investment.heading.name,
|
||||
budget_investments_path(budget_id: investment.budget_id,
|
||||
heading_id: investment.heading_id)) %>
|
||||
<% change_ballot = link_to(t("budgets.ballots.reasons_for_not_balloting.change_ballot"),
|
||||
budget_ballot_path(budget)) %>
|
||||
|
||||
<p>
|
||||
<small>
|
||||
<%= sanitize(t("budgets.ballots.reasons_for_not_balloting.#{reason}",
|
||||
verify_account: link_to_verify_account, signin: link_to_signin,
|
||||
signup: link_to_signup, my_heading: my_heading,
|
||||
change_ballot: change_ballot,
|
||||
signup: link_to_signup, my_heading: link_to_my_heading,
|
||||
change_ballot: link_to_change_ballot,
|
||||
heading_link: heading_link(assigned_heading, budget))) %>
|
||||
</small>
|
||||
</p>
|
||||
|
||||
@@ -15,4 +15,23 @@ class Budgets::Investments::BallotComponent < ApplicationComponent
|
||||
def budget
|
||||
ballot.budget
|
||||
end
|
||||
|
||||
def voted?
|
||||
ballot.has_investment?(investment)
|
||||
end
|
||||
|
||||
def reason
|
||||
@reason ||= investment.reason_for_not_being_ballotable_by(current_user, ballot)
|
||||
end
|
||||
|
||||
def link_to_my_heading
|
||||
link_to(investment.heading.name,
|
||||
budget_investments_path(budget_id: investment.budget_id,
|
||||
heading_id: investment.heading_id))
|
||||
end
|
||||
|
||||
def link_to_change_ballot
|
||||
link_to(t("budgets.ballots.reasons_for_not_balloting.change_ballot"),
|
||||
budget_ballot_path(budget))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<% voted_classes = css_classes_for_vote(debate) %>
|
||||
<div class="votes">
|
||||
<div class="in-favor inline-block">
|
||||
<% if current_user %>
|
||||
@@ -43,21 +42,21 @@
|
||||
<%= t("debates.debate.votes", count: debate.votes_score) %>
|
||||
</span>
|
||||
|
||||
<% if current_user&.organization? %>
|
||||
<% if !current_user %>
|
||||
<div tabindex="0">
|
||||
<%= render "shared/login_to_vote" %>
|
||||
</div>
|
||||
<% elsif organization? %>
|
||||
<div class="participation-not-allowed" style="display:none" aria-hidden="false">
|
||||
<p>
|
||||
<%= t("votes.organizations") %>
|
||||
</p>
|
||||
</div>
|
||||
<% elsif current_user && !debate.votable_by?(current_user) %>
|
||||
<% elsif !can_vote? %>
|
||||
<div class="participation-not-allowed" style="display:none" aria-hidden="false">
|
||||
<p>
|
||||
<%= sanitize(t("votes.anonymous", verify_account: link_to_verify_account)) %>
|
||||
</p>
|
||||
</div>
|
||||
<% elsif !current_user %>
|
||||
<div tabindex="0">
|
||||
<%= render "shared/login_to_vote" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -5,4 +5,18 @@ class Debates::VotesComponent < ApplicationComponent
|
||||
def initialize(debate)
|
||||
@debate = debate
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def voted_classes
|
||||
@voted_classes ||= css_classes_for_vote(debate)
|
||||
end
|
||||
|
||||
def can_vote?
|
||||
debate.votable_by?(current_user)
|
||||
end
|
||||
|
||||
def organization?
|
||||
current_user&.organization?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<% voted_classes = css_classes_for_vote(proposal) %>
|
||||
<div class="votes">
|
||||
<% if proposal.process.proposals_phase.open? %>
|
||||
<div class="in-favor inline-block">
|
||||
@@ -45,23 +44,23 @@
|
||||
<%= t("proposals.proposal.votes", count: proposal.votes_score) %>
|
||||
</span>
|
||||
|
||||
<% if current_user&.organization? %>
|
||||
<% if !current_user %>
|
||||
<div tabindex="0">
|
||||
<%= render "shared/login_to_vote" %>
|
||||
</div>
|
||||
<% elsif organization? %>
|
||||
<div class="participation-not-allowed" style="display:none" aria-hidden="false">
|
||||
<p>
|
||||
<%= t("votes.organizations") %>
|
||||
</p>
|
||||
</div>
|
||||
<% elsif current_user && !proposal.votable_by?(current_user) %>
|
||||
<% elsif !can_vote? %>
|
||||
<div class="participation-not-allowed" style="display:none" aria-hidden="false">
|
||||
<p>
|
||||
<%= sanitize(t("legislation.proposals.not_verified",
|
||||
verify_account: link_to_verify_account)) %>
|
||||
</p>
|
||||
</div>
|
||||
<% elsif !current_user %>
|
||||
<div tabindex="0">
|
||||
<%= render "shared/login_to_vote" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if current_user&.voted_as_when_voted_for(proposal) && setting["twitter_handle"] %>
|
||||
|
||||
@@ -5,4 +5,18 @@ class Legislation::Proposals::VotesComponent < ApplicationComponent
|
||||
def initialize(proposal)
|
||||
@proposal = proposal
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def voted_classes
|
||||
@voted_classes ||= css_classes_for_vote(proposal)
|
||||
end
|
||||
|
||||
def can_vote?
|
||||
proposal.votable_by?(current_user)
|
||||
end
|
||||
|
||||
def organization?
|
||||
current_user&.organization?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<%= render "proposals/supports", proposal: proposal %>
|
||||
|
||||
<div class="in-favor">
|
||||
<% if current_user&.voted_for?(proposal) %>
|
||||
<% if voted? %>
|
||||
<div class="supported callout success">
|
||||
<%= t("proposals.proposal.already_supported") %>
|
||||
</div>
|
||||
<% elsif current_user && proposal.votable_by?(current_user) %>
|
||||
<% elsif can_vote? %>
|
||||
<%= link_to vote_url,
|
||||
class: "button button-support small expanded",
|
||||
title: t("proposals.proposal.support_title"), method: "post", remote: true do %>
|
||||
@@ -19,13 +19,17 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if current_user&.organization? %>
|
||||
<% if !current_user %>
|
||||
<div tabindex="0">
|
||||
<%= render "shared/login_to_vote" %>
|
||||
</div>
|
||||
<% elsif organization? %>
|
||||
<div class="participation-not-allowed" style="display:none" aria-hidden="false">
|
||||
<p>
|
||||
<%= t("votes.organizations") %>
|
||||
</p>
|
||||
</div>
|
||||
<% elsif current_user && !proposal.votable_by?(current_user) %>
|
||||
<% elsif !can_vote? %>
|
||||
<div tabindex="0">
|
||||
<div class="participation-not-allowed" style="display:none" aria-hidden="false">
|
||||
<p>
|
||||
@@ -33,13 +37,9 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<% elsif !current_user %>
|
||||
<div tabindex="0">
|
||||
<%= render "shared/login_to_vote" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if current_user&.voted_for?(proposal) && setting["twitter_handle"] %>
|
||||
<% if voted? && setting["twitter_handle"] %>
|
||||
<div class="share-supported">
|
||||
<%= render "proposals/social_share", proposal: proposal, share_title: false %>
|
||||
</div>
|
||||
|
||||
@@ -10,4 +10,18 @@ class Proposals::VotesComponent < ApplicationComponent
|
||||
def vote_url
|
||||
@vote_url || vote_proposal_path(proposal, value: "yes")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def voted?
|
||||
current_user&.voted_for?(proposal)
|
||||
end
|
||||
|
||||
def can_vote?
|
||||
proposal.votable_by?(current_user)
|
||||
end
|
||||
|
||||
def organization?
|
||||
current_user&.organization?
|
||||
end
|
||||
end
|
||||
|
||||
77
spec/components/proposals/votes_component_spec.rb
Normal file
77
spec/components/proposals/votes_component_spec.rb
Normal file
@@ -0,0 +1,77 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Proposals::VotesComponent do
|
||||
let(:proposal) { create(:proposal, title: "Create a monthly transport ticket") }
|
||||
let(:component) { Proposals::VotesComponent.new(proposal) }
|
||||
|
||||
describe "support proposal link" do
|
||||
it "is shown as plain text to unverified users" do
|
||||
sign_in(create(:user))
|
||||
|
||||
render_inline component
|
||||
|
||||
expect(page).to have_content "Support"
|
||||
expect(page).not_to have_link "Support"
|
||||
end
|
||||
|
||||
it "is shown to verified users" do
|
||||
sign_in(create(:user, :level_two))
|
||||
|
||||
render_inline component
|
||||
|
||||
expect(page).to have_link count: 1
|
||||
expect(page).to have_link "Support", title: "Support this proposal"
|
||||
expect(page).not_to have_content "You have already supported this proposal. Share it!"
|
||||
end
|
||||
|
||||
it "is replaced with a success message when the proposal is already supported" do
|
||||
sign_in(create(:user, :level_two, votables: [proposal]))
|
||||
|
||||
render_inline component
|
||||
|
||||
expect(page).to have_content "You have already supported this proposal. Share it!"
|
||||
expect(page).not_to have_link "Support"
|
||||
end
|
||||
end
|
||||
|
||||
describe "participation not allowed" do
|
||||
it "asks anonymous users to sign in or sign up" do
|
||||
render_inline component
|
||||
|
||||
expect(page).to have_link "sign in", visible: :hidden
|
||||
expect(page).to have_link "sign up", visible: :hidden
|
||||
end
|
||||
|
||||
it "says voting is not allowed to organizations" do
|
||||
sign_in(create(:organization, user: create(:user, :level_two)).user)
|
||||
|
||||
render_inline component
|
||||
|
||||
expect(page).to have_content "Organizations are not permitted to vote"
|
||||
expect(page).not_to have_link "sign in", visible: :all
|
||||
expect(page).not_to have_link "sign up", visible: :all
|
||||
end
|
||||
|
||||
it "says only verified users can vote to unverified users" do
|
||||
sign_in(create(:user))
|
||||
|
||||
render_inline component
|
||||
|
||||
expect(page).to have_content "Only verified users can vote on proposals"
|
||||
expect(page).to have_link "verify your account", visible: :hidden
|
||||
expect(page).not_to have_link "sign in", visible: :all
|
||||
expect(page).not_to have_link "sign up", visible: :all
|
||||
end
|
||||
|
||||
it "is not rendered for verified users" do
|
||||
sign_in(create(:user, :level_two))
|
||||
|
||||
render_inline component
|
||||
|
||||
expect(page).not_to have_css ".participation-not-allowed"
|
||||
expect(page).not_to have_link "verify your account", visible: :all
|
||||
expect(page).not_to have_link "sign in", visible: :all
|
||||
expect(page).not_to have_link "sign up", visible: :all
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -181,28 +181,6 @@ describe "Votes" do
|
||||
describe "Proposals" do
|
||||
before { login_as(verified) }
|
||||
|
||||
scenario "Index shows user votes on proposals" do
|
||||
proposal1 = create(:proposal, voters: [verified])
|
||||
proposal2 = create(:proposal)
|
||||
proposal3 = create(:proposal)
|
||||
|
||||
visit proposals_path
|
||||
|
||||
within("#proposals") do
|
||||
within("#proposal_#{proposal1.id}_votes") do
|
||||
expect(page).to have_content "You have already supported this proposal. Share it!"
|
||||
end
|
||||
|
||||
within("#proposal_#{proposal2.id}_votes") do
|
||||
expect(page).not_to have_content "You have already supported this proposal. Share it!"
|
||||
end
|
||||
|
||||
within("#proposal_#{proposal3.id}_votes") do
|
||||
expect(page).not_to have_content "You have already supported this proposal. Share it!"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Single proposal" do
|
||||
let!(:proposal) { create(:proposal) }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user