77
app/controllers/budgets/ballot/lines_controller.rb
Normal file
77
app/controllers/budgets/ballot/lines_controller.rb
Normal file
@@ -0,0 +1,77 @@
|
||||
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 @ballot.add_investment(@investment)
|
||||
#@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
|
||||
@investment = @line.investment
|
||||
load_heading
|
||||
|
||||
@line.destroy
|
||||
load_investments
|
||||
#@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
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
18
app/controllers/budgets/ballots_controller.rb
Normal file
18
app/controllers/budgets/ballots_controller.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
module Budgets
|
||||
class BallotsController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
load_and_authorize_resource :budget
|
||||
before_action :load_ballot
|
||||
|
||||
def show
|
||||
render template: "budgets/ballot/show"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_ballot
|
||||
@ballot = Budget::Ballot.where(user: current_user, budget: @budget).first_or_create
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
10
app/controllers/budgets/groups_controller.rb
Normal file
10
app/controllers/budgets/groups_controller.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
module Budgets
|
||||
class GroupsController < ApplicationController
|
||||
load_and_authorize_resource :budget
|
||||
load_and_authorize_resource :group, class: "Budget::Group"
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -99,7 +99,7 @@ module Budgets
|
||||
end
|
||||
|
||||
def load_heading
|
||||
@heading = @budget.headings.find(params[:heading_id]) if params[:geozone_id].present?
|
||||
@heading = @budget.headings.find(params[:heading_id]) if params[:heading_id].present?
|
||||
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,17 @@ module BudgetHelper
|
||||
budget_investment_path(investment, options)
|
||||
end
|
||||
end
|
||||
|
||||
def display_budget_countdown?(budget)
|
||||
budget.balloting?
|
||||
end
|
||||
|
||||
def css_for_ballot_heading(heading)
|
||||
return '' unless current_ballot.present?
|
||||
current_ballot.has_lines_in_heading?(heading) ? 'active' : ''
|
||||
end
|
||||
|
||||
def current_ballot
|
||||
Budget::Ballot.where(user: current_user, budget: @budget).first
|
||||
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,13 +6,14 @@ 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
|
||||
can :read, User
|
||||
can [:search, :read], Annotation
|
||||
can [:read], Budget
|
||||
can [:read], Budget::Group
|
||||
can [:read], Budget::Investment
|
||||
can :new, DirectMessage
|
||||
end
|
||||
|
||||
@@ -5,6 +5,8 @@ class Budget
|
||||
|
||||
has_many :lines, dependent: :destroy
|
||||
has_many :investments, through: :lines
|
||||
has_many :groups, -> { uniq }, through: :lines
|
||||
has_many :headings, -> { uniq }, through: :groups
|
||||
|
||||
def add_investment(investment)
|
||||
lines.create!(budget: budget, investment: investment, heading: investment.heading, group_id: investment.heading.group_id)
|
||||
@@ -22,6 +24,10 @@ class Budget
|
||||
budget.heading_price(heading) - amount_spent(heading.id)
|
||||
end
|
||||
|
||||
def has_lines_in_group?(group)
|
||||
self.groups.include?(group)
|
||||
end
|
||||
|
||||
def valid_heading?(heading)
|
||||
group = heading.group
|
||||
return false if group.budget_id != budget_id
|
||||
@@ -40,8 +46,17 @@ class Budget
|
||||
self.heading_id.present?
|
||||
end
|
||||
|
||||
def has_lines_in_heading?(heading)
|
||||
investments.by_heading(heading.id).any?
|
||||
end
|
||||
|
||||
def has_investment?(investment)
|
||||
self.investment_ids.include?(investment.id)
|
||||
end
|
||||
|
||||
def heading_for_group(group)
|
||||
self.headings.where(group: group).first
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,15 +13,15 @@ class Budget
|
||||
#needed? validates :ballot_id, :budget_id, :group_id, :heading_id, :investment_id, presence: true
|
||||
|
||||
def insufficient_funds
|
||||
errors.add(:money, "") if ballot.amount_available(investment.heading) < investment.price.to_i
|
||||
errors.add(:money, "insufficient funds") if ballot.amount_available(investment.heading) < investment.price.to_i
|
||||
end
|
||||
|
||||
def different_geozone
|
||||
errors.add(:heading, "") if (ballot.heading.present? && investment.heading != ballot.heading)
|
||||
errors.add(:heading, "different heading assigned") if (ballot.heading.present? && investment.heading != ballot.heading)
|
||||
end
|
||||
|
||||
def unfeasible
|
||||
errors.add(:unfeasible, "") unless investment.feasible?
|
||||
errors.add(:unfeasible, "unfeasible investment") unless investment.feasible?
|
||||
end
|
||||
|
||||
def heading_proposal?
|
||||
|
||||
@@ -45,6 +45,7 @@ class Budget
|
||||
scope :undecided, -> { where(feasibility: "undecided") }
|
||||
scope :with_supports, -> { where('cached_votes_up > 0') }
|
||||
|
||||
scope :by_group, -> (group_id) { where(group_id: group_id) }
|
||||
scope :by_heading, -> (heading_id) { where(heading_id: heading_id) }
|
||||
scope :by_admin, -> (admin_id) { where(administrator_id: admin_id) }
|
||||
scope :by_tag, -> (tag_name) { tagged_with(tag_name) }
|
||||
|
||||
55
app/views/budgets/ballot/_ballot.html.erb
Normal file
55
app/views/budgets/ballot/_ballot.html.erb
Normal file
@@ -0,0 +1,55 @@
|
||||
<div class="row ballot">
|
||||
|
||||
<%= render 'shared/back_link' %>
|
||||
|
||||
<h1 class="text-center"><%= t("budgets.ballots.show.title") %></h1>
|
||||
|
||||
<div class="small-12 medium-8 column small-centered text-center">
|
||||
<h2>
|
||||
<%= t("budgets.ballots.show.voted_html",
|
||||
count: @ballot.investments.count) %>
|
||||
</h2>
|
||||
<p>
|
||||
<small>
|
||||
<%= t("budgets.ballots.show.voted_info_html") %>
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<div class="margin-top">
|
||||
<% @ballot.groups.each do |group| %>
|
||||
<div id="<%= dom_id(group) %>"
|
||||
class="small-12 medium-6 column">
|
||||
<h3 class="subtitle">
|
||||
<%= group.name %> - <%= group.headings.first.name %>
|
||||
</h3>
|
||||
<% if @ballot.has_lines_in_group?(group) %>
|
||||
<h4 class="amount-spent text-right">
|
||||
<%= t("budgets.ballots.show.amount_spent") %>
|
||||
<span>
|
||||
<%= format_price(@budget, @ballot.amount_spent(@ballot.heading_for_group(group).id)) %>
|
||||
</span>
|
||||
</h4>
|
||||
<% else %>
|
||||
<p>
|
||||
<%= t("budgets.ballots.show.zero") %><br>
|
||||
<%= link_to t("budgets.ballots.show.heading_link"),
|
||||
budget_investments_path(budget, heading_id: heading.id),
|
||||
data: { no_turbolink: true } %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<ul class="ballot-list">
|
||||
<%= render partial: 'budgets/ballot/investment',
|
||||
collection: @ballot.investments.by_group(group.id) %>
|
||||
</ul>
|
||||
|
||||
<h4>
|
||||
<%= t("budgets.ballots.show.remaining",
|
||||
amount_city: format_price(@budget, @ballot.amount_available(@ballot.heading_for_group(group)))).html_safe %>
|
||||
</h4>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,9 +1,9 @@
|
||||
<li id="<%= dom_id(investment) %>">
|
||||
<%= link_to investment.title, investment %>
|
||||
<span><%= format_price(investment.price) %></span>
|
||||
<%= link_to investment.title, budget_investment_path(@budget, investment) %>
|
||||
<span><%= format_price(@budget, investment.price) %></span>
|
||||
|
||||
<% if @budget.balloting? %>
|
||||
<%= link_to ballot_line_path(id: investment.id),
|
||||
<%= link_to budget_ballot_line_path(@budget, id: investment.id),
|
||||
title: t('budgets.ballots.show.remove'),
|
||||
class: "remove-investment-project",
|
||||
method: :delete,
|
||||
@@ -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 @investments.present? %>
|
||||
<% @investments.each do |investment| %>
|
||||
$("#<%= dom_id(investment) %>_ballot").html('<%= j render("budgets/investments/ballot", investment: investment) %>');
|
||||
<% 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("budgets/ballot/progress_bar", ballot: @ballot) %>');
|
||||
$("#sidebar").html('<%= j render("budgets/investments/sidebar") %>');
|
||||
$("#ballot").html('<%= j render("budgets/ballot/ballot") %>')
|
||||
$("#<%= dom_id(@investment) %>_ballot").html('<%= j render("budgets/investments/ballot", investment: @investment) %>');
|
||||
|
||||
<%= 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();
|
||||
3
app/views/budgets/ballot/show.html.erb
Normal file
3
app/views/budgets/ballot/show.html.erb
Normal file
@@ -0,0 +1,3 @@
|
||||
<div id="ballot">
|
||||
<%= render "budgets/ballot/ballot" %>
|
||||
</div>
|
||||
@@ -1,94 +0,0 @@
|
||||
<div class="row ballot">
|
||||
|
||||
<%= render 'shared/back_link' %>
|
||||
|
||||
<h1 class="text-center"><%= t("budgets.ballots.show.title") %></h1>
|
||||
|
||||
<div class="small-12 medium-8 column small-centered text-center">
|
||||
<h2>
|
||||
<%= t("budgets.ballots.show.voted_html",
|
||||
count: @ballot.investments.count) %>
|
||||
</h2>
|
||||
|
||||
<% if @ballot.geozone.present? && district_wide_amount_spent(@ballot) > 0 %>
|
||||
<%= social_share_button_tag("#{t('budgets.ballots.show.social_share',
|
||||
amount: format_price(district_wide_amount_spent(@ballot)),
|
||||
geozone: @ballot.geozone.name)} #{setting['twitter_hashtag']}",
|
||||
url: participatory_budget_url) %>
|
||||
<% end %>
|
||||
|
||||
<h3>
|
||||
<%= t("budgets.ballots.show.remaining_city_html",
|
||||
amount_city: format_price(@ballot.amount_available(nil))) %>
|
||||
</h3>
|
||||
|
||||
<% if @ballot.geozone.present? %>
|
||||
<h3>
|
||||
<%= t("budgets.ballots.show.remaining_district_html",
|
||||
amount_district: format_price(@ballot.amount_available(@ballot.geozone)),
|
||||
geozone: @ballot.geozone.name) %>
|
||||
</h3>
|
||||
<% end %>
|
||||
|
||||
<p>
|
||||
<small>
|
||||
<%= t("budgets.ballots.show.voted_info_html") %>
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="margin-top">
|
||||
<div id="city_wide" class="small-12 medium-6 column">
|
||||
<h3 class="subtitle">
|
||||
<%= t("budgets.ballots.show.city_wide") %>
|
||||
</h3>
|
||||
<% if @ballot.investments.by_geozone(nil).count > 0 %>
|
||||
<h4 class="amount-spent text-right">
|
||||
<%= t("budgets.ballots.show.amount_spent") %>
|
||||
<span><%= format_price(city_wide_amount_spent(@ballot)) %></span>
|
||||
</h4>
|
||||
<% else %>
|
||||
<p>
|
||||
<%= t("budgets.ballots.show.zero") %><br>
|
||||
<%= link_to t("budgets.ballots.show.city_link"),
|
||||
investments_path(geozone: 'all'),
|
||||
data: { no_turbolink: true } %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<ul class="ballot-list">
|
||||
<%= render partial: 'budgets/ballots/investment',
|
||||
collection: @ballot.investments.no_heading %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="district_wide" class="small-12 medium-6 column">
|
||||
<h3 class="subtitle">
|
||||
<%= t("budgets.ballots.show.district_wide") %>
|
||||
<span>
|
||||
<% if @ballot.geozone.present? %>
|
||||
(<%= @ballot.geozone.name %>)
|
||||
<% end %>
|
||||
</span>
|
||||
</h3>
|
||||
<% if @ballot.geozone.present? %>
|
||||
<h4 class="amount-spent text-right">
|
||||
<%= t("budgets.ballots.show.amount_spent") %>
|
||||
<span><%= format_price(district_wide_amount_spent(@ballot)) %></span>
|
||||
</h4>
|
||||
<% else %>
|
||||
<p>
|
||||
<%= t("budgets.ballots.show.zero") %><br>
|
||||
<%= link_to t("budgets.ballots.show.districts_link"), select_district_path %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<ul class="ballot-list">
|
||||
<%= render partial: 'budgets/ballots/investment',
|
||||
collection: @ballot.investments.with_heading %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,3 +0,0 @@
|
||||
<div id="ballot">
|
||||
<%= render partial: "ballots/ballot" %>
|
||||
</div>
|
||||
29
app/views/budgets/groups/show.html.erb
Normal file
29
app/views/budgets/groups/show.html.erb
Normal file
@@ -0,0 +1,29 @@
|
||||
<div class="row investment-projects-scope margin-bottom no-margin-top">
|
||||
<div id="select-district" class="small-12 medium-7 column select-district">
|
||||
<%= link_to budget_path(@budget), class: "back" do %>
|
||||
<span class="icon-angle-left"></span>
|
||||
<%= t('shared.back') %>
|
||||
<% end %>
|
||||
|
||||
<h2><%# t("spending_proposals.welcome.districts") %></h2>
|
||||
|
||||
<div class="row">
|
||||
<% @group.headings.each_slice(7) do |slice| %>
|
||||
<div class="small-6 medium-4 column end">
|
||||
<% slice.each do |heading| %>
|
||||
<span id="<%= dom_id(heading) %>"
|
||||
class="<%= css_for_ballot_heading(heading) %>">
|
||||
<%= link_to heading.name,
|
||||
budget_investments_path(heading_id: heading.id),
|
||||
data: { no_turbolink: true } %><br>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="medium-5 column show-for-medium text-center margin-top">
|
||||
<%= image_tag "map.jpg" %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -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>
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
<%= link_to @budget, class: "back" do %>
|
||||
<%= link_to budget_group_path(@budget, @heading.group), class: "back" do %>
|
||||
<i class="icon-angle-left"></i>
|
||||
<%= t("shared.back") %>
|
||||
<% 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,10 +23,15 @@
|
||||
<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 %>
|
||||
<% if false
|
||||
#@heading.present? &&
|
||||
#@ballot.heading.present? &&
|
||||
#@ballot.heading != @heading
|
||||
%>
|
||||
<br>
|
||||
<p class="callout warning inline-block">
|
||||
<%= t("budget.investments.header.different_heading_active") %>
|
||||
@@ -32,7 +39,7 @@
|
||||
</p>
|
||||
<% else %>
|
||||
<div id="progress_bar" class="no-margin-top">
|
||||
<%= render 'progress_bar' %>
|
||||
<%= render 'budgets/ballot/progress_bar' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -43,18 +43,23 @@
|
||||
</div>
|
||||
|
||||
<% unless investment.unfeasible? %>
|
||||
<% if feature?("investment_features.phase2") %>
|
||||
|
||||
<% if @budget.selecting? || @budget.on_hold? %>
|
||||
|
||||
<div id="<%= dom_id(investment) %>_votes"
|
||||
class="small-12 medium-3 column text-center">
|
||||
<%= render 'votes',
|
||||
{ investment: investment, vote_url: vote_investment_path(investment, value: 'yes') } %>
|
||||
{ investment: investment,
|
||||
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 %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<div class="supported">
|
||||
<%= t("budget.investments.investment.already_supported") %>
|
||||
</div>
|
||||
<% elsif voting_allowed %>
|
||||
<% elsif @budget.selecting? %>
|
||||
|
||||
<%= link_to vote_url,
|
||||
class: "button button-support small expanded",
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
|
||||
<main id="budget-investments-main">
|
||||
|
||||
<%= render 'header' %>
|
||||
<% unless params[:search].present? %>
|
||||
<%= render 'header' %>
|
||||
<% end %>
|
||||
|
||||
<div class="wrap row">
|
||||
<div id="budget-investments" class="budget-investments-list small-12 medium-9 column">
|
||||
|
||||
@@ -45,15 +45,19 @@
|
||||
</div>
|
||||
|
||||
<% if (@budget.selecting? && !@investment.unfeasible?) ||
|
||||
(@budget.balloting? && @investment.feasible?) %>
|
||||
(@budget.balloting? && @investment.feasible? ||
|
||||
(@budget.on_hold?)) %>
|
||||
<aside class="small-12 medium-3 column">
|
||||
<div class="sidebar-divider"></div>
|
||||
<h3><%= t("votes.supports") %></h3>
|
||||
<div class="text-center">
|
||||
<% if @budget.selecting? %>
|
||||
|
||||
<% if @budget.selecting? || @budget.on_hold? %>
|
||||
<div id="<%= dom_id(@investment) %>_votes">
|
||||
<%= render 'votes',
|
||||
{ investment: @investment, vote_url: vote_budget_investment_path(budget_id: @budget.id, id: @investment.id) } %>
|
||||
{ investment: @investment,
|
||||
vote_url: vote_budget_investment_path(@budget, @investment, value: 'yes') }
|
||||
%>
|
||||
</div>
|
||||
<% else %>
|
||||
<div id="<%= dom_id(@investment) %>_ballot">
|
||||
|
||||
1
app/views/budgets/investments/vote.js.erb
Normal file
1
app/views/budgets/investments/vote.js.erb
Normal file
@@ -0,0 +1 @@
|
||||
$("#<%= dom_id(@investment) %>_votes").html('<%= j render("budgets/investments/votes", investment: @investment, vote_url: vote_budget_investment_path(@budget, @investment, value: "yes")) %>');
|
||||
@@ -16,29 +16,24 @@
|
||||
<div class="small-12 medium-6 column">
|
||||
<table class="table-fixed">
|
||||
<thead>
|
||||
<th><%= t('budget.show.heading') %></th>
|
||||
<th><%= t('budget.show.price') %></th>
|
||||
<th><%= t('budget.show.group') %></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<%= link_to t('budget.show.no_heading'), budget_investments_path(budget_id: @budget.id, heading_id: nil) %>
|
||||
</td>
|
||||
<td>
|
||||
<%# format_price(@budget, @budget.price) %>
|
||||
</td>
|
||||
</tr>
|
||||
<% @budget.headings.each do |heading| %>
|
||||
<% @budget.groups.each do |group| %>
|
||||
<tr>
|
||||
<td>
|
||||
<%= link_to heading.name, budget_investments_path(budget_id: @budget.id, heading_id: heading.id) %>
|
||||
</td>
|
||||
<td>
|
||||
<%= format_price(@budget, heading.price) %>
|
||||
<% if group.headings.count == 1 %>
|
||||
<%= link_to group.name,
|
||||
budget_investments_path(@budget, heading_id: group.headings.first.id),
|
||||
data: { no_turbolink: true } %>
|
||||
<% else %>
|
||||
<%= link_to group.name, budget_group_path(@budget, group) %>
|
||||
<% end %>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2,15 +2,15 @@ en:
|
||||
budgets:
|
||||
ballots:
|
||||
show:
|
||||
amount_spent: "pending translation"
|
||||
city_wide: "pending translation"
|
||||
districts_link: "pending translation"
|
||||
remaining_district_html: "pending translation"
|
||||
social_share: "pending translation"
|
||||
title: "pending translation"
|
||||
voted_html: "pending translation"
|
||||
voted_info_html: "pending translation"
|
||||
zero: "pending translation"
|
||||
title: Your ballot
|
||||
amount_spent: Amount spent
|
||||
remaining: "You still have <span>%{amount_city}</span> to invest."
|
||||
remove: Remove vote
|
||||
voted_html:
|
||||
one: "You have voted <span>one</span> proposal."
|
||||
other: "You have voted <span>%{count}</span> proposals."
|
||||
voted_info_html: "You can change your vote at any time until the close of this phase.<br> No need to invest all the money available."
|
||||
zero: You have not voted any investment project.
|
||||
budget:
|
||||
phase:
|
||||
on_hold: On hold
|
||||
@@ -18,6 +18,9 @@ en:
|
||||
selecting: Selecting
|
||||
balloting: Balloting
|
||||
finished: Finished
|
||||
groups:
|
||||
index:
|
||||
group_title: "Groups"
|
||||
headings:
|
||||
none: Whole City
|
||||
all: All scopes
|
||||
@@ -101,6 +104,7 @@ en:
|
||||
check_ballot: Check my ballot
|
||||
different_heading_active: You have active votes in another district.
|
||||
show:
|
||||
group: Group
|
||||
heading: Heading
|
||||
price: Price
|
||||
no_heading: No Heading
|
||||
@@ -2,15 +2,15 @@ es:
|
||||
budgets:
|
||||
ballots:
|
||||
show:
|
||||
amount_spent: "pending translation"
|
||||
city_wide: "pending translation"
|
||||
districts_link: "pending translation"
|
||||
remaining_district_html: "pending translation"
|
||||
social_share: "pending translation"
|
||||
title: "pending translation"
|
||||
voted_html: "pending translation"
|
||||
voted_info_html: "pending translation"
|
||||
zero: "pending translation"
|
||||
title: Mis votos
|
||||
amount_spent: Coste total
|
||||
remaining: "Te quedan <span>%{amount_city}</span> para invertir"
|
||||
remove: Quitar voto
|
||||
voted_html:
|
||||
one: "Has votado <span>una</span> propuesta."
|
||||
other: "Has votado <span>%{count}</span> propuestas."
|
||||
voted_info_html: "Puedes cambiar tus votos en cualquier momento hasta el cierre de esta fase.<br> No hace falta que inviertas todo el dinero disponible."
|
||||
zero: "Todavía no has votado ninguna propuesta de inversión."
|
||||
budget:
|
||||
phase:
|
||||
on_hold: En pausa
|
||||
@@ -18,6 +18,9 @@ es:
|
||||
selecting: Fase de selección
|
||||
balloting: Fase de Votación
|
||||
finished: Terminado
|
||||
groups:
|
||||
index:
|
||||
group_title: "Grupos"
|
||||
headings:
|
||||
none: Toda la ciudad
|
||||
all: Todos los ámbitos
|
||||
@@ -101,6 +104,7 @@ es:
|
||||
check_ballot: Revisar mis votos
|
||||
different_heading_active: Ya apoyaste propuestas de otro distrito.
|
||||
show:
|
||||
group: Grupo
|
||||
heading: Partida
|
||||
price: Cantidad
|
||||
no_heading: Sin línea
|
||||
@@ -70,10 +70,11 @@ Rails.application.routes.draw do
|
||||
end
|
||||
|
||||
resources :budgets, only: [:show, :index] do
|
||||
resources :groups, controller: "budgets/groups", only: [:show]
|
||||
resources :investments, controller: "budgets/investments", only: [:index, :new, :create, :show, :destroy] do
|
||||
member { post :vote }
|
||||
end
|
||||
resource :ballot, only: :show do
|
||||
resource :ballot, only: :show, controller: "budgets/ballots" do
|
||||
resources :lines, controller: "budgets/ballot/lines", only: [:create, :destroy]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -298,11 +298,12 @@ end
|
||||
|
||||
puts "Creating Budgets"
|
||||
|
||||
(1..10).each do |i|
|
||||
phases = %w{on_hold accepting selecting balloting finished}
|
||||
phases.each_with_index do |phase, i|
|
||||
budget = Budget.create!(name: (Date.today.year - 10 + i).to_s,
|
||||
description: "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>",
|
||||
currency_symbol: "€",
|
||||
phase: %w{on_hold accepting selecting balloting finished}.sample,
|
||||
phase: phase,
|
||||
valuating: [false, true].sample)
|
||||
puts budget.name
|
||||
|
||||
@@ -313,7 +314,7 @@ puts "Creating Budgets"
|
||||
geozones.each do |geozone|
|
||||
group.headings << group.headings.create!(name: geozone.name,
|
||||
geozone: geozone,
|
||||
price: rand(1 .. 100) * 10000)
|
||||
price: rand(1 .. 100) * 100000)
|
||||
|
||||
end
|
||||
print "#{group.name} "
|
||||
@@ -324,7 +325,7 @@ end
|
||||
|
||||
puts "Creating Investments"
|
||||
tags = Faker::Lorem.words(10)
|
||||
(1..60).each do |i|
|
||||
(1..100).each do |i|
|
||||
heading = Budget::Heading.reorder("RANDOM()").first
|
||||
|
||||
investment = Budget::Investment.create!(
|
||||
@@ -340,7 +341,7 @@ tags = Faker::Lorem.words(10)
|
||||
unfeasibility_explanation: "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>",
|
||||
valuation_finished: [false, true].sample,
|
||||
tag_list: tags.sample(3).join(','),
|
||||
price: rand(1 .. 100) * 1000000,
|
||||
price: rand(1 .. 100) * 100000,
|
||||
terms_of_service: "1")
|
||||
puts " #{investment.title}"
|
||||
end
|
||||
|
||||
661
spec/features/budgets/ballots_spec.rb
Normal file
661
spec/features/budgets/ballots_spec.rb
Normal file
@@ -0,0 +1,661 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Ballots' do
|
||||
|
||||
let(:budget) { create(:budget, phase: "balloting") }
|
||||
let(:group) { create(:budget_group, budget: budget, name: "Group 1") }
|
||||
let(:heading) { create(:budget_heading, group: group, name: "Heading 1", price: 1000000) }
|
||||
|
||||
context "Voting" do
|
||||
let!(:user) { create(:user, :level_two) }
|
||||
|
||||
background do
|
||||
login_as(user)
|
||||
visit budget_path(budget)
|
||||
end
|
||||
|
||||
context "Group and Heading Navigation" do
|
||||
|
||||
scenario "Groups" do
|
||||
city = create(:budget_group, budget: budget, name: "City")
|
||||
districts = create(:budget_group, budget: budget, name: "Districts")
|
||||
|
||||
visit budget_path(budget)
|
||||
|
||||
expect(page).to have_link "City"
|
||||
expect(page).to have_link "Districts"
|
||||
end
|
||||
|
||||
scenario "Headings" do
|
||||
city = create(:budget_group, budget: budget, name: "City")
|
||||
districts = create(:budget_group, budget: budget, name: "Districts")
|
||||
|
||||
city_heading1 = create(:budget_heading, group: city, name: "Investments Type1")
|
||||
city_heading2 = create(:budget_heading, group: city, name: "Investments Type2")
|
||||
district_heading1 = create(:budget_heading, group: districts, name: "District 1")
|
||||
district_heading2 = create(:budget_heading, group: districts, name: "District 2")
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "City"
|
||||
|
||||
expect(page).to have_link "Investments Type1"
|
||||
expect(page).to have_link "Investments Type2"
|
||||
|
||||
click_link "Go back"
|
||||
click_link "Districts"
|
||||
|
||||
expect(page).to have_link "District 1"
|
||||
expect(page).to have_link "District 2"
|
||||
|
||||
end
|
||||
|
||||
scenario "Investments" do
|
||||
city = create(:budget_group, budget: budget, name: "City")
|
||||
districts = create(:budget_group, budget: budget, name: "Districts")
|
||||
|
||||
city_heading1 = create(:budget_heading, group: city, name: "Investments Type1")
|
||||
city_heading2 = create(:budget_heading, group: city, name: "Investments Type2")
|
||||
district_heading1 = create(:budget_heading, group: districts, name: "District 1")
|
||||
district_heading2 = create(:budget_heading, group: districts, name: "District 2")
|
||||
|
||||
city_investment1 = create(:budget_investment, :feasible, :finished, heading: city_heading1)
|
||||
city_investment2 = create(:budget_investment, :feasible, :finished, heading: city_heading1)
|
||||
district1_investment1 = create(:budget_investment, :feasible, :finished, heading: district_heading1)
|
||||
district1_investment2 = create(:budget_investment, :feasible, :finished, heading: district_heading1)
|
||||
district2_investment1 = create(:budget_investment, :feasible, :finished, heading: district_heading2)
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "City"
|
||||
click_link "Investments Type1"
|
||||
|
||||
expect(page).to have_css(".budget-investment", count: 2)
|
||||
expect(page).to have_content city_investment1.title
|
||||
expect(page).to have_content city_investment2.title
|
||||
|
||||
click_link "Go back"
|
||||
click_link "Go back"
|
||||
|
||||
click_link "Districts"
|
||||
click_link "District 1"
|
||||
|
||||
expect(page).to have_css(".budget-investment", count: 2)
|
||||
expect(page).to have_content district1_investment1.title
|
||||
expect(page).to have_content district1_investment2.title
|
||||
|
||||
click_link "Go back"
|
||||
click_link "District 2"
|
||||
|
||||
expect(page).to have_css(".budget-investment", count: 1)
|
||||
expect(page).to have_content district2_investment1.title
|
||||
end
|
||||
|
||||
scenario "Redirect to first heading if there is only one" do
|
||||
city = create(:budget_group, budget: budget, name: "City")
|
||||
districts = create(:budget_group, budget: budget, name: "Districts")
|
||||
|
||||
city_heading = create(:budget_heading, group: city, name: "City")
|
||||
district_heading1 = create(:budget_heading, group: districts, name: "District 1")
|
||||
district_heading2 = create(:budget_heading, group: districts, name: "District 2")
|
||||
|
||||
city_investment = create(:budget_investment, :feasible, :finished, heading: city_heading)
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "City"
|
||||
|
||||
expect(page).to have_content city_investment.title
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "Adding and Removing Investments" do
|
||||
|
||||
scenario "Add a proposal", :js do
|
||||
investment1 = create(:budget_investment, :feasible, :finished, budget: budget, heading: heading, group: group, price: 10000)
|
||||
investment2 = create(:budget_investment, :feasible, :finished, budget: budget, heading: heading, group: group, price: 20000)
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "Group 1"
|
||||
|
||||
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
|
||||
investment1 = create(:budget_investment, :feasible, :finished, budget: budget, heading: heading, group: group, price: 10000)
|
||||
ballot = create(:budget_ballot, user: user, budget: budget, investments: [investment1])
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "Group 1"
|
||||
|
||||
expect(page).to have_content investment1.title
|
||||
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_#{investment1.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: "€1,000,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to_not have_content investment1.title
|
||||
expect(page).to_not have_content "€10,000"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#Break up or simplify with helpers
|
||||
context "Balloting in multiple headings" do
|
||||
|
||||
scenario "Independent progress bar for headings", :js do
|
||||
city = create(:budget_group, budget: budget, name: "City")
|
||||
districts = create(:budget_group, budget: budget, name: "Districts")
|
||||
|
||||
city_heading = create(:budget_heading, group: city, name: "All city", price: 10000000)
|
||||
district_heading1 = create(:budget_heading, group: districts, name: "District 1", price: 1000000)
|
||||
district_heading2 = create(:budget_heading, group: districts, name: "District 2", price: 2000000)
|
||||
|
||||
investment1 = create(:budget_investment, :feasible, :finished, heading: city_heading, price: 10000)
|
||||
investment2 = create(:budget_investment, :feasible, :finished, heading: district_heading1, price: 20000)
|
||||
investment3 = create(:budget_investment, :feasible, :finished, heading: district_heading2, price: 30000)
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "City"
|
||||
|
||||
within("#budget_investment_#{investment1.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: "€9,990,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content investment1.title
|
||||
expect(page).to have_content "€10,000"
|
||||
end
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "Districts"
|
||||
click_link "District 1"
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€0")
|
||||
expect(page).to have_css("#amount-spent", text: "€1,000,000")
|
||||
|
||||
within("#budget_investment_#{investment2.id}") do
|
||||
find('.add a').trigger('click')
|
||||
expect(page).to have_content "Remove"
|
||||
end
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "Districts"
|
||||
click_link "District 1"
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€20,000")
|
||||
expect(page).to have_css("#amount-available", text: "€980,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content investment2.title
|
||||
expect(page).to have_content "€20,000"
|
||||
|
||||
expect(page).to_not have_content investment1.title
|
||||
expect(page).to_not have_content "€10,000"
|
||||
end
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "City"
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€10,000")
|
||||
expect(page).to have_css("#amount-available", text: "€9,990,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to have_content investment1.title
|
||||
expect(page).to have_content "€10,000"
|
||||
|
||||
expect(page).to_not have_content investment2.title
|
||||
expect(page).to_not have_content "€20,000"
|
||||
end
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "Districts"
|
||||
click_link "District 2"
|
||||
|
||||
expect(page).to have_css("#amount-spent", text: "€0")
|
||||
expect(page).to have_css("#amount-spent", text: "€2,000,000")
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Display progress bar after first vote", :js do
|
||||
investment = create(:budget_investment, :feasible, :finished, heading: heading, price: 10000)
|
||||
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
expect(page).to have_content investment.title
|
||||
within("#budget_investment_#{investment.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 "Groups" do
|
||||
let!(:user) { create(:user, :level_two) }
|
||||
let!(:districts_group) { create(:budget_group, budget: budget, name: "Districts") }
|
||||
let!(:california_heading) { create(:budget_heading, group: districts_group, name: "California") }
|
||||
let!(:new_york_heading) { create(:budget_heading, group: districts_group, name: "New York") }
|
||||
let!(:investment) { create(:budget_investment, :feasible, :finished, heading: california_heading) }
|
||||
|
||||
background do
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
scenario 'Select my heading', :js do
|
||||
visit budget_path(budget)
|
||||
click_link "Districts"
|
||||
click_link "California"
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
find('.add a').trigger('click')
|
||||
expect(page).to have_content "Remove"
|
||||
end
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "Districts"
|
||||
|
||||
expect(page).to have_content "California"
|
||||
expect(page).to have_css("#budget_heading_#{california_heading.id}.active")
|
||||
end
|
||||
|
||||
scenario 'Change my heading', :js do
|
||||
investment1 = create(:budget_investment, :feasible, :finished, heading: california_heading)
|
||||
investment2 = create(:budget_investment, :feasible, :finished, heading: new_york_heading)
|
||||
|
||||
create(:budget_ballot, user: user, budget: budget, investments: [investment1])
|
||||
|
||||
visit budget_investments_path(budget, heading_id: california_heading.id)
|
||||
|
||||
within("#budget_investment_#{investment1.id}") do
|
||||
find('.remove a').trigger('click')
|
||||
end
|
||||
|
||||
visit budget_investments_path(budget, heading_id: new_york_heading.id)
|
||||
|
||||
within("#budget_investment_#{investment2.id}") do
|
||||
find('.add a').trigger('click')
|
||||
end
|
||||
|
||||
visit budget_path(budget)
|
||||
click_link "Districts"
|
||||
expect(page).to have_css("#budget_heading_#{new_york_heading.id}.active")
|
||||
expect(page).to_not have_css("#budget_heading_#{california_heading.id}.active")
|
||||
end
|
||||
|
||||
scenario 'View another heading' do
|
||||
investment = create(:budget_investment, :feasible, :finished, heading: california_heading)
|
||||
|
||||
create(:budget_ballot, user: user, budget: budget, investments: [investment])
|
||||
|
||||
visit budget_investments_path(budget, heading_id: new_york_heading.id)
|
||||
|
||||
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_heading.name, href: budget_investments_path(budget, heading: california_heading)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'Showing the ballot' do
|
||||
pending "Do not display heading name if there is only one heading in the group (example: group city)"
|
||||
|
||||
scenario 'Displaying the correct count & amount' do
|
||||
user = create(:user, :level_two)
|
||||
|
||||
group1 = create(:budget_group, budget: budget)
|
||||
group2 = create(:budget_group, budget: budget)
|
||||
|
||||
heading1 = create(:budget_heading, name: "District 1", group: group1, price: 100)
|
||||
heading2 = create(:budget_heading, name: "District 2", group: group2, price: 50)
|
||||
|
||||
ballot = create(:budget_ballot, user: user, budget: budget)
|
||||
|
||||
investment1 = create(:budget_investment, :feasible, price: 10, heading: heading1, group: group1)
|
||||
investment2 = create(:budget_investment, :feasible, price: 10, heading: heading1, group: group1)
|
||||
|
||||
investment3 = create(:budget_investment, :feasible, price: 5, heading: heading2, group: group2)
|
||||
investment4 = create(:budget_investment, :feasible, price: 5, heading: heading2, group: group2)
|
||||
investment5 = create(:budget_investment, :feasible, price: 5, heading: heading2, group: group2)
|
||||
|
||||
create(:budget_ballot_line, ballot: ballot, investment: investment1, group: group1)
|
||||
create(:budget_ballot_line, ballot: ballot, investment: investment2, group: group1)
|
||||
|
||||
create(:budget_ballot_line, ballot: ballot, investment: investment3, group: group2)
|
||||
create(:budget_ballot_line, ballot: ballot, investment: investment4, group: group2)
|
||||
create(:budget_ballot_line, ballot: ballot, investment: investment5, group: group2)
|
||||
|
||||
login_as(user)
|
||||
visit budget_ballot_path(budget)
|
||||
|
||||
expect(page).to have_content("You have voted 5 proposals")
|
||||
|
||||
within("#budget_group_#{group1.id}") do
|
||||
expect(page).to have_content "#{group1.name} - #{heading1.name}"
|
||||
expect(page).to have_content "Amount spent €20"
|
||||
expect(page).to have_content "You still have €80 to invest"
|
||||
end
|
||||
|
||||
within("#budget_group_#{group2.id}") do
|
||||
expect(page).to have_content "#{group2.name} - #{heading2.name}"
|
||||
expect(page).to have_content "Amount spent €15"
|
||||
expect(page).to have_content "You still have €35 to invest"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
scenario 'Removing spending proposals from ballot', :js do
|
||||
user = create(:user, :level_two)
|
||||
ballot = create(:budget_ballot, user: user, budget: budget)
|
||||
investment = create(:budget_investment, :feasible, :finished, price: 10, heading: heading, group: group)
|
||||
create(:budget_ballot_line, ballot: ballot, investment: investment, heading: heading, group: group)
|
||||
|
||||
login_as(user)
|
||||
visit budget_ballot_path(budget)
|
||||
|
||||
expect(page).to have_content("You have voted one proposal")
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
find(".remove-investment-project").trigger('click')
|
||||
end
|
||||
|
||||
expect(current_path).to eq(budget_ballot_path(budget))
|
||||
expect(page).to have_content("You have voted 0 proposals")
|
||||
end
|
||||
|
||||
scenario 'Removing spending proposals from ballot (sidebar)', :js do
|
||||
user = create(:user, :level_two)
|
||||
investment1 = create(:budget_investment, :feasible, :finished, price: 10000, heading: heading)
|
||||
investment2 = create(:budget_investment, :feasible, :finished, price: 20000, heading: heading)
|
||||
|
||||
ballot = create(:budget_ballot, budget: budget, user: user, investments: [investment1, investment2])
|
||||
|
||||
login_as(user)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
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 investment1.title
|
||||
expect(page).to have_content "€10,000"
|
||||
|
||||
expect(page).to have_content investment2.title
|
||||
expect(page).to have_content "€20,000"
|
||||
end
|
||||
|
||||
within("#sidebar #budget_investment_#{investment1.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: "€980,000")
|
||||
|
||||
within("#sidebar") do
|
||||
expect(page).to_not have_content investment1.title
|
||||
expect(page).to_not have_content "€10,000"
|
||||
|
||||
expect(page).to have_content investment2.title
|
||||
expect(page).to have_content "€20,000"
|
||||
end
|
||||
end
|
||||
|
||||
context 'Permissions' do
|
||||
|
||||
scenario 'User not logged in', :js do
|
||||
investment = create(:budget_investment, :feasible, :finished, heading: heading)
|
||||
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
find("div.ballot").hover
|
||||
expect_message_you_need_to_sign_in_to_ballot
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'User not verified', :js do
|
||||
user = create(:user)
|
||||
investment = create(:budget_investment, :feasible, :finished, heading: heading)
|
||||
|
||||
login_as(user)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
find("div.ballot").hover
|
||||
expect_message_only_verified_can_vote_investments
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'User is organization', :js do
|
||||
org = create(:organization)
|
||||
investment = create(:budget_investment, :feasible, :finished, heading: heading)
|
||||
|
||||
login_as(org.user)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
find("div.ballot").hover
|
||||
expect_message_organizations_cannot_vote
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Unfeasible investments' do
|
||||
user = create(:user, :level_two)
|
||||
investment = create(:budget_investment, :finished, :unfeasible, heading: heading)
|
||||
|
||||
login_as(user)
|
||||
visit budget_investments_path(budget, heading_id: heading.id, unfeasible: 1)
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
expect(page).to_not have_css("div.ballot")
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Investments with feasibility undecided are not shown' do
|
||||
user = create(:user, :level_two)
|
||||
investment = create(:budget_investment, :finished, feasibility: "undecided", heading: heading)
|
||||
|
||||
login_as(user)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
within("#budget-investments") do
|
||||
expect(page).to_not have_css("div.ballot")
|
||||
expect(page).to_not have_css("#budget_investment_#{investment.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
|
||||
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
|
||||
|
||||
@@ -10,12 +10,11 @@ feature 'Budgets' do
|
||||
|
||||
scenario 'Show' do
|
||||
budget = create(:budget)
|
||||
group = create(:budget_group, budget: budget)
|
||||
heading = create(:budget_heading, group: group)
|
||||
group1 = create(:budget_group, budget: budget)
|
||||
group2 = create(:budget_group, budget: budget)
|
||||
|
||||
visit budget_path(budget)
|
||||
|
||||
expect(page).to have_content(budget.name)
|
||||
expect(page).to have_content(heading.name)
|
||||
budget.groups.each {|group| expect(page).to have_link(group.name)}
|
||||
end
|
||||
end
|
||||
@@ -11,7 +11,7 @@ feature 'Budget Investments' do
|
||||
investments = [create(:budget_investment, budget: budget, group: group, heading: heading), create(:budget_investment, budget: budget, group: group, heading: heading), create(:budget_investment, :feasible, budget: budget, group: group, heading: heading)]
|
||||
unfeasible_investment = create(:budget_investment, :unfeasible, budget: budget, group: group, heading: heading)
|
||||
|
||||
visit budget_investments_path(budget_id: budget.id)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
expect(page).to have_selector('#budget-investments .budget-investment', count: 3)
|
||||
investments.each do |investment|
|
||||
@@ -29,7 +29,7 @@ feature 'Budget Investments' do
|
||||
investment2 = create(:budget_investment, budget: budget, group: group, heading: heading, title: "Schwifty Hello")
|
||||
investment3 = create(:budget_investment, budget: budget, group: group, heading: heading, title: "Do not show me")
|
||||
|
||||
visit budget_investments_path(budget_id: budget.id)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
within(".expanded #search_form") do
|
||||
fill_in "search", with: "Schwifty"
|
||||
@@ -53,7 +53,7 @@ feature 'Budget Investments' do
|
||||
investment3 = create(:budget_investment, budget: budget, group: group, heading: heading)
|
||||
investment4 = create(:budget_investment, :feasible, budget: budget, group: group, heading: heading)
|
||||
|
||||
visit budget_investments_path(budget_id: budget.id, unfeasible: 1)
|
||||
visit budget_investments_path(budget_id: budget.id, heading_id: heading.id, unfeasible: 1)
|
||||
|
||||
within("#budget-investments") do
|
||||
expect(page).to have_css('.budget-investment', count: 1)
|
||||
@@ -72,10 +72,10 @@ feature 'Budget Investments' do
|
||||
per_page = Kaminari.config.default_per_page
|
||||
(per_page + 2).times { create(:budget_investment) }
|
||||
|
||||
visit budget_investments_path(budget_id: budget.id)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
order = all(".budget-investment h3").collect {|i| i.text }
|
||||
|
||||
visit budget_investments_path(budget_id: budget.id)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
new_order = eq(all(".budget-investment h3").collect {|i| i.text })
|
||||
|
||||
expect(order).to_not eq(new_order)
|
||||
@@ -85,13 +85,13 @@ feature 'Budget Investments' do
|
||||
per_page = Kaminari.config.default_per_page
|
||||
(per_page + 2).times { create(:budget_investment) }
|
||||
|
||||
visit budget_investments_path(budget_id: budget.id)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
click_link "highest rated"
|
||||
click_link "random"
|
||||
|
||||
order = all(".budget-investment h3").collect {|i| i.text }
|
||||
|
||||
visit budget_investments_path(budget_id: budget.id)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
new_order = eq(all(".budget-investment h3").collect {|i| i.text })
|
||||
|
||||
expect(order).to_not eq(new_order)
|
||||
@@ -101,7 +101,7 @@ feature 'Budget Investments' do
|
||||
per_page = Kaminari.config.default_per_page
|
||||
(per_page + 2).times { create(:budget_investment, budget: budget, group: group, heading: heading) }
|
||||
|
||||
visit budget_investments_path(budget_id: budget.id)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
order = all(".budget-investment h3").collect {|i| i.text }
|
||||
|
||||
@@ -120,7 +120,7 @@ feature 'Budget Investments' do
|
||||
create(:budget_investment, budget: budget, group: group, heading: heading, title: 'Worst proposal').update_column(:confidence_score, 2)
|
||||
create(:budget_investment, budget: budget, group: group, heading: heading, title: 'Medium proposal').update_column(:confidence_score, 5)
|
||||
|
||||
visit budget_investments_path(budget_id: budget.id)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
click_link 'highest rated'
|
||||
expect(page).to have_selector('a.active', text: 'highest rated')
|
||||
|
||||
@@ -274,23 +274,6 @@ feature 'Budget Investments' do
|
||||
|
||||
end
|
||||
|
||||
context "Badge" do
|
||||
|
||||
scenario "Spending proposal created by a User" do
|
||||
user = create(:user)
|
||||
user_investment = create(:budget_investment, budget: budget, group: group, heading: heading)
|
||||
|
||||
visit budget_investment_path(budget_id: budget.id, id: user_investment.id)
|
||||
expect(page).to_not have_css "is-forum"
|
||||
|
||||
visit budget_investments_path(budget_id: budget.id, id: user_investment.id)
|
||||
within "#budget_investment_#{user_investment.id}" do
|
||||
expect(page).to_not have_css "is-forum"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "Phase 3 - Final Voting" do
|
||||
|
||||
background do
|
||||
@@ -325,7 +308,7 @@ feature 'Budget Investments' do
|
||||
create(:budget_investment, :feasible, :finished, budget: budget, group: group, heading: heading, title: 'Build an ugly house', price: 1000).update_column(:confidence_score, 5)
|
||||
create(:budget_investment, :feasible, :finished, budget: budget, group: group, heading: heading, title: 'Build a skyscraper', price: 20000)
|
||||
|
||||
visit budget_investments_path(budget_id: budget.id)
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
click_link 'by price'
|
||||
expect(page).to have_selector('a.active', text: 'by price')
|
||||
@@ -344,11 +327,7 @@ feature 'Budget Investments' do
|
||||
sp1 = create(:budget_investment, :feasible, :finished, budget: budget, group: group, heading: heading, price: 10000)
|
||||
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
first(:link, "Participatory budgeting").click
|
||||
click_link budget.name
|
||||
click_link "No Heading"
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
click_link sp1.title
|
||||
|
||||
|
||||
109
spec/features/budgets/votes_spec.rb
Normal file
109
spec/features/budgets/votes_spec.rb
Normal file
@@ -0,0 +1,109 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Votes' do
|
||||
|
||||
background do
|
||||
@manuela = create(:user, verified_at: Time.now)
|
||||
end
|
||||
|
||||
feature 'Investments' do
|
||||
|
||||
let(:budget) { create(:budget, phase: "selecting") }
|
||||
let(:group) { create(:budget_group, budget: budget) }
|
||||
let(:heading) { create(:budget_heading, group: group) }
|
||||
|
||||
background { login_as(@manuela) }
|
||||
|
||||
feature 'Index' do
|
||||
|
||||
scenario "Index shows user votes on proposals" do
|
||||
investment1 = create(:budget_investment, heading: heading)
|
||||
investment2 = create(:budget_investment, heading: heading)
|
||||
investment3 = create(:budget_investment, heading: heading)
|
||||
create(:vote, voter: @manuela, votable: investment1, vote_flag: true)
|
||||
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
within("#budget-investments") do
|
||||
within("#budget_investment_#{investment1.id}_votes") do
|
||||
expect(page).to have_content "You have already supported this. Share it!"
|
||||
end
|
||||
|
||||
within("#budget_investment_#{investment2.id}_votes") do
|
||||
expect(page).to_not have_content "You have already supported this. Share it!"
|
||||
end
|
||||
|
||||
within("#budget_investment_#{investment3.id}_votes") do
|
||||
expect(page).to_not have_content "You have already supported this. Share it!"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Create from spending proposal index', :js do
|
||||
investment = create(:budget_investment, heading: heading, budget: budget)
|
||||
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
within('.supports') do
|
||||
find('.in-favor a').click
|
||||
|
||||
expect(page).to have_content "1 support"
|
||||
expect(page).to have_content "You have already supported this. Share it!"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature 'Single spending proposal' do
|
||||
background do
|
||||
@investment = create(:budget_investment, budget: budget)
|
||||
end
|
||||
|
||||
scenario 'Show no votes' do
|
||||
visit budget_investment_path(budget, @investment)
|
||||
expect(page).to have_content "No supports"
|
||||
end
|
||||
|
||||
scenario 'Trying to vote multiple times', :js do
|
||||
visit budget_investment_path(budget, @investment)
|
||||
|
||||
within('.supports') do
|
||||
find('.in-favor a').click
|
||||
expect(page).to have_content "1 support"
|
||||
|
||||
expect(page).to_not have_selector ".in-favor a"
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Create from proposal show', :js do
|
||||
visit budget_investment_path(budget, @investment)
|
||||
|
||||
within('.supports') do
|
||||
find('.in-favor a').click
|
||||
|
||||
expect(page).to have_content "1 support"
|
||||
expect(page).to have_content "You have already supported this. Share it!"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Disable voting on spending proposals', :js do
|
||||
login_as(@manuela)
|
||||
budget.update(phase: "on_hold")
|
||||
investment = create(:budget_investment, budget: budget, heading: heading)
|
||||
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
find("div.supports").hover
|
||||
expect_message_selecting_not_allowed
|
||||
end
|
||||
|
||||
visit budget_investment_path(budget, investment)
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
find("div.supports").hover
|
||||
expect_message_selecting_not_allowed
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -434,25 +434,26 @@ feature 'Votes' do
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Disable voting on spending proposals', :js do
|
||||
login_as(@manuela)
|
||||
Setting["feature.spending_proposal_features.voting_allowed"] = nil
|
||||
spending_proposal = create(:spending_proposal)
|
||||
scenario 'Disable voting on spending proposals', :js do
|
||||
login_as(@manuela)
|
||||
Setting["feature.spending_proposal_features.voting_allowed"] = nil
|
||||
spending_proposal = create(:spending_proposal)
|
||||
|
||||
visit spending_proposals_path
|
||||
visit spending_proposals_path
|
||||
|
||||
within("#spending_proposal_#{spending_proposal.id}") do
|
||||
find("div.supports").hover
|
||||
expect_message_voting_not_allowed
|
||||
end
|
||||
within("#spending_proposal_#{spending_proposal.id}") do
|
||||
find("div.supports").hover
|
||||
expect_message_voting_not_allowed
|
||||
end
|
||||
|
||||
visit spending_proposal_path(spending_proposal)
|
||||
visit spending_proposal_path(spending_proposal)
|
||||
|
||||
within("#spending_proposal_#{spending_proposal.id}") do
|
||||
find("div.supports").hover
|
||||
expect_message_voting_not_allowed
|
||||
within("#spending_proposal_#{spending_proposal.id}") do
|
||||
find("div.supports").hover
|
||||
expect_message_voting_not_allowed
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -159,6 +159,11 @@ module CommonActions
|
||||
expect(page).to have_selector('.in-favor a', visible: false)
|
||||
end
|
||||
|
||||
def expect_message_you_need_to_sign_in_to_ballot
|
||||
expect(page).to have_content 'Not Logged In'
|
||||
expect(page).to have_selector('.in-favor a', visible: false)
|
||||
end
|
||||
|
||||
def expect_message_you_need_to_sign_in_to_vote_comments
|
||||
expect(page).to have_content 'You must Sign in or Sign up to vote'
|
||||
expect(page).to have_selector('.logged', visible: false)
|
||||
@@ -175,11 +180,27 @@ module CommonActions
|
||||
expect(page).to have_selector('.in-favor a', visible: false)
|
||||
end
|
||||
|
||||
def expect_message_only_verified_can_vote_investments
|
||||
expect(page).to have_content 'Not Verified'
|
||||
expect(page).to have_selector('.in-favor a', visible: false)
|
||||
end
|
||||
|
||||
def expect_message_voting_not_allowed
|
||||
expect(page).to have_content 'Voting phase is closed'
|
||||
expect(page).to_not have_selector('.in-favor a')
|
||||
end
|
||||
|
||||
def expect_message_selecting_not_allowed
|
||||
expect(page).to have_content 'No Selecting Allowed'
|
||||
expect(page).to_not have_selector('.in-favor a')
|
||||
end
|
||||
|
||||
def expect_message_organizations_cannot_vote
|
||||
#expect(page).to have_content 'Organisations are not permitted to vote.'
|
||||
expect(page).to have_content 'Organization'
|
||||
expect(page).to have_selector('.in-favor a', visible: false)
|
||||
end
|
||||
|
||||
def create_featured_proposals
|
||||
[create(:proposal, :with_confidence_score, cached_votes_up: 100),
|
||||
create(:proposal, :with_confidence_score, cached_votes_up: 90),
|
||||
|
||||
Reference in New Issue
Block a user