Merge pull request #3345 from consul/backport-polls-officer-for-voter

Add officing booths
This commit is contained in:
Javier Martín
2019-04-03 18:26:05 +02:00
committed by GitHub
36 changed files with 505 additions and 67 deletions

View File

@@ -1,12 +1,46 @@
class Officing::BaseController < ApplicationController
layout "admin"
helper_method :current_booth
before_action :authenticate_user!
before_action :verify_officer
skip_authorization_check
def verify_officer
raise CanCan::AccessDenied unless current_user.try(:poll_officer?)
end
private
def verify_officer
raise CanCan::AccessDenied unless current_user.try(:poll_officer?)
end
def load_officer_assignment
@officer_assignments ||= current_user.poll_officer.
officer_assignments.
voting_days.
where(date: Time.current.to_date)
end
def verify_officer_assignment
if @officer_assignments.blank?
redirect_to officing_root_path, notice: t("officing.residence.flash.not_allowed")
end
end
def verify_booth
return unless current_booth.blank?
booths = current_user.poll_officer.todays_booths
case booths.count
when 0
redirect_to officing_root_path
when 1
session[:booth_id] = booths.first.id
else
redirect_to new_officing_booth_path
end
end
def current_booth
Poll::Booth.where(id: session[:booth_id]).first
end
end

View File

@@ -0,0 +1,24 @@
class Officing::BoothController < Officing::BaseController
before_action :load_officer_assignment
before_action :verify_officer_assignment
def new
@booths = current_user.poll_officer.todays_booths
end
def create
set_booth(Poll::Booth.find(booth_params[:id]))
redirect_to officing_root_path
end
private
def booth_params
params.require(:booth).permit(:id)
end
def set_booth(booth)
session[:booth_id] = booth.id
end
end

View File

@@ -1,4 +1,5 @@
class Officing::PollsController < Officing::BaseController
before_action :verify_booth
def index
@polls = current_user.poll_officer? ? current_user.poll_officer.voting_days_assigned_polls : []

View File

@@ -1,7 +1,8 @@
class Officing::ResidenceController < Officing::BaseController
before_action :load_officer_assignment
before_action :validate_officer_assignment, only: :create
before_action :verify_officer_assignment
before_action :verify_booth
def new
@residence = Officing::Residence.new
@@ -22,16 +23,4 @@ class Officing::ResidenceController < Officing::BaseController
params.require(:residence).permit(:document_number, :document_type, :year_of_birth)
end
def load_officer_assignment
@officer_assignments = current_user.poll_officer.
officer_assignments.
voting_days.
where(date: Date.current)
end
def validate_officer_assignment
if @officer_assignments.blank?
redirect_to officing_root_path, notice: t("officing.residence.flash.not_allowed")
end
end
end

View File

@@ -7,6 +7,7 @@ class Officing::ResultsController < Officing::BaseController
before_action :load_officer_assignment, only: :create
before_action :check_officer_assignment, only: :create
before_action :build_results, only: :create
before_action :verify_booth
def new
end

View File

@@ -1,6 +1,10 @@
class Officing::VotersController < Officing::BaseController
respond_to :html, :js
before_action :load_officer_assignment
before_action :verify_officer_assignment
before_action :verify_booth
def new
@user = User.find(params[:id])
booths = current_user.poll_officer.shifts.current.vote_collection.pluck(:booth_id).uniq
@@ -15,7 +19,9 @@ class Officing::VotersController < Officing::BaseController
user: @user,
poll: @poll,
origin: "booth",
officer: current_user.poll_officer)
officer: current_user.poll_officer,
booth_assignment: Poll::BoothAssignment.where(poll: @poll, booth: current_booth).first,
officer_assignment: officer_assignment(@poll))
@voter.save!
end
@@ -25,4 +31,13 @@ class Officing::VotersController < Officing::BaseController
params.require(:voter).permit(:poll_id, :user_id)
end
def officer_assignment(poll)
Poll::OfficerAssignment.by_officer(current_user.poll_officer)
.by_poll(poll)
.by_booth(current_booth)
.by_date(Date.current)
.where(final: false)
.first
end
end

View File

