Merge pull request #3344 from consul/backport-budget_ballots
Allow voting Budget Investments in booths
This commit is contained in:
@@ -7,7 +7,7 @@ class Admin::Poll::PollsController < Admin::Poll::BaseController
|
||||
before_action :load_geozones, only: [:new, :create, :edit, :update]
|
||||
|
||||
def index
|
||||
@polls = Poll.order(starts_at: :desc)
|
||||
@polls = Poll.not_budget.order(starts_at: :desc)
|
||||
end
|
||||
|
||||
def show
|
||||
@@ -22,7 +22,12 @@ class Admin::Poll::PollsController < Admin::Poll::BaseController
|
||||
def create
|
||||
@poll = Poll.new(poll_params.merge(author: current_user))
|
||||
if @poll.save
|
||||
redirect_to [:admin, @poll], notice: t("flash.actions.create.poll")
|
||||
notice = t("flash.actions.create.poll")
|
||||
if @poll.budget.present?
|
||||
redirect_to admin_poll_booth_assignments_path(@poll), notice: notice
|
||||
else
|
||||
redirect_to [:admin, @poll], notice: notice
|
||||
end
|
||||
else
|
||||
render :new
|
||||
end
|
||||
@@ -63,7 +68,7 @@ class Admin::Poll::PollsController < Admin::Poll::BaseController
|
||||
|
||||
def poll_params
|
||||
attributes = [:name, :starts_at, :ends_at, :geozone_restricted, :results_enabled,
|
||||
:stats_enabled, geozone_ids: [],
|
||||
:stats_enabled, :budget_id, geozone_ids: [],
|
||||
image_attributes: image_attributes]
|
||||
params.require(:poll).permit(*attributes, translation_params(Poll))
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ class Admin::Poll::QuestionsController < Admin::Poll::BaseController
|
||||
load_and_authorize_resource :question, class: "Poll::Question"
|
||||
|
||||
def index
|
||||
@polls = Poll.all
|
||||
@polls = Poll.not_budget
|
||||
@search = search_params[:search]
|
||||
|
||||
@questions = @questions.search(search_params).page(params[:page]).order("created_at DESC")
|
||||
|
||||
@@ -11,7 +11,7 @@ class PollsController < ApplicationController
|
||||
::Poll::Answer # trigger autoload
|
||||
|
||||
def index
|
||||
@polls = @polls.send(@current_filter).includes(:geozones).sort_for_list.page(params[:page])
|
||||
@polls = @polls.not_budget.send(@current_filter).includes(:geozones).sort_for_list.page(params[:page])
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -96,4 +96,16 @@ module BudgetsHelper
|
||||
!current_user.voted_in_group?(investment.group) &&
|
||||
investment.group.headings.count > 1
|
||||
end
|
||||
|
||||
def link_to_create_budget_poll(budget)
|
||||
balloting_phase = budget.phases.where(kind: "balloting").first
|
||||
|
||||
link_to t("admin.budgets.index.admin_ballots"),
|
||||
admin_polls_path(poll: {
|
||||
name: budget.name,
|
||||
budget_id: budget.id,
|
||||
starts_at: balloting_phase.starts_at,
|
||||
ends_at: balloting_phase.ends_at }),
|
||||
method: :post
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,6 +21,8 @@ class Budget < ActiveRecord::Base
|
||||
has_many :headings, through: :groups
|
||||
has_many :phases, class_name: Budget::Phase
|
||||
|
||||
has_one :poll
|
||||
|
||||
before_validation :sanitize_descriptions
|
||||
|
||||
after_create :generate_phases
|
||||
|
||||
@@ -70,5 +70,9 @@ class Budget
|
||||
investments.where(group: group).first.heading
|
||||
end
|
||||
|
||||
def casted_offline?
|
||||
budget.poll&.voted_by?(user)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -248,6 +248,7 @@ class Budget
|
||||
return :no_ballots_allowed unless budget.balloting?
|
||||
return :different_heading_assigned_html unless ballot.valid_heading?(heading)
|
||||
return :not_enough_money_html if ballot.present? && !enough_money?(ballot)
|
||||
return :casted_offline if ballot.casted_offline?
|
||||
end
|
||||
|
||||
def permission_problem(user)
|
||||
|
||||
@@ -23,6 +23,7 @@ class Poll < ActiveRecord::Base
|
||||
|
||||
has_and_belongs_to_many :geozones
|
||||
belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
|
||||
belongs_to :budget
|
||||
|
||||
validates_translation :name, presence: true
|
||||
validate :date_range
|
||||
@@ -33,6 +34,7 @@ class Poll < ActiveRecord::Base
|
||||
scope :published, -> { where("published = ?", true) }
|
||||
scope :by_geozone_id, ->(geozone_id) { where(geozones: {id: geozone_id}.joins(:geozones)) }
|
||||
scope :public_for_api, -> { all }
|
||||
scope :not_budget, -> { where(budget_id: nil) }
|
||||
|
||||
scope :sort_for_list, -> { order(:geozone_restricted, :starts_at, :name) }
|
||||
|
||||
@@ -71,10 +73,15 @@ class Poll < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def votable_by?(user)
|
||||
return false if user_has_an_online_ballot(user)
|
||||
answerable_by?(user) &&
|
||||
not_voted_by?(user)
|
||||
end
|
||||
|
||||
def user_has_an_online_ballot(user)
|
||||
budget.present? && budget.ballots.find_by(user: user)&.lines.present?
|
||||
end
|
||||
|
||||
def self.not_voted_by(user)
|
||||
where("polls.id not in (?)", poll_ids_voted_by(user))
|
||||
end
|
||||
@@ -107,4 +114,7 @@ class Poll < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def budget_poll?
|
||||
budget.present?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<th><%= t("admin.budgets.index.table_investments") %></th>
|
||||
<th><%= t("admin.budgets.index.table_edit_groups") %></th>
|
||||
<th><%= t("admin.budgets.index.table_edit_budget") %></th>
|
||||
<th><%= t("admin.budgets.index.table_admin_ballots") %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -39,6 +40,13 @@
|
||||
<td class="small">
|
||||
<%= link_to t("admin.budgets.index.edit_budget"), edit_admin_budget_path(budget) %>
|
||||
</td>
|
||||
<td class="small">
|
||||
<% if budget.poll.present? %>
|
||||
<%= link_to t("admin.budgets.index.admin_ballots"), admin_poll_booth_assignments_path(budget.poll) %>
|
||||
<% else %>
|
||||
<%= link_to_create_budget_poll(budget) %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
class: "button hollow float-right" %>
|
||||
|
||||
<% if @booth_assignments.empty? %>
|
||||
<div class="callout primary margin-top">
|
||||
<div class="callout primary margin-top clear">
|
||||
<%= t("admin.poll_booth_assignments.index.no_booths") %>
|
||||
</div>
|
||||
<% else %>
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
<ul class="menu simple clear" id="assigned-resources-tabs">
|
||||
<% if controller_name == "polls" %>
|
||||
<li class="is-active">
|
||||
<h2>
|
||||
<%= t("admin.polls.show.questions_tab") %>
|
||||
(<%= @poll.questions.count %>)
|
||||
</h2>
|
||||
</li>
|
||||
<% else %>
|
||||
<li>
|
||||
<%= link_to admin_poll_path(@poll) do %>
|
||||
<%= t("admin.polls.show.questions_tab") %>
|
||||
(<%= @poll.questions.count %>)
|
||||
<% end %>
|
||||
</li>
|
||||
<% unless @poll.budget_poll? %>
|
||||
<% if controller_name == "polls" %>
|
||||
<li class="is-active">
|
||||
<h2>
|
||||
<%= t("admin.polls.show.questions_tab") %>
|
||||
(<%= @poll.questions.count %>)
|
||||
</h2>
|
||||
</li>
|
||||
<% else %>
|
||||
<li>
|
||||
<%= link_to admin_poll_path(@poll) do %>
|
||||
<%= t("admin.polls.show.questions_tab") %>
|
||||
(<%= @poll.questions.count %>)
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if controller_name == "booth_assignments" %>
|
||||
|
||||
@@ -14,14 +14,18 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center"></th>
|
||||
<th class="text-center"><%= t("admin.recounts.index.total_final") %></th>
|
||||
<% unless @poll.budget_poll? %>
|
||||
<th class="text-center"><%= t("admin.recounts.index.total_final") %></th>
|
||||
<% end %>
|
||||
<th class="text-center"><%= t("admin.recounts.index.total_system") %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong><%= t("admin.recounts.index.all_booths_total") %></strong></td>
|
||||
<td class="text-center" id="total_final"><%= @all_booths_counts[:final] %></td>
|
||||
<% unless @poll.budget_poll? %>
|
||||
<td class="text-center" id="total_final"><%= @all_booths_counts[:final] %></td>
|
||||
<% end %>
|
||||
<td class="text-center" id="total_system"><%= @all_booths_counts[:system] %></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -30,7 +34,9 @@
|
||||
<table class="fixed margin">
|
||||
<thead>
|
||||
<th><%= t("admin.recounts.index.table_booth_name") %></th>
|
||||
<th class="text-center"><%= t("admin.recounts.index.table_total_recount") %></th>
|
||||
<% unless @poll.budget_poll? %>
|
||||
<th class="text-center"><%= t("admin.recounts.index.table_total_recount") %></th>
|
||||
<% end %>
|
||||
<th class="text-center"><%= t("admin.recounts.index.table_system_count") %></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -43,13 +49,15 @@
|
||||
<%= link_to booth_assignment.booth.name, admin_poll_booth_assignment_path(@poll, booth_assignment, anchor: "tab-recounts") %>
|
||||
</strong>
|
||||
</td>
|
||||
<td class="text-center <%= "count-error" if total_recounts.to_i != system_count %>" id="<%= dom_id(booth_assignment) %>_recount">
|
||||
<% if total_recounts.present? %>
|
||||
<strong><%= total_recounts %></strong>
|
||||
<% else %>
|
||||
<span>-</span>
|
||||
<% end %>
|
||||
</td>
|
||||
<% unless @poll.budget_poll? %>
|
||||
<td class="text-center <%= "count-error" if total_recounts.to_i != system_count %>" id="<%= dom_id(booth_assignment) %>_recount">
|
||||
<% if total_recounts.present? %>
|
||||
<strong><%= total_recounts %></strong>
|
||||
<% else %>
|
||||
<span>-</span>
|
||||
<% end %>
|
||||
</td>
|
||||
<% end %>
|
||||
<td class="text-center" id="<%= dom_id(booth_assignment) %>_system">
|
||||
<% if system_count.present? %>
|
||||
<strong><%= system_count %></strong>
|
||||
|
||||
@@ -85,8 +85,10 @@ en:
|
||||
table_investments: Investments
|
||||
table_edit_groups: Headings groups
|
||||
table_edit_budget: Edit
|
||||
table_admin_ballots: Ballots
|
||||
edit_groups: Edit headings groups
|
||||
edit_budget: Edit budget
|
||||
admin_ballots: Admin ballots
|
||||
no_budgets: "There are no budgets."
|
||||
create:
|
||||
notice: New participatory budget created successfully!
|
||||
|
||||
@@ -22,6 +22,7 @@ en:
|
||||
no_ballots_allowed: Selecting phase is closed
|
||||
different_heading_assigned_html: "You have already voted a different heading: %{heading_link}"
|
||||
change_ballot: change your votes
|
||||
casted_offline: You have already participated offline
|
||||
groups:
|
||||
show:
|
||||
title: Select an option
|
||||
|
||||
@@ -85,8 +85,10 @@ es:
|
||||
table_investments: Proyectos de gasto
|
||||
table_edit_groups: Grupos de partidas
|
||||
table_edit_budget: Editar
|
||||
table_admin_ballots: Urnas
|
||||
edit_groups: Editar grupos de partidas
|
||||
edit_budget: Editar presupuesto
|
||||
admin_ballots: Gestionar urnas
|
||||
no_budgets: "No hay presupuestos participativos."
|
||||
create:
|
||||
notice: "¡Presupuestos participativos creados con éxito!"
|
||||
|
||||
@@ -22,6 +22,7 @@ es:
|
||||
no_ballots_allowed: El periodo de votación está cerrado.
|
||||
different_heading_assigned_html: "Ya has votado proyectos de otra partida: %{heading_link}"
|
||||
change_ballot: cambiar tus votos
|
||||
casted_offline: Ya has participado presencialmente
|
||||
groups:
|
||||
show:
|
||||
title: Selecciona una opción
|
||||
|
||||
5
db/migrate/20180604173248_add_budget_to_polls.rb
Normal file
5
db/migrate/20180604173248_add_budget_to_polls.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class AddBudgetToPolls < ActiveRecord::Migration
|
||||
def change
|
||||
add_reference :polls, :budget, index: { unique: true }, foreign_key: true
|
||||
end
|
||||
end
|
||||
@@ -1129,8 +1129,10 @@ ActiveRecord::Schema.define(version: 20190205131722) do
|
||||
t.boolean "stats_enabled", default: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "budget_id"
|
||||
end
|
||||
|
||||
add_index "polls", ["budget_id"], name: "index_polls_on_budget_id", unique: true, using: :btree
|
||||
add_index "polls", ["starts_at", "ends_at"], name: "index_polls_on_starts_at_and_ends_at", using: :btree
|
||||
|
||||
create_table "progress_bar_translations", force: :cascade do |t|
|
||||
@@ -1614,6 +1616,7 @@ ActiveRecord::Schema.define(version: 20190205131722) do
|
||||
add_foreign_key "poll_recounts", "poll_booth_assignments", column: "booth_assignment_id"
|
||||
add_foreign_key "poll_recounts", "poll_officer_assignments", column: "officer_assignment_id"
|
||||
add_foreign_key "poll_voters", "polls"
|
||||
add_foreign_key "polls", "budgets"
|
||||
add_foreign_key "proposals", "communities"
|
||||
add_foreign_key "related_content_scores", "related_contents"
|
||||
add_foreign_key "related_content_scores", "users"
|
||||
|
||||
62
spec/features/budget_polls/budgets_spec.rb
Normal file
62
spec/features/budget_polls/budgets_spec.rb
Normal file
@@ -0,0 +1,62 @@
|
||||
require "rails_helper"
|
||||
|
||||
feature "Admin Budgets" do
|
||||
|
||||
background do
|
||||
admin = create(:administrator).user
|
||||
login_as(admin)
|
||||
end
|
||||
|
||||
context "Index" do
|
||||
|
||||
scenario "Create poll if the budget does not have a poll associated" do
|
||||
budget = create(:budget)
|
||||
|
||||
visit admin_budgets_path
|
||||
|
||||
click_link "Admin ballots"
|
||||
|
||||
balloting_phase = budget.phases.where(kind: "balloting").first
|
||||
|
||||
expect(current_path).to match(/admin\/polls\/\d+/)
|
||||
expect(page).to have_content(budget.name)
|
||||
expect(page).to have_content(balloting_phase.starts_at.to_date)
|
||||
expect(page).to have_content(balloting_phase.ends_at.to_date)
|
||||
|
||||
expect(Poll.count).to eq(1)
|
||||
expect(Poll.last.budget).to eq(budget)
|
||||
end
|
||||
|
||||
scenario "Display link to poll if the budget has a poll associated" do
|
||||
budget = create(:budget)
|
||||
poll = create(:poll, budget: budget)
|
||||
|
||||
visit admin_budgets_path
|
||||
|
||||
within "#budget_#{budget.id}" do
|
||||
expect(page).to have_link("Admin ballots", admin_poll_path(poll))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "Show" do
|
||||
|
||||
scenario "Do not show questions section if the budget have a poll associated" do
|
||||
budget = create(:budget)
|
||||
poll = create(:poll, budget: budget)
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
|
||||
within "#poll-resources" do
|
||||
expect(page).not_to have_content("Questions")
|
||||
expect(page).to have_content("Booths")
|
||||
expect(page).to have_content("Officers")
|
||||
expect(page).to have_content("Recounting")
|
||||
expect(page).to have_content("Results")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
34
spec/features/budget_polls/polls_spec.rb
Normal file
34
spec/features/budget_polls/polls_spec.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
require "rails_helper"
|
||||
|
||||
feature "Polls" do
|
||||
|
||||
context "Public index" do
|
||||
|
||||
scenario "Budget polls should not be listed" do
|
||||
poll = create(:poll)
|
||||
budget_poll = create(:poll, budget: create(:budget))
|
||||
|
||||
visit polls_path
|
||||
|
||||
expect(page).to have_content(poll.name)
|
||||
expect(page).not_to have_content(budget_poll.name)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "Admin index" do
|
||||
|
||||
scenario "Budget polls should not appear in the list" do
|
||||
login_as(create(:administrator).user)
|
||||
|
||||
poll = create(:poll)
|
||||
budget_poll = create(:poll, budget: create(:budget))
|
||||
|
||||
visit admin_polls_path
|
||||
|
||||
expect(page).to have_content(poll.name)
|
||||
expect(page).not_to have_content(budget_poll.name)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
22
spec/features/budget_polls/questions_spec.rb
Normal file
22
spec/features/budget_polls/questions_spec.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
require "rails_helper"
|
||||
|
||||
feature "Poll Questions" do
|
||||
|
||||
before do
|
||||
admin = create(:administrator).user
|
||||
login_as(admin)
|
||||
end
|
||||
|
||||
scenario "Do not display polls associated to a budget" do
|
||||
budget = create(:budget)
|
||||
|
||||
poll1 = create(:poll, name: "Citizen Proposal Poll")
|
||||
poll2 = create(:poll, budget: budget, name: "Participatory Budget Poll")
|
||||
|
||||
visit admin_questions_path
|
||||
|
||||
expect(page).to have_select("poll_id", text: "Citizen Proposal Poll")
|
||||
expect(page).not_to have_select("poll_id", text: "Participatory Budget Poll")
|
||||
end
|
||||
|
||||
end
|
||||
146
spec/features/budget_polls/voter_spec.rb
Normal file
146
spec/features/budget_polls/voter_spec.rb
Normal file
@@ -0,0 +1,146 @@
|
||||
require "rails_helper"
|
||||
|
||||
feature "BudgetPolls", :with_frozen_time do
|
||||
let(:budget) { create(:budget, :balloting) }
|
||||
let(:group) { create(:budget_group, budget: budget) }
|
||||
let(:heading) { create(:budget_heading, group: group) }
|
||||
let(:investment) { create(:budget_investment, :selected, heading: heading) }
|
||||
let(:poll) { create(:poll, :current, budget: budget) }
|
||||
let(:booth) { create(:poll_booth) }
|
||||
let(:officer) { create(:poll_officer) }
|
||||
let(:admin) { create(:administrator) }
|
||||
let!(:user) { create(:user, :in_census) }
|
||||
|
||||
background do
|
||||
create(:poll_shift, officer: officer, booth: booth, date: Date.current, task: :vote_collection)
|
||||
booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth)
|
||||
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment, date: Date.current)
|
||||
end
|
||||
|
||||
context "Offline" do
|
||||
scenario "A citizen can cast a paper vote", :js do
|
||||
login_through_form_as_officer(officer.user)
|
||||
|
||||
visit new_officing_residence_path
|
||||
officing_verify_residence
|
||||
|
||||
expect(page).to have_content poll.name
|
||||
|
||||
within("#poll_#{poll.id}") do
|
||||
click_button("Confirm vote")
|
||||
expect(page).not_to have_button("Confirm vote")
|
||||
expect(page).to have_content "Vote introduced!"
|
||||
end
|
||||
|
||||
expect(Poll::Voter.count).to eq(1)
|
||||
expect(Poll::Voter.first.origin).to eq("booth")
|
||||
|
||||
visit root_path
|
||||
click_link "Sign out"
|
||||
login_as(admin.user)
|
||||
visit admin_poll_recounts_path(poll)
|
||||
|
||||
within("#total_system") do
|
||||
expect(page).to have_content "1"
|
||||
end
|
||||
|
||||
within("#poll_booth_assignment_#{Poll::BoothAssignment.where(poll: poll, booth: booth).first.id}_recounts") do
|
||||
expect(page).to have_content "1"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "A citizen cannot vote offline again", :js do
|
||||
login_through_form_as_officer(officer.user)
|
||||
|
||||
visit new_officing_residence_path
|
||||
officing_verify_residence
|
||||
|
||||
within("#poll_#{poll.id}") do
|
||||
click_button("Confirm vote")
|
||||
end
|
||||
|
||||
visit new_officing_residence_path
|
||||
officing_verify_residence
|
||||
|
||||
within("#poll_#{poll.id}") do
|
||||
expect(page).to have_content "Has already participated in this poll"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "A citizen cannot vote online after voting offline", :js do
|
||||
login_through_form_as_officer(officer.user)
|
||||
|
||||
visit new_officing_residence_path
|
||||
officing_verify_residence
|
||||
|
||||
within("#poll_#{poll.id}") do
|
||||
click_button("Confirm vote")
|
||||
end
|
||||
|
||||
expect(page).to have_content "Vote introduced!"
|
||||
|
||||
login_as(user)
|
||||
|
||||
visit budget_investment_path(budget, investment)
|
||||
find("div.ballot").hover
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
expect(page).to have_content "You have already participated offline"
|
||||
expect(page).to have_css(".add a", visible: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "Online" do
|
||||
scenario "A citizen can cast vote online", :js do
|
||||
login_as(user)
|
||||
visit budget_investment_path(budget, investment)
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
find(".add a").click
|
||||
expect(page).to have_content "Remove"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "A citizen cannot vote online again", :js do
|
||||
login_as(user)
|
||||
visit budget_investment_path(budget, investment)
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
find(".add a").click
|
||||
expect(page).to have_content "Remove"
|
||||
end
|
||||
|
||||
visit budget_investment_path(budget, investment)
|
||||
find("div.ballot").hover
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
expect(page).to have_content "Remove vote"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "A citizen cannot vote offline after voting online", :js do
|
||||
login_as(user)
|
||||
visit budget_investment_path(budget, investment)
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
find(".add a").click
|
||||
expect(page).to have_content "Remove"
|
||||
end
|
||||
|
||||
logout
|
||||
login_through_form_as_officer(officer.user)
|
||||
|
||||
visit new_officing_residence_path
|
||||
officing_verify_residence
|
||||
|
||||
expect(page).to have_content poll.name
|
||||
|
||||
within("#poll_#{poll.id}") do
|
||||
expect(page).not_to have_button("Confirm vote")
|
||||
expect(page).to have_content("Has already participated in this poll")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -258,4 +258,24 @@ describe Poll do
|
||||
|
||||
end
|
||||
|
||||
context "scopes" do
|
||||
|
||||
describe "#not_budget" do
|
||||
|
||||
it "returns polls not associated to a budget" do
|
||||
budget = create(:budget)
|
||||
|
||||
poll1 = create(:poll)
|
||||
poll2 = create(:poll)
|
||||
poll3 = create(:poll, budget: budget)
|
||||
|
||||
expect(Poll.not_budget).to include(poll1)
|
||||
expect(Poll.not_budget).to include(poll2)
|
||||
expect(Poll.not_budget).not_to include(poll3)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user