can add investments to ballot
This commit is contained in:
80
app/controllers/budgets/ballot/lines_controller.rb
Normal file
80
app/controllers/budgets/ballot/lines_controller.rb
Normal file
@@ -0,0 +1,80 @@
|
||||
module Budgets
|
||||
module Ballot
|
||||
class LinesController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
#before_action :ensure_final_voting_allowed
|
||||
before_action :load_budget
|
||||
before_action :load_ballot
|
||||
|
||||
before_action :load_investments
|
||||
|
||||
load_and_authorize_resource :budget
|
||||
load_and_authorize_resource :ballot, class: "Budget::Ballot"
|
||||
load_and_authorize_resource :line, through: :ballot, find_by: :investment_id, class: "Budget::Ballot::Line"
|
||||
|
||||
def create
|
||||
load_investment
|
||||
load_heading
|
||||
|
||||
if @line.save
|
||||
#@ballot.set_geozone(@geozone)
|
||||
#@current_user.update(representative_id: nil)
|
||||
if request.get?
|
||||
redirect_to @spending_proposal, notice: t('spending_proposals.notice.voted')
|
||||
end
|
||||
else
|
||||
if request.get?
|
||||
redirect_to @spending_proposal, notice: t('spending_proposals.notice.could_not_vote')
|
||||
else
|
||||
render :new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
load_spending_proposal
|
||||
load_spending_proposals
|
||||
load_geozone
|
||||
|
||||
@ballot_line.destroy
|
||||
@ballot.reset_geozone
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_final_voting_allowed
|
||||
return head(:forbidden) unless @budget.balloting?
|
||||
end
|
||||
|
||||
def line_params
|
||||
params.permit(:investment_id)
|
||||
end
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.find(params[:budget_id])
|
||||
end
|
||||
|
||||
def load_ballot
|
||||
@ballot = Budget::Ballot.where(user: current_user, budget: @budget).first_or_create
|
||||
end
|
||||
|
||||
def load_investment
|
||||
@investment = Budget::Investment.find(params[:investment_id])
|
||||
end
|
||||
|
||||
def load_investments
|
||||
if params[:investments_ids].present?
|
||||
@investments = Budget::Investment.where(id: params[:investments_ids])
|
||||
end
|
||||
end
|
||||
|
||||
def load_heading
|
||||
@heading = @investment.heading
|
||||
end
|
||||
|
||||
def load_geozone
|
||||
@geozone = @line.investment.geozone
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
17
app/controllers/budgets/ballots_controller.rb
Normal file
17
app/controllers/budgets/ballots_controller.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
module Budgets
|
||||
class BallotsController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
before_action :load_ballot
|
||||
load_and_authorize_resource
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_ballot
|
||||
@ballot = Ballot.where(user: current_user).first_or_create
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
7
app/helpers/ballots_helper.rb
Normal file
7
app/helpers/ballots_helper.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
module BallotsHelper
|
||||
|
||||
def progress_bar_width(amount_available, amount_spent)
|
||||
(amount_spent/amount_available.to_f * 100).to_s + "%"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -20,4 +20,8 @@ module BudgetHelper
|
||||
budget_investment_path(investment, options)
|
||||
end
|
||||
end
|
||||
|
||||
def display_budget_countdown?(budget)
|
||||
budget.balloting?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -45,9 +45,10 @@ module Abilities
|
||||
can :vote, SpendingProposal
|
||||
can :create, SpendingProposal
|
||||
|
||||
can :create, Budget::Investment, budget: { phase: "accepting" }
|
||||
can :vote, Budget::Investment, budget: { phase: "selecting" }
|
||||
can :create, Budget::Ballot, budget: { phase: "balloting" }
|
||||
can :create, Budget::Investment, budget: { phase: "accepting" }
|
||||
can :vote, Budget::Investment, budget: { phase: "selecting" }
|
||||
can [:show, :create], Budget::Ballot, budget: { phase: "balloting" }
|
||||
can [:create, :destroy], Budget::Ballot::Line#, budget: { phase: "balloting" }
|
||||
|
||||
can :create, DirectMessage
|
||||
can :show, DirectMessage, sender_id: user.id
|
||||
|
||||
@@ -6,7 +6,7 @@ module Abilities
|
||||
can [:read, :map], Debate
|
||||
can [:read, :map, :summary], Proposal
|
||||
can :read, Comment
|
||||
can :read, Budget
|
||||
can [:read, :welcome], Budget
|
||||
can :read, Budget::Investment
|
||||
can :read, SpendingProposal
|
||||
can :read, Legislation
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<li id="<%= dom_id(investment) %>_sidebar">
|
||||
<%= investment.title %>
|
||||
<span><%= format_price(investment.price) %></span>
|
||||
<span><%= format_price(@budget, investment.price) %></span>
|
||||
|
||||
<% if @budget.balloting? %>
|
||||
<%= link_to ballot_line_path(id: investment.id,
|
||||
investments_ids: investment_ids),
|
||||
<%= link_to budget_ballot_line_url(id: investment.id,
|
||||
investments_ids: investment_ids),
|
||||
title: t('budgets.ballots.show.remove'),
|
||||
class: "remove-investment-project",
|
||||
method: :delete,
|
||||
28
app/views/budgets/ballot/_progress_bar.html.erb
Normal file
28
app/views/budgets/ballot/_progress_bar.html.erb
Normal file
@@ -0,0 +1,28 @@
|
||||
<span class="total-amount">
|
||||
<%= format_price(@budget, @budget.heading_price(@heading)) %>
|
||||
</span>
|
||||
|
||||
<div class="progress" role="progressbar" tabindex="0"
|
||||
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||
<div class="progress-meter"
|
||||
style="width:
|
||||
<%= progress_bar_width(@budget.heading_price(@heading),
|
||||
@ballot.amount_spent(@heading.id)) %>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="progress spent-amount-progress" role="progressbar" tabindex="0"
|
||||
aria-valuenow="20" aria-valuemin="0" aria-valuetext="25 percent" aria-valuemax="100">
|
||||
<span class="progress-meter spent-amount-meter"
|
||||
style="width:
|
||||
<%= progress_bar_width(@budget.heading_price(@heading),
|
||||
@ballot.amount_spent(@heading.id)) %>">
|
||||
<p id="amount-spent" class="progress-meter-text spent-amount-text">
|
||||
<%= format_price(@budget, @ballot.amount_spent(@heading.id)) %>
|
||||
<span id="amount-available" class="amount-available">
|
||||
<%= t("spending_proposals.index.available") %>
|
||||
<span><%= format_price(@budget, @ballot.amount_available(@heading)) %></span>
|
||||
</span>
|
||||
</p>
|
||||
</span>
|
||||
</div>
|
||||
@@ -4,12 +4,12 @@
|
||||
</span>
|
||||
|
||||
<p class="investment-project-amount">
|
||||
<%= format_price(investment.price) %>
|
||||
<%= format_price(@budget, investment.price) %>
|
||||
</p>
|
||||
|
||||
<% if @budget.balloting? %>
|
||||
<%= link_to t('budgets.ballots.show.remove'),
|
||||
ballot_line_path(id: investment.id,
|
||||
budget_ballot_line_path(id: investment.id,
|
||||
investments_ids: investment_ids),
|
||||
class: "delete small expanded",
|
||||
method: :delete,
|
||||
5
app/views/budgets/ballot/lines/_refresh_ballots.js.erb
Normal file
5
app/views/budgets/ballot/lines/_refresh_ballots.js.erb
Normal file
@@ -0,0 +1,5 @@
|
||||
<% if @spending_proposals.present? %>
|
||||
<% @spending_proposals.each do |spending_proposal| %>
|
||||
$("#<%= dom_id(spending_proposal) %>_ballot").html('<%= j render("spending_proposals/ballot", spending_proposal: spending_proposal) %>');
|
||||
<% end %>
|
||||
<% end %>
|
||||
5
app/views/budgets/ballot/lines/create.js.erb
Normal file
5
app/views/budgets/ballot/lines/create.js.erb
Normal file
@@ -0,0 +1,5 @@
|
||||
$("#progress_bar").html('<%= j render("budgets/ballot/progress_bar", ballot: @ballot) %>');
|
||||
$("#sidebar").html('<%= j render("budgets/investments/sidebar") %>');
|
||||
$("#<%= dom_id(@investment) %>_ballot").html('<%= j render("budgets/investments/ballot", investment: @investment) %>');
|
||||
|
||||
<%= render 'refresh_ballots' %>
|
||||
6
app/views/budgets/ballot/lines/destroy.js.erb
Normal file
6
app/views/budgets/ballot/lines/destroy.js.erb
Normal file
@@ -0,0 +1,6 @@
|
||||
$("#progress_bar").html('<%= j render("spending_proposals/progress_bar", ballot: @ballot) %>');
|
||||
$("#sidebar").html('<%= j render("spending_proposals/sidebar") %>');
|
||||
$("#ballot").html('<%= j render("ballots/ballot") %>')
|
||||
$("#<%= dom_id(@spending_proposal) %>_ballot").html('<%= j render("spending_proposals/ballot", spending_proposal: @spending_proposal) %>');
|
||||
|
||||
<%= render 'refresh_ballots' %>
|
||||
2
app/views/budgets/ballot/lines/new.js.erb
Normal file
2
app/views/budgets/ballot/lines/new.js.erb
Normal file
@@ -0,0 +1,2 @@
|
||||
$("#<%= dom_id(@spending_proposal) %>_ballot").html('<%= j render("spending_proposals/ballot", spending_proposal: @spending_proposal) %>');
|
||||
$(".no-supports-allowed").show();
|
||||
@@ -1,9 +1,13 @@
|
||||
<% reason = investment.reason_for_not_being_ballotable_by(current_user, @ballot) %>
|
||||
<div class="supports ballot">
|
||||
<% if @ballot.has_investment?(investment) %>
|
||||
<%= render 'budgets/ballots/remove', investment: investment %>
|
||||
<%= render 'budgets/ballot/remove',
|
||||
investment: investment,
|
||||
investment_ids: @investments %>
|
||||
<% else %>
|
||||
<%= render 'budgets/ballots/add', investment: investment %>
|
||||
<%= render 'budgets/ballot/add',
|
||||
investment: investment,
|
||||
investment_ids: @investments %>
|
||||
<% end %>
|
||||
|
||||
<% if reason.present? && !@ballot.has_investment?(investment) %>
|
||||
@@ -14,7 +18,7 @@
|
||||
verify_account: link_to(t("votes.verify_account"), verification_path),
|
||||
signin: link_to(t("votes.signin"), new_user_session_path),
|
||||
signup: link_to(t("votes.signup"), new_user_registration_path),
|
||||
my_heading: link_to(@ballot.heading.try(:name), budget_investments_path(budget_id: @budget.id, heading_id: @ballot.heading_id))
|
||||
my_heading: link_to(@ballot.try(:heading).try(:name), budget_investments_path(budget_id: @budget.id, heading_id: @ballot.try(:heading_id)))
|
||||
).html_safe %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
<% end %>
|
||||
|
||||
<% if can? :show, @ballot %>
|
||||
<%= link_to t("budget.investments.header.check_ballot"), budget_ballot_path(@budget, @ballot), class: "button float-right" %>
|
||||
<%= link_to t("budget.investments.header.check_ballot"),
|
||||
budget_ballot_path(@budget, @ballot),
|
||||
class: "button float-right" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -21,7 +23,8 @@
|
||||
<h1 class="inline-block"><%= @filter_geozone_name %></h1>
|
||||
<div id="check-ballot" style="display: none;">
|
||||
<% if can? :show, @ballot %>
|
||||
<%= link_to t("budget.investments.header.check_ballot"), ballot_path %>
|
||||
<%= link_to t("budget.investments.header.check_ballot"),
|
||||
budget_ballot_path(@budget) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% if @heading.present? && @ballot.heading.present? && @ballot.heading != @heading %>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
vote_url: vote_budget_investment_path(@budget, investment, value: 'yes') } %>
|
||||
</div>
|
||||
|
||||
<% elsif feature?("investment_features.phase3") %>
|
||||
<% elsif @budget.balloting? %>
|
||||
<div id="<%= dom_id(investment) %>_ballot"
|
||||
class="small-12 medium-3 column text-center">
|
||||
<%= render 'ballot', investment: investment %>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<em>
|
||||
<%= t("budget.investments.index.sidebar.voted_html",
|
||||
count: @ballot.investments.by_heading(@heading.id).count,
|
||||
amount_spent: format_price(@ballot.amount_spent(@heading))) %>
|
||||
amount_spent: format_price(@budget, @ballot.amount_spent(@heading))) %>
|
||||
</em>
|
||||
</p>
|
||||
<% else %>
|
||||
@@ -22,7 +22,9 @@
|
||||
|
||||
<ul class="ballot-list">
|
||||
<% @ballot.investments.by_heading(@heading).each do |investment| %>
|
||||
<%= render 'ballots/investment_for_sidebar', investment: investment %>
|
||||
<%= render 'budgets/ballot/investment_for_sidebar',
|
||||
investment: investment,
|
||||
investment_ids: @investments %>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
|
||||
700
spec/features/budgets/ballots_spec.rb
Normal file
700
spec/features/budgets/ballots_spec.rb
Normal file
@@ -0,0 +1,700 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Ballots' do
|
||||
|
||||
let(:budget) { create(:budget, phase: "balloting") }
|
||||
let(:group) { create(:budget_group, budget: budget) }
|
||||
let(:heading) { create(:budget_heading, group: group) }
|
||||
|
||||
context "Voting" do
|
||||
let!(:user) { create(:user, :level_two) }
|
||||
|
||||
background do
|
||||
login_as(user)
|
||||
visit budget_path(budget)
|
||||
end
|
||||
|
||||
context "City" do
|
||||
|
||||
scenario "Add a proposal", :js, :focus do
|
||||
investment1 = create(:budget_investment, :feasible, :finished, budget: budget, heading: heading, price: 10000)
|
||||
investment2 = create(:budget_investment, :feasible, :finished, budget: budget, heading: heading, price: 20000)
|
||||
|
||||
click_link "No Heading"
|
||||
|
||||
within("#budget_investment_#{investment1.id}") do
|
||||
find('.add a').trigger('click')
|
||||
end
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€10,000")
|
||||
expect(page).to have_css("#amount-available", text: "€990,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content investment1.title
|
||||
expect(page).to have_content "€10,000"
|
||||
end
|
||||
|
||||
within("#budget_investment_#{investment2.id}") do
|
||||
find('.add a').trigger('click')
|
||||
end
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€30,000")
|
||||
expect(page).to have_css("#amount-available", text: "€970,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content investment2.title
|
||||
expect(page).to have_content "€20,000"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Remove a proposal", :js do
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, price: 10000)
|
||||
ballot = create(:ballot, user: user, spending_proposals: [sp1])
|
||||
|
||||
click_link "Vote city proposals"
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€10,000")
|
||||
expect(page).to have_css("#amount-available", text: "€23,990,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content sp1.title
|
||||
expect(page).to have_content "€10,000"
|
||||
end
|
||||
|
||||
within("#spending_proposal_#{sp1.id}") do
|
||||
find('.remove a').trigger('click')
|
||||
end
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€0")
|
||||
expect(page).to have_css("#amount-available", text: "€24,000,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to_not have_content sp1.title
|
||||
expect(page).to_not have_content "€10,000"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'District' do
|
||||
|
||||
scenario "Add a proposal", :js do
|
||||
carabanchel = create(:geozone, name: "Carabanchel")
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, geozone: carabanchel, price: 10000)
|
||||
sp2 = create(:spending_proposal, :feasible, :finished, geozone: carabanchel, price: 20000)
|
||||
|
||||
click_link "Vote district proposals"
|
||||
click_link carabanchel.name
|
||||
|
||||
within("#spending_proposal_#{sp1.id}") do
|
||||
find('.add a').trigger('click')
|
||||
expect(page).to have_content "Remove"
|
||||
end
|
||||
|
||||
visit spending_proposals_path(geozone: carabanchel)
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€10,000")
|
||||
expect(page).to have_css("#amount-available", text: "€3,237,830")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content sp1.title
|
||||
expect(page).to have_content "€10,000"
|
||||
end
|
||||
|
||||
within("#spending_proposal_#{sp2.id}") do
|
||||
find('.add a').trigger('click')
|
||||
end
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€30,000")
|
||||
expect(page).to have_css("#amount-available", text: "€3,217,830")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content sp2.title
|
||||
expect(page).to have_content "€20,000"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Remove a proposal", :js do
|
||||
carabanchel = create(:geozone, name: "Carabanchel")
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, geozone: carabanchel, price: 10000)
|
||||
ballot = create(:ballot, user: user, geozone: carabanchel, spending_proposals: [sp1])
|
||||
|
||||
click_link "Vote district proposals"
|
||||
click_link carabanchel.name
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€10,000")
|
||||
expect(page).to have_css("#amount-available", text: "€3,237,830")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content sp1.title
|
||||
expect(page).to have_content "€10,000"
|
||||
end
|
||||
|
||||
within("#spending_proposal_#{sp1.id}") do
|
||||
find('.remove a').trigger('click')
|
||||
end
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€0")
|
||||
expect(page).to have_css("#amount-available", text: "€3,247,830")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to_not have_content sp1.title
|
||||
expect(page).to_not have_content "€10,000"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "City and District" do
|
||||
|
||||
scenario "Independent progress bar for city and district proposals", :js do
|
||||
carabanchel = create(:geozone, name: "Carabanchel")
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, geozone: nil, price: 10000)
|
||||
sp2 = create(:spending_proposal, :feasible, :finished, geozone: carabanchel, price: 20000)
|
||||
|
||||
click_link "Vote city proposals"
|
||||
|
||||
within("#spending_proposal_#{sp1.id}") do
|
||||
find('.add a').trigger('click')
|
||||
expect(page).to have_content "Remove"
|
||||
end
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€10,000")
|
||||
expect(page).to have_css("#amount-available", text: "€23,990,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content sp1.title
|
||||
expect(page).to have_content "€10,000"
|
||||
end
|
||||
|
||||
visit spending_proposals_path(geozone: carabanchel)
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€0")
|
||||
expect(page).to have_css("#amount-spent", text: "€3,247,830")
|
||||
|
||||
within("#spending_proposal_#{sp2.id}") do
|
||||
find('.add a').trigger('click')
|
||||
expect(page).to have_content "Remove"
|
||||
end
|
||||
|
||||
visit spending_proposals_path(geozone: carabanchel)
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€20,000")
|
||||
expect(page).to have_css("#amount-available", text: "€3,227,830")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content sp2.title
|
||||
expect(page).to have_content "€20,000"
|
||||
|
||||
expect(page).to_not have_content sp1.title
|
||||
expect(page).to_not have_content "€10,000"
|
||||
end
|
||||
|
||||
click_link "Participatory budgeting"
|
||||
click_link "Vote city proposals"
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€10,000")
|
||||
expect(page).to have_css("#amount-available", text: "€23,990,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content sp1.title
|
||||
expect(page).to have_content "€10,000"
|
||||
|
||||
expect(page).to_not have_content sp2.title
|
||||
expect(page).to_not have_content "€20,000"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Display progress bar after first district vote", :js do
|
||||
carabanchel = create(:geozone, name: "Carabanchel")
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, geozone: carabanchel, price: 10000)
|
||||
|
||||
click_link "Vote district proposals"
|
||||
click_link carabanchel.name
|
||||
|
||||
within("#spending_proposal_#{sp1.id}") do
|
||||
find('.add a').trigger('click')
|
||||
expect(page).to have_content "Remove"
|
||||
end
|
||||
|
||||
within("#progress_bar") do
|
||||
expect(page).to have_css("#amount-spent", text: "€10,000")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "Choosing my district" do
|
||||
let!(:user) { create(:user, :level_two) }
|
||||
|
||||
background do
|
||||
login_as(user)
|
||||
visit welcome_spending_proposals_path
|
||||
end
|
||||
|
||||
scenario 'Select my district', :js do
|
||||
california = create(:geozone)
|
||||
new_york = create(:geozone)
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, geozone: california)
|
||||
|
||||
click_link "Vote district proposals"
|
||||
click_link california.name
|
||||
|
||||
within("#spending_proposal_#{sp1.id}") do
|
||||
find('.add a').trigger('click')
|
||||
end
|
||||
|
||||
visit select_district_path
|
||||
expect(page).to have_css("#geozone_#{california.id}.active")
|
||||
end
|
||||
|
||||
scenario 'Change my district', :js do
|
||||
california = create(:geozone)
|
||||
new_york = create(:geozone)
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, geozone: california)
|
||||
sp2 = create(:spending_proposal, :feasible, :finished, geozone: new_york)
|
||||
|
||||
create(:ballot, user: user, geozone: california, spending_proposals: [sp1])
|
||||
|
||||
visit spending_proposals_path(geozone: california)
|
||||
|
||||
within("#spending_proposal_#{sp1.id}") do
|
||||
find('.remove a').trigger('click')
|
||||
end
|
||||
|
||||
visit spending_proposals_path(geozone: new_york)
|
||||
|
||||
within("#spending_proposal_#{sp2.id}") do
|
||||
find('.add a').trigger('click')
|
||||
end
|
||||
|
||||
visit select_district_path
|
||||
expect(page).to have_css("#geozone_#{new_york.id}.active")
|
||||
expect(page).to_not have_css("#geozone_#{california.id}.active")
|
||||
end
|
||||
|
||||
scenario 'View another district' do
|
||||
california = create(:geozone)
|
||||
new_york = create(:geozone)
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, geozone: california)
|
||||
sp2 = create(:spending_proposal, :feasible, :finished, geozone: new_york)
|
||||
|
||||
create(:ballot, user: user, geozone: california, spending_proposals: [sp1])
|
||||
|
||||
visit spending_proposals_path(geozone: new_york)
|
||||
|
||||
expect(page).to_not have_css "#progressbar"
|
||||
expect(page).to have_content "You have active votes in another district:"
|
||||
expect(page).to have_link california.name, href: spending_proposals_path(geozone: california)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'Showing the ballot' do
|
||||
|
||||
scenario 'Displaying the correct count & amount' do
|
||||
user = create(:user, :level_two)
|
||||
geozone = create(:geozone, name: "Carabanchel")
|
||||
ballot = create(:ballot, user: user, geozone: geozone)
|
||||
|
||||
ballot.spending_proposals =
|
||||
create_list(:spending_proposal, 2, :feasible, :finished, price: 10) +
|
||||
create_list(:spending_proposal, 3, :feasible, :finished, price: 5, geozone: geozone)
|
||||
|
||||
login_as(user)
|
||||
visit ballot_path
|
||||
|
||||
expect(page).to have_content("You voted 5 proposals")
|
||||
within("#city_wide") { expect(page).to have_content "€20" }
|
||||
within("#district_wide") { expect(page).to have_content "€15" }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
scenario 'Removing spending proposals from ballot', :js do
|
||||
user = create(:user, :level_two)
|
||||
ballot = create(:ballot, user: user)
|
||||
sp = create(:spending_proposal, :feasible, :finished, price: 10)
|
||||
ballot.spending_proposals = [sp]
|
||||
|
||||
login_as(user)
|
||||
visit ballot_path
|
||||
|
||||
expect(page).to have_content("You voted one proposal")
|
||||
|
||||
within("#spending_proposal_#{sp.id}") do
|
||||
find(".remove-investment-project").trigger('click')
|
||||
end
|
||||
|
||||
expect(current_path).to eq(ballot_path)
|
||||
expect(page).to have_content("You voted 0 proposals")
|
||||
end
|
||||
|
||||
scenario 'Removing spending proposals from ballot (sidebar)', :js do
|
||||
user = create(:user, :level_two)
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, price: 10000)
|
||||
sp2 = create(:spending_proposal, :feasible, :finished, price: 20000)
|
||||
|
||||
ballot = create(:ballot, user: user, spending_proposals: [sp1, sp2])
|
||||
|
||||
login_as(user)
|
||||
visit spending_proposals_path(geozone: 'all')
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€30,000")
|
||||
expect(page).to have_css("#amount-available", text: "€23,970,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content sp1.title
|
||||
expect(page).to have_content "€10,000"
|
||||
|
||||
expect(page).to have_content sp2.title
|
||||
expect(page).to have_content "€20,000"
|
||||
end
|
||||
|
||||
within("#sidebar #spending_proposal_#{sp1.id}_sidebar") do
|
||||
find(".remove-investment-project").trigger('click')
|
||||
end
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€20,000")
|
||||
expect(page).to have_css("#amount-available", text: "€23,980,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to_not have_content sp1.title
|
||||
expect(page).to_not have_content "€10,000"
|
||||
|
||||
expect(page).to have_content sp2.title
|
||||
expect(page).to have_content "€20,000"
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Removing spending proposals from ballot (sidebar)', :js do
|
||||
user = create(:user, :level_two)
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, price: 10000)
|
||||
sp2 = create(:spending_proposal, :feasible, :finished, price: 20000)
|
||||
|
||||
ballot = create(:ballot, user: user, spending_proposals: [sp1, sp2])
|
||||
|
||||
login_as(user)
|
||||
visit spending_proposals_path(geozone: 'all')
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€30,000")
|
||||
expect(page).to have_css("#amount-available", text: "€23,970,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content sp1.title
|
||||
expect(page).to have_content "€10,000"
|
||||
|
||||
expect(page).to have_content sp2.title
|
||||
expect(page).to have_content "€20,000"
|
||||
end
|
||||
|
||||
within("#sidebar #spending_proposal_#{sp1.id}_sidebar") do
|
||||
find(".remove-investment-project").trigger('click')
|
||||
end
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€20,000")
|
||||
expect(page).to have_css("#amount-available", text: "€23,980,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to_not have_content sp1.title
|
||||
expect(page).to_not have_content "€10,000"
|
||||
|
||||
expect(page).to have_content sp2.title
|
||||
expect(page).to have_content "€20,000"
|
||||
end
|
||||
end
|
||||
|
||||
context 'Permissions' do
|
||||
|
||||
scenario 'User not logged in', :js do
|
||||
spending_proposal = create(:spending_proposal, :feasible, :finished)
|
||||
|
||||
visit spending_proposals_path
|
||||
|
||||
within("#spending_proposal_#{spending_proposal.id}") do
|
||||
find("div.ballot").hover
|
||||
expect_message_you_need_to_sign_in
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'User not verified', :js do
|
||||
user = create(:user)
|
||||
spending_proposal = create(:spending_proposal, :feasible, :finished)
|
||||
|
||||
login_as(user)
|
||||
visit spending_proposals_path
|
||||
|
||||
within("#spending_proposal_#{spending_proposal.id}") do
|
||||
find("div.ballot").hover
|
||||
expect_message_only_verified_can_vote_proposals
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'User is organization', :js do
|
||||
org = create(:organization)
|
||||
spending_proposal = create(:spending_proposal, :feasible, :finished)
|
||||
|
||||
login_as(org.user)
|
||||
visit spending_proposals_path
|
||||
|
||||
within("#spending_proposal_#{spending_proposal.id}") do
|
||||
find("div.ballot").hover
|
||||
expect_message_organizations_cannot_vote
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Spending proposal unfeasible' do
|
||||
user = create(:user, :level_two)
|
||||
spending_proposal = create(:spending_proposal, :finished, feasible: false)
|
||||
|
||||
login_as(user)
|
||||
visit spending_proposals_path(unfeasible: 1)
|
||||
|
||||
within("#spending_proposal_#{spending_proposal.id}") do
|
||||
expect(page).to_not have_css("div.ballot")
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Spending proposal with feasibility undecided are not shown' do
|
||||
user = create(:user, :level_two)
|
||||
spending_proposal = create(:spending_proposal, :finished, feasible: nil)
|
||||
|
||||
login_as(user)
|
||||
visit spending_proposals_path
|
||||
|
||||
within("#investment-projects") do
|
||||
expect(page).to_not have_css("div.ballot")
|
||||
expect(page).to_not have_css("#spending_proposal_#{spending_proposal.id}")
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Different district', :js do
|
||||
user = create(:user, :level_two)
|
||||
california = create(:geozone)
|
||||
new_york = create(:geozone)
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, geozone: california)
|
||||
sp2 = create(:spending_proposal, :feasible, :finished, geozone: new_york)
|
||||
|
||||
create(:ballot, user: user, geozone: california, spending_proposals: [sp1])
|
||||
|
||||
login_as(user)
|
||||
visit spending_proposals_path(geozone: new_york)
|
||||
|
||||
within("#spending_proposal_#{sp2.id}") do
|
||||
find("div.ballot").hover
|
||||
expect_message_already_voted_in_another_geozone(california)
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Insufficient funds', :js do
|
||||
user = create(:user, :level_two)
|
||||
california = create(:geozone)
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, price: 25000000)
|
||||
|
||||
login_as(user)
|
||||
visit spending_proposals_path(geozone: 'all')
|
||||
|
||||
within("#spending_proposal_#{sp1.id}") do
|
||||
find('.add a').trigger('click')
|
||||
expect_message_insufficient_funds
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Displays error message for all proposals (on create)', :js do
|
||||
user = create(:user, :level_two)
|
||||
california = create(:geozone)
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, price: 20000000)
|
||||
sp2 = create(:spending_proposal, :feasible, :finished, price: 5000000)
|
||||
|
||||
login_as(user)
|
||||
visit spending_proposals_path(geozone: 'all')
|
||||
|
||||
within("#spending_proposal_#{sp1.id}") do
|
||||
find('.add a').trigger('click')
|
||||
expect(page).to have_content "Remove vote"
|
||||
end
|
||||
|
||||
within("#spending_proposal_#{sp2.id}") do
|
||||
find("div.ballot").hover
|
||||
expect_message_insufficient_funds
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
scenario 'Displays error message for all proposals (on destroy)', :js do
|
||||
user = create(:user, :level_two)
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, price: 24000000)
|
||||
sp2 = create(:spending_proposal, :feasible, :finished, price: 5000000)
|
||||
|
||||
create(:ballot, user: user, spending_proposals: [sp1])
|
||||
|
||||
login_as(user)
|
||||
visit spending_proposals_path(geozone: 'all')
|
||||
|
||||
within("#spending_proposal_#{sp2.id}") do
|
||||
find("div.ballot").hover
|
||||
expect(page).to have_content "This proposal's price is more than the available amount left"
|
||||
expect(page).to have_selector('.in-favor a', visible: false)
|
||||
end
|
||||
|
||||
within("#spending_proposal_#{sp1.id}") do
|
||||
find('.remove a').trigger('click')
|
||||
end
|
||||
|
||||
within("#spending_proposal_#{sp2.id}") do
|
||||
find("div.ballot").hover
|
||||
expect(page).to_not have_content "This proposal's price is more than the available amount left"
|
||||
expect(page).to have_selector('.in-favor a', visible: true)
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Displays error message for all proposals (on destroy from sidebar)', :js do
|
||||
user = create(:user, :level_two)
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, price: 24000000)
|
||||
sp2 = create(:spending_proposal, :feasible, :finished, price: 5000000)
|
||||
|
||||
create(:ballot, user: user, spending_proposals: [sp1])
|
||||
|
||||
login_as(user)
|
||||
visit spending_proposals_path(geozone: 'all')
|
||||
|
||||
within("#spending_proposal_#{sp2.id}") do
|
||||
find("div.ballot").hover
|
||||
expect(page).to have_content "This proposal's price is more than the available amount left"
|
||||
expect(page).to have_selector('.in-favor a', visible: false)
|
||||
end
|
||||
|
||||
within("#spending_proposal_#{sp1.id}_sidebar") do
|
||||
find('.remove-investment-project').trigger('click')
|
||||
end
|
||||
|
||||
expect(page).to_not have_css "#spending_proposal_#{sp1.id}_sidebar"
|
||||
|
||||
within("#spending_proposal_#{sp2.id}") do
|
||||
find("div.ballot").hover
|
||||
expect(page).to_not have_content "This proposal's price is more than the available amount left"
|
||||
expect(page).to have_selector('.in-favor a', visible: true)
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Display hover for ajax generated content", :js do
|
||||
user = create(:user, :level_two)
|
||||
california = create(:geozone)
|
||||
|
||||
sp1 = create(:spending_proposal, :feasible, :finished, price: 20000000)
|
||||
sp2 = create(:spending_proposal, :feasible, :finished, price: 5000000)
|
||||
|
||||
login_as(user)
|
||||
visit spending_proposals_path(geozone: 'all')
|
||||
|
||||
within("#spending_proposal_#{sp1.id}") do
|
||||
find('.add a').trigger('click')
|
||||
expect(page).to have_content "Remove vote"
|
||||
end
|
||||
|
||||
within("#spending_proposal_#{sp2.id}") do
|
||||
find("div.ballot").trigger(:mouseover)
|
||||
expect_message_insufficient_funds
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Voting proposals when delegating", :js do
|
||||
forum = create(:forum, name: 'hydra')
|
||||
user = create(:user, :level_two, representative_id: forum.id)
|
||||
sp = create(:spending_proposal, :feasible, :finished)
|
||||
|
||||
login_as(user)
|
||||
visit forums_path
|
||||
expect(page).to have_content("You are delegating your votes on hydra")
|
||||
|
||||
visit spending_proposals_path(geozone: 'all')
|
||||
|
||||
within("#spending_proposal_#{sp.id}") do
|
||||
find('.add a').trigger('click')
|
||||
expect(page).to have_content "Remove vote"
|
||||
end
|
||||
|
||||
visit forums_path
|
||||
expect(page).to_not have_content("You are delegating your votes on hydra")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "voting with GET" do
|
||||
let!(:user) { create(:user, :level_two) }
|
||||
let!(:sp_city) { create(:spending_proposal, :feasible, :finished, price: 10000) }
|
||||
let!(:sp_district) { create(:spending_proposal, :feasible, :finished, price: 10000, geozone: create(:geozone, name: "Barajas")) }
|
||||
|
||||
context "When logged in" do
|
||||
background { login_as(user) }
|
||||
|
||||
scenario "Vote a City proposal", :js do
|
||||
visit create_ballot_line_path(spending_proposal_id: sp_city.id)
|
||||
expect(page).to have_content("You have voted this proposal")
|
||||
expect(page).to have_link "Remove vote"
|
||||
end
|
||||
|
||||
scenario "Vote a District proposal", :js do
|
||||
visit create_ballot_line_path(spending_proposal_id: sp_district.id)
|
||||
expect(page).to have_content("You have voted this proposal")
|
||||
expect(page).to have_link "Remove vote"
|
||||
end
|
||||
end
|
||||
|
||||
context "When not logged in" do
|
||||
scenario "Vote a City proposal", :js do
|
||||
visit create_ballot_line_path(spending_proposal_id: sp_city.id)
|
||||
|
||||
expect(page).to have_content "You must sign in or register to continue"
|
||||
fill_in 'user_email', with: user.email
|
||||
fill_in 'user_password', with: user.password
|
||||
click_button 'Enter'
|
||||
|
||||
expect(page).to have_content("You have voted this proposal")
|
||||
expect(page).to have_link "Remove vote"
|
||||
end
|
||||
|
||||
scenario "Vote a District proposal", :js do
|
||||
visit create_ballot_line_path(spending_proposal_id: sp_district.id)
|
||||
|
||||
expect(page).to have_content "You must sign in or register to continue"
|
||||
fill_in 'user_email', with: user.email
|
||||
fill_in 'user_password', with: user.password
|
||||
click_button 'Enter'
|
||||
|
||||
expect(page).to have_content("You have voted this proposal")
|
||||
expect(page).to have_link "Remove vote"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature "Ballots in the wrong phase" do
|
||||
|
||||
background { login_as(create(:user, :level_two)) }
|
||||
let(:sp) { create(:spending_proposal, :feasible, :finished, price: 10000) }
|
||||
|
||||
scenario "When not on phase 3" do
|
||||
Setting['feature.spending_proposal_features.phase3'] = nil
|
||||
visit create_ballot_line_path(spending_proposal_id: sp.id)
|
||||
expect(page.status_code).to eq(403)
|
||||
end
|
||||
|
||||
scenario "When in phase 3 but voting disabled" do
|
||||
Setting['feature.spending_proposal_features.phase3'] = true
|
||||
Setting['feature.spending_proposal_features.final_voting_allowed'] = nil
|
||||
expect{visit create_ballot_line_path(spending_proposal_id: sp.id)}.to raise_error(ActionController::RoutingError)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user