@@ -3,7 +3,9 @@ class Users::SessionsController < Devise::SessionsController
private
def after_sign_in_path_for(resource)
if !verifying_via_email? && resource.show_welcome_screen?
if current_user.poll_officer?
new_officing_booth_path
elsif !verifying_via_email? && resource.show_welcome_screen?
welcome_path
else
super

View File

@@ -5,11 +5,15 @@ module OfficersHelper
end
def vote_collection_shift?
current_user.poll_officer.officer_assignments.where(date: Time.current.to_date).any?
current_user.poll_officer.officer_assignments.voting_days.where(date: Time.current.to_date).any?
end
def final_recount_shift?
current_user.poll_officer.officer_assignments.final.where(date: Time.current.to_date).any?
end
def no_shifts?
current_user.poll_officer.officer_assignments.where(date: Time.current.to_date).blank?
end
end

View File

@@ -23,5 +23,9 @@ class Poll
sort {|x, y| y.ends_at <=> x.ends_at}
end
def todays_booths
officer_assignments.by_date(Date.current).map(&:booth).uniq
end
end
end

View File

@@ -17,11 +17,20 @@ class Poll
scope :by_officer_and_poll, ->(officer_id, poll_id) do
where("officer_id = ? AND poll_booth_assignments.poll_id = ?", officer_id, poll_id)
end
scope :by_officer, ->(officer){ where(officer_id: officer.id) }
scope :by_poll, ->(poll){ joins(:booth_assignment).where("poll_booth_assignments.poll_id" => poll.id) }
scope :by_booth, ->(booth){ joins(:booth_assignment).where("poll_booth_assignments.booth_id" => booth.id) }
scope :by_date, ->(date){ where(date: date) }
before_create :log_user_data
def log_user_data
self.user_data_log = "#{officer.user_id} - #{officer.user.name_and_email}"
end
def booth
booth_assignment.booth
end
end
end

View File

@@ -12,11 +12,13 @@ class Poll
validates :poll_id, presence: true
validates :user_id, presence: true
validates :booth_assignment_id, presence: true, if: ->(voter) { voter.origin == "booth" }
validates :officer_assignment_id, presence: true, if: ->(voter) { voter.origin == "booth" }
validates :document_number, presence: true, uniqueness: { scope: [:poll_id, :document_type], message: :has_voted }
validates :origin, inclusion: { in: VALID_ORIGINS }
before_validation :set_demographic_info, :set_document_info
before_validation :set_demographic_info, :set_document_info, :set_denormalized_booth_assignment_id
scope :web, -> { where(origin: "web") }
scope :booth, -> { where(origin: "booth") }
@@ -38,6 +40,10 @@ class Poll
private
def set_denormalized_booth_assignment_id
self.booth_assignment_id ||= officer_assignment.try(:booth_assignment_id)
end
def in_census?
census_api_response.valid?
end

View File

@@ -43,14 +43,14 @@
<%= 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 %>">
<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>
<td class="text-center">
<td class="text-center" id="<%= dom_id(booth_assignment) %>_system">
<% if system_count.present? %>
<strong><%= system_count %></strong>
<% else %>

View File

@@ -0,0 +1,5 @@
<% if current_user.poll_officer? %>
<div id="officing-booth" class="callout info">
<%= t("admin.officing_booth.title", booth: try(:current_booth).try(:location)) %>
</div>
<% end %>

View File

@@ -33,6 +33,7 @@
<div class="admin-content small-12 medium-9 column" data-equalizer-watch>
<%= render "layouts/flash" %>
<%= render "layouts/officing_booth" %>
<%= yield %>
</div>
</div>

View File

@@ -0,0 +1,25 @@
<div class="row margin-top">
<div class="small-12 medium-6 column small-centered">
<div class="panel margin-top">
<h1 class="text-center">
<%= t("officing.booth.new.title") %>
</h1>
<%= form_for Poll::Booth.new,
as: :booth,
url: officing_booth_path,
method: :post do |f| %>
<div class="row">
<div class="small-12 column">
<%= f.select :id,
@booths.collect { |booth| [booth.location, booth.id] },
selected: @booths.first,
label: false,
tabindex: "1" %>
<%= f.submit(t("devise_views.sessions.new.submit"), class: "button expanded") %>
</div>
</div>
<% end %>
</div>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<p><%= t("officing.dashboard.index.info") %></p>
<% unless final_recount_shift? && vote_collection_shift? %>
<% if no_shifts? %>
<div class="callout warning">
<%= t("officing.dashboard.index.no_shifts") %>
</div>

