Merge branch 'master' into site-customization
This commit is contained in:
@@ -22,6 +22,9 @@ FactoryGirl.define do
|
||||
sms_confirmation_code "1234"
|
||||
document_type "1"
|
||||
document_number
|
||||
date_of_birth Date.new(1980, 12, 31)
|
||||
gender "female"
|
||||
geozone
|
||||
end
|
||||
|
||||
trait :level_three do
|
||||
@@ -37,6 +40,7 @@ FactoryGirl.define do
|
||||
trait :with_confirmed_hide do
|
||||
confirmed_hide_at Time.current
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
factory :identity do
|
||||
@@ -181,6 +185,10 @@ FactoryGirl.define do
|
||||
4.times { create(:vote, votable: debate) }
|
||||
end
|
||||
end
|
||||
|
||||
trait :successful do
|
||||
cached_votes_up { Proposal.votes_needed_for_success + 100 }
|
||||
end
|
||||
end
|
||||
|
||||
factory :spending_proposal do
|
||||
@@ -359,6 +367,127 @@ FactoryGirl.define do
|
||||
user
|
||||
end
|
||||
|
||||
factory :poll_officer, class: 'Poll::Officer' do
|
||||
user
|
||||
end
|
||||
|
||||
factory :poll do
|
||||
sequence(:name) { |n| "Poll #{n}" }
|
||||
|
||||
starts_at { 1.month.ago }
|
||||
ends_at { 1.month.from_now }
|
||||
|
||||
trait :incoming do
|
||||
starts_at { 2.days.from_now }
|
||||
ends_at { 1.month.from_now }
|
||||
end
|
||||
|
||||
trait :expired do
|
||||
starts_at { 1.month.ago }
|
||||
ends_at { 15.days.ago }
|
||||
end
|
||||
|
||||
trait :published do
|
||||
published true
|
||||
end
|
||||
end
|
||||
|
||||
factory :poll_question, class: 'Poll::Question' do
|
||||
poll
|
||||
association :author, factory: :user
|
||||
sequence(:title) { |n| "Question title #{n}" }
|
||||
sequence(:description) { |n| "Question description #{n}" }
|
||||
valid_answers { Faker::Lorem.words(3).join(', ') }
|
||||
end
|
||||
|
||||
factory :poll_booth, class: 'Poll::Booth' do
|
||||
sequence(:name) { |n| "Booth #{n}" }
|
||||
sequence(:location) { |n| "Street #{n}" }
|
||||
end
|
||||
|
||||
factory :poll_booth_assignment, class: 'Poll::BoothAssignment' do
|
||||
poll
|
||||
association :booth, factory: :poll_booth
|
||||
end
|
||||
|
||||
factory :poll_officer_assignment, class: 'Poll::OfficerAssignment' do
|
||||
association :officer, factory: :poll_officer
|
||||
association :booth_assignment, factory: :poll_booth_assignment
|
||||
date Time.current.to_date
|
||||
|
||||
trait :final do
|
||||
final true
|
||||
end
|
||||
end
|
||||
|
||||
factory :poll_recount, class: 'Poll::Recount' do
|
||||
association :officer_assignment, factory: :poll_officer_assignment
|
||||
association :booth_assignment, factory: :poll_booth_assignment
|
||||
count (1..100).to_a.sample
|
||||
date (1.month.ago.to_datetime..1.month.from_now.to_datetime).to_a.sample
|
||||
end
|
||||
|
||||
factory :poll_final_recount, class: 'Poll::FinalRecount' do
|
||||
association :officer_assignment, factory: [:poll_officer_assignment, :final]
|
||||
association :booth_assignment, factory: :poll_booth_assignment
|
||||
count (1..100).to_a.sample
|
||||
date (1.month.ago.to_datetime..1.month.from_now.to_datetime).to_a.sample
|
||||
end
|
||||
|
||||
factory :poll_voter, class: 'Poll::Voter' do
|
||||
poll
|
||||
association :user, :level_two
|
||||
|
||||
trait :from_booth do
|
||||
association :booth_assignment, factory: :poll_booth_assignment
|
||||
end
|
||||
|
||||
trait :valid_document do
|
||||
document_type "1"
|
||||
document_number "12345678Z"
|
||||
end
|
||||
|
||||
trait :invalid_document do
|
||||
document_type "1"
|
||||
document_number "99999999A"
|
||||
end
|
||||
end
|
||||
|
||||
factory :poll_answer, class: 'Poll::Answer' do
|
||||
association :question, factory: :poll_question
|
||||
association :author, factory: [:user, :level_two]
|
||||
answer { question.valid_answers.sample }
|
||||
end
|
||||
|
||||
factory :poll_partial_result, class: 'Poll::PartialResult' do
|
||||
association :question, factory: :poll_question
|
||||
association :author, factory: :user
|
||||
origin { 'web' }
|
||||
answer { question.valid_answers.sample }
|
||||
end
|
||||
|
||||
factory :poll_white_result, class: 'Poll::WhiteResult' do
|
||||
association :author, factory: :user
|
||||
origin { 'web' }
|
||||
end
|
||||
|
||||
factory :poll_null_result, class: 'Poll::NullResult' do
|
||||
association :author, factory: :user
|
||||
origin { 'web' }
|
||||
end
|
||||
|
||||
factory :officing_residence, class: 'Officing::Residence' do
|
||||
user
|
||||
association :officer, factory: :poll_officer
|
||||
document_number
|
||||
document_type "1"
|
||||
year_of_birth "1980"
|
||||
|
||||
trait :invalid do
|
||||
year_of_birth Time.current.year
|
||||
end
|
||||
end
|
||||
|
||||
factory :organization do
|
||||
user
|
||||
responsible_name "Johnny Utah"
|
||||
@@ -415,6 +544,10 @@ FactoryGirl.define do
|
||||
sequence(:name) { |n| "District #{n}" }
|
||||
sequence(:external_code) { |n| "#{n}" }
|
||||
sequence(:census_code) { |n| "#{n}" }
|
||||
|
||||
trait :in_census do
|
||||
census_code "01"
|
||||
end
|
||||
end
|
||||
|
||||
factory :banner do
|
||||
|
||||
@@ -112,8 +112,13 @@ feature 'Account' do
|
||||
end
|
||||
|
||||
scenario 'Errors editing credentials' do
|
||||
visit account_path
|
||||
visit root_path
|
||||
|
||||
click_link 'My account'
|
||||
|
||||
expect(current_path).to eq(account_path)
|
||||
|
||||
expect(page).to have_link('Change my credentials')
|
||||
click_link 'Change my credentials'
|
||||
click_button 'Update'
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ feature 'Admin banners magement' do
|
||||
visit admin_root_path
|
||||
|
||||
within('#side_menu') do
|
||||
click_link "Banners"
|
||||
click_link "Manage banners"
|
||||
end
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ feature 'Admin feature flags' do
|
||||
visit admin_root_path
|
||||
|
||||
within('#side_menu') do
|
||||
expect(page).not_to have_link "Budgets"
|
||||
expect(page).not_to have_link "Spending proposals"
|
||||
end
|
||||
|
||||
@@ -45,6 +46,7 @@ feature 'Admin feature flags' do
|
||||
visit admin_root_path
|
||||
|
||||
within('#side_menu') do
|
||||
expect(page).not_to have_link "Budgets"
|
||||
expect(page).not_to have_link "Spending proposals"
|
||||
end
|
||||
|
||||
|
||||
181
spec/features/admin/poll/booth_assigments_spec.rb
Normal file
181
spec/features/admin/poll/booth_assigments_spec.rb
Normal file
@@ -0,0 +1,181 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Admin booths assignments' do
|
||||
|
||||
background do
|
||||
admin = create(:administrator)
|
||||
login_as(admin.user)
|
||||
end
|
||||
|
||||
scenario 'Assign booth to poll', :js do
|
||||
poll = create(:poll)
|
||||
booth = create(:poll_booth)
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
within('#poll-resources') do
|
||||
click_link 'Booths (0)'
|
||||
end
|
||||
|
||||
expect(page).to have_content 'There are no booths assigned to this poll.'
|
||||
|
||||
fill_in 'search-booths', with: booth.name
|
||||
click_button 'Search'
|
||||
expect(page).to have_content(booth.name)
|
||||
|
||||
within('#search-booths-results') do
|
||||
click_link 'Assign booth'
|
||||
end
|
||||
|
||||
expect(page).to have_content 'Booth assigned'
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
within('#poll-resources') do
|
||||
click_link 'Booths (1)'
|
||||
end
|
||||
|
||||
expect(page).to_not have_content 'There are no booths assigned to this poll.'
|
||||
expect(page).to have_content booth.name
|
||||
end
|
||||
|
||||
scenario 'Remove booth from poll', :js do
|
||||
poll = create(:poll)
|
||||
booth = create(:poll_booth)
|
||||
assignment = create(:poll_booth_assignment, poll: poll, booth: booth)
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
within('#poll-resources') do
|
||||
click_link 'Booths (1)'
|
||||
end
|
||||
|
||||
expect(page).to_not have_content 'There are no booths assigned to this poll.'
|
||||
expect(page).to have_content booth.name
|
||||
|
||||
within("#poll_booth_assignment_#{assignment.id}") do
|
||||
click_link 'Remove booth from poll'
|
||||
end
|
||||
|
||||
expect(page).to have_content 'Booth not assigned anymore'
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
within('#poll-resources') do
|
||||
click_link 'Booths (0)'
|
||||
end
|
||||
|
||||
expect(page).to have_content 'There are no booths assigned to this poll.'
|
||||
expect(page).to_not have_content booth.name
|
||||
end
|
||||
|
||||
feature 'Show' do
|
||||
scenario 'Lists all assigned poll oficers' do
|
||||
poll = create(:poll)
|
||||
booth = create(:poll_booth)
|
||||
booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth)
|
||||
officer_assignment = create(:poll_officer_assignment, booth_assignment: booth_assignment)
|
||||
officer = officer_assignment.officer
|
||||
|
||||
booth_assignment_2 = create(:poll_booth_assignment, poll: poll)
|
||||
officer_assignment_2 = create(:poll_officer_assignment, booth_assignment: booth_assignment_2)
|
||||
officer_2 = officer_assignment_2.officer
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
click_link 'Booths (2)'
|
||||
|
||||
within('#assigned_booths_list') { click_link booth.name }
|
||||
|
||||
click_link 'Officers'
|
||||
within('#officers_list') do
|
||||
expect(page).to have_content officer.name
|
||||
expect(page).to_not have_content officer_2.name
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Lists all recounts for the booth assignment' do
|
||||
poll = create(:poll, starts_at: 2.weeks.ago, ends_at: 1.week.ago)
|
||||
booth = create(:poll_booth)
|
||||
booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth)
|
||||
officer_assignment_1 = create(:poll_officer_assignment, booth_assignment: booth_assignment, date: poll.starts_at)
|
||||
officer_assignment_2 = create(:poll_officer_assignment, booth_assignment: booth_assignment, date: poll.ends_at)
|
||||
final_officer_assignment = create(:poll_officer_assignment, :final, booth_assignment: booth_assignment, date: poll.ends_at)
|
||||
|
||||
recount_1 = create(:poll_recount,
|
||||
booth_assignment: booth_assignment,
|
||||
officer_assignment: officer_assignment_1,
|
||||
date: officer_assignment_1.date,
|
||||
count: 33)
|
||||
recount_2 = create(:poll_recount,
|
||||
booth_assignment: booth_assignment,
|
||||
officer_assignment: officer_assignment_2,
|
||||
date: officer_assignment_2.date,
|
||||
count: 78)
|
||||
final_recount = create(:poll_final_recount,
|
||||
booth_assignment: booth_assignment,
|
||||
officer_assignment: final_officer_assignment,
|
||||
date: final_officer_assignment.date,
|
||||
count: 5678)
|
||||
|
||||
booth_assignment_2 = create(:poll_booth_assignment, poll: poll)
|
||||
other_recount = create(:poll_recount, booth_assignment: booth_assignment_2, count: 100)
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
click_link 'Booths (2)'
|
||||
|
||||
within('#assigned_booths_list') { click_link booth.name }
|
||||
|
||||
click_link 'Recounts'
|
||||
within('#recounts_list') do
|
||||
expect(page).to_not have_content other_recount.count
|
||||
|
||||
within("#recounting_#{recount_1.date.strftime('%Y%m%d')}") do
|
||||
expect(page).to have_content recount_1.count
|
||||
end
|
||||
|
||||
within("#recounting_#{recount_2.date.strftime('%Y%m%d')}") do
|
||||
expect(page).to have_content recount_2.count
|
||||
end
|
||||
|
||||
within("#recounting_#{final_recount.date.strftime('%Y%m%d')}") do
|
||||
expect(page).to have_content final_recount.count
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Marks recount values with count-errors' do
|
||||
poll = create(:poll)
|
||||
booth = create(:poll_booth)
|
||||
booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth)
|
||||
today = Time.current.to_date
|
||||
officer_assignment = create(:poll_officer_assignment, booth_assignment: booth_assignment, date: today)
|
||||
|
||||
recount = create(:poll_recount,
|
||||
booth_assignment: booth_assignment,
|
||||
officer_assignment: officer_assignment,
|
||||
date: officer_assignment.date,
|
||||
count: 1)
|
||||
|
||||
visit admin_poll_booth_assignment_path(poll, booth_assignment)
|
||||
click_link 'Recounts'
|
||||
|
||||
within('#recounts_list') do
|
||||
expect(page).to have_css("#recounting_#{recount.date.strftime('%Y%m%d')} td.count-error")
|
||||
within("#recounting_#{recount.date.strftime('%Y%m%d')}") do
|
||||
expect(page).to have_content recount.count
|
||||
expect(page).to have_content 0
|
||||
end
|
||||
end
|
||||
|
||||
create(:poll_voter, :valid_document, poll: poll, booth_assignment: booth_assignment)
|
||||
|
||||
visit admin_poll_booth_assignment_path(poll, booth_assignment)
|
||||
click_link 'Recounts'
|
||||
|
||||
within('#recounts_list') do
|
||||
expect(page).to_not have_css('.count-error')
|
||||
within("#recounting_#{recount.date.strftime('%Y%m%d')}") do
|
||||
expect(page).to have_content(recount.count)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
86
spec/features/admin/poll/booths_spec.rb
Normal file
86
spec/features/admin/poll/booths_spec.rb
Normal file
@@ -0,0 +1,86 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Admin booths' do
|
||||
|
||||
background do
|
||||
admin = create(:administrator)
|
||||
login_as(admin.user)
|
||||
end
|
||||
|
||||
scenario 'Index empty' do
|
||||
visit admin_root_path
|
||||
|
||||
within('#side_menu') do
|
||||
click_link "Booths location"
|
||||
end
|
||||
|
||||
expect(page).to have_content "There are no booths"
|
||||
end
|
||||
|
||||
scenario 'Index' do
|
||||
3.times { create(:poll_booth) }
|
||||
|
||||
visit admin_root_path
|
||||
|
||||
within('#side_menu') do
|
||||
click_link "Booths location"
|
||||
end
|
||||
|
||||
booths = Poll::Booth.all
|
||||
booths.each do |booth|
|
||||
within("#booth_#{booth.id}") do
|
||||
expect(page).to have_content booth.name
|
||||
expect(page).to have_content booth.location
|
||||
end
|
||||
end
|
||||
expect(page).to_not have_content "There are no booths"
|
||||
end
|
||||
|
||||
scenario 'Show' do
|
||||
booth = create(:poll_booth)
|
||||
|
||||
visit admin_booths_path
|
||||
|
||||
expect(page).to have_content booth.name
|
||||
expect(page).to have_content booth.location
|
||||
end
|
||||
|
||||
scenario "Create" do
|
||||
visit admin_booths_path
|
||||
click_link "Add booth"
|
||||
|
||||
fill_in "poll_booth_name", with: "Upcoming booth"
|
||||
fill_in "poll_booth_location", with: "39th Street, number 2, ground floor"
|
||||
click_button "Create booth"
|
||||
|
||||
expect(page).to have_content "Booth created successfully"
|
||||
|
||||
visit admin_booths_path
|
||||
expect(page).to have_content "Upcoming booth"
|
||||
expect(page).to have_content "39th Street, number 2, ground floor"
|
||||
end
|
||||
|
||||
scenario "Edit" do
|
||||
booth = create(:poll_booth)
|
||||
|
||||
visit admin_booths_path
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Edit"
|
||||
end
|
||||
|
||||
fill_in "poll_booth_name", with: "Next booth"
|
||||
fill_in "poll_booth_location", with: "40th Street, number 1, firts floor"
|
||||
click_button "Update booth"
|
||||
|
||||
expect(page).to have_content "Booth updated successfully"
|
||||
|
||||
visit admin_booths_path
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
expect(page).to have_content "Next booth"
|
||||
expect(page).to have_content "40th Street, number 1, firts floor"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
97
spec/features/admin/poll/officer_assignments_spec.rb
Normal file
97
spec/features/admin/poll/officer_assignments_spec.rb
Normal file
@@ -0,0 +1,97 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Admin officer assignments in poll' do
|
||||
|
||||
background do
|
||||
admin = create(:administrator)
|
||||
login_as(admin.user)
|
||||
end
|
||||
|
||||
scenario 'Assign officer to poll', :js do
|
||||
booth_assignment = create(:poll_booth_assignment)
|
||||
officer = create(:poll_officer)
|
||||
|
||||
visit admin_poll_path(booth_assignment.poll)
|
||||
within('#poll-resources') do
|
||||
click_link 'Officers (0)'
|
||||
end
|
||||
|
||||
expect(page).to have_content 'There are no officers assigned to this poll'
|
||||
|
||||
fill_in 'search-officers', with: officer.name
|
||||
click_button 'Search'
|
||||
|
||||
within('#search-officers-results') do
|
||||
click_link 'Add shifts as officer'
|
||||
end
|
||||
|
||||
expect(page).to have_content 'This user has no officing shifts in this poll'
|
||||
expect(page).to have_content officer.name
|
||||
expect(page).to have_content booth_assignment.poll.name
|
||||
|
||||
within('#officer_assignment_form') do
|
||||
select I18n.l(booth_assignment.poll.ends_at.to_date, format: :long), from: 'date'
|
||||
select "#{booth_assignment.booth.name} (#{booth_assignment.booth.location})", from: 'booth_id'
|
||||
click_button 'Add shift'
|
||||
end
|
||||
|
||||
expect(page).to have_content 'Officing shift added'
|
||||
expect(page).to_not have_content 'This user has no officing shifts in this poll'
|
||||
|
||||
visit admin_poll_path(booth_assignment.poll)
|
||||
within('#poll-resources') do
|
||||
click_link 'Officers (1)'
|
||||
end
|
||||
|
||||
expect(page).to_not have_content 'There are no officers in this poll'
|
||||
expect(page).to have_content officer.name
|
||||
expect(page).to have_content officer.email
|
||||
end
|
||||
|
||||
scenario 'Remove officer assignment from poll' do
|
||||
officer_assignment = create(:poll_officer_assignment)
|
||||
poll = officer_assignment.booth_assignment.poll
|
||||
booth = officer_assignment.booth_assignment.booth
|
||||
officer = officer_assignment.officer
|
||||
|
||||
visit by_officer_admin_poll_officer_assignments_path(poll, officer_id: officer.id)
|
||||
|
||||
expect(page).to_not have_content 'This user has no officing shifts in this poll'
|
||||
within("#poll_officer_assignment_#{officer_assignment.id}") do
|
||||
expect(page).to have_content booth.name
|
||||
click_link 'Remove'
|
||||
end
|
||||
|
||||
expect(page).to have_content 'Officing shift removed'
|
||||
expect(page).to have_content 'This user has no officing shifts in this poll'
|
||||
end
|
||||
|
||||
scenario 'Index view shows recounts info for officer' do
|
||||
booth_assignment = create(:poll_booth_assignment)
|
||||
poll = booth_assignment.poll
|
||||
officer = create(:poll_officer)
|
||||
officer_assignment = create(:poll_officer_assignment,
|
||||
booth_assignment: booth_assignment,
|
||||
officer: officer,
|
||||
date: poll.starts_at)
|
||||
final_officer_assignment = create(:poll_officer_assignment, :final,
|
||||
booth_assignment: booth_assignment,
|
||||
officer: officer,
|
||||
date: poll.ends_at + 1.day)
|
||||
recount = create(:poll_recount,
|
||||
booth_assignment: booth_assignment,
|
||||
officer_assignment: officer_assignment,
|
||||
date: officer_assignment.date,
|
||||
count: 77)
|
||||
final_recount = create(:poll_final_recount,
|
||||
booth_assignment: booth_assignment,
|
||||
officer_assignment: final_officer_assignment,
|
||||
date: poll.ends_at,
|
||||
count: 9876)
|
||||
|
||||
visit by_officer_admin_poll_officer_assignments_path(poll, officer_id: officer.id)
|
||||
|
||||
within('#recount_list') { expect(page).to have_content('77') }
|
||||
within('#final_recount_list') { expect(page).to have_content('9876') }
|
||||
end
|
||||
end
|
||||
36
spec/features/admin/poll/officers_spec.rb
Normal file
36
spec/features/admin/poll/officers_spec.rb
Normal file
@@ -0,0 +1,36 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Admin poll officers' do
|
||||
|
||||
background do
|
||||
@admin = create(:administrator)
|
||||
@user = create(:user, username: 'Pedro Jose Garcia')
|
||||
@officer = create(:poll_officer)
|
||||
login_as(@admin.user)
|
||||
visit admin_officers_path
|
||||
end
|
||||
|
||||
scenario 'Index' do
|
||||
expect(page).to have_content @officer.name
|
||||
expect(page).to have_content @officer.email
|
||||
expect(page).to_not have_content @user.name
|
||||
end
|
||||
|
||||
scenario 'Create', :js do
|
||||
fill_in 'email', with: @user.email
|
||||
click_button 'Search'
|
||||
|
||||
expect(page).to have_content @user.name
|
||||
click_link 'Add'
|
||||
within("#officers") do
|
||||
expect(page).to have_content @user.name
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Delete' do
|
||||
click_link 'Delete position'
|
||||
|
||||
expect(page).to_not have_css '#officers'
|
||||
end
|
||||
|
||||
end
|
||||
366
spec/features/admin/poll/polls_spec.rb
Normal file
366
spec/features/admin/poll/polls_spec.rb
Normal file
@@ -0,0 +1,366 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Admin polls' do
|
||||
|
||||
background do
|
||||
admin = create(:administrator)
|
||||
login_as(admin.user)
|
||||
end
|
||||
|
||||
scenario 'Index empty', :js do
|
||||
visit admin_root_path
|
||||
|
||||
click_link "Polls"
|
||||
within('#polls_menu') do
|
||||
click_link "Polls"
|
||||
end
|
||||
|
||||
expect(page).to have_content "There are no polls"
|
||||
end
|
||||
|
||||
scenario 'Index', :js do
|
||||
3.times { create(:poll) }
|
||||
|
||||
visit admin_root_path
|
||||
|
||||
click_link "Polls"
|
||||
within('#polls_menu') do
|
||||
click_link "Polls"
|
||||
end
|
||||
|
||||
expect(page).to have_css ".poll", count: 3
|
||||
|
||||
polls = Poll.all
|
||||
polls.each do |poll|
|
||||
within("#poll_#{poll.id}") do
|
||||
expect(page).to have_content poll.name
|
||||
end
|
||||
end
|
||||
expect(page).to_not have_content "There are no polls"
|
||||
end
|
||||
|
||||
scenario 'Show' do
|
||||
poll = create(:poll)
|
||||
|
||||
visit admin_polls_path
|
||||
click_link poll.name
|
||||
|
||||
expect(page).to have_content poll.name
|
||||
end
|
||||
|
||||
scenario "Create" do
|
||||
visit admin_polls_path
|
||||
click_link "Create poll"
|
||||
|
||||
start_date = 1.week.from_now
|
||||
end_date = 2.weeks.from_now
|
||||
|
||||
fill_in "poll_name", with: "Upcoming poll"
|
||||
fill_in 'poll_starts_at', with: start_date.strftime("%d/%m/%Y")
|
||||
fill_in 'poll_ends_at', with: end_date.strftime("%d/%m/%Y")
|
||||
click_button "Create poll"
|
||||
|
||||
expect(page).to have_content "Poll created successfully"
|
||||
expect(page).to have_content "Upcoming poll"
|
||||
expect(page).to have_content I18n.l(start_date.to_date)
|
||||
expect(page).to have_content I18n.l(end_date.to_date)
|
||||
end
|
||||
|
||||
scenario "Edit" do
|
||||
poll = create(:poll)
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
click_link "Edit"
|
||||
|
||||
end_date = 1.year.from_now
|
||||
|
||||
fill_in "poll_name", with: "Next Poll"
|
||||
fill_in 'poll_ends_at', with: end_date.strftime("%d/%m/%Y")
|
||||
click_button "Update poll"
|
||||
|
||||
expect(page).to have_content "Poll updated successfully"
|
||||
expect(page).to have_content "Next Poll"
|
||||
expect(page).to have_content I18n.l(end_date.to_date)
|
||||
end
|
||||
|
||||
scenario 'Edit from index' do
|
||||
poll = create(:poll)
|
||||
visit admin_polls_path
|
||||
|
||||
within("#poll_#{poll.id}") do
|
||||
click_link "Edit"
|
||||
end
|
||||
|
||||
expect(current_path).to eq(edit_admin_poll_path(poll))
|
||||
end
|
||||
|
||||
context "Booths" do
|
||||
|
||||
context "Poll show" do
|
||||
|
||||
scenario "No booths" do
|
||||
poll = create(:poll)
|
||||
visit admin_poll_path(poll)
|
||||
click_link "Booths (0)"
|
||||
|
||||
expect(page).to have_content "There are no booths assigned to this poll."
|
||||
end
|
||||
|
||||
scenario "Booth list" do
|
||||
poll = create(:poll)
|
||||
3.times { create(:poll_booth, polls: [poll]) }
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
click_link "Booths (3)"
|
||||
|
||||
expect(page).to have_css ".booth", count: 3
|
||||
|
||||
poll.booth_assignments.each do |ba|
|
||||
within("#poll_booth_assignment_#{ba.id}") do
|
||||
expect(page).to have_content ba.booth.name
|
||||
expect(page).to have_content ba.booth.location
|
||||
end
|
||||
end
|
||||
expect(page).to_not have_content "There are no booths assigned to this poll."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "Officers" do
|
||||
|
||||
context "Poll show" do
|
||||
|
||||
scenario "No officers", :js do
|
||||
poll = create(:poll)
|
||||
visit admin_poll_path(poll)
|
||||
click_link "Officers (0)"
|
||||
|
||||
expect(page).to have_content "There are no officers assigned to this poll"
|
||||
end
|
||||
|
||||
scenario "Officer list", :js do
|
||||
poll = create(:poll)
|
||||
booth = create(:poll_booth, polls: [poll])
|
||||
|
||||
booth.booth_assignments.each do |booth_assignment|
|
||||
3.times {create(:poll_officer_assignment, booth_assignment: booth_assignment) }
|
||||
end
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
|
||||
click_link "Officers (3)"
|
||||
|
||||
expect(page).to have_css ".officer", count: 3
|
||||
|
||||
officers = Poll::Officer.all
|
||||
officers.each do |officer|
|
||||
within("#officer_#{officer.id}") do
|
||||
expect(page).to have_content officer.name
|
||||
expect(page).to have_content officer.email
|
||||
end
|
||||
end
|
||||
expect(page).to_not have_content "There are no officers assigned to this poll"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "Questions" do
|
||||
|
||||
context "Poll show" do
|
||||
|
||||
scenario "Question list", :js do
|
||||
poll = create(:poll)
|
||||
question = create(:poll_question, poll: poll)
|
||||
other_question = create(:poll_question)
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
|
||||
expect(page).to have_content "Questions (1)"
|
||||
expect(page).to have_content question.title
|
||||
expect(page).to_not have_content other_question.title
|
||||
expect(page).to_not have_content "There are no questions assigned to this poll"
|
||||
end
|
||||
|
||||
scenario 'Add question to poll', :js do
|
||||
poll = create(:poll)
|
||||
question = create(:poll_question, poll: nil, title: 'Should we rebuild the city?')
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
|
||||
expect(page).to have_content 'Questions (0)'
|
||||
expect(page).to have_content 'There are no questions assigned to this poll'
|
||||
|
||||
fill_in 'search-questions', with: 'rebuild'
|
||||
click_button 'Search'
|
||||
|
||||
within('#search-questions-results') do
|
||||
click_link 'Include question'
|
||||
end
|
||||
|
||||
expect(page).to have_content 'Question added to this poll'
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
|
||||
expect(page).to have_content 'Questions (1)'
|
||||
expect(page).to_not have_content 'There are no questions assigned to this poll'
|
||||
expect(page).to have_content question.title
|
||||
end
|
||||
|
||||
scenario 'Remove question from poll', :js do
|
||||
poll = create(:poll)
|
||||
question = create(:poll_question, poll: poll)
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
|
||||
expect(page).to have_content 'Questions (1)'
|
||||
expect(page).to_not have_content 'There are no questions assigned to this poll'
|
||||
expect(page).to have_content question.title
|
||||
|
||||
within("#poll_question_#{question.id}") do
|
||||
click_link 'Remove question from poll'
|
||||
end
|
||||
|
||||
expect(page).to have_content 'Question removed from this poll'
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
|
||||
expect(page).to have_content 'Questions (0)'
|
||||
expect(page).to have_content 'There are no questions assigned to this poll'
|
||||
expect(page).to_not have_content question.title
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
context "Recounting" do
|
||||
context "Poll show" do
|
||||
scenario "No recounts", :js do
|
||||
poll = create(:poll)
|
||||
visit admin_poll_path(poll)
|
||||
click_link "Recounting"
|
||||
|
||||
expect(page).to have_content "There is nothing to be recounted"
|
||||
end
|
||||
|
||||
scenario "Recounts list", :js do
|
||||
poll = create(:poll)
|
||||
booth_assignment = create(:poll_booth_assignment, poll: poll)
|
||||
booth_assignment_recounted = create(:poll_booth_assignment, poll: poll)
|
||||
booth_assignment_final_recounted = create(:poll_booth_assignment, poll: poll)
|
||||
|
||||
3.times { |i| create(:poll_recount,
|
||||
booth_assignment: booth_assignment,
|
||||
date: poll.starts_at + i.days,
|
||||
count: 33) }
|
||||
|
||||
3.times { |i| create(:poll_final_recount,
|
||||
booth_assignment: booth_assignment,
|
||||
date: poll.starts_at + i.days,
|
||||
count: 21) }
|
||||
|
||||
2.times { create(:poll_voter,
|
||||
booth_assignment: booth_assignment_final_recounted) }
|
||||
|
||||
create(:poll_recount,
|
||||
booth_assignment: booth_assignment_recounted,
|
||||
date: poll.ends_at,
|
||||
count: 777)
|
||||
|
||||
create(:poll_final_recount,
|
||||
booth_assignment: booth_assignment_final_recounted,
|
||||
date: poll.ends_at,
|
||||
count: 55555)
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
|
||||
click_link "Recounting"
|
||||
|
||||
expect(page).to have_css ".booth_recounts", count: 3
|
||||
|
||||
within("#poll_booth_assignment_#{booth_assignment.id}_recounts") do
|
||||
expect(page).to have_content(booth_assignment.booth.name)
|
||||
expect(page).to have_content('99')
|
||||
expect(page).to have_content('63')
|
||||
end
|
||||
|
||||
within("#poll_booth_assignment_#{booth_assignment_recounted.id}_recounts") do
|
||||
expect(page).to have_content(booth_assignment_recounted.booth.name)
|
||||
expect(page).to have_content('777')
|
||||
expect(page).to have_content('-')
|
||||
end
|
||||
|
||||
within("#poll_booth_assignment_#{booth_assignment_final_recounted.id}_recounts") do
|
||||
expect(page).to have_content(booth_assignment_final_recounted.booth.name)
|
||||
expect(page).to have_content('-')
|
||||
expect(page).to have_content('55555')
|
||||
expect(page).to have_content('2')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "Results" do
|
||||
context "Poll show" do
|
||||
scenario "No results", :js do
|
||||
poll = create(:poll)
|
||||
visit admin_poll_path(poll)
|
||||
click_link "Results"
|
||||
|
||||
expect(page).to have_content "There are no results"
|
||||
end
|
||||
|
||||
scenario "Results by answer", :js do
|
||||
poll = create(:poll)
|
||||
booth_assignment_1 = create(:poll_booth_assignment, poll: poll)
|
||||
booth_assignment_2 = create(:poll_booth_assignment, poll: poll)
|
||||
booth_assignment_3 = create(:poll_booth_assignment, poll: poll)
|
||||
|
||||
question_1 = create(:poll_question, poll: poll, valid_answers: "Yes,No")
|
||||
question_2 = create(:poll_question, poll: poll, valid_answers: "Today,Tomorrow")
|
||||
|
||||
[booth_assignment_1, booth_assignment_2, booth_assignment_3].each do |ba|
|
||||
create(:poll_partial_result,
|
||||
booth_assignment: ba,
|
||||
question: question_1,
|
||||
answer: 'Yes',
|
||||
amount: 11)
|
||||
create(:poll_partial_result,
|
||||
booth_assignment: ba,
|
||||
question: question_2,
|
||||
answer: 'Tomorrow',
|
||||
amount: 5)
|
||||
end
|
||||
create(:poll_white_result,
|
||||
booth_assignment: booth_assignment_1,
|
||||
amount: 21)
|
||||
create(:poll_null_result,
|
||||
booth_assignment: booth_assignment_3,
|
||||
amount: 44)
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
|
||||
click_link "Results"
|
||||
|
||||
expect(page).to have_content(question_1.title)
|
||||
question_1.valid_answers.each_with_index do |answer, i|
|
||||
within("#question_#{question_1.id}_#{i}_result") do
|
||||
expect(page).to have_content(answer)
|
||||
expect(page).to have_content([33, 0][i])
|
||||
end
|
||||
end
|
||||
|
||||
expect(page).to have_content(question_2.title)
|
||||
question_2.valid_answers.each_with_index do |answer, i|
|
||||
within("#question_#{question_2.id}_#{i}_result") do
|
||||
expect(page).to have_content(answer)
|
||||
expect(page).to have_content([0,15][i])
|
||||
end
|
||||
end
|
||||
|
||||
within('#white_results') { expect(page).to have_content('21') }
|
||||
within('#null_results') { expect(page).to have_content('44') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
116
spec/features/admin/poll/questions_spec.rb
Normal file
116
spec/features/admin/poll/questions_spec.rb
Normal file
@@ -0,0 +1,116 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Admin poll questions' do
|
||||
|
||||
background do
|
||||
login_as(create(:administrator).user)
|
||||
end
|
||||
|
||||
scenario 'Index' do
|
||||
question1 = create(:poll_question)
|
||||
question2 = create(:poll_question)
|
||||
|
||||
visit admin_questions_path
|
||||
|
||||
expect(page).to have_content(question1.title)
|
||||
expect(page).to have_content(question2.title)
|
||||
end
|
||||
|
||||
scenario 'Show' do
|
||||
geozone = create(:geozone)
|
||||
poll = create(:poll, geozone_restricted: true, geozone_ids: [geozone.id])
|
||||
question = create(:poll_question, poll: poll)
|
||||
|
||||
visit admin_question_path(question)
|
||||
|
||||
expect(page).to have_content(question.title)
|
||||
expect(page).to have_content(question.description)
|
||||
expect(page).to have_content(question.author.name)
|
||||
expect(page).to have_content(question.valid_answers.join(" "))
|
||||
end
|
||||
|
||||
scenario 'Create' do
|
||||
poll = create(:poll, name: 'Movies')
|
||||
title = "Star Wars: Episode IV - A New Hope"
|
||||
description = %{
|
||||
During the battle, Rebel spies managed to steal secret plans to the Empire's ultimate weapon, the DEATH STAR, an armored space station with enough power to destroy an entire planet.
|
||||
Pursued by the Empire's sinister agents, Princess Leia races home aboard her starship, custodian of the stolen plans that can save her people and restore freedom to the galaxy....
|
||||
}
|
||||
|
||||
visit admin_questions_path
|
||||
click_link "Create question"
|
||||
|
||||
select 'Movies', from: 'poll_question_poll_id'
|
||||
fill_in 'poll_question_title', with: title
|
||||
fill_in 'poll_question_description', with: description
|
||||
|
||||
click_button 'Save'
|
||||
|
||||
expect(page).to have_content(title)
|
||||
expect(page).to have_content(description)
|
||||
end
|
||||
|
||||
scenario 'Create from successful proposal index' do
|
||||
poll = create(:poll, name: 'Proposals')
|
||||
proposal = create(:proposal, :successful)
|
||||
|
||||
visit proposals_path
|
||||
click_link "Create question"
|
||||
|
||||
expect(current_path).to eq(new_admin_question_path)
|
||||
expect(page).to have_field('poll_question_title', with: proposal.title)
|
||||
expect(page).to have_field('poll_question_description', with: proposal.description)
|
||||
expect(page).to have_field('poll_question_valid_answers', with: "Yes, No")
|
||||
|
||||
select 'Proposals', from: 'poll_question_poll_id'
|
||||
|
||||
click_button 'Save'
|
||||
|
||||
expect(page).to have_content(proposal.title)
|
||||
expect(page).to have_content(proposal.description)
|
||||
expect(page).to have_link(proposal.title, href: proposal_path(proposal))
|
||||
expect(page).to have_link(proposal.author.name, href: user_path(proposal.author))
|
||||
end
|
||||
|
||||
pending "Create from successul proposal show"
|
||||
|
||||
scenario 'Update' do
|
||||
question1 = create(:poll_question)
|
||||
|
||||
visit admin_questions_path
|
||||
within("#poll_question_#{question1.id}") do
|
||||
click_link "Edit"
|
||||
end
|
||||
|
||||
old_title = question1.title
|
||||
new_title = "Potatoes are great and everyone should have one"
|
||||
fill_in 'poll_question_title', with: new_title
|
||||
|
||||
click_button 'Save'
|
||||
|
||||
expect(page).to have_content "Changes saved"
|
||||
expect(page).to have_content new_title
|
||||
|
||||
visit admin_questions_path
|
||||
|
||||
expect(page).to have_content(new_title)
|
||||
expect(page).to_not have_content(old_title)
|
||||
end
|
||||
|
||||
scenario 'Destroy' do
|
||||
question1 = create(:poll_question)
|
||||
question2 = create(:poll_question)
|
||||
|
||||
visit admin_questions_path
|
||||
|
||||
within("#poll_question_#{question1.id}") do
|
||||
click_link "Delete"
|
||||
end
|
||||
|
||||
expect(page).to_not have_content(question1.title)
|
||||
expect(page).to have_content(question2.title)
|
||||
end
|
||||
|
||||
pending "Mark all city by default when creating a poll question from a successful proposal"
|
||||
|
||||
end
|
||||
@@ -93,11 +93,11 @@ feature 'Admin spending proposals' do
|
||||
expect(page).to have_button("Update")
|
||||
click_link("Back")
|
||||
expect(page).to_not have_button("Update")
|
||||
expect(page).to have_link("Back")
|
||||
click_link("Back")
|
||||
|
||||
expect(page).to_not have_link("Destroy the city")
|
||||
expect(page).to have_link("Realocate visitors")
|
||||
|
||||
end
|
||||
|
||||
scenario "Filtering by admin", :js do
|
||||
@@ -135,8 +135,10 @@ feature 'Admin spending proposals' do
|
||||
click_link("Realocate visitors")
|
||||
click_link("Edit classification")
|
||||
expect(page).to have_button("Update")
|
||||
expect(page).to have_link("Back")
|
||||
click_link("Back")
|
||||
expect(page).to_not have_button("Update")
|
||||
expect(page).to have_link("Back")
|
||||
click_link("Back")
|
||||
|
||||
expect(page).to have_content('There is 1 spending proposal')
|
||||
@@ -182,8 +184,10 @@ feature 'Admin spending proposals' do
|
||||
click_link("Realocate visitors")
|
||||
click_link("Edit classification")
|
||||
expect(page).to have_button("Update")
|
||||
expect(page).to have_link("Back")
|
||||
click_link("Back")
|
||||
expect(page).to_not have_button("Update")
|
||||
expect(page).to have_link("Back")
|
||||
click_link("Back")
|
||||
|
||||
expect(page).to have_content('There is 1 spending proposal')
|
||||
|
||||
@@ -16,7 +16,7 @@ feature 'Admin' do
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as a moderator is not authorized' do
|
||||
scenario 'Access as moderator is not authorized' do
|
||||
create(:moderator, user: user)
|
||||
login_as(user)
|
||||
visit admin_root_path
|
||||
@@ -26,7 +26,7 @@ feature 'Admin' do
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as a valuator is not authorized' do
|
||||
scenario 'Access as valuator is not authorized' do
|
||||
create(:valuator, user: user)
|
||||
login_as(user)
|
||||
visit admin_root_path
|
||||
@@ -36,7 +36,7 @@ feature 'Admin' do
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as a manager is not authorized' do
|
||||
scenario 'Access as manager is not authorized' do
|
||||
create(:manager, user: user)
|
||||
login_as(user)
|
||||
visit admin_root_path
|
||||
@@ -46,7 +46,17 @@ feature 'Admin' do
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as an administrator is authorized' do
|
||||
scenario 'Access as poll officer is not authorized' do
|
||||
create(:poll_officer, user: user)
|
||||
login_as(user)
|
||||
visit admin_root_path
|
||||
|
||||
expect(current_path).not_to eq(admin_root_path)
|
||||
expect(current_path).to eq(proposals_path)
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as administrator is authorized' do
|
||||
login_as(administrator)
|
||||
visit admin_root_path
|
||||
|
||||
|
||||
1
spec/features/comments/poll_questions_spec.rb
Normal file
1
spec/features/comments/poll_questions_spec.rb
Normal file
@@ -0,0 +1 @@
|
||||
#refactor specs and test as one more commmentable
|
||||
@@ -43,7 +43,7 @@ feature "Home" do
|
||||
end
|
||||
|
||||
def ie_alert_box_xpath
|
||||
"/html/body/div[@class='wrapper']/comment()[contains(.,'ie-callout')]"
|
||||
"/html/body/div[@class='wrapper ']/comment()[contains(.,'ie-callout')]"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -84,6 +84,8 @@ feature 'Moderate comments' do
|
||||
end
|
||||
|
||||
scenario "select all/none", :js do
|
||||
Capybara.current_driver = :poltergeist_no_js_errors
|
||||
|
||||
create_list(:comment, 2)
|
||||
|
||||
visit moderation_comments_path
|
||||
|
||||
@@ -91,6 +91,8 @@ feature 'Moderate debates' do
|
||||
end
|
||||
|
||||
scenario "select all/none", :js do
|
||||
Capybara.current_driver = :poltergeist_no_js_errors
|
||||
|
||||
create_list(:debate, 2)
|
||||
|
||||
visit moderation_debates_path
|
||||
|
||||
@@ -83,6 +83,8 @@ feature 'Moderate proposals' do
|
||||
end
|
||||
|
||||
scenario "select all/none", :js do
|
||||
Capybara.current_driver = :poltergeist_no_js_errors
|
||||
|
||||
create_list(:proposal, 2)
|
||||
|
||||
visit moderation_proposals_path
|
||||
|
||||
@@ -43,6 +43,20 @@ feature 'Moderation' do
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as poll officer is not authorized' do
|
||||
create(:poll_officer, user: user)
|
||||
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to_not have_link("Moderation")
|
||||
visit moderation_root_path
|
||||
|
||||
expect(current_path).not_to eq(moderation_root_path)
|
||||
expect(current_path).to eq(proposals_path)
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as a moderator is authorized' do
|
||||
create(:moderator, user: user)
|
||||
|
||||
|
||||
147
spec/features/officing/final_recount_spec.rb
Normal file
147
spec/features/officing/final_recount_spec.rb
Normal file
@@ -0,0 +1,147 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Officing Final Recount' do
|
||||
|
||||
background do
|
||||
@poll_officer = create(:poll_officer)
|
||||
@officer_assignment = create(:poll_officer_assignment, :final, officer: @poll_officer)
|
||||
@poll = @officer_assignment.booth_assignment.poll
|
||||
@poll.update(ends_at: 1.day.ago)
|
||||
login_as(@poll_officer.user)
|
||||
end
|
||||
|
||||
scenario 'Only polls where user is officer for final recounts are accessible' do
|
||||
regular_officer_assignment_1 = create(:poll_officer_assignment, officer: @poll_officer)
|
||||
regular_officer_assignment_2 = create(:poll_officer_assignment, officer: @poll_officer)
|
||||
|
||||
not_allowed_poll_1 = create(:poll, :expired)
|
||||
not_allowed_poll_2 = regular_officer_assignment_1.booth_assignment.poll
|
||||
not_allowed_poll_2.update(ends_at: 1.day.ago)
|
||||
not_allowed_poll_3 = regular_officer_assignment_2.booth_assignment.poll
|
||||
|
||||
visit root_path
|
||||
click_link 'Polling officers'
|
||||
|
||||
expect(page).to have_content('Poll officing')
|
||||
within('#side_menu') do
|
||||
click_link 'Final recounts and results'
|
||||
end
|
||||
|
||||
expect(page).to_not have_content(not_allowed_poll_1.name)
|
||||
expect(page).to_not have_content(not_allowed_poll_2.name)
|
||||
expect(page).to_not have_content(not_allowed_poll_3.name)
|
||||
expect(page).to have_content(@poll.name)
|
||||
|
||||
visit new_officing_poll_final_recount_path(not_allowed_poll_1)
|
||||
expect(page).to have_content('You are allowed to add final recounts for this poll')
|
||||
end
|
||||
|
||||
scenario 'Add final recount' do
|
||||
visit officing_root_path
|
||||
|
||||
within('#side_menu') do
|
||||
click_link 'Final recounts and results'
|
||||
end
|
||||
|
||||
within("#poll_#{@poll.id}") do
|
||||
expect(page).to have_content(@poll.name)
|
||||
click_link 'Add final recount'
|
||||
end
|
||||
|
||||
expect(page).to_not have_content('Your recounts')
|
||||
|
||||
booth_name = @officer_assignment.booth_assignment.booth.name
|
||||
date = I18n.l(@poll.starts_at.to_date, format: :long)
|
||||
select booth_name, from: 'officer_assignment_id'
|
||||
select date, from: 'date'
|
||||
fill_in :count, with: '33'
|
||||
click_button 'Save'
|
||||
|
||||
expect(page).to have_content('Your final recounts')
|
||||
|
||||
within("#poll_final_recount_#{@officer_assignment.booth_assignment.final_recounts.first.id}") do
|
||||
expect(page).to have_content(date)
|
||||
expect(page).to have_content(booth_name)
|
||||
expect(page).to have_content('33')
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Edit final recount' do
|
||||
final_recount = create(:poll_final_recount,
|
||||
officer_assignment: @officer_assignment,
|
||||
booth_assignment: @officer_assignment.booth_assignment,
|
||||
date: @poll.starts_at,
|
||||
count: 100)
|
||||
|
||||
booth_name = @officer_assignment.booth_assignment.booth.name
|
||||
date = I18n.l(final_recount.date.to_date, format: :long)
|
||||
|
||||
visit new_officing_poll_final_recount_path(@poll)
|
||||
|
||||
expect(page).to have_content('Your final recounts')
|
||||
|
||||
within("#poll_final_recount_#{final_recount.id}") do
|
||||
expect(page).to have_content(date)
|
||||
expect(page).to have_content(booth_name)
|
||||
expect(page).to have_content('100')
|
||||
end
|
||||
|
||||
select booth_name, from: 'officer_assignment_id'
|
||||
select date, from: 'date'
|
||||
fill_in :count, with: '42'
|
||||
click_button 'Save'
|
||||
|
||||
expect(page).to have_content "Data added"
|
||||
|
||||
within("#poll_final_recount_#{final_recount.id}") do
|
||||
expect(page).to have_content(date)
|
||||
expect(page).to have_content(booth_name)
|
||||
expect(page).to have_content('42')
|
||||
end
|
||||
expect(page).to_not have_content('100')
|
||||
end
|
||||
|
||||
scenario 'Show final and system recounts to compare' do
|
||||
final_officer_assignment = create(:poll_officer_assignment, :final, officer: @poll_officer)
|
||||
poll = final_officer_assignment.booth_assignment.poll
|
||||
poll.update(ends_at: 1.day.ago)
|
||||
final_recount = create(:poll_final_recount,
|
||||
officer_assignment: final_officer_assignment,
|
||||
booth_assignment: final_officer_assignment.booth_assignment,
|
||||
date: 7.days.ago,
|
||||
count: 100)
|
||||
33.times { create(:poll_voter, :valid_document,
|
||||
poll: poll,
|
||||
booth_assignment: final_officer_assignment.booth_assignment,
|
||||
created_at: final_recount.date) }
|
||||
|
||||
visit new_officing_poll_final_recount_path(poll)
|
||||
within("#poll_final_recount_#{final_recount.id}") do
|
||||
expect(page).to have_content(I18n.l(final_recount.date.to_date, format: :long))
|
||||
expect(page).to have_content(final_officer_assignment.booth_assignment.booth.name)
|
||||
expect(page).to have_content('100')
|
||||
expect(page).to have_content('33')
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Show link to add results for same booth/date" do
|
||||
final_officer_assignment = create(:poll_officer_assignment, :final, officer: @poll_officer)
|
||||
poll = final_officer_assignment.booth_assignment.poll
|
||||
poll.update(ends_at: 1.day.ago)
|
||||
final_recount = create(:poll_final_recount,
|
||||
officer_assignment: final_officer_assignment,
|
||||
booth_assignment: final_officer_assignment.booth_assignment,
|
||||
date: 7.days.ago,
|
||||
count: 100)
|
||||
visit new_officing_poll_final_recount_path(poll)
|
||||
within("#poll_final_recount_#{final_recount.id}") do
|
||||
click_link "Add results"
|
||||
end
|
||||
|
||||
expected_path = new_officing_poll_result_path(poll, oa: final_recount.officer_assignment.id, d: I18n.l(final_recount.date.to_date))
|
||||
expect(page).to have_current_path(expected_path)
|
||||
expect(page).to have_select('officer_assignment_id', selected: final_recount.booth_assignment.booth.name)
|
||||
expect(page).to have_select('date', selected: I18n.l(final_recount.date.to_date, format: :long))
|
||||
end
|
||||
|
||||
end
|
||||
87
spec/features/officing/recount_spec.rb
Normal file
87
spec/features/officing/recount_spec.rb
Normal file
@@ -0,0 +1,87 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Officing Recount' do
|
||||
|
||||
background do
|
||||
@poll_officer = create(:poll_officer)
|
||||
@officer_assignment = create(:poll_officer_assignment, officer: @poll_officer)
|
||||
@poll = @officer_assignment.booth_assignment.poll
|
||||
login_as(@poll_officer.user)
|
||||
end
|
||||
|
||||
scenario 'Only polls where user is officer are accessible' do
|
||||
not_allowed_poll = create(:poll)
|
||||
|
||||
visit root_path
|
||||
click_link 'Polling officers'
|
||||
|
||||
expect(page).to have_content('Poll officing')
|
||||
within('#side_menu') do
|
||||
click_link 'Store recount'
|
||||
end
|
||||
|
||||
expect(page).to_not have_content(not_allowed_poll.name)
|
||||
expect(page).to have_content(@poll.name)
|
||||
|
||||
visit new_officing_poll_recount_path(not_allowed_poll)
|
||||
expect(page).to have_content('You are not a poll officer for this poll')
|
||||
end
|
||||
|
||||
scenario 'Add recount' do
|
||||
visit officing_root_path
|
||||
|
||||
within('#side_menu') do
|
||||
click_link 'Store recount'
|
||||
end
|
||||
|
||||
click_link @poll.name
|
||||
|
||||
expect(page).to_not have_content('Your recounts')
|
||||
|
||||
booth_name = @officer_assignment.booth_assignment.booth.name
|
||||
date = I18n.l(@officer_assignment.date.to_date, format: :long)
|
||||
select "#{booth_name}: #{date}", from: 'officer_assignment_id'
|
||||
fill_in :count, with: '33'
|
||||
click_button 'Save'
|
||||
|
||||
expect(page).to have_content('Your recounts')
|
||||
|
||||
within("#poll_recount_#{@officer_assignment.booth_assignment.recounts.first.id}") do
|
||||
expect(page).to have_content(date)
|
||||
expect(page).to have_content(booth_name)
|
||||
expect(page).to have_content('33')
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Edit recount' do
|
||||
recount = create(:poll_recount,
|
||||
officer_assignment: @officer_assignment,
|
||||
booth_assignment: @officer_assignment.booth_assignment,
|
||||
date: @officer_assignment.date,
|
||||
count: 100)
|
||||
|
||||
booth_name = @officer_assignment.booth_assignment.booth.name
|
||||
date = I18n.l(@officer_assignment.date.to_date, format: :long)
|
||||
|
||||
visit new_officing_poll_recount_path(@poll)
|
||||
|
||||
expect(page).to have_content('Your recounts')
|
||||
|
||||
within("#poll_recount_#{recount.id}") do
|
||||
expect(page).to have_content(date)
|
||||
expect(page).to have_content(booth_name)
|
||||
expect(page).to have_content('100')
|
||||
end
|
||||
|
||||
select "#{booth_name}: #{date}", from: 'officer_assignment_id'
|
||||
fill_in :count, with: '42'
|
||||
click_button 'Save'
|
||||
|
||||
within("#poll_recount_#{recount.id}") do
|
||||
expect(page).to have_content(date)
|
||||
expect(page).to have_content(booth_name)
|
||||
expect(page).to have_content('42')
|
||||
end
|
||||
expect(page).to_not have_content('100')
|
||||
end
|
||||
end
|
||||
96
spec/features/officing/residence_spec.rb
Normal file
96
spec/features/officing/residence_spec.rb
Normal file
@@ -0,0 +1,96 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Residence' do
|
||||
let(:officer) { create(:poll_officer) }
|
||||
|
||||
feature "Officers without assignments" do
|
||||
|
||||
scenario "Can not access residence verification" do
|
||||
login_as(officer.user)
|
||||
visit officing_root_path
|
||||
|
||||
within("#side_menu") do
|
||||
click_link "Validate document"
|
||||
end
|
||||
|
||||
expect(page).to have_content("You don't have officing shifts today")
|
||||
|
||||
create(:poll_officer_assignment, officer: officer, date: 1.day.from_now)
|
||||
|
||||
visit new_officing_residence_path
|
||||
|
||||
expect(page).to have_content("You don't have officing shifts today")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
feature "Assigned officers" do
|
||||
|
||||
background do
|
||||
create(:poll_officer_assignment, officer: officer)
|
||||
login_as(officer.user)
|
||||
visit officing_root_path
|
||||
end
|
||||
|
||||
scenario "Verify voter" do
|
||||
within("#side_menu") do
|
||||
click_link "Validate document"
|
||||
end
|
||||
|
||||
select 'DNI', from: 'residence_document_type'
|
||||
fill_in 'residence_document_number', with: "12345678Z"
|
||||
fill_in 'residence_year_of_birth', with: '1980'
|
||||
|
||||
click_button 'Validate document'
|
||||
|
||||
expect(page).to have_content 'Document verified with Census'
|
||||
end
|
||||
|
||||
scenario "Error on verify" do
|
||||
within("#side_menu") do
|
||||
click_link "Validate document"
|
||||
end
|
||||
|
||||
click_button 'Validate document'
|
||||
expect(page).to have_content(/\d errors? prevented the verification of this document/)
|
||||
end
|
||||
|
||||
scenario "Error on Census (document number)" do
|
||||
initial_failed_census_calls_count = officer.failed_census_calls_count
|
||||
within("#side_menu") do
|
||||
click_link "Validate document"
|
||||
end
|
||||
|
||||
select 'DNI', from: 'residence_document_type'
|
||||
fill_in 'residence_document_number', with: "9999999A"
|
||||
fill_in 'residence_year_of_birth', with: '1980'
|
||||
|
||||
click_button 'Validate document'
|
||||
|
||||
expect(page).to have_content 'The Census was unable to verify this document'
|
||||
|
||||
officer.reload
|
||||
fcc = FailedCensusCall.last
|
||||
expect(fcc).to be
|
||||
expect(fcc.poll_officer).to eq(officer)
|
||||
expect(officer.failed_census_calls.last).to eq(fcc)
|
||||
expect(officer.failed_census_calls_count).to eq(initial_failed_census_calls_count + 1)
|
||||
end
|
||||
|
||||
scenario "Error on Census (year of birth)" do
|
||||
within("#side_menu") do
|
||||
click_link "Validate document"
|
||||
end
|
||||
|
||||
select 'DNI', from: 'residence_document_type'
|
||||
fill_in 'residence_document_number', with: "12345678Z"
|
||||
fill_in 'residence_year_of_birth', with: '1981'
|
||||
|
||||
click_button 'Validate document'
|
||||
|
||||
expect(page).to have_content 'The Census was unable to verify this document'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
159
spec/features/officing/results_spec.rb
Normal file
159
spec/features/officing/results_spec.rb
Normal file
@@ -0,0 +1,159 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Officing Results' do
|
||||
|
||||
background do
|
||||
@poll_officer = create(:poll_officer)
|
||||
@officer_assignment = create(:poll_officer_assignment, :final, officer: @poll_officer)
|
||||
@poll = @officer_assignment.booth_assignment.poll
|
||||
@poll.update(ends_at: 1.day.ago)
|
||||
@question_1 = create(:poll_question, poll: @poll, valid_answers: "Yes,No")
|
||||
@question_2 = create(:poll_question, poll: @poll, valid_answers: "Today,Tomorrow")
|
||||
login_as(@poll_officer.user)
|
||||
end
|
||||
|
||||
scenario 'Only polls where user is officer for results are accessible' do
|
||||
regular_officer_assignment_1 = create(:poll_officer_assignment, officer: @poll_officer)
|
||||
regular_officer_assignment_2 = create(:poll_officer_assignment, officer: @poll_officer)
|
||||
|
||||
not_allowed_poll_1 = create(:poll, :expired)
|
||||
not_allowed_poll_2 = regular_officer_assignment_1.booth_assignment.poll
|
||||
not_allowed_poll_2.update(ends_at: 1.day.ago)
|
||||
not_allowed_poll_3 = regular_officer_assignment_2.booth_assignment.poll
|
||||
|
||||
visit root_path
|
||||
click_link 'Polling officers'
|
||||
|
||||
expect(page).to have_content('Poll officing')
|
||||
within('#side_menu') do
|
||||
click_link 'Final recounts and results'
|
||||
end
|
||||
|
||||
expect(page).to_not have_content(not_allowed_poll_1.name)
|
||||
expect(page).to_not have_content(not_allowed_poll_2.name)
|
||||
expect(page).to_not have_content(not_allowed_poll_3.name)
|
||||
expect(page).to have_content(@poll.name)
|
||||
|
||||
visit new_officing_poll_result_path(not_allowed_poll_1)
|
||||
expect(page).to have_content('You are allowed to add results for this poll')
|
||||
end
|
||||
|
||||
scenario 'Add results' do
|
||||
visit officing_root_path
|
||||
|
||||
within('#side_menu') do
|
||||
click_link 'Final recounts and results'
|
||||
end
|
||||
|
||||
within("#poll_#{@poll.id}") do
|
||||
expect(page).to have_content(@poll.name)
|
||||
click_link 'Add results'
|
||||
end
|
||||
|
||||
expect(page).to_not have_content('Your results')
|
||||
|
||||
booth_name = @officer_assignment.booth_assignment.booth.name
|
||||
date = I18n.l(@poll.starts_at.to_date, format: :long)
|
||||
select booth_name, from: 'officer_assignment_id'
|
||||
select date, from: 'date'
|
||||
|
||||
fill_in "questions[#{@question_1.id}][0]", with: '100'
|
||||
fill_in "questions[#{@question_1.id}][1]", with: '200'
|
||||
|
||||
fill_in "questions[#{@question_2.id}][0]", with: '333'
|
||||
fill_in "questions[#{@question_2.id}][1]", with: '444'
|
||||
|
||||
fill_in "whites", with: '66'
|
||||
fill_in "nulls", with: '77'
|
||||
|
||||
click_button 'Save'
|
||||
|
||||
expect(page).to have_content('Your results')
|
||||
|
||||
within("#results_#{@officer_assignment.booth_assignment_id}_#{@poll.starts_at.to_date.strftime('%Y%m%d')}") do
|
||||
expect(page).to have_content(date)
|
||||
expect(page).to have_content(booth_name)
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Edit result' do
|
||||
partial_result = create(:poll_partial_result,
|
||||
officer_assignment: @officer_assignment,
|
||||
booth_assignment: @officer_assignment.booth_assignment,
|
||||
date: @poll.starts_at,
|
||||
question: @question_1,
|
||||
answer: @question_1.valid_answers[0],
|
||||
author: @poll_officer.user,
|
||||
amount: 7777)
|
||||
|
||||
visit officing_poll_results_path(@poll, date: I18n.l(partial_result.date), booth_assignment_id: partial_result.booth_assignment_id)
|
||||
|
||||
within("#question_#{@question_1.id}_0_result") { expect(page).to have_content('7777') }
|
||||
|
||||
visit new_officing_poll_result_path(@poll)
|
||||
|
||||
booth_name = partial_result.booth_assignment.booth.name
|
||||
date = I18n.l(partial_result.date, format: :long)
|
||||
select booth_name, from: 'officer_assignment_id'
|
||||
select date, from: 'date'
|
||||
|
||||
fill_in "questions[#{@question_1.id}][0]", with: '5555'
|
||||
fill_in "questions[#{@question_1.id}][1]", with: '200'
|
||||
fill_in "whites", with: '6'
|
||||
fill_in "nulls", with: '7'
|
||||
|
||||
click_button 'Save'
|
||||
|
||||
within("#results_#{partial_result.booth_assignment_id}_#{partial_result.date.strftime('%Y%m%d')}") do
|
||||
expect(page).to have_content(I18n.l(partial_result.date, format: :long))
|
||||
expect(page).to have_content(partial_result.booth_assignment.booth.name)
|
||||
click_link "See results"
|
||||
end
|
||||
|
||||
expect(page).to_not have_content('7777')
|
||||
within("#white_results") { expect(page).to have_content('6') }
|
||||
within("#null_results") { expect(page).to have_content('7') }
|
||||
within("#question_#{@question_1.id}_0_result") { expect(page).to have_content('5555') }
|
||||
within("#question_#{@question_1.id}_1_result") { expect(page).to have_content('200') }
|
||||
end
|
||||
|
||||
scenario 'Index lists all questions and answers' do
|
||||
partial_result = create(:poll_partial_result,
|
||||
officer_assignment: @officer_assignment,
|
||||
booth_assignment: @officer_assignment.booth_assignment,
|
||||
date: @poll.ends_at,
|
||||
question: @question_1,
|
||||
amount: 33)
|
||||
white_result = create(:poll_white_result,
|
||||
officer_assignment: @officer_assignment,
|
||||
booth_assignment: @officer_assignment.booth_assignment,
|
||||
date: @poll.ends_at,
|
||||
amount: 21)
|
||||
null_result = create(:poll_null_result,
|
||||
officer_assignment: @officer_assignment,
|
||||
booth_assignment: @officer_assignment.booth_assignment,
|
||||
date: @poll.ends_at,
|
||||
amount: 44)
|
||||
|
||||
visit officing_poll_results_path(@poll,
|
||||
date: I18n.l(@poll.ends_at.to_date),
|
||||
booth_assignment_id: @officer_assignment.booth_assignment_id)
|
||||
|
||||
expect(page).to have_content(I18n.l(@poll.ends_at.to_date, format: :long))
|
||||
expect(page).to have_content(@officer_assignment.booth_assignment.booth.name)
|
||||
|
||||
expect(page).to have_content(@question_1.title)
|
||||
@question_1.valid_answers.each_with_index do |answer, i|
|
||||
within("#question_#{@question_1.id}_#{i}_result") { expect(page).to have_content(answer) }
|
||||
end
|
||||
|
||||
expect(page).to have_content(@question_2.title)
|
||||
@question_2.valid_answers.each_with_index do |answer, i|
|
||||
within("#question_#{@question_2.id}_#{i}_result") { expect(page).to have_content(answer) }
|
||||
end
|
||||
|
||||
within('#white_results') { expect(page).to have_content('21') }
|
||||
within('#null_results') { expect(page).to have_content('44') }
|
||||
end
|
||||
|
||||
end
|
||||
67
spec/features/officing/voters_spec.rb
Normal file
67
spec/features/officing/voters_spec.rb
Normal file
@@ -0,0 +1,67 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Voters' do
|
||||
|
||||
let(:officer) { create(:poll_officer) }
|
||||
|
||||
background do
|
||||
login_as(officer.user)
|
||||
create(:geozone, :in_census)
|
||||
|
||||
#remove once foundation.equalizer js error has been fixed
|
||||
Capybara.current_driver = :poltergeist_no_js_errors
|
||||
end
|
||||
|
||||
scenario "Can vote", :js do
|
||||
poll = create(:poll_officer_assignment, officer: officer).booth_assignment.poll
|
||||
|
||||
visit new_officing_residence_path
|
||||
officing_verify_residence
|
||||
|
||||
expect(page).to have_content "Polls"
|
||||
expect(page).to have_content poll.name
|
||||
|
||||
click_button "Confirm vote"
|
||||
|
||||
expect(page).to have_content "Vote introduced!"
|
||||
expect(page).to_not have_button "Confirm vote"
|
||||
|
||||
page.evaluate_script("window.location.reload()")
|
||||
expect(page).to have_content "Has already participated in this poll"
|
||||
expect(page).to_not have_button "Confirm vote"
|
||||
end
|
||||
|
||||
scenario "Already voted", :js do
|
||||
poll1 = create(:poll)
|
||||
poll2 = create(:poll)
|
||||
|
||||
user = create(:user, :level_two)
|
||||
voter = create(:poll_voter, poll: poll1, user: user)
|
||||
|
||||
visit new_officing_voter_path(id: voter.user.id)
|
||||
|
||||
within("#poll_#{poll1.id}") do
|
||||
expect(page).to have_content "Has already participated in this poll"
|
||||
expect(page).to_not have_button "Confirm vote"
|
||||
end
|
||||
|
||||
within("#poll_#{poll2.id}") do
|
||||
expect(page).to have_button "Confirm vote"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Had already verified his residence, but is not level 2 yet", :js do
|
||||
user = create(:user, residence_verified_at: Time.current, document_type: "1", document_number: "12345678Z")
|
||||
expect(user).to_not be_level_two_verified
|
||||
poll = create(:poll_officer_assignment, officer: officer).booth_assignment.poll
|
||||
|
||||
visit new_officing_residence_path
|
||||
officing_verify_residence
|
||||
|
||||
expect(page).to have_content "Polls"
|
||||
expect(page).to have_content poll.name
|
||||
end
|
||||
|
||||
#Fix and use answerable_by(user)
|
||||
xscenario "Display only answerable polls"
|
||||
end
|
||||
109
spec/features/officing_spec.rb
Normal file
109
spec/features/officing_spec.rb
Normal file
@@ -0,0 +1,109 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Poll Officing' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
scenario 'Access as regular user is not authorized' do
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to_not have_link("Polling officers")
|
||||
visit officing_root_path
|
||||
|
||||
expect(current_path).not_to eq(officing_root_path)
|
||||
expect(current_path).to eq(proposals_path)
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as moderator is not authorized' do
|
||||
create(:moderator, user: user)
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to_not have_link("Polling officers")
|
||||
visit officing_root_path
|
||||
|
||||
expect(current_path).not_to eq(officing_root_path)
|
||||
expect(current_path).to eq(proposals_path)
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as manager is not authorized' do
|
||||
create(:manager, user: user)
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to_not have_link("Polling officers")
|
||||
visit officing_root_path
|
||||
|
||||
expect(current_path).not_to eq(officing_root_path)
|
||||
expect(current_path).to eq(proposals_path)
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as a valuator is not authorized' do
|
||||
create(:valuator, user: user)
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to_not have_link("Polling officers")
|
||||
visit officing_root_path
|
||||
|
||||
expect(current_path).not_to eq(officing_root_path)
|
||||
expect(current_path).to eq(proposals_path)
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as an poll officer is authorized' do
|
||||
create(:poll_officer, user: user)
|
||||
create(:poll)
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to have_link("Polling officers")
|
||||
click_on "Polling officers"
|
||||
|
||||
expect(current_path).to eq(officing_root_path)
|
||||
expect(page).to_not have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as an administrator is authorized' do
|
||||
create(:administrator, user: user)
|
||||
create(:poll)
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to have_link("Polling officers")
|
||||
click_on "Polling officers"
|
||||
|
||||
expect(current_path).to eq(officing_root_path)
|
||||
expect(page).to_not have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario "Poll officer access links" do
|
||||
create(:poll_officer, user: user)
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to have_link("Polling officers")
|
||||
expect(page).to_not have_link('Valuation')
|
||||
expect(page).to_not have_link('Administration')
|
||||
expect(page).to_not have_link('Moderation')
|
||||
end
|
||||
|
||||
scenario 'Officing dashboard' do
|
||||
create(:poll_officer, user: user)
|
||||
create(:poll)
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
click_link 'Polling officers'
|
||||
|
||||
expect(current_path).to eq(officing_root_path)
|
||||
expect(page).to have_css('#officing_menu')
|
||||
expect(page).to_not have_css('#valuation_menu')
|
||||
expect(page).to_not have_css('#admin_menu')
|
||||
expect(page).to_not have_css('#moderation_menu')
|
||||
end
|
||||
|
||||
end
|
||||
197
spec/features/polls/polls_spec.rb
Normal file
197
spec/features/polls/polls_spec.rb
Normal file
@@ -0,0 +1,197 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Polls' do
|
||||
|
||||
context '#index' do
|
||||
|
||||
scenario 'Polls can be listed' do
|
||||
polls = create_list(:poll, 3)
|
||||
|
||||
visit polls_path
|
||||
|
||||
polls.each do |poll|
|
||||
expect(page).to have_content(poll.name)
|
||||
expect(page).to have_link("Participate in this poll")
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Filtering polls' do
|
||||
create(:poll, name: "Current poll")
|
||||
create(:poll, :incoming, name: "Incoming poll")
|
||||
create(:poll, :expired, name: "Expired poll")
|
||||
|
||||
visit polls_path
|
||||
expect(page).to have_content('Current poll')
|
||||
expect(page).to have_link('Participate in this poll')
|
||||
expect(page).to_not have_content('Incoming poll')
|
||||
expect(page).to_not have_content('Expired poll')
|
||||
|
||||
visit polls_path(filter: 'incoming')
|
||||
expect(page).to_not have_content('Current poll')
|
||||
expect(page).to have_content('Incoming poll')
|
||||
expect(page).to have_link('More information')
|
||||
expect(page).to_not have_content('Expired poll')
|
||||
|
||||
visit polls_path(filter: 'expired')
|
||||
expect(page).to_not have_content('Current poll')
|
||||
expect(page).to_not have_content('Incoming poll')
|
||||
expect(page).to have_content('Expired poll')
|
||||
expect(page).to have_link('Poll ended')
|
||||
end
|
||||
|
||||
scenario "Current filter is properly highlighted" do
|
||||
visit polls_path
|
||||
expect(page).to_not have_link('Open')
|
||||
expect(page).to have_link('Incoming')
|
||||
expect(page).to have_link('Expired')
|
||||
|
||||
visit polls_path(filter: 'incoming')
|
||||
expect(page).to have_link('Open')
|
||||
expect(page).to_not have_link('Incoming')
|
||||
expect(page).to have_link('Expired')
|
||||
|
||||
visit polls_path(filter: 'expired')
|
||||
expect(page).to have_link('Open')
|
||||
expect(page).to have_link('Incoming')
|
||||
expect(page).to_not have_link('Expired')
|
||||
end
|
||||
end
|
||||
|
||||
context 'Show' do
|
||||
let(:geozone) { create(:geozone) }
|
||||
let(:poll) { create(:poll) }
|
||||
|
||||
scenario 'Lists questions from proposals as well as regular ones' do
|
||||
normal_question = create(:poll_question, poll: poll)
|
||||
proposal_question = create(:poll_question, poll: poll, proposal: create(:proposal))
|
||||
|
||||
visit poll_path(poll)
|
||||
expect(page).to have_content(poll.name)
|
||||
|
||||
expect(page).to have_content(normal_question.title)
|
||||
expect(page).to have_content(proposal_question.title)
|
||||
end
|
||||
|
||||
scenario 'Non-logged in users' do
|
||||
create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
|
||||
visit poll_path(poll)
|
||||
|
||||
expect(page).to have_content('Han Solo')
|
||||
expect(page).to have_content('Chewbacca')
|
||||
expect(page).to have_content('You must Sign in or Sign up to participate')
|
||||
|
||||
expect(page).to_not have_link('Han Solo')
|
||||
expect(page).to_not have_link('Chewbacca')
|
||||
end
|
||||
|
||||
scenario 'Level 1 users' do
|
||||
poll.update(geozone_restricted: true)
|
||||
poll.geozones << geozone
|
||||
create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
|
||||
login_as(create(:user, geozone: geozone))
|
||||
visit poll_path(poll)
|
||||
|
||||
expect(page).to have_content('You must verify your account in order to answer')
|
||||
|
||||
expect(page).to have_content('Han Solo')
|
||||
expect(page).to have_content('Chewbacca')
|
||||
|
||||
expect(page).to_not have_link('Han Solo')
|
||||
expect(page).to_not have_link('Chewbacca')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users in an incoming poll' do
|
||||
incoming_poll = create(:poll, :incoming, geozone_restricted: true)
|
||||
incoming_poll.geozones << geozone
|
||||
create(:poll_question, poll: incoming_poll, valid_answers: 'Rey, Finn')
|
||||
login_as(create(:user, :level_two, geozone: geozone))
|
||||
|
||||
visit poll_path(incoming_poll)
|
||||
|
||||
expect(page).to have_content('Rey')
|
||||
expect(page).to have_content('Finn')
|
||||
expect(page).to_not have_link('Rey')
|
||||
expect(page).to_not have_link('Finn')
|
||||
|
||||
expect(page).to have_content('This poll has not yet started')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users in an expired poll' do
|
||||
expired_poll = create(:poll, :expired, geozone_restricted: true)
|
||||
expired_poll.geozones << geozone
|
||||
create(:poll_question, poll: expired_poll, valid_answers: 'Luke, Leia')
|
||||
login_as(create(:user, :level_two, geozone: geozone))
|
||||
|
||||
visit poll_path(expired_poll)
|
||||
|
||||
expect(page).to have_content('Luke')
|
||||
expect(page).to have_content('Leia')
|
||||
expect(page).to_not have_link('Luke')
|
||||
expect(page).to_not have_link('Leia')
|
||||
|
||||
expect(page).to have_content('This poll has finished')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users in a poll with questions for a geozone which is not theirs' do
|
||||
poll.update(geozone_restricted: true)
|
||||
poll.geozones << create(:geozone)
|
||||
create(:poll_question, poll: poll, valid_answers: 'Vader, Palpatine')
|
||||
login_as(create(:user, :level_two))
|
||||
|
||||
visit poll_path(poll)
|
||||
|
||||
expect(page).to have_content('Vader')
|
||||
expect(page).to have_content('Palpatine')
|
||||
expect(page).to_not have_link('Vader')
|
||||
expect(page).to_not have_link('Palpatine')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users reading a same-geozone poll' do
|
||||
poll.update(geozone_restricted: true)
|
||||
poll.geozones << geozone
|
||||
create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
|
||||
login_as(create(:user, :level_two, geozone: geozone))
|
||||
visit poll_path(poll)
|
||||
|
||||
expect(page).to have_link('Han Solo')
|
||||
expect(page).to have_link('Chewbacca')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users reading a all-geozones poll' do
|
||||
create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
|
||||
login_as(create(:user, :level_two))
|
||||
visit poll_path(poll)
|
||||
|
||||
expect(page).to have_link('Han Solo')
|
||||
expect(page).to have_link('Chewbacca')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users who have already answered' do
|
||||
question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
|
||||
user = create(:user, :level_two)
|
||||
create(:poll_answer, question: question, author: user, answer: 'Chewbacca')
|
||||
|
||||
login_as user
|
||||
visit poll_path(poll)
|
||||
|
||||
expect(page).to have_link('Han Solo')
|
||||
expect(page).to_not have_link('Chewbacca')
|
||||
expect(page).to have_content('Chewbacca')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users answering', :js do
|
||||
poll.update(geozone_restricted: true)
|
||||
poll.geozones << geozone
|
||||
create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
|
||||
user = create(:user, :level_two, geozone: geozone)
|
||||
login_as user
|
||||
visit poll_path(poll)
|
||||
|
||||
click_link 'Han Solo'
|
||||
|
||||
expect(page).to_not have_link('Han Solo')
|
||||
expect(page).to have_link('Chewbacca')
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
112
spec/features/polls/questions_spec.rb
Normal file
112
spec/features/polls/questions_spec.rb
Normal file
@@ -0,0 +1,112 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Poll Questions' do
|
||||
|
||||
scenario 'Lists questions from proposals before regular questions' do
|
||||
poll = create(:poll)
|
||||
normal_question = create(:poll_question, poll: poll)
|
||||
proposal_question = create(:poll_question, proposal: create(:proposal), poll: poll)
|
||||
|
||||
visit poll_path(poll)
|
||||
|
||||
expect(proposal_question.title).to appear_before(normal_question.title)
|
||||
end
|
||||
|
||||
scenario 'shows the author visible name instead of a link to the author' do
|
||||
poll = create(:poll)
|
||||
question_with_author = create(:poll_question, poll: poll)
|
||||
question_with_author_visible_name = create(:poll_question, poll: poll, author_visible_name: 'potato')
|
||||
|
||||
visit question_path(question_with_author)
|
||||
expect(page).to have_link(question_with_author.author.name)
|
||||
|
||||
visit question_path(question_with_author_visible_name)
|
||||
expect(page).to_not have_link(question_with_author_visible_name.author.name)
|
||||
expect(page).to have_content(question_with_author_visible_name.author_visible_name)
|
||||
end
|
||||
|
||||
context 'Answering' do
|
||||
let(:geozone) { create(:geozone) }
|
||||
let(:poll) { create(:poll, geozone_restricted: true, geozone_ids: [geozone.id]) }
|
||||
|
||||
scenario 'Non-logged in users' do
|
||||
question = create(:poll_question, valid_answers: 'Han Solo, Chewbacca')
|
||||
|
||||
visit question_path(question)
|
||||
|
||||
expect(page).to have_content('You must Sign in or Sign up to participate')
|
||||
end
|
||||
|
||||
scenario 'Level 1 users' do
|
||||
question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
|
||||
|
||||
login_as(create(:user, geozone: geozone))
|
||||
visit question_path(question)
|
||||
|
||||
expect(page).to have_content('You must verify your account in order to answer')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users in an poll question for a geozone which is not theirs' do
|
||||
|
||||
other_poll = create(:poll, geozone_restricted: true, geozone_ids: [create(:geozone).id])
|
||||
question = create(:poll_question, poll: other_poll, valid_answers: 'Vader, Palpatine')
|
||||
|
||||
login_as(create(:user, :level_two, geozone: geozone))
|
||||
visit question_path(question)
|
||||
|
||||
expect(page).to have_content('This question is not available on your geozone')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users who can answer' do
|
||||
question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
|
||||
|
||||
login_as(create(:user, :level_two, geozone: geozone))
|
||||
visit question_path(question)
|
||||
|
||||
expect(page).to have_link('Answer this question')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users who have already answered' do
|
||||
question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
|
||||
|
||||
user = create(:user, :level_two, geozone: geozone)
|
||||
create(:poll_answer, question: question, author: user, answer: 'Chewbacca')
|
||||
|
||||
login_as user
|
||||
visit question_path(question)
|
||||
|
||||
expect(page).to have_link('Answer this question')
|
||||
end
|
||||
|
||||
scenario 'Level 2 users answering', :js do
|
||||
question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
|
||||
user = create(:user, :level_two, geozone: geozone)
|
||||
|
||||
login_as user
|
||||
visit question_path(question)
|
||||
|
||||
expect(page).to have_link('Answer this question')
|
||||
end
|
||||
|
||||
scenario 'Records participation', :js do
|
||||
question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
|
||||
user = create(:user, :level_two, geozone: geozone, gender: 'female', date_of_birth: 33.years.ago)
|
||||
|
||||
login_as user
|
||||
visit question_path(question)
|
||||
|
||||
click_link 'Answer this question'
|
||||
click_link 'Han Solo'
|
||||
|
||||
expect(page).to_not have_link('Han Solo')
|
||||
|
||||
voter = poll.voters.first
|
||||
expect(voter.document_number).to eq(user.document_number)
|
||||
expect(voter.geozone_id).to eq(user.geozone_id)
|
||||
expect(voter.gender).to eq(user.gender)
|
||||
expect(voter.age).to eq(33)
|
||||
expect(voter.poll_id).to eq(poll.id)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -10,7 +10,7 @@ feature 'Proposal ballots' do
|
||||
expect(page).to_not have_css("#next-voting")
|
||||
expect(page).to have_css("#featured-proposals")
|
||||
|
||||
create_successfull_proposals
|
||||
create_successful_proposals
|
||||
|
||||
visit proposals_path
|
||||
|
||||
@@ -18,22 +18,22 @@ feature 'Proposal ballots' do
|
||||
expect(page).to_not have_css("#featured-proposals")
|
||||
end
|
||||
|
||||
scenario 'Successfull proposals do not show support buttons in index' do
|
||||
successfull_proposals = create_successfull_proposals
|
||||
scenario 'Successful proposals do not show support buttons in index' do
|
||||
successful_proposals = create_successful_proposals
|
||||
|
||||
visit proposals_path
|
||||
|
||||
successfull_proposals.each do |proposal|
|
||||
successful_proposals.each do |proposal|
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).to have_content "This proposal has reached the required supports"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Successfull proposals do not show support buttons in show' do
|
||||
successfull_proposals = create_successfull_proposals
|
||||
scenario 'Successful proposals do not show support buttons in show' do
|
||||
successful_proposals = create_successful_proposals
|
||||
|
||||
successfull_proposals.each do |proposal|
|
||||
successful_proposals.each do |proposal|
|
||||
visit proposal_path(proposal)
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).to have_content "This proposal has reached the required supports"
|
||||
@@ -41,15 +41,5 @@ feature 'Proposal ballots' do
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Successfull proposals are listed in the proposal ballots index' do
|
||||
successfull_proposals = create_successfull_proposals
|
||||
|
||||
visit proposal_ballots_path
|
||||
|
||||
successfull_proposals.each do |proposal|
|
||||
expect(page).to have_content(proposal.title)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1372,3 +1372,69 @@ feature 'Proposals' do
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
feature 'Successful proposals' do
|
||||
|
||||
scenario 'Banner shows in proposal index' do
|
||||
create_featured_proposals
|
||||
|
||||
visit proposals_path
|
||||
expect(page).to_not have_css("#next-voting")
|
||||
expect(page).to have_css("#featured-proposals")
|
||||
|
||||
create_successful_proposals
|
||||
|
||||
visit proposals_path
|
||||
|
||||
expect(page).to have_css("#next-voting")
|
||||
expect(page).to_not have_css("#featured-proposals")
|
||||
end
|
||||
|
||||
scenario 'Successful proposals do not show support buttons in index' do
|
||||
successful_proposals = create_successful_proposals
|
||||
|
||||
visit proposals_path
|
||||
|
||||
successful_proposals.each do |proposal|
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).to_not have_css(".supports")
|
||||
expect(page).to have_content "This proposal has reached the required supports"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Successful proposals do not show support buttons in show' do
|
||||
successful_proposals = create_successful_proposals
|
||||
|
||||
successful_proposals.each do |proposal|
|
||||
visit proposal_path(proposal)
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).to_not have_css(".supports")
|
||||
expect(page).to have_content "This proposal has reached the required supports"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Successful proposals show create question button to admin users' do
|
||||
successful_proposals = create_successful_proposals
|
||||
|
||||
visit proposals_path
|
||||
|
||||
successful_proposals.each do |proposal|
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).to_not have_link "Create question"
|
||||
end
|
||||
end
|
||||
|
||||
login_as(create(:administrator).user)
|
||||
|
||||
visit proposals_path
|
||||
|
||||
successful_proposals.each do |proposal|
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).to have_link "Create question"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -61,6 +61,8 @@ feature 'Valuation budget investments' do
|
||||
end
|
||||
|
||||
scenario "Index filtering by heading", :js do
|
||||
Capybara.current_driver = :poltergeist_no_js_errors
|
||||
|
||||
group = create(:budget_group, budget: @budget)
|
||||
heading1 = create(:budget_heading, name: "District 9", group: group)
|
||||
heading2 = create(:budget_heading, name: "Down to the river", group: group)
|
||||
|
||||
@@ -83,6 +83,8 @@ feature 'Valuation spending proposals' do
|
||||
end
|
||||
|
||||
scenario "Index filtering by geozone", :js do
|
||||
Capybara.current_driver = :poltergeist_no_js_errors
|
||||
|
||||
geozone = create(:geozone, name: "District 9")
|
||||
spending_proposal1 = create(:spending_proposal, title: "Realocate visitors", geozone: geozone)
|
||||
spending_proposal2 = create(:spending_proposal, title: "Destroy the city")
|
||||
|
||||
@@ -46,6 +46,19 @@ feature 'Valuation' do
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as poll officer is not authorized' do
|
||||
create(:poll_officer, user: user)
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to_not have_link("Valuation")
|
||||
visit valuation_root_path
|
||||
|
||||
expect(current_path).not_to eq(valuation_root_path)
|
||||
expect(current_path).to eq(proposals_path)
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario 'Access as a valuator is authorized' do
|
||||
create(:valuator, user: user)
|
||||
login_as(user)
|
||||
|
||||
@@ -22,6 +22,31 @@ feature 'Residence' do
|
||||
expect(page).to have_content 'Residence verified'
|
||||
end
|
||||
|
||||
scenario 'When trying to verify a deregistered account old votes are reassigned' do
|
||||
erased_user = create(:user, document_number: '12345678Z', document_type: '1', erased_at: Time.current)
|
||||
vote = create(:vote, voter: erased_user)
|
||||
new_user = create(:user)
|
||||
|
||||
login_as(new_user)
|
||||
|
||||
visit account_path
|
||||
click_link 'Verify my account'
|
||||
|
||||
fill_in 'residence_document_number', with: '12345678Z'
|
||||
select 'DNI', from: 'residence_document_type'
|
||||
select_date '31-December-1980', from: 'residence_date_of_birth'
|
||||
fill_in 'residence_postal_code', with: '28013'
|
||||
check 'residence_terms_of_service'
|
||||
|
||||
click_button 'Verify residence'
|
||||
|
||||
expect(page).to have_content 'Residence verified'
|
||||
|
||||
expect(vote.reload.voter).to eq(new_user)
|
||||
expect(erased_user.reload.document_number).to be_blank
|
||||
expect(new_user.reload.document_number).to eq('12345678Z')
|
||||
end
|
||||
|
||||
scenario 'Error on verify' do
|
||||
user = create(:user)
|
||||
login_as(user)
|
||||
@@ -102,24 +127,4 @@ feature 'Residence' do
|
||||
expect(page).to have_content "You have reached the maximum number of attempts. Please try again later."
|
||||
expect(current_path).to eq(account_path)
|
||||
end
|
||||
|
||||
scenario 'Error when trying to verify a deregistered account' do
|
||||
create(:user, document_number: '12345678Z', document_type: '1', erased_at: Time.now)
|
||||
|
||||
login_as(create(:user))
|
||||
|
||||
visit account_path
|
||||
click_link 'Verify my account'
|
||||
|
||||
fill_in 'residence_document_number', with: "12345678Z"
|
||||
select 'DNI', from: 'residence_document_type'
|
||||
select_date '31-December-1980', from: 'residence_date_of_birth'
|
||||
fill_in 'residence_postal_code', with: '28013'
|
||||
check 'residence_terms_of_service'
|
||||
|
||||
click_button 'Verify residence'
|
||||
|
||||
expect(page).to_not have_content 'Residence verified'
|
||||
expect(page).to have_content 'has already been taken'
|
||||
end
|
||||
end
|
||||
|
||||
19
spec/helpers/admin_helper_spec.rb
Normal file
19
spec/helpers/admin_helper_spec.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe AdminHelper do
|
||||
|
||||
describe "#admin_submit_action" do
|
||||
|
||||
it "returns new when the the resource has not been persisted" do
|
||||
poll = build(:poll)
|
||||
expect(admin_submit_action(poll)).to eq("new")
|
||||
end
|
||||
|
||||
it "returns edit when the the resource has been persisted" do
|
||||
poll = create(:poll)
|
||||
expect(admin_submit_action(poll)).to eq("edit")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
58
spec/lib/age_spec.rb
Normal file
58
spec/lib/age_spec.rb
Normal file
@@ -0,0 +1,58 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Age do
|
||||
describe '.in_years' do
|
||||
it "handles nils" do
|
||||
expect(Age.in_years(nil)).to be_nil
|
||||
end
|
||||
|
||||
it "calculates age correctly for common dates" do
|
||||
d = Date.new(1980, 3, 13)
|
||||
expect(Age.in_years(d, Date.new(2000, 3, 12))).to eq(19)
|
||||
expect(Age.in_years(d, Date.new(2000, 3, 13))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2000, 3, 14))).to eq(20)
|
||||
end
|
||||
|
||||
it "calculates age correctly for people born near a year's limit" do
|
||||
d = Date.new(1980, 12, 31)
|
||||
expect(Age.in_years(d, Date.new(2000, 12, 30))).to eq(19)
|
||||
expect(Age.in_years(d, Date.new(2000, 12, 31))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2001, 1, 1))).to eq(20)
|
||||
|
||||
d = Date.new(1980, 1, 1)
|
||||
expect(Age.in_years(d, Date.new(2000, 12, 31))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2001, 1, 1))).to eq(21)
|
||||
expect(Age.in_years(d, Date.new(2001, 1, 2))).to eq(21)
|
||||
end
|
||||
|
||||
it "calculates age correctly for people born around February the 29th" do
|
||||
# 1980 and 2000 are leap years. 2001 is a regular year
|
||||
d = Date.new(1980, 2, 29)
|
||||
expect(Age.in_years(d, Date.new(2000, 2, 27))).to eq(19)
|
||||
expect(Age.in_years(d, Date.new(2000, 2, 28))).to eq(19)
|
||||
expect(Age.in_years(d, Date.new(2000, 2, 29))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2000, 3, 1))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2001, 2, 27))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2001, 2, 28))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2001, 3, 1))).to eq(21)
|
||||
|
||||
d = Date.new(1980, 2, 28)
|
||||
expect(Age.in_years(d, Date.new(2000, 2, 27))).to eq(19)
|
||||
expect(Age.in_years(d, Date.new(2000, 2, 28))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2000, 2, 29))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2000, 3, 1))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2001, 2, 27))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2001, 2, 28))).to eq(21)
|
||||
expect(Age.in_years(d, Date.new(2001, 3, 1))).to eq(21)
|
||||
|
||||
d = Date.new(1980, 3, 1)
|
||||
expect(Age.in_years(d, Date.new(2000, 2, 27))).to eq(19)
|
||||
expect(Age.in_years(d, Date.new(2000, 2, 28))).to eq(19)
|
||||
expect(Age.in_years(d, Date.new(2000, 2, 29))).to eq(19)
|
||||
expect(Age.in_years(d, Date.new(2000, 3, 1))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2001, 2, 27))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2001, 2, 28))).to eq(20)
|
||||
expect(Age.in_years(d, Date.new(2001, 3, 1))).to eq(21)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -67,5 +67,4 @@ describe "Abilities::Administrator" do
|
||||
|
||||
it { should be_able_to(:valuate, create(:budget_investment, budget: create(:budget, phase: 'valuating'))) }
|
||||
it { should be_able_to(:valuate, create(:budget_investment, budget: create(:budget, phase: 'finished'))) }
|
||||
|
||||
end
|
||||
|
||||
@@ -3,12 +3,17 @@ require 'cancan/matchers'
|
||||
|
||||
describe "Abilities::Common" do
|
||||
subject(:ability) { Ability.new(user) }
|
||||
let(:geozone) { create(:geozone) }
|
||||
|
||||
let(:user) { create(:user) }
|
||||
let(:user) { create(:user, geozone: geozone) }
|
||||
|
||||
let(:debate) { create(:debate) }
|
||||
let(:comment) { create(:comment) }
|
||||
let(:proposal) { create(:proposal) }
|
||||
let(:own_debate) { create(:debate, author: user) }
|
||||
let(:own_comment) { create(:comment, author: user) }
|
||||
let(:own_proposal) { create(:proposal, author: user) }
|
||||
|
||||
let(:debate) { create(:debate) }
|
||||
let(:comment) { create(:comment) }
|
||||
let(:proposal) { create(:proposal) }
|
||||
let(:accepting_budget) { create(:budget, phase: 'accepting') }
|
||||
let(:reviewing_budget) { create(:budget, phase: 'reviewing') }
|
||||
let(:selecting_budget) { create(:budget, phase: 'selecting') }
|
||||
@@ -25,122 +30,188 @@ describe "Abilities::Common" do
|
||||
let(:ballot_in_accepting_budget) { create(:budget_ballot, budget: accepting_budget) }
|
||||
let(:ballot_in_selecting_budget) { create(:budget_ballot, budget: selecting_budget) }
|
||||
let(:ballot_in_balloting_budget) { create(:budget_ballot, budget: balloting_budget) }
|
||||
let(:own_debate) { create(:debate, author: user) }
|
||||
let(:own_comment) { create(:comment, author: user) }
|
||||
let(:own_proposal) { create(:proposal, author: user) }
|
||||
|
||||
let(:current_poll) { create(:poll) }
|
||||
let(:incoming_poll) { create(:poll, :incoming) }
|
||||
let(:incoming_poll_from_own_geozone) { create(:poll, :incoming, geozone_restricted: true, geozones: [geozone]) }
|
||||
let(:incoming_poll_from_other_geozone) { create(:poll, :incoming, geozone_restricted: true, geozones: [create(:geozone)]) }
|
||||
let(:expired_poll) { create(:poll, :expired) }
|
||||
let(:expired_poll_from_own_geozone) { create(:poll, :expired, geozone_restricted: true, geozones: [geozone]) }
|
||||
let(:expired_poll_from_other_geozone) { create(:poll, :expired, geozone_restricted: true, geozones: [create(:geozone)]) }
|
||||
let(:poll) { create(:poll, geozone_restricted: false) }
|
||||
let(:poll_from_own_geozone) { create(:poll, geozone_restricted: true, geozones: [geozone]) }
|
||||
let(:poll_from_other_geozone) { create(:poll, geozone_restricted: true, geozones: [create(:geozone)]) }
|
||||
|
||||
let(:poll_question_from_own_geozone) { create(:poll_question, poll: poll_from_own_geozone) }
|
||||
let(:poll_question_from_other_geozone) { create(:poll_question, poll: poll_from_other_geozone) }
|
||||
let(:poll_question_from_all_geozones) { create(:poll_question, poll: poll) }
|
||||
|
||||
let(:expired_poll_question_from_own_geozone) { create(:poll_question, poll: expired_poll_from_own_geozone) }
|
||||
let(:expired_poll_question_from_other_geozone) { create(:poll_question, poll: expired_poll_from_other_geozone) }
|
||||
let(:expired_poll_question_from_all_geozones) { create(:poll_question, poll: expired_poll) }
|
||||
|
||||
let(:incoming_poll_question_from_own_geozone) { create(:poll_question, poll: incoming_poll_from_own_geozone) }
|
||||
let(:incoming_poll_question_from_other_geozone) { create(:poll_question, poll: incoming_poll_from_other_geozone) }
|
||||
let(:incoming_poll_question_from_all_geozones) { create(:poll_question, poll: incoming_poll) }
|
||||
|
||||
it { should be_able_to(:index, Debate) }
|
||||
it { should be_able_to(:show, debate) }
|
||||
it { should be_able_to(:vote, debate) }
|
||||
it { should be_able_to(:show, debate) }
|
||||
it { should be_able_to(:vote, debate) }
|
||||
|
||||
it { should be_able_to(:show, user) }
|
||||
it { should be_able_to(:edit, user) }
|
||||
|
||||
it { should be_able_to(:create, Comment) }
|
||||
it { should be_able_to(:vote, Comment) }
|
||||
it { should be_able_to(:vote, Comment) }
|
||||
|
||||
it { should be_able_to(:index, Proposal) }
|
||||
it { should be_able_to(:show, proposal) }
|
||||
it { should be_able_to(:index, Proposal) }
|
||||
it { should be_able_to(:show, proposal) }
|
||||
it { should_not be_able_to(:vote, Proposal) }
|
||||
it { should_not be_able_to(:vote_featured, Proposal) }
|
||||
|
||||
it { should be_able_to(:index, SpendingProposal) }
|
||||
it { should_not be_able_to(:create, SpendingProposal) }
|
||||
it { should be_able_to(:index, SpendingProposal) }
|
||||
it { should_not be_able_to(:create, SpendingProposal) }
|
||||
it { should_not be_able_to(:destroy, SpendingProposal) }
|
||||
|
||||
it { should_not be_able_to(:comment_as_administrator, debate) }
|
||||
it { should_not be_able_to(:comment_as_moderator, debate) }
|
||||
it { should_not be_able_to(:comment_as_administrator, debate) }
|
||||
it { should_not be_able_to(:comment_as_moderator, debate) }
|
||||
it { should_not be_able_to(:comment_as_administrator, proposal) }
|
||||
it { should_not be_able_to(:comment_as_moderator, proposal) }
|
||||
it { should_not be_able_to(:comment_as_moderator, proposal) }
|
||||
|
||||
it { should be_able_to(:new, DirectMessage) }
|
||||
it { should be_able_to(:new, DirectMessage) }
|
||||
it { should_not be_able_to(:create, DirectMessage) }
|
||||
it { should_not be_able_to(:show, DirectMessage) }
|
||||
it { should_not be_able_to(:show, DirectMessage) }
|
||||
|
||||
describe 'flagging content' do
|
||||
it { should be_able_to(:flag, debate) }
|
||||
it { should be_able_to(:flag, debate) }
|
||||
it { should be_able_to(:unflag, debate) }
|
||||
|
||||
it { should be_able_to(:flag, comment) }
|
||||
it { should be_able_to(:flag, comment) }
|
||||
it { should be_able_to(:unflag, comment) }
|
||||
|
||||
it { should be_able_to(:flag, proposal) }
|
||||
it { should be_able_to(:flag, proposal) }
|
||||
it { should be_able_to(:unflag, proposal) }
|
||||
|
||||
describe "own content" do
|
||||
it { should_not be_able_to(:flag, own_comment) }
|
||||
it { should_not be_able_to(:flag, own_comment) }
|
||||
it { should_not be_able_to(:unflag, own_comment) }
|
||||
|
||||
it { should_not be_able_to(:flag, own_debate) }
|
||||
it { should_not be_able_to(:flag, own_debate) }
|
||||
it { should_not be_able_to(:unflag, own_debate) }
|
||||
|
||||
it { should_not be_able_to(:flag, own_proposal) }
|
||||
it { should_not be_able_to(:flag, own_proposal) }
|
||||
it { should_not be_able_to(:unflag, own_proposal) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "other users" do
|
||||
let(:other_user) { create(:user) }
|
||||
it { should be_able_to(:show, other_user) }
|
||||
|
||||
it { should be_able_to(:show, other_user) }
|
||||
it { should_not be_able_to(:edit, other_user) }
|
||||
end
|
||||
|
||||
describe "editing debates" do
|
||||
let(:own_debate_non_editable) { create(:debate, author: user) }
|
||||
|
||||
before { allow(own_debate_non_editable).to receive(:editable?).and_return(false) }
|
||||
|
||||
it { should be_able_to(:edit, own_debate) }
|
||||
it { should_not be_able_to(:edit, debate) } # Not his
|
||||
it { should be_able_to(:edit, own_debate) }
|
||||
it { should_not be_able_to(:edit, debate) } # Not his
|
||||
it { should_not be_able_to(:edit, own_debate_non_editable) }
|
||||
end
|
||||
|
||||
describe "editing proposals" do
|
||||
let(:own_proposal_non_editable) { create(:proposal, author: user) }
|
||||
|
||||
before { allow(own_proposal_non_editable).to receive(:editable?).and_return(false) }
|
||||
|
||||
it { should be_able_to(:edit, own_proposal) }
|
||||
it { should_not be_able_to(:edit, proposal) } # Not his
|
||||
it { should be_able_to(:edit, own_proposal) }
|
||||
it { should_not be_able_to(:edit, proposal) } # Not his
|
||||
it { should_not be_able_to(:edit, own_proposal_non_editable) }
|
||||
end
|
||||
|
||||
describe "when level 2 verified" do
|
||||
let(:own_spending_proposal) { create(:spending_proposal, author: user) }
|
||||
|
||||
let(:own_direct_message) { create(:direct_message, sender: user) }
|
||||
before{ user.update(residence_verified_at: Time.current, confirmed_phone: "1") }
|
||||
|
||||
it { should be_able_to(:vote, Proposal) }
|
||||
it { should be_able_to(:vote_featured, Proposal) }
|
||||
describe "Proposal" do
|
||||
it { should be_able_to(:vote, Proposal) }
|
||||
it { should be_able_to(:vote_featured, Proposal) }
|
||||
end
|
||||
|
||||
it { should be_able_to(:create, SpendingProposal) }
|
||||
it { should_not be_able_to(:destroy, create(:spending_proposal)) }
|
||||
it { should_not be_able_to(:destroy, own_spending_proposal) }
|
||||
describe "Spending Proposal" do
|
||||
it { should be_able_to(:create, SpendingProposal) }
|
||||
it { should_not be_able_to(:destroy, create(:spending_proposal)) }
|
||||
it { should_not be_able_to(:destroy, own_spending_proposal) }
|
||||
end
|
||||
|
||||
it { should be_able_to(:create, investment_in_accepting_budget) }
|
||||
it { should_not be_able_to(:create, investment_in_selecting_budget) }
|
||||
it { should_not be_able_to(:create, investment_in_balloting_budget) }
|
||||
describe "Direct Message" do
|
||||
it { should be_able_to(:new, DirectMessage) }
|
||||
it { should be_able_to(:create, DirectMessage) }
|
||||
it { should be_able_to(:show, own_direct_message) }
|
||||
it { should_not be_able_to(:show, create(:direct_message)) }
|
||||
end
|
||||
|
||||
it { should_not be_able_to(:vote, investment_in_accepting_budget) }
|
||||
it { should be_able_to(:vote, investment_in_selecting_budget) }
|
||||
it { should_not be_able_to(:vote, investment_in_balloting_budget) }
|
||||
describe "Poll" do
|
||||
it { should be_able_to(:answer, current_poll) }
|
||||
it { should_not be_able_to(:answer, expired_poll) }
|
||||
it { should_not be_able_to(:answer, incoming_poll) }
|
||||
|
||||
it { should_not be_able_to(:destroy, investment_in_accepting_budget) }
|
||||
it { should_not be_able_to(:destroy, investment_in_reviewing_budget) }
|
||||
it { should_not be_able_to(:destroy, investment_in_selecting_budget) }
|
||||
it { should_not be_able_to(:destroy, investment_in_balloting_budget) }
|
||||
it { should be_able_to(:answer, poll_question_from_own_geozone) }
|
||||
it { should be_able_to(:answer, poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, poll_question_from_other_geozone) }
|
||||
|
||||
it { should be_able_to(:destroy, own_investment_in_accepting_budget) }
|
||||
it { should be_able_to(:destroy, own_investment_in_reviewing_budget) }
|
||||
it { should_not be_able_to(:destroy, own_investment_in_selecting_budget) }
|
||||
it { should_not be_able_to(:destroy, investment_in_balloting_budget) }
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_own_geozone) }
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_other_geozone) }
|
||||
|
||||
it { should_not be_able_to(:create, ballot_in_accepting_budget) }
|
||||
it { should_not be_able_to(:create, ballot_in_selecting_budget) }
|
||||
it { should be_able_to(:create, ballot_in_balloting_budget) }
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_own_geozone) }
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_other_geozone) }
|
||||
|
||||
it { should be_able_to(:new, DirectMessage) }
|
||||
it { should be_able_to(:create, DirectMessage) }
|
||||
it { should be_able_to(:show, own_direct_message) }
|
||||
it { should_not be_able_to(:show, create(:direct_message)) }
|
||||
context "without geozone" do
|
||||
before(:each) { user.geozone = nil }
|
||||
|
||||
it { should_not be_able_to(:answer, poll_question_from_own_geozone) }
|
||||
it { should be_able_to(:answer, poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, poll_question_from_other_geozone) }
|
||||
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_own_geozone) }
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_other_geozone) }
|
||||
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_own_geozone) }
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_other_geozone) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "Budgets" do
|
||||
it { should be_able_to(:create, investment_in_accepting_budget) }
|
||||
it { should_not be_able_to(:create, investment_in_selecting_budget) }
|
||||
it { should_not be_able_to(:create, investment_in_balloting_budget) }
|
||||
|
||||
it { should_not be_able_to(:vote, investment_in_accepting_budget) }
|
||||
it { should be_able_to(:vote, investment_in_selecting_budget) }
|
||||
it { should_not be_able_to(:vote, investment_in_balloting_budget) }
|
||||
|
||||
it { should_not be_able_to(:destroy, investment_in_accepting_budget) }
|
||||
it { should_not be_able_to(:destroy, investment_in_reviewing_budget) }
|
||||
it { should_not be_able_to(:destroy, investment_in_selecting_budget) }
|
||||
it { should_not be_able_to(:destroy, investment_in_balloting_budget) }
|
||||
|
||||
it { should be_able_to(:destroy, own_investment_in_accepting_budget) }
|
||||
it { should be_able_to(:destroy, own_investment_in_reviewing_budget) }
|
||||
it { should_not be_able_to(:destroy, own_investment_in_selecting_budget) }
|
||||
it { should_not be_able_to(:destroy, investment_in_balloting_budget) }
|
||||
|
||||
it { should_not be_able_to(:create, ballot_in_accepting_budget) }
|
||||
it { should_not be_able_to(:create, ballot_in_selecting_budget) }
|
||||
it { should be_able_to(:create, ballot_in_balloting_budget) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "when level 3 verified" do
|
||||
@@ -148,16 +219,47 @@ describe "Abilities::Common" do
|
||||
let(:own_direct_message) { create(:direct_message, sender: user) }
|
||||
before{ user.update(verified_at: Time.current) }
|
||||
|
||||
it { should be_able_to(:vote, Proposal) }
|
||||
it { should be_able_to(:vote, Proposal) }
|
||||
it { should be_able_to(:vote_featured, Proposal) }
|
||||
|
||||
it { should be_able_to(:create, SpendingProposal) }
|
||||
it { should be_able_to(:create, SpendingProposal) }
|
||||
it { should_not be_able_to(:destroy, create(:spending_proposal)) }
|
||||
it { should_not be_able_to(:destroy, own_spending_proposal) }
|
||||
it { should_not be_able_to(:destroy, own_spending_proposal) }
|
||||
|
||||
it { should be_able_to(:new, DirectMessage) }
|
||||
it { should be_able_to(:create, DirectMessage) }
|
||||
it { should be_able_to(:show, own_direct_message) }
|
||||
it { should be_able_to(:new, DirectMessage) }
|
||||
it { should be_able_to(:create, DirectMessage) }
|
||||
it { should be_able_to(:show, own_direct_message) }
|
||||
it { should_not be_able_to(:show, create(:direct_message)) }
|
||||
|
||||
it { should be_able_to(:answer, current_poll) }
|
||||
it { should_not be_able_to(:answer, expired_poll) }
|
||||
it { should_not be_able_to(:answer, incoming_poll) }
|
||||
|
||||
it { should be_able_to(:answer, poll_question_from_own_geozone) }
|
||||
it { should be_able_to(:answer, poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, poll_question_from_other_geozone) }
|
||||
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_own_geozone) }
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_other_geozone) }
|
||||
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_own_geozone) }
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_other_geozone) }
|
||||
|
||||
context "without geozone" do
|
||||
before(:each) { user.geozone = nil }
|
||||
it { should_not be_able_to(:answer, poll_question_from_own_geozone) }
|
||||
it { should be_able_to(:answer, poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, poll_question_from_other_geozone) }
|
||||
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_own_geozone) }
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, expired_poll_question_from_other_geozone) }
|
||||
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_own_geozone) }
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_all_geozones) }
|
||||
it { should_not be_able_to(:answer, incoming_poll_question_from_other_geozone) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
121
spec/models/officing/residence_spec.rb
Normal file
121
spec/models/officing/residence_spec.rb
Normal file
@@ -0,0 +1,121 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Officing::Residence do
|
||||
|
||||
let!(:geozone) { create(:geozone, census_code: "01") }
|
||||
let(:residence) { build(:officing_residence, document_number: "12345678Z") }
|
||||
|
||||
describe "validations" do
|
||||
|
||||
it "should be valid" do
|
||||
expect(residence).to be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a document number" do
|
||||
residence.document_number = nil
|
||||
expect(residence).to_not be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a document type" do
|
||||
residence.document_type = nil
|
||||
expect(residence).to_not be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a year of birth" do
|
||||
residence.year_of_birth = nil
|
||||
expect(residence).to_not be_valid
|
||||
end
|
||||
|
||||
describe "allowed age" do
|
||||
it "should not be valid if user is under allowed age" do
|
||||
allow_any_instance_of(Officing::Residence).to receive(:date_of_birth).and_return(15.years.ago)
|
||||
expect(residence).to_not be_valid
|
||||
expect(residence.errors[:year_of_birth]).to include("You don't have the required age to participate")
|
||||
end
|
||||
|
||||
it "should be valid if user is above allowed age" do
|
||||
allow_any_instance_of(Officing::Residence).to receive(:date_of_birth).and_return(16.years.ago)
|
||||
expect(residence).to be_valid
|
||||
expect(residence.errors[:year_of_birth]).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "new" do
|
||||
it "should upcase document number" do
|
||||
residence = Officing::Residence.new({document_number: "x1234567z"})
|
||||
expect(residence.document_number).to eq("X1234567Z")
|
||||
end
|
||||
|
||||
it "should remove all characters except numbers and letters" do
|
||||
residence = Officing::Residence.new({document_number: " 12.345.678 - B"})
|
||||
expect(residence.document_number).to eq("12345678B")
|
||||
end
|
||||
end
|
||||
|
||||
describe "save" do
|
||||
|
||||
it "should store document number, document type, geozone, date of birth and gender" do
|
||||
residence.save
|
||||
user = residence.user
|
||||
|
||||
expect(user.document_number).to eq('12345678Z')
|
||||
expect(user.document_type).to eq("1")
|
||||
expect(user.date_of_birth.year).to eq(1980)
|
||||
expect(user.date_of_birth.month).to eq(12)
|
||||
expect(user.date_of_birth.day).to eq(31)
|
||||
expect(user.gender).to eq('male')
|
||||
expect(user.geozone).to eq(geozone)
|
||||
end
|
||||
|
||||
it "should find existing user and use demographic information" do
|
||||
geozone = create(:geozone)
|
||||
create(:user, document_number: "12345678Z",
|
||||
document_type: "1",
|
||||
date_of_birth: Date.new(1981, 11, 30),
|
||||
gender: 'female',
|
||||
geozone: geozone)
|
||||
|
||||
residence = build(:officing_residence,
|
||||
document_number: "12345678Z",
|
||||
document_type: "1")
|
||||
|
||||
residence.save
|
||||
user = residence.user
|
||||
|
||||
expect(user.document_number).to eq('12345678Z')
|
||||
expect(user.document_type).to eq("1")
|
||||
expect(user.date_of_birth.year).to eq(1981)
|
||||
expect(user.date_of_birth.month).to eq(11)
|
||||
expect(user.date_of_birth.day).to eq(30)
|
||||
expect(user.gender).to eq('female')
|
||||
expect(user.geozone).to eq(geozone)
|
||||
end
|
||||
|
||||
it "makes half-verified users fully verified" do
|
||||
user = create(:user, residence_verified_at: Time.current, document_type: "1", document_number: "12345678Z")
|
||||
expect(user).to be_unverified
|
||||
residence = build(:officing_residence, document_number: "12345678Z", year_of_birth: 1980)
|
||||
expect(residence).to be_valid
|
||||
expect(user.reload).to be_unverified
|
||||
residence.save
|
||||
expect(user.reload).to be_level_three_verified
|
||||
end
|
||||
|
||||
it "stores failed census calls" do
|
||||
residence = build(:officing_residence, :invalid, document_number: "12345678Z")
|
||||
residence.save
|
||||
|
||||
expect(FailedCensusCall.count).to eq(1)
|
||||
expect(FailedCensusCall.first).to have_attributes({
|
||||
user_id: residence.user.id,
|
||||
poll_officer_id: residence.officer.id,
|
||||
document_number: "12345678Z",
|
||||
document_type: "1",
|
||||
year_of_birth: Time.current.year
|
||||
})
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
30
spec/models/poll/answer_spec.rb
Normal file
30
spec/models/poll/answer_spec.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Poll::Answer do
|
||||
|
||||
describe "validations" do
|
||||
it "validates that the answers are included in the Poll::Question's list" do
|
||||
q = create(:poll_question, valid_answers: 'One, Two, Three')
|
||||
expect(build(:poll_answer, question: q, answer: 'One')).to be_valid
|
||||
expect(build(:poll_answer, question: q, answer: 'Two')).to be_valid
|
||||
expect(build(:poll_answer, question: q, answer: 'Three')).to be_valid
|
||||
|
||||
expect(build(:poll_answer, question: q, answer: 'Four')).to_not be_valid
|
||||
end
|
||||
end
|
||||
|
||||
describe "#record_voter_participation" do
|
||||
it "creates a poll_voter with user and poll data" do
|
||||
answer = create(:poll_answer)
|
||||
expect(answer.poll.voters).to be_blank
|
||||
|
||||
answer.record_voter_participation
|
||||
expect(answer.poll.reload.voters.size).to eq(1)
|
||||
voter = answer.poll.voters.first
|
||||
|
||||
expect(voter.document_number).to eq(answer.author.document_number)
|
||||
expect(voter.poll_id).to eq(answer.poll.id)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
27
spec/models/poll/booth_spec.rb
Normal file
27
spec/models/poll/booth_spec.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe :booth do
|
||||
|
||||
let(:booth) { build(:poll_booth) }
|
||||
|
||||
it "should be valid" do
|
||||
expect(booth).to be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a name" do
|
||||
booth.name = nil
|
||||
expect(booth).to_not be_valid
|
||||
end
|
||||
|
||||
describe "#search" do
|
||||
it "should find booths searching by name or location" do
|
||||
booth1 = create(:poll_booth, name: "Booth number 1", location: "City center")
|
||||
booth2 = create(:poll_booth, name: "Central", location: "Town hall")
|
||||
|
||||
expect(Poll::Booth.search("number")).to eq([booth1])
|
||||
expect(Poll::Booth.search("hall")).to eq([booth2])
|
||||
expect(Poll::Booth.search("cen").size).to eq 2
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
40
spec/models/poll/final_recount_spec.rb
Normal file
40
spec/models/poll/final_recount_spec.rb
Normal file
@@ -0,0 +1,40 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe :final_recount do
|
||||
|
||||
it "should update count_log if count changes" do
|
||||
final_recount = create(:poll_final_recount, count: 33)
|
||||
|
||||
expect(final_recount.count_log).to eq("")
|
||||
|
||||
final_recount.count = 33
|
||||
final_recount.save
|
||||
final_recount.count = 32
|
||||
final_recount.save
|
||||
final_recount.count = 34
|
||||
final_recount.save
|
||||
|
||||
expect(final_recount.count_log).to eq(":33:32")
|
||||
end
|
||||
|
||||
it "should update officer_assignment_id_log if count changes" do
|
||||
final_recount = create(:poll_final_recount, count: 33)
|
||||
|
||||
expect(final_recount.count_log).to eq("")
|
||||
|
||||
final_recount.count = 33
|
||||
final_recount.officer_assignment = create(:poll_officer_assignment, id: 111)
|
||||
final_recount.save
|
||||
|
||||
final_recount.count = 32
|
||||
final_recount.officer_assignment = create(:poll_officer_assignment, id: 112)
|
||||
final_recount.save
|
||||
|
||||
final_recount.count = 34
|
||||
final_recount.officer_assignment = create(:poll_officer_assignment, id: 113)
|
||||
final_recount.save
|
||||
|
||||
expect(final_recount.officer_assignment_id_log).to eq(":111:112")
|
||||
end
|
||||
|
||||
end
|
||||
70
spec/models/poll/null_result_spec.rb
Normal file
70
spec/models/poll/null_result_spec.rb
Normal file
@@ -0,0 +1,70 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Poll::NullResult do
|
||||
|
||||
describe "logging changes" do
|
||||
it "should update amount_log if amount changes" do
|
||||
null_result = create(:poll_null_result, amount: 33)
|
||||
|
||||
expect(null_result.amount_log).to eq("")
|
||||
|
||||
null_result.amount = 33
|
||||
null_result.save
|
||||
null_result.amount = 32
|
||||
null_result.save
|
||||
null_result.amount = 34
|
||||
null_result.save
|
||||
|
||||
expect(null_result.amount_log).to eq(":33:32")
|
||||
end
|
||||
|
||||
it "should update officer_assignment_id_log if amount changes" do
|
||||
null_result = create(:poll_null_result, amount: 33)
|
||||
|
||||
expect(null_result.amount_log).to eq("")
|
||||
expect(null_result.officer_assignment_id_log).to eq("")
|
||||
|
||||
null_result.amount = 33
|
||||
null_result.officer_assignment = create(:poll_officer_assignment, id: 101)
|
||||
null_result.save
|
||||
|
||||
null_result.amount = 32
|
||||
null_result.officer_assignment = create(:poll_officer_assignment, id: 102)
|
||||
null_result.save
|
||||
|
||||
null_result.amount = 34
|
||||
null_result.officer_assignment = create(:poll_officer_assignment, id: 103)
|
||||
null_result.save
|
||||
|
||||
expect(null_result.amount_log).to eq(":33:32")
|
||||
expect(null_result.officer_assignment_id_log).to eq(":101:102")
|
||||
end
|
||||
|
||||
it "should update author_id if amount changes" do
|
||||
null_result = create(:poll_null_result, amount: 33)
|
||||
|
||||
expect(null_result.amount_log).to eq("")
|
||||
expect(null_result.author_id_log).to eq("")
|
||||
|
||||
author_A = create(:poll_officer).user
|
||||
author_B = create(:poll_officer).user
|
||||
author_C = create(:poll_officer).user
|
||||
|
||||
null_result.amount = 33
|
||||
null_result.author_id = author_A.id
|
||||
null_result.save!
|
||||
|
||||
null_result.amount = 32
|
||||
null_result.author_id = author_B.id
|
||||
null_result.save!
|
||||
|
||||
null_result.amount = 34
|
||||
null_result.author_id = author_C.id
|
||||
null_result.save!
|
||||
|
||||
expect(null_result.amount_log).to eq(":33:32")
|
||||
expect(null_result.author_id_log).to eq(":#{author_A.id}:#{author_B.id}")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
12
spec/models/poll/officer_assignment_spec.rb
Normal file
12
spec/models/poll/officer_assignment_spec.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe :officer_assignment do
|
||||
it "should log user data on creation" do
|
||||
user = create(:user, username: "Larry Bird", email: "larry@lege.nd")
|
||||
officer = create(:poll_officer, user: user)
|
||||
|
||||
oa = create(:poll_officer_assignment, officer: officer)
|
||||
|
||||
expect(oa.reload.user_data_log).to eq "#{user.id} - Larry Bird (larry@lege.nd)"
|
||||
end
|
||||
end
|
||||
124
spec/models/poll/officer_spec.rb
Normal file
124
spec/models/poll/officer_spec.rb
Normal file
@@ -0,0 +1,124 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe :officer do
|
||||
|
||||
describe "#voting_days_assigned_polls" do
|
||||
it "should return all polls with this officer assigned during voting days" do
|
||||
officer = create(:poll_officer)
|
||||
|
||||
poll_1 = create(:poll)
|
||||
poll_2 = create(:poll)
|
||||
poll_3 = create(:poll)
|
||||
|
||||
booth_assignment_1a = create(:poll_booth_assignment, poll: poll_1)
|
||||
booth_assignment_1b = create(:poll_booth_assignment, poll: poll_1)
|
||||
booth_assignment_2 = create(:poll_booth_assignment, poll: poll_2)
|
||||
|
||||
create(:poll_officer_assignment, booth_assignment: booth_assignment_1a, officer: officer, date: poll_1.starts_at)
|
||||
create(:poll_officer_assignment, booth_assignment: booth_assignment_1b, officer: officer, date: poll_1.ends_at)
|
||||
create(:poll_officer_assignment, booth_assignment: booth_assignment_2, officer: officer)
|
||||
|
||||
assigned_polls = officer.voting_days_assigned_polls
|
||||
expect(assigned_polls.size).to eq 2
|
||||
expect(assigned_polls.include?(poll_1)).to eq(true)
|
||||
expect(assigned_polls.include?(poll_2)).to eq(true)
|
||||
expect(assigned_polls.include?(poll_3)).to eq(false)
|
||||
end
|
||||
|
||||
it "should not return polls with this officer assigned for final recount/results" do
|
||||
officer = create(:poll_officer)
|
||||
|
||||
poll_1 = create(:poll)
|
||||
poll_2 = create(:poll)
|
||||
|
||||
booth_assignment_1 = create(:poll_booth_assignment, poll: poll_1)
|
||||
booth_assignment_2 = create(:poll_booth_assignment, poll: poll_2)
|
||||
|
||||
create(:poll_officer_assignment, booth_assignment: booth_assignment_1, officer: officer, date: poll_1.starts_at)
|
||||
create(:poll_officer_assignment, booth_assignment: booth_assignment_2, officer: officer, final: true)
|
||||
|
||||
assigned_polls = officer.voting_days_assigned_polls
|
||||
expect(assigned_polls.size).to eq 1
|
||||
expect(assigned_polls.include?(poll_1)).to eq(true)
|
||||
expect(assigned_polls.include?(poll_2)).to eq(false)
|
||||
end
|
||||
|
||||
it "should return polls ordered by end date (desc)" do
|
||||
officer = create(:poll_officer)
|
||||
|
||||
poll_1 = create(:poll, ends_at: 1.day.ago)
|
||||
poll_2 = create(:poll, ends_at: 10.days.from_now)
|
||||
poll_3 = create(:poll, ends_at: 10.day.ago)
|
||||
|
||||
[poll_1, poll_2, poll_3].each do |p|
|
||||
create(:poll_officer_assignment, officer: officer, booth_assignment: create(:poll_booth_assignment, poll: p))
|
||||
end
|
||||
|
||||
assigned_polls = officer.voting_days_assigned_polls
|
||||
|
||||
expect(assigned_polls.first).to eq(poll_2)
|
||||
expect(assigned_polls.second).to eq(poll_1)
|
||||
expect(assigned_polls.last).to eq(poll_3)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#final_days_assigned_polls" do
|
||||
it "should return all polls with this officer assigned for final recount/results" do
|
||||
officer = create(:poll_officer)
|
||||
|
||||
poll_1 = create(:poll)
|
||||
poll_2 = create(:poll)
|
||||
poll_3 = create(:poll)
|
||||
|
||||
booth_assignment_1a = create(:poll_booth_assignment, poll: poll_1)
|
||||
booth_assignment_1b = create(:poll_booth_assignment, poll: poll_1)
|
||||
booth_assignment_2 = create(:poll_booth_assignment, poll: poll_2)
|
||||
|
||||
create(:poll_officer_assignment, booth_assignment: booth_assignment_1a, officer: officer, date: poll_1.starts_at, final: true)
|
||||
create(:poll_officer_assignment, booth_assignment: booth_assignment_1b, officer: officer, date: poll_1.ends_at, final: true)
|
||||
create(:poll_officer_assignment, booth_assignment: booth_assignment_2, officer: officer, final: true)
|
||||
|
||||
assigned_polls = officer.final_days_assigned_polls
|
||||
expect(assigned_polls.size).to eq 2
|
||||
expect(assigned_polls.include?(poll_1)).to eq(true)
|
||||
expect(assigned_polls.include?(poll_2)).to eq(true)
|
||||
expect(assigned_polls.include?(poll_3)).to eq(false)
|
||||
end
|
||||
|
||||
it "should not return polls with this officer assigned for voting days" do
|
||||
officer = create(:poll_officer)
|
||||
|
||||
poll_1 = create(:poll)
|
||||
poll_2 = create(:poll)
|
||||
|
||||
booth_assignment_1 = create(:poll_booth_assignment, poll: poll_1)
|
||||
booth_assignment_2 = create(:poll_booth_assignment, poll: poll_2)
|
||||
|
||||
create(:poll_officer_assignment, booth_assignment: booth_assignment_1, officer: officer, date: poll_1.starts_at)
|
||||
create(:poll_officer_assignment, booth_assignment: booth_assignment_2, officer: officer, final: true)
|
||||
|
||||
assigned_polls = officer.final_days_assigned_polls
|
||||
expect(assigned_polls.size).to eq 1
|
||||
expect(assigned_polls.include?(poll_1)).to eq(false)
|
||||
expect(assigned_polls.include?(poll_2)).to eq(true)
|
||||
end
|
||||
|
||||
it "should return polls ordered by end date (desc)" do
|
||||
officer = create(:poll_officer)
|
||||
|
||||
poll_1 = create(:poll, ends_at: 1.day.ago)
|
||||
poll_2 = create(:poll, ends_at: 10.days.from_now)
|
||||
poll_3 = create(:poll, ends_at: 10.day.ago)
|
||||
|
||||
[poll_1, poll_2, poll_3].each do |p|
|
||||
create(:poll_officer_assignment, officer: officer, booth_assignment: create(:poll_booth_assignment, poll: p), final: true)
|
||||
end
|
||||
|
||||
assigned_polls = officer.final_days_assigned_polls
|
||||
|
||||
expect(assigned_polls.first).to eq(poll_2)
|
||||
expect(assigned_polls.second).to eq(poll_1)
|
||||
expect(assigned_polls.last).to eq(poll_3)
|
||||
end
|
||||
end
|
||||
end
|
||||
81
spec/models/poll/partial_result_spec.rb
Normal file
81
spec/models/poll/partial_result_spec.rb
Normal file
@@ -0,0 +1,81 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Poll::PartialResult do
|
||||
|
||||
describe "validations" do
|
||||
it "validates that the answers are included in the Poll::Question's list" do
|
||||
q = create(:poll_question, valid_answers: 'One, Two, Three')
|
||||
expect(build(:poll_partial_result, question: q, answer: 'One')).to be_valid
|
||||
expect(build(:poll_partial_result, question: q, answer: 'Two')).to be_valid
|
||||
expect(build(:poll_partial_result, question: q, answer: 'Three')).to be_valid
|
||||
|
||||
expect(build(:poll_partial_result, question: q, answer: 'Four')).to_not be_valid
|
||||
end
|
||||
end
|
||||
|
||||
describe "logging changes" do
|
||||
it "should update amount_log if amount changes" do
|
||||
partial_result = create(:poll_partial_result, amount: 33)
|
||||
|
||||
expect(partial_result.amount_log).to eq("")
|
||||
|
||||
partial_result.amount = 33
|
||||
partial_result.save
|
||||
partial_result.amount = 32
|
||||
partial_result.save
|
||||
partial_result.amount = 34
|
||||
partial_result.save
|
||||
|
||||
expect(partial_result.amount_log).to eq(":33:32")
|
||||
end
|
||||
|
||||
it "should update officer_assignment_id_log if amount changes" do
|
||||
partial_result = create(:poll_partial_result, amount: 33)
|
||||
|
||||
expect(partial_result.amount_log).to eq("")
|
||||
expect(partial_result.officer_assignment_id_log).to eq("")
|
||||
|
||||
partial_result.amount = 33
|
||||
partial_result.officer_assignment = create(:poll_officer_assignment, id: 10)
|
||||
partial_result.save
|
||||
|
||||
partial_result.amount = 32
|
||||
partial_result.officer_assignment = create(:poll_officer_assignment, id: 20)
|
||||
partial_result.save
|
||||
|
||||
partial_result.amount = 34
|
||||
partial_result.officer_assignment = create(:poll_officer_assignment, id: 30)
|
||||
partial_result.save
|
||||
|
||||
expect(partial_result.amount_log).to eq(":33:32")
|
||||
expect(partial_result.officer_assignment_id_log).to eq(":10:20")
|
||||
end
|
||||
|
||||
it "should update author_id if amount changes" do
|
||||
partial_result = create(:poll_partial_result, amount: 33)
|
||||
|
||||
expect(partial_result.amount_log).to eq("")
|
||||
expect(partial_result.author_id_log).to eq("")
|
||||
|
||||
author_A = create(:poll_officer).user
|
||||
author_B = create(:poll_officer).user
|
||||
author_C = create(:poll_officer).user
|
||||
|
||||
partial_result.amount = 33
|
||||
partial_result.author_id = author_A.id
|
||||
partial_result.save!
|
||||
|
||||
partial_result.amount = 32
|
||||
partial_result.author_id = author_B.id
|
||||
partial_result.save!
|
||||
|
||||
partial_result.amount = 34
|
||||
partial_result.author_id = author_C.id
|
||||
partial_result.save!
|
||||
|
||||
expect(partial_result.amount_log).to eq(":33:32")
|
||||
expect(partial_result.author_id_log).to eq(":#{author_A.id}:#{author_B.id}")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
143
spec/models/poll/poll_spec.rb
Normal file
143
spec/models/poll/poll_spec.rb
Normal file
@@ -0,0 +1,143 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe :poll do
|
||||
|
||||
let(:poll) { build(:poll) }
|
||||
|
||||
describe "validations" do
|
||||
it "should be valid" do
|
||||
expect(poll).to be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a name" do
|
||||
poll.name = nil
|
||||
expect(poll).to_not be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a start date" do
|
||||
poll.starts_at = nil
|
||||
expect(poll).to_not be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without an end date" do
|
||||
poll.ends_at = nil
|
||||
expect(poll).to_not be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a proper start/end date range" do
|
||||
poll.starts_at = 1.week.ago
|
||||
poll.ends_at = 2.months.ago
|
||||
expect(poll).to_not be_valid
|
||||
end
|
||||
end
|
||||
|
||||
describe "#opened?" do
|
||||
it "returns true only when it isn't too early or too late" do
|
||||
expect(create(:poll, :incoming)).to_not be_current
|
||||
expect(create(:poll, :expired)).to_not be_current
|
||||
expect(create(:poll)).to be_current
|
||||
end
|
||||
end
|
||||
|
||||
describe "#incoming?" do
|
||||
it "returns true only when it is too early" do
|
||||
expect(create(:poll, :incoming)).to be_incoming
|
||||
expect(create(:poll, :expired)).to_not be_incoming
|
||||
expect(create(:poll)).to_not be_incoming
|
||||
end
|
||||
end
|
||||
|
||||
describe "#expired?" do
|
||||
it "returns true only when it is too late" do
|
||||
expect(create(:poll, :incoming)).to_not be_expired
|
||||
expect(create(:poll, :expired)).to be_expired
|
||||
expect(create(:poll)).to_not be_expired
|
||||
end
|
||||
end
|
||||
|
||||
describe "#published?" do
|
||||
it "returns true only when published is true" do
|
||||
expect(create(:poll)).to_not be_published
|
||||
expect(create(:poll, :published)).to be_published
|
||||
end
|
||||
end
|
||||
|
||||
describe "#document_has_voted?" do
|
||||
it "returns true if Poll::Voter with document exists" do
|
||||
poll = create(:poll)
|
||||
voter = create(:poll_voter, :valid_document, poll: poll)
|
||||
|
||||
expect(poll.document_has_voted?(voter.document_number, voter.document_type)).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if Poll::Voter with document does not exists" do
|
||||
poll_2 = create(:poll)
|
||||
voter = create(:poll_voter, :valid_document, poll: poll_2)
|
||||
|
||||
expect(poll.document_has_voted?(voter.document_number, voter.document_type)).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "answerable_by" do
|
||||
let(:geozone) {create(:geozone) }
|
||||
|
||||
let!(:current_poll) { create(:poll) }
|
||||
let!(:expired_poll) { create(:poll, :expired) }
|
||||
let!(:incoming_poll) { create(:poll, :incoming) }
|
||||
let!(:current_restricted_poll) { create(:poll, geozone_restricted: true, geozones: [geozone]) }
|
||||
let!(:expired_restricted_poll) { create(:poll, :expired, geozone_restricted: true, geozones: [geozone]) }
|
||||
let!(:incoming_restricted_poll) { create(:poll, :incoming, geozone_restricted: true, geozones: [geozone]) }
|
||||
let!(:all_polls) { [current_poll, expired_poll, incoming_poll, current_poll, expired_restricted_poll, incoming_restricted_poll] }
|
||||
let(:non_current_polls) { [expired_poll, incoming_poll, expired_restricted_poll, incoming_restricted_poll] }
|
||||
|
||||
let(:non_user) { nil }
|
||||
let(:level1) { create(:user) }
|
||||
let(:level2) { create(:user, :level_two) }
|
||||
let(:level2_from_geozone) { create(:user, :level_two, geozone: geozone) }
|
||||
let(:all_users) { [non_user, level1, level2, level2_from_geozone] }
|
||||
|
||||
describe 'instance method' do
|
||||
it "rejects non-users and level 1 users" do
|
||||
all_polls.each do |poll|
|
||||
expect(poll).to_not be_answerable_by(non_user)
|
||||
expect(poll).to_not be_answerable_by(level1)
|
||||
end
|
||||
end
|
||||
|
||||
it "rejects everyone when not current" do
|
||||
non_current_polls.each do |poll|
|
||||
all_users.each do |user|
|
||||
expect(poll).to_not be_answerable_by(user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "accepts level 2 users when unrestricted and current" do
|
||||
expect(current_poll).to be_answerable_by(level2)
|
||||
expect(current_poll).to be_answerable_by(level2_from_geozone)
|
||||
end
|
||||
|
||||
it "accepts level 2 users only from the same geozone when restricted by geozone" do
|
||||
expect(current_restricted_poll).to_not be_answerable_by(level2)
|
||||
expect(current_restricted_poll).to be_answerable_by(level2_from_geozone)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'class method' do
|
||||
it "returns no polls for non-users and level 1 users" do
|
||||
expect(Poll.answerable_by(nil)).to be_empty
|
||||
expect(Poll.answerable_by(level1)).to be_empty
|
||||
end
|
||||
|
||||
it "returns unrestricted polls for level 2 users" do
|
||||
expect(Poll.answerable_by(level2).to_a).to eq([current_poll])
|
||||
end
|
||||
|
||||
it "returns restricted & unrestricted polls for level 2 users of the correct geozone" do
|
||||
list = Poll.answerable_by(level2_from_geozone)
|
||||
.order(:geozone_restricted)
|
||||
expect(list.to_a).to eq([current_poll, current_restricted_poll])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
26
spec/models/poll/question_spec.rb
Normal file
26
spec/models/poll/question_spec.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Poll::Question, type: :model do
|
||||
|
||||
describe "#valid_answers" do
|
||||
it "gets a comma-separated string, but returns an array" do
|
||||
q = create(:poll_question, valid_answers: "Yes, No")
|
||||
expect(q.valid_answers).to eq(["Yes", "No"])
|
||||
end
|
||||
end
|
||||
|
||||
describe "#copy_attributes_from_proposal" do
|
||||
it "copies the attributes from the proposal" do
|
||||
create_list(:geozone, 3)
|
||||
p = create(:proposal)
|
||||
q = create(:poll_question)
|
||||
q.copy_attributes_from_proposal(p)
|
||||
expect(q.valid_answers).to eq(['Yes', 'No'])
|
||||
expect(q.author).to eq(p.author)
|
||||
expect(q.author_visible_name).to eq(p.author.name)
|
||||
expect(q.proposal_id).to eq(p.id)
|
||||
expect(q.title).to eq(p.title)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
40
spec/models/poll/recount_spec.rb
Normal file
40
spec/models/poll/recount_spec.rb
Normal file
@@ -0,0 +1,40 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe :recount do
|
||||
|
||||
it "should update count_log if count changes" do
|
||||
recount = create(:poll_recount, count: 33)
|
||||
|
||||
expect(recount.count_log).to eq("")
|
||||
|
||||
recount.count = 33
|
||||
recount.save
|
||||
recount.count = 32
|
||||
recount.save
|
||||
recount.count = 34
|
||||
recount.save
|
||||
|
||||
expect(recount.count_log).to eq(":33:32")
|
||||
end
|
||||
|
||||
it "should update officer_assignment_id_log if count changes" do
|
||||
recount = create(:poll_recount, count: 33)
|
||||
|
||||
expect(recount.count_log).to eq("")
|
||||
|
||||
recount.count = 33
|
||||
recount.officer_assignment = create(:poll_officer_assignment, id: 11)
|
||||
recount.save
|
||||
|
||||
recount.count = 32
|
||||
recount.officer_assignment = create(:poll_officer_assignment, id: 12)
|
||||
recount.save
|
||||
|
||||
recount.count = 34
|
||||
recount.officer_assignment = create(:poll_officer_assignment, id: 13)
|
||||
recount.save
|
||||
|
||||
expect(recount.officer_assignment_id_log).to eq(":11:12")
|
||||
end
|
||||
|
||||
end
|
||||
114
spec/models/poll/voter_spec.rb
Normal file
114
spec/models/poll/voter_spec.rb
Normal file
@@ -0,0 +1,114 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe :voter do
|
||||
|
||||
let(:poll) { create(:poll) }
|
||||
let(:booth) { create(:poll_booth) }
|
||||
let(:booth_assignment) { create(:poll_booth_assignment, poll: poll, booth: booth) }
|
||||
let(:voter) { create(:poll_voter) }
|
||||
|
||||
describe "validations" do
|
||||
|
||||
it "should be valid" do
|
||||
expect(voter).to be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a user" do
|
||||
voter.user = nil
|
||||
expect(voter).to_not be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a poll" do
|
||||
voter.poll = nil
|
||||
expect(voter).to_not be_valid
|
||||
end
|
||||
|
||||
it "should be valid if has not voted" do
|
||||
voter = build(:poll_voter, :valid_document)
|
||||
|
||||
expect(voter).to be_valid
|
||||
end
|
||||
|
||||
it "should not be valid if the user has already voted in the same poll or booth_assignment" do
|
||||
user = create(:user, :level_two)
|
||||
|
||||
voter1 = create(:poll_voter, user: user, poll: poll)
|
||||
voter2 = build(:poll_voter, user: user, poll: poll)
|
||||
|
||||
expect(voter2).to_not be_valid
|
||||
expect(voter2.errors.messages[:document_number]).to eq(["User has already voted"])
|
||||
end
|
||||
|
||||
it "should not be valid if the user has already voted in the same poll/booth" do
|
||||
user = create(:user, :level_two)
|
||||
|
||||
voter1 = create(:poll_voter, user: user, poll: poll, booth_assignment: booth_assignment)
|
||||
voter2 = build(:poll_voter, user: user, poll: poll, booth_assignment: booth_assignment)
|
||||
|
||||
expect(voter2).to_not be_valid
|
||||
expect(voter2.errors.messages[:document_number]).to eq(["User has already voted"])
|
||||
end
|
||||
|
||||
it "should not be valid if the user has already voted in different booth in the same poll" do
|
||||
booth_assignment1 = create(:poll_booth_assignment, poll: poll)
|
||||
booth_assignment2 = create(:poll_booth_assignment, poll: poll)
|
||||
|
||||
user = create(:user, :level_two)
|
||||
|
||||
voter1 = create(:poll_voter, user: user, poll: poll, booth_assignment: booth_assignment1)
|
||||
voter2 = build(:poll_voter, user: user, poll: poll, booth_assignment: booth_assignment2)
|
||||
|
||||
expect(voter2).to_not be_valid
|
||||
expect(voter2.errors.messages[:document_number]).to eq(["User has already voted"])
|
||||
end
|
||||
|
||||
it "should be valid if the user has already voted in the same booth in different poll" do
|
||||
booth_assignment1 = create(:poll_booth_assignment, booth: booth)
|
||||
booth_assignment2 = create(:poll_booth_assignment, booth: booth, poll: poll)
|
||||
|
||||
user = create(:user, :level_two)
|
||||
|
||||
voter1 = create(:poll_voter, user: user, booth_assignment: booth_assignment1)
|
||||
voter2 = build(:poll_voter, user: user, booth_assignment: booth_assignment2)
|
||||
|
||||
expect(voter2).to be_valid
|
||||
end
|
||||
|
||||
it "should not be valid if the user has voted via web" do
|
||||
answer = create(:poll_answer)
|
||||
answer.record_voter_participation
|
||||
|
||||
voter = build(:poll_voter, poll: answer.question.poll, user: answer.author)
|
||||
expect(voter).to_not be_valid
|
||||
expect(voter.errors.messages[:document_number]).to eq(["User has already voted"])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "save" do
|
||||
|
||||
it "sets demographic info" do
|
||||
geozone = create(:geozone)
|
||||
user = create(:user,
|
||||
geozone: geozone,
|
||||
date_of_birth: 30.years.ago,
|
||||
gender: "female")
|
||||
|
||||
voter = build(:poll_voter, user: user)
|
||||
voter.save
|
||||
|
||||
expect(voter.geozone).to eq(geozone)
|
||||
expect(voter.age).to eq(30)
|
||||
expect(voter.gender).to eq("female")
|
||||
end
|
||||
|
||||
it "sets user info" do
|
||||
user = create(:user, document_number: "1234A", document_type: "1")
|
||||
voter = build(:poll_voter, user: user)
|
||||
voter.save
|
||||
|
||||
expect(voter.document_number).to eq("1234A")
|
||||
expect(voter.document_type).to eq("1")
|
||||
end
|
||||
end
|
||||
end
|
||||
70
spec/models/poll/white_result_spec.rb
Normal file
70
spec/models/poll/white_result_spec.rb
Normal file
@@ -0,0 +1,70 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Poll::WhiteResult do
|
||||
|
||||
describe "logging changes" do
|
||||
it "should update amount_log if amount changes" do
|
||||
white_result = create(:poll_white_result, amount: 33)
|
||||
|
||||
expect(white_result.amount_log).to eq("")
|
||||
|
||||
white_result.amount = 33
|
||||
white_result.save
|
||||
white_result.amount = 32
|
||||
white_result.save
|
||||
white_result.amount = 34
|
||||
white_result.save
|
||||
|
||||
expect(white_result.amount_log).to eq(":33:32")
|
||||
end
|
||||
|
||||
it "should update officer_assignment_id_log if amount changes" do
|
||||
white_result = create(:poll_white_result, amount: 33)
|
||||
|
||||
expect(white_result.amount_log).to eq("")
|
||||
expect(white_result.officer_assignment_id_log).to eq("")
|
||||
|
||||
white_result.amount = 33
|
||||
white_result.officer_assignment = create(:poll_officer_assignment, id: 21)
|
||||
white_result.save
|
||||
|
||||
white_result.amount = 32
|
||||
white_result.officer_assignment = create(:poll_officer_assignment, id: 22)
|
||||
white_result.save
|
||||
|
||||
white_result.amount = 34
|
||||
white_result.officer_assignment = create(:poll_officer_assignment, id: 23)
|
||||
white_result.save
|
||||
|
||||
expect(white_result.amount_log).to eq(":33:32")
|
||||
expect(white_result.officer_assignment_id_log).to eq(":21:22")
|
||||
end
|
||||
|
||||
it "should update author_id if amount changes" do
|
||||
white_result = create(:poll_white_result, amount: 33)
|
||||
|
||||
expect(white_result.amount_log).to eq("")
|
||||
expect(white_result.author_id_log).to eq("")
|
||||
|
||||
author_A = create(:poll_officer).user
|
||||
author_B = create(:poll_officer).user
|
||||
author_C = create(:poll_officer).user
|
||||
|
||||
white_result.amount = 33
|
||||
white_result.author_id = author_A.id
|
||||
white_result.save!
|
||||
|
||||
white_result.amount = 32
|
||||
white_result.author_id = author_B.id
|
||||
white_result.save!
|
||||
|
||||
white_result.amount = 34
|
||||
white_result.author_id = author_C.id
|
||||
white_result.save!
|
||||
|
||||
expect(white_result.amount_log).to eq(":33:32")
|
||||
expect(white_result.author_id_log).to eq(":#{author_A.id}:#{author_B.id}")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -65,6 +65,13 @@ describe User do
|
||||
end
|
||||
end
|
||||
|
||||
describe "#age" do
|
||||
it "is the rounded integer age based on the date_of_birth" do
|
||||
user = create(:user, date_of_birth: 33.years.ago)
|
||||
expect(user.age).to eq(33)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'preferences' do
|
||||
describe 'email_on_comment' do
|
||||
it 'should be false by default' do
|
||||
@@ -151,6 +158,18 @@ describe User do
|
||||
end
|
||||
end
|
||||
|
||||
describe "poll_officer?" do
|
||||
it "is false when the user is not a poll officer" do
|
||||
expect(subject.poll_officer?).to be false
|
||||
end
|
||||
|
||||
it "is true when the user is a poll officer" do
|
||||
subject.save
|
||||
create(:poll_officer, user: subject)
|
||||
expect(subject.poll_officer?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe "organization?" do
|
||||
it "is false when the user is not an organization" do
|
||||
expect(subject.organization?).to be false
|
||||
@@ -351,6 +370,20 @@ describe User do
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "erased" do
|
||||
|
||||
it "returns users that have been erased" do
|
||||
user1 = create(:user, erased_at: Time.current)
|
||||
user2 = create(:user, erased_at: Time.current)
|
||||
user3 = create(:user, erased_at: nil)
|
||||
|
||||
expect(User.erased).to include(user1)
|
||||
expect(User.erased).to include(user2)
|
||||
expect(User.erased).to_not include(user3)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
describe "self.search" do
|
||||
@@ -469,4 +502,134 @@ describe User do
|
||||
|
||||
end
|
||||
|
||||
describe "#take_votes_from" do
|
||||
it "logs info of previous users" do
|
||||
user = create(:user, :level_three)
|
||||
other_user = create(:user, :level_three)
|
||||
another_user = create(:user)
|
||||
|
||||
expect(user.former_users_data_log).to be_blank
|
||||
|
||||
user.take_votes_from other_user
|
||||
|
||||
expect(user.former_users_data_log).to include("id: #{other_user.id}")
|
||||
|
||||
user.take_votes_from another_user
|
||||
|
||||
expect(user.former_users_data_log).to include("id: #{other_user.id}")
|
||||
expect(user.former_users_data_log).to include("| id: #{another_user.id}")
|
||||
end
|
||||
|
||||
it "reassigns votes from other user" do
|
||||
other_user = create(:user, :level_three)
|
||||
user = create(:user, :level_three)
|
||||
|
||||
v1 = create(:vote, voter: other_user, votable: create(:debate))
|
||||
v2 = create(:vote, voter: other_user, votable: create(:proposal))
|
||||
v3 = create(:vote, voter: other_user, votable: create(:comment))
|
||||
|
||||
create(:vote)
|
||||
|
||||
expect(other_user.votes.count).to eq(3)
|
||||
expect(user.votes.count).to eq(0)
|
||||
|
||||
user.take_votes_from other_user
|
||||
|
||||
expect(other_user.votes.count).to eq(0)
|
||||
expect(user.vote_ids.sort).to eq([v1.id, v2.id, v3.id].sort)
|
||||
end
|
||||
|
||||
it "reassigns budget ballots from other user" do
|
||||
other_user = create(:user, :level_three)
|
||||
user = create(:user, :level_three)
|
||||
|
||||
b1 = create(:budget_ballot, user: other_user)
|
||||
b2 = create(:budget_ballot, user: other_user)
|
||||
|
||||
create(:budget_ballot)
|
||||
|
||||
expect(Budget::Ballot.where(user: other_user).count).to eq(2)
|
||||
expect(Budget::Ballot.where(user: user).count).to eq(0)
|
||||
|
||||
user.take_votes_from other_user
|
||||
|
||||
expect(Budget::Ballot.where(user: other_user).count).to eq(0)
|
||||
expect(Budget::Ballot.where(user: user).sort).to eq([b1, b2].sort)
|
||||
end
|
||||
|
||||
it "reassigns poll voters from other user" do
|
||||
other_user = create(:user, :level_three)
|
||||
user = create(:user, :level_three)
|
||||
|
||||
v1 = create(:poll_voter, user: other_user)
|
||||
v2 = create(:poll_voter, user: other_user)
|
||||
|
||||
create(:poll_voter)
|
||||
|
||||
expect(Poll::Voter.where(user: other_user).count).to eq(2)
|
||||
expect(Poll::Voter.where(user: user).count).to eq(0)
|
||||
|
||||
user.take_votes_from other_user
|
||||
|
||||
expect(Poll::Voter.where(user: other_user).count).to eq(0)
|
||||
expect(Poll::Voter.where(user: user).sort).to eq([v1, v2].sort)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#take_votes_if_erased_document" do
|
||||
it "does nothing if no erased user with received document" do
|
||||
user_1 = create(:user, :level_three)
|
||||
user_2 = create(:user, :level_three)
|
||||
|
||||
create(:vote, voter: user_1)
|
||||
create(:budget_ballot, user: user_1)
|
||||
create(:poll_voter, user: user_1)
|
||||
|
||||
user_2.take_votes_if_erased_document(111, 1)
|
||||
|
||||
expect(user_1.votes.count).to eq(1)
|
||||
expect(user_2.votes.count).to eq(0)
|
||||
|
||||
expect(Budget::Ballot.where(user: user_1).count).to eq(1)
|
||||
expect(Budget::Ballot.where(user: user_2).count).to eq(0)
|
||||
|
||||
expect(Poll::Voter.where(user: user_1).count).to eq(1)
|
||||
expect(Poll::Voter.where(user: user_2).count).to eq(0)
|
||||
end
|
||||
|
||||
it "takes votes from erased user with received document" do
|
||||
user_1 = create(:user, :level_two, document_number: "12345777", document_type: "1")
|
||||
user_2 = create(:user)
|
||||
|
||||
create(:vote, voter: user_1)
|
||||
create(:budget_ballot, user: user_1)
|
||||
create(:poll_voter, user: user_1)
|
||||
|
||||
user_1.erase
|
||||
|
||||
user_2.take_votes_if_erased_document("12345777", "1")
|
||||
|
||||
expect(user_1.votes.count).to eq(0)
|
||||
expect(user_2.votes.count).to eq(1)
|
||||
|
||||
expect(Budget::Ballot.where(user: user_1).count).to eq(0)
|
||||
expect(Budget::Ballot.where(user: user_2).count).to eq(1)
|
||||
|
||||
expect(Poll::Voter.where(user: user_1).count).to eq(0)
|
||||
expect(Poll::Voter.where(user: user_2).count).to eq(1)
|
||||
end
|
||||
|
||||
it "removes document from erased user and logs info" do
|
||||
user_1 = create(:user, document_number: "12345777", document_type: "1")
|
||||
user_2 = create(:user)
|
||||
user_1.erase
|
||||
|
||||
user_2.take_votes_if_erased_document("12345777", "1")
|
||||
|
||||
expect(user_2.reload.former_users_data_log).to include("id: #{user_1.id}")
|
||||
expect(user_1.reload.document_number).to be_blank
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -105,4 +105,9 @@ RSpec.configure do |config|
|
||||
end
|
||||
|
||||
# Parallel build helper configuration for travis
|
||||
Knapsack::Adapters::RSpecAdapter.bind
|
||||
Knapsack::Adapters::RSpecAdapter.bind
|
||||
|
||||
options = {js_errors: false}
|
||||
Capybara.register_driver :poltergeist_no_js_errors do |app|
|
||||
Capybara::Poltergeist::Driver.new(app, options)
|
||||
end
|
||||
@@ -141,6 +141,16 @@ module CommonActions
|
||||
expect(page).to have_content 'Residence verified'
|
||||
end
|
||||
|
||||
def officing_verify_residence
|
||||
select 'DNI', from: 'residence_document_type'
|
||||
fill_in 'residence_document_number', with: "12345678Z"
|
||||
fill_in 'residence_year_of_birth', with: "1980"
|
||||
|
||||
click_button 'Validate document'
|
||||
|
||||
expect(page).to have_content 'Document verified with Census'
|
||||
end
|
||||
|
||||
def confirm_phone
|
||||
fill_in 'sms_phone', with: "611111111"
|
||||
click_button 'Send'
|
||||
@@ -203,7 +213,7 @@ module CommonActions
|
||||
create(:debate, :with_confidence_score, cached_votes_up: 80)]
|
||||
end
|
||||
|
||||
def create_successfull_proposals
|
||||
def create_successful_proposals
|
||||
[create(:proposal, title: "Winter is coming", question: "Do you speak it?", cached_votes_up: Proposal.votes_needed_for_success + 100),
|
||||
create(:proposal, title: "Fire and blood", question: "You talking to me?", cached_votes_up: Proposal.votes_needed_for_success + 1)]
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user