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:
Javi Martín
2021-09-29 04:06:51 +02:00
parent 70f717e564
commit 4e3b3f2028
10 changed files with 163 additions and 56 deletions

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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"] %>

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View 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

View File

@@ -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) }