View File

@@ -1,32 +1,25 @@
<h2><%= t("officing.residence.new.title") %></h2>
<% if @officer_assignments.present? %>
<div class="row verification account">
<div class="small-12 medium-8 column">
<%= form_for @residence, as: "residence", url: officing_residence_path do |f| %>
<%= render "errors" %>
<div class="row verification account">
<div class="small-12 medium-8 column">
<%= form_for @residence, as: "residence", url: officing_residence_path do |f| %>
<%= render "errors" %>
<div class="small-12 medium-6">
<%= f.select :document_type, document_types, prompt: "" %>
<div class="small-12 medium-6">
<%= f.select :document_type, document_types, prompt: "" %>
<%= f.text_field :document_number,
<%= f.text_field :document_number,
placeholder: t("officing.residence.new.document_number"),
autocomplete: "off" %>
</div>
</div>
<div class="date-of-birth small-12 medium-6">
<%= f.text_field :year_of_birth, type: "number", autocomplete: "off" %>
</div>
<div class="date-of-birth small-12 medium-6">
<%= f.text_field :year_of_birth, type: "number", autocomplete: "off" %>
</div>
<div class="small-12 medium-6">
<input type="submit" value="<%= t("officing.residence.new.submit") %>" class="button expanded">
</div>
<% end %>
</div>
<div class="small-12 medium-6">
<input type="submit" value="<%= t("officing.residence.new.submit") %>" class="button expanded">
</div>
<% end %>
</div>
<% else %>
<div class="callout primary">
<%= t("officing.residence.new.no_assignments") %>
</div>
<% end %>
</div>

View File

@@ -1,3 +1,4 @@
$("#<%= dom_id(@poll) %> #actions").html("<%= j render("voted") %>");
$("#<%= dom_id(@poll) %> #can_vote_callout").hide();
$("#not_voted").hide();
$(".js-vote-collection").removeClass("is-hidden");

View File

@@ -28,4 +28,8 @@
</table>
<% end %>
<%= link_to t("officing.voters.new.not_to_vote"), namespaced_root_path, class: "button" %>
<% if Poll.votable_by(@user).any? %>
<div id="not_voted">
<%= link_to t("officing.voters.new.not_to_vote"), namespaced_root_path, class: "button" %>
</div>
<% end %>

View File

@@ -14,6 +14,8 @@ en:
edit: Edit
configure: Configure
delete: Delete
officing_booth:
title: "You are officing the booth located at %{booth}. If this is not correct, do not continue and call the help phone number. Thank you."
banners:
index:
title: Banners

View File

@@ -16,6 +16,9 @@ en:
no_polls: You are not officing final recounts in any active poll
select_poll: Select poll
add_results: Add results
booth:
new:
title: "Choose your booth"
results:
flash:
create: "Results saved"
@@ -51,7 +54,6 @@ en:
submit: Validate document
error_verifying_census: "The Census was unable to verify this document."
form_errors: prevented the verification of this document
no_assignments: "You don't have officing shifts today"
voters:
new:
title: Polls

View File

@@ -14,6 +14,8 @@ es:
edit: Editar
configure: Configurar
delete: Borrar
officing_booth:
title: "Estás ahora mismo en la mesa ubicada en %{booth}. Si esto no es correcto no sigas adelante y llama al teléfono de incidencias. Gracias."
banners:
index:
title: Banners

View File

@@ -16,6 +16,9 @@ es:
no_polls: No tienes permiso para recuento final en ninguna votación reciente
select_poll: Selecciona votación
add_results: Añadir resultados
booth:
new:
title: "Escoge tu urna"
results:
flash:
create: "Datos guardados"
@@ -51,7 +54,6 @@ es:
submit: Validar documento
error_verifying_census: "El Padrón no pudo verificar este documento."
form_errors: evitaron verificar este documento
no_assignments: "Hoy no tienes turno de presidente de mesa"
voters:
new:
title: Votaciones

View File

@@ -4,6 +4,7 @@ namespace :officing do
resources :results, only: [:new, :create, :index]
end
resource :booth, controller: "booth", only: [:new, :create]
resource :residence, controller: "residence", only: [:new, :create]
resources :voters, only: [:new, :create]
root to: "dashboard#index"

View File

@@ -42,24 +42,24 @@ end
section "Creating Poll Questions & Answers" do
Poll.find_each do |poll|
(1..4).to_a.sample.times do
title = Faker::Lorem.sentence(3).truncate(60) + "?"
question_title = Faker::Lorem.sentence(3).truncate(60) + "?"
question = Poll::Question.new(author: User.all.sample,
title: title,
title: question_title,
poll: poll)
I18n.available_locales.map do |locale|
Globalize.with_locale(locale) do
question.title = "#{title} (#{locale})"
question.title = "#{question_title} (#{locale})"
end
end
question.save!
Faker::Lorem.words((2..4).to_a.sample).each do |title|
Faker::Lorem.words((2..4).to_a.sample).each do |answer_title|
description = "<p>#{Faker::Lorem.paragraphs.join("</p><p>")}</p>"
answer = Poll::Question::Answer.new(question: question,
title: title.capitalize,
title: answer_title.capitalize,
description: description)
I18n.available_locales.map do |locale|
Globalize.with_locale(locale) do
answer.title = "#{title} (#{locale})"
answer.title = "#{answer_title} (#{locale})"
answer.description = "#{description} (#{locale})"
end
end
@@ -114,12 +114,16 @@ end
section "Creating Poll Voters" do
def vote_poll_on_booth(user, poll)
officer = Poll::Officer.all.sample
Poll::Voter.create!(document_type: user.document_type,
document_number: user.document_number,
user: user,
poll: poll,
origin: "booth",
officer: Poll::Officer.all.sample)
officer: officer,
officer_assignment: officer.officer_assignments.sample,
booth_assignment: poll.booth_assignments.sample)
end
def vote_poll_on_web(user, poll)
@@ -142,11 +146,11 @@ section "Creating Poll Voters" do
end
(Poll.expired + Poll.current + Poll.recounting).uniq.each do |poll|
level_two_verified_users = User.level_two_verified
verified_users = User.level_two_or_three_verified
if poll.geozone_restricted?
level_two_verified_users = level_two_verified_users.where(geozone_id: poll.geozone_ids)
verified_users = verified_users.where(geozone_id: poll.geozone_ids)
end
user_groups = level_two_verified_users.in_groups(2)
user_groups = verified_users.in_groups(2)
user_groups.first.each { |user| vote_poll_on_booth(user, poll) }
user_groups.second.compact.each { |user| vote_poll_on_web(user, poll) }
end
@@ -158,13 +162,23 @@ section "Creating Poll Recounts" do
officer_assignment = poll.officer_assignments.first
author = Poll::Officer.first.user
total_amount = white_amount = null_amount = 0
booth_assignment.voters.count.times do
case rand
when 0...0.1 then null_amount += 1
when 0.1...0.2 then white_amount += 1
else total_amount += 1
end
end
Poll::Recount.create!(officer_assignment: officer_assignment,
booth_assignment: booth_assignment,
author: author,
date: poll.ends_at,
white_amount: rand(0..10),
null_amount: rand(0..10),
total_amount: rand(100..9999),
white_amount: white_amount,
null_amount: null_amount,
total_amount: total_amount,
origin: "booth")
end
end

View File

@@ -8,7 +8,7 @@ section "Creating Users" do
password_confirmation: password,
confirmed_at: Time.current,
terms_of_service: "1",
gender: ["Male", "Female"].sample,
gender: %w[male female].sample,
date_of_birth: rand((Time.current - 80.years)..(Time.current - 16.years)),
public_activity: (rand(1..100) > 30)
)

View File

@@ -2,7 +2,7 @@ require "rails_helper"
feature "Budget Poll Officing" do
scenario "Show sidebar menu if officer has shifts assigned" do
scenario "Show sidebar menus if officer has shifts assigned" do
poll = create(:poll)
booth = create(:poll_booth)
booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth)
@@ -10,13 +10,21 @@ feature "Budget Poll Officing" do
user = create(:user)
officer = create(:poll_officer, user: user)
create(:poll_shift, officer: officer, booth: booth, date: Date.current, task: :vote_collection)
login_as user
visit officing_root_path
expect(page).not_to have_content("You don't have officing shifts today")
expect(page).to have_content("Validate document")
expect(page).not_to have_content("Total recounts and results")
create(:poll_shift, officer: officer, booth: booth, date: Date.current, task: :recount_scrutiny)
officer_assignment = create(:poll_officer_assignment,
booth_assignment: booth_assignment,
officer: officer)
login_as user
visit officing_root_path
expect(page).not_to have_content("You don't have officing shifts today")
@@ -24,7 +32,7 @@ feature "Budget Poll Officing" do
expect(page).to have_content("Total recounts and results")
end
scenario "Do not show sidebar menu if officer has no shifts assigned" do
scenario "Do not show sidebar menus if officer has no shifts assigned" do
user = create(:user)
officer = create(:poll_officer, user: user)

View File

@@ -0,0 +1,87 @@
require "rails_helper"
feature "Booth", :with_frozen_time do
scenario "Officer with no booth assignments today" do
officer = create(:poll_officer)
login_through_form_as_officer(officer.user)
expect(page).to have_content "You don't have officing shifts today"
end
scenario "Officer with booth assignments another day" do
officer = create(:poll_officer)
create(:poll_officer_assignment, officer: officer, date: Date.current + 1.day)
login_through_form_as_officer(officer.user)
expect(page).to have_content "You don't have officing shifts today"
end
scenario "Officer with single booth assignment today" do
officer = create(:poll_officer)
poll = create(:poll)
booth = create(:poll_booth)
booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth)
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment, date: Date.current)
login_through_form_as_officer(officer.user)
within("#officing-booth") do
expect(page).to have_content "You are officing the booth located at #{booth.location}."
end
end
scenario "Officer with multiple booth assignments today" do
officer = create(:poll_officer)
poll = create(:poll)
booth1 = create(:poll_booth)
booth2 = create(:poll_booth)
ba1 = create(:poll_booth_assignment, poll: poll, booth: booth1)
ba2 = create(:poll_booth_assignment, poll: poll, booth: booth2)
create(:poll_officer_assignment, officer: officer, booth_assignment: ba1, date: Date.current)
create(:poll_officer_assignment, officer: officer, booth_assignment: ba2, date: Date.current)
login_through_form_as_officer(officer.user)
expect(page).to have_content "Choose your booth"
select booth2.location, from: "booth_id"
click_button "Enter"
within("#officing-booth") do
expect(page).to have_content "You are officing the booth located at #{booth2.location}."
end
end
scenario "Display single booth for any number of polls" do
officer = create(:poll_officer)
booth1 = create(:poll_booth)
booth2 = create(:poll_booth)
poll1 = create(:poll)
poll2 = create(:poll)
ba1 = create(:poll_booth_assignment, poll: poll1, booth: booth1)
ba2 = create(:poll_booth_assignment, poll: poll2, booth: booth2)
ba3 = create(:poll_booth_assignment, poll: poll2, booth: booth2)
create(:poll_officer_assignment, officer: officer, booth_assignment: ba1, date: Date.current)
create(:poll_officer_assignment, officer: officer, booth_assignment: ba2, date: Date.current)
create(:poll_officer_assignment, officer: officer, booth_assignment: ba3, date: Date.current)
login_through_form_as_officer(officer.user)
expect(page).to have_content "Choose your booth"
expect(page).to have_select("booth_id", options: [booth1.location, booth2.location])
end
end

View File

@@ -25,7 +25,7 @@ feature "Residence", :with_frozen_time do
background do
create(:poll_officer_assignment, officer: officer)
login_as(officer.user)
login_through_form_as_officer(officer.user)
visit officing_root_path
end
@@ -93,4 +93,27 @@ feature "Residence", :with_frozen_time do
end
scenario "Verify booth", :js do
booth = create(:poll_booth)
poll = create(:poll)
ba = create(:poll_booth_assignment, poll: poll, booth: booth)
create(:poll_officer_assignment, officer: officer, booth_assignment: ba)
create(:poll_shift, officer: officer, booth: booth, date: Date.current)
login_as(officer.user)
visit new_officing_residence_path
within("#officing-booth") do
expect(page).to have_content "You are officing the booth located at #{booth.location}."
end
officing_verify_residence
expect(page).to have_content poll.name
click_button "Confirm vote"
expect(page).to have_content "Vote introduced!"
end
end

View File

@@ -5,6 +5,7 @@ feature "Officing Results", :with_frozen_time do
background do
@poll_officer = create(:poll_officer)
@officer_assignment = create(:poll_officer_assignment, :final, officer: @poll_officer)
create(:poll_shift, officer: @poll_officer, booth: @officer_assignment.booth, date: Date.current)
@poll = @officer_assignment.booth_assignment.poll
@poll.update(ends_at: 1.day.ago)
@question_1 = create(:poll_question, poll: @poll)
@@ -15,6 +16,7 @@ feature "Officing Results", :with_frozen_time do
create(:poll_question_answer, title: "Tomorrow", question: @question_2)
login_as(@poll_officer.user)
set_officing_booth(@officer_assignment.booth)
end
scenario "Only polls where user is officer for results are accessible" do
@@ -30,6 +32,7 @@ feature "Officing Results", :with_frozen_time do
click_link "Polling officers"
expect(page).to have_content("Poll officing")
within("#side_menu") do
click_link "Total recounts and results"
end

View File

@@ -12,9 +12,12 @@ feature "Voters" 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)
set_officing_booth(booth)
end
scenario "Can vote", :js do
create(:poll_officer_assignment, officer: officer)
visit new_officing_residence_path
officing_verify_residence
@@ -57,6 +60,10 @@ feature "Voters" do
user = create(:user, residence_verified_at: Time.current, document_type: "1", document_number: "12345678Z")
expect(user).not_to be_level_two_verified
visit root_path
click_link "Sign out"
login_through_form_as_officer(officer.user)
visit new_officing_residence_path
officing_verify_residence
@@ -83,6 +90,7 @@ feature "Voters" do
booth_assignment = create(:poll_booth_assignment, poll: poll_geozone_restricted_out, booth: booth)
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment)
set_officing_booth(second_booth)
visit new_officing_residence_path
officing_verify_residence
@@ -93,4 +101,44 @@ feature "Voters" do
expect(page).to have_content poll_geozone_restricted_in.name
expect(page).not_to have_content poll_geozone_restricted_out.name
end
scenario "Store officer and booth information", :js do
create(:user, :in_census, id: rand(9999999))
poll1 = create(:poll, name: "¿Quieres que XYZ sea aprobado?")
poll2 = create(:poll, name: "Pregunta de votación de prueba")
second_booth = create(:poll_booth)
ba1 = create(:poll_booth_assignment, poll: poll1, booth: second_booth )
ba2 = create(:poll_booth_assignment, poll: poll2, booth: second_booth )
create(:poll_shift, officer: officer, booth: second_booth, date: Date.current, task: :vote_collection)
validate_officer
visit new_officing_residence_path
set_officing_booth(second_booth)
officing_verify_residence
within("#poll_#{poll1.id}") do
click_button "Confirm vote"
expect(page).to have_content "Vote introduced!"
end
within("#poll_#{poll2.id}") do
click_button "Confirm vote"
expect(page).to have_content "Vote introduced!"
end
expect(Poll::Voter.count).to eq(2)
voter1 = Poll::Voter.first
expect(voter1.booth_assignment).to eq(ba1)
expect(voter1.officer_assignment).to eq(ba1.officer_assignments.first)
voter2 = Poll::Voter.last
expect(voter2.booth_assignment).to eq(ba2)
expect(voter2.officer_assignment).to eq(ba2.officer_assignments.first)
end
end

View File

@@ -97,6 +97,7 @@ feature "Poll Officing" do
end
scenario "Poll officer access links" do
create(:poll)
create(:poll_officer, user: user)
login_as(user)
visit root_path

View File

@@ -8,6 +8,7 @@ feature "Voter" do
let(:question) { create(:poll_question, poll: poll) }
let(:booth) { create(:poll_booth) }
let(:officer) { create(:poll_officer) }
let(:admin) { create(:administrator) }
let!(:answer_yes) { create(:poll_question_answer, question: question, title: "Yes") }
let!(:answer_no) { create(:poll_question_answer, question: question, title: "No") }
@@ -71,6 +72,56 @@ feature "Voter" do
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
context "The person has decided not to vote at this time" do
let!(:user) { create(:user, :in_census) }
scenario "Show not to vote at this time button" do
login_through_form_as_officer(officer.user)
visit new_officing_residence_path
officing_verify_residence
expect(page).to have_content poll.name
expect(page).to have_button "Confirm vote"
expect(page).to have_content "Can vote"
expect(page).to have_link "The person has decided not to vote at this time"
end
scenario "Hides not to vote at this time button if already voted", :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")
expect(page).not_to have_button("Confirm vote")
expect(page).to have_content "Vote introduced!"
expect(page).not_to have_content "The person has decided not to vote at this time"
end
visit new_officing_residence_path
officing_verify_residence
expect(page).to have_content "Has already participated in this poll"
expect(page).not_to have_content "The person has decided not to vote at this time"
end
end
context "Trying to vote the same poll in booth and web" do
@@ -107,6 +158,19 @@ feature "Voter" do
expect(page).not_to have_link(answer_yes.title)
expect(page).to have_content "You have already participated in a physical booth. You can not participate again."
expect(Poll::Voter.count).to eq(1)
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 "Trying to vote in web again", :js do
@@ -162,6 +226,19 @@ feature "Voter" do
expect(page).not_to have_link(answer_yes.title)
expect(page).to have_content "You have already participated in a physical booth. You can not participate again."
expect(Poll::Voter.count).to eq(1)
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
context "Side menu" do

View File

@@ -121,4 +121,21 @@ describe Poll::Officer do
expect(assigned_polls.last).to eq(poll_3)
end
end
describe "todays_booths" do
let(:officer) { create(:poll_officer) }
it "returns booths for the application's time zone date", :with_different_time_zone do
assignment_with_local_time_zone = create(:poll_officer_assignment,
date: Date.today,
officer: officer)
assignment_with_application_time_zone = create(:poll_officer_assignment,
date: Date.current,
officer: officer)
expect(officer.todays_booths).to include(assignment_with_application_time_zone.booth)
expect(officer.todays_booths).not_to include(assignment_with_local_time_zone.booth)
end
end
end

View File

@@ -6,6 +6,7 @@ describe Poll::Voter do
let(:booth) { create(:poll_booth) }
let(:booth_assignment) { create(:poll_booth_assignment, poll: poll, booth: booth) }
let(:voter) { create(:poll_voter) }
let(:officer_assignment) { create(:poll_officer_assignment) }
describe "validations" do
@@ -97,6 +98,7 @@ describe Poll::Voter do
it "is valid with a booth origin" do
voter.origin = "booth"
voter.officer_assignment = officer_assignment
expect(voter).to be_valid
end
@@ -104,7 +106,27 @@ describe Poll::Voter do
voter.origin = "web"
expect(voter).to be_valid
end
end
context "assignments" do
it "should not be valid without a booth_assignment_id when origin is booth" do
voter.origin = "booth"
voter.booth_assignment_id = nil
expect(voter).not_to be_valid
end
it "should not be valid without an officer_assignment_id when origin is booth" do
voter.origin = "booth"
voter.officer_assignment_id = nil
expect(voter).not_to be_valid
end
it "should be valid without assignments when origin is web" do
voter.origin = "web"
voter.booth_assignment_id = nil
voter.officer_assignment_id = nil
expect(voter).to be_valid
end
end
end

View File

@@ -21,4 +21,15 @@ module CommonActions
check "user_terms_of_service"
end
def validate_officer
allow_any_instance_of(Officing::BaseController).
to receive(:verify_officer_assignment).and_return(true)
end
def set_officing_booth(booth=nil)
booth = create(:poll_booth) if booth.blank?
allow_any_instance_of(Officing::BaseController).
to receive(:current_booth).and_return(booth)
end
end