When calculating the stats on, say, January 1st 2024, and using a group age of, say, between 20 and 24 years, we were considering that everyone born between 2000 and 2004 had between 20 and 24 years. This wasn't accurate, since most people born in 2004 would have 19 years at that point, and most people born in 1999 would have 24 years.
303 lines
10 KiB
Ruby
303 lines
10 KiB
Ruby
require "rails_helper"
|
|
|
|
describe Poll::Stats do
|
|
let(:poll) { create(:poll) }
|
|
let(:stats) { Poll::Stats.new(poll) }
|
|
|
|
describe "#participants" do
|
|
it "includes hidden users" do
|
|
create(:poll_voter, poll: poll)
|
|
create(:poll_voter, poll: poll, user: create(:user, :level_two, :hidden))
|
|
|
|
expect(stats.participants.count).to eq(2)
|
|
end
|
|
end
|
|
|
|
describe "total participants" do
|
|
before { allow(stats).to receive(:total_web_white).and_return(1) }
|
|
|
|
it "supports every channel" do
|
|
3.times { create(:poll_voter, :from_web, poll: poll) }
|
|
create(:poll_recount, :from_booth, poll: poll,
|
|
total_amount: 8,
|
|
white_amount: 4,
|
|
null_amount: 1)
|
|
|
|
expect(stats.total_participants_web).to eq(3)
|
|
expect(stats.total_participants_booth).to eq(13)
|
|
expect(stats.total_participants).to eq(16)
|
|
end
|
|
end
|
|
|
|
describe "#total_participants_booth" do
|
|
it "uses recounts even if there are discrepancies when recounting" do
|
|
create(:poll_recount, :from_booth, poll: poll, total_amount: 1)
|
|
2.times { create(:poll_voter, :from_booth, poll: poll) }
|
|
|
|
expect(stats.total_participants_booth).to eq(1)
|
|
end
|
|
end
|
|
|
|
describe "total participants percentage by channel" do
|
|
it "is relative to the total amount of participants" do
|
|
create(:poll_voter, :from_web, poll: poll)
|
|
create(:poll_recount, :from_booth, poll: poll, total_amount: 5)
|
|
|
|
expect(stats.total_participants_web_percentage).to eq(16.667)
|
|
expect(stats.total_participants_booth_percentage).to eq(83.333)
|
|
end
|
|
end
|
|
|
|
describe "#total_web_valid" do
|
|
before { allow(stats).to receive(:total_web_white).and_return(1) }
|
|
|
|
it "returns only valid votes" do
|
|
3.times { create(:poll_voter, :from_web, poll: poll) }
|
|
|
|
expect(stats.total_web_valid).to eq(2)
|
|
end
|
|
end
|
|
|
|
describe "#total_web_null" do
|
|
it "returns 0" do
|
|
expect(stats.total_web_null).to eq(0)
|
|
end
|
|
end
|
|
|
|
describe "#total_booth_valid" do
|
|
it "sums the total amounts in the recounts" do
|
|
create(:poll_recount, :from_booth, poll: poll, total_amount: 3, white_amount: 1)
|
|
create(:poll_recount, :from_booth, poll: poll, total_amount: 4, null_amount: 2)
|
|
|
|
expect(stats.total_booth_valid).to eq(7)
|
|
end
|
|
end
|
|
|
|
describe "#total_booth_white" do
|
|
it "sums the white amounts in the recounts" do
|
|
create(:poll_recount, :from_booth, poll: poll, white_amount: 120, total_amount: 3)
|
|
create(:poll_recount, :from_booth, poll: poll, white_amount: 203, null_amount: 5)
|
|
|
|
expect(stats.total_booth_white).to eq(323)
|
|
end
|
|
end
|
|
|
|
describe "#total_booth_null" do
|
|
it "sums the null amounts in the recounts" do
|
|
create(:poll_recount, :from_booth, poll: poll, null_amount: 125, total_amount: 3)
|
|
create(:poll_recount, :from_booth, poll: poll, null_amount: 34, white_amount: 5)
|
|
|
|
expect(stats.total_booth_null).to eq(159)
|
|
end
|
|
end
|
|
|
|
describe "valid percentage by channel" do
|
|
it "is relative to the total amount of valid votes" do
|
|
create(:poll_recount, :from_booth, poll: poll, total_amount: 2)
|
|
create(:poll_voter, :from_web, poll: poll)
|
|
|
|
expect(stats.valid_percentage_web).to eq(33.333)
|
|
expect(stats.valid_percentage_booth).to eq(66.667)
|
|
end
|
|
end
|
|
|
|
describe "white percentage by channel" do
|
|
before { allow(stats).to receive(:total_web_white).and_return(10) }
|
|
|
|
it "is relative to the total amount of white votes" do
|
|
create(:poll_recount, :from_booth, poll: poll, white_amount: 70)
|
|
|
|
expect(stats.white_percentage_web).to eq(12.5)
|
|
expect(stats.white_percentage_booth).to eq(87.5)
|
|
end
|
|
end
|
|
|
|
describe "null percentage by channel" do
|
|
it "only accepts null votes from booth" do
|
|
create(:poll_recount, :from_booth, poll: poll, null_amount: 70)
|
|
|
|
expect(stats.null_percentage_web).to eq(0)
|
|
expect(stats.null_percentage_booth).to eq(100)
|
|
end
|
|
end
|
|
|
|
describe "#total_valid_votes" do
|
|
it "counts valid votes from every channel" do
|
|
2.times { create(:poll_voter, :from_web, poll: poll) }
|
|
create(:poll_recount, :from_booth, poll: poll, total_amount: 3, white_amount: 10)
|
|
create(:poll_recount, :from_booth, poll: poll, total_amount: 4, null_amount: 20)
|
|
|
|
expect(stats.total_valid_votes).to eq(9)
|
|
end
|
|
end
|
|
|
|
describe "#total_white_votes" do
|
|
before { allow(stats).to receive(:total_web_white).and_return(9) }
|
|
|
|
it "counts white votes on every channel" do
|
|
create(:poll_recount, :from_booth, poll: poll, white_amount: 12)
|
|
|
|
expect(stats.total_white_votes).to eq(21)
|
|
end
|
|
end
|
|
|
|
describe "#total_null_votes" do
|
|
it "only accepts null votes from booth" do
|
|
create(:poll_recount, :from_booth, poll: poll, null_amount: 32)
|
|
|
|
expect(stats.total_null_votes).to eq(32)
|
|
end
|
|
end
|
|
|
|
describe "total percentage by type" do
|
|
before { allow(stats).to receive(:total_web_white).and_return(1) }
|
|
|
|
it "is relative to the total amount of votes" do
|
|
3.times { create(:poll_voter, :from_web, poll: poll) }
|
|
create(:poll_recount, :from_booth, poll: poll,
|
|
total_amount: 8,
|
|
white_amount: 5,
|
|
null_amount: 4)
|
|
|
|
expect(stats.total_valid_percentage).to eq(50)
|
|
expect(stats.total_white_percentage).to eq(30)
|
|
expect(stats.total_null_percentage).to eq(20)
|
|
end
|
|
end
|
|
|
|
describe "#participants_by_age" do
|
|
it "returns stats based on what happened when the voting took place" do
|
|
travel_to(100.years.ago) do
|
|
[16, 18, 32, 32, 33, 34, 64, 65, 71, 73, 90, 99, 105].each do |age|
|
|
create(:user, date_of_birth: age.years.ago - rand(0..11).months)
|
|
end
|
|
|
|
create(:poll, starts_at: 1.minute.from_now, ends_at: 2.minutes.from_now)
|
|
end
|
|
|
|
stats = Poll::Stats.new(Poll.last)
|
|
allow(stats).to receive(:participants).and_return(User.all)
|
|
|
|
expect(stats.participants_by_age["16 - 19"][:count]).to eq 2
|
|
expect(stats.participants_by_age["20 - 24"][:count]).to eq 0
|
|
expect(stats.participants_by_age["25 - 29"][:count]).to eq 0
|
|
expect(stats.participants_by_age["30 - 34"][:count]).to eq 4
|
|
expect(stats.participants_by_age["35 - 39"][:count]).to eq 0
|
|
expect(stats.participants_by_age["40 - 44"][:count]).to eq 0
|
|
expect(stats.participants_by_age["45 - 49"][:count]).to eq 0
|
|
expect(stats.participants_by_age["50 - 54"][:count]).to eq 0
|
|
expect(stats.participants_by_age["55 - 59"][:count]).to eq 0
|
|
expect(stats.participants_by_age["60 - 64"][:count]).to eq 1
|
|
expect(stats.participants_by_age["65 - 69"][:count]).to eq 1
|
|
expect(stats.participants_by_age["70 - 74"][:count]).to eq 2
|
|
expect(stats.participants_by_age["75 - 79"][:count]).to eq 0
|
|
expect(stats.participants_by_age["80 - 84"][:count]).to eq 0
|
|
expect(stats.participants_by_age["85 - 89"][:count]).to eq 0
|
|
expect(stats.participants_by_age["90 - 300"][:count]).to eq 3
|
|
end
|
|
end
|
|
|
|
describe "#participation_date", :with_frozen_time do
|
|
let(:poll) { create(:poll, starts_at: 3.years.ago, ends_at: 2.years.ago) }
|
|
|
|
it "returns the date when the poll finishes" do
|
|
expect(stats.participation_date).to eq 2.years.ago
|
|
end
|
|
end
|
|
|
|
describe "#participants_by_geozone" do
|
|
it "groups by geozones in alphabetic order" do
|
|
%w[Oceania Eurasia Eastasia].each { |name| create(:geozone, name: name) }
|
|
|
|
expect(stats.participants_by_geozone.keys).to eq %w[Eastasia Eurasia Oceania]
|
|
end
|
|
|
|
it "calculates percentage relative to total participants" do
|
|
hobbiton = create(:geozone, name: "Hobbiton")
|
|
rivendel = create(:geozone, name: "Rivendel")
|
|
|
|
3.times { create(:poll_voter, poll: poll, user: create(:user, :level_two, geozone: hobbiton)) }
|
|
2.times { create(:poll_voter, poll: poll, user: create(:user, :level_two, geozone: rivendel)) }
|
|
|
|
expect(stats.participants_by_geozone["Hobbiton"][:count]).to eq 3
|
|
expect(stats.participants_by_geozone["Hobbiton"][:percentage]).to eq 60.0
|
|
expect(stats.participants_by_geozone["Rivendel"][:count]).to eq 2
|
|
expect(stats.participants_by_geozone["Rivendel"][:percentage]).to eq 40.0
|
|
end
|
|
end
|
|
|
|
describe "#total_no_demographic_data" do
|
|
before do
|
|
create(:poll_voter, :from_web, poll: poll, user: create(:user, :level_two, gender: nil))
|
|
end
|
|
|
|
context "more registered participants than participants in recounts" do
|
|
before do
|
|
create(:poll_recount, :from_booth, poll: poll, total_amount: 1)
|
|
2.times { create(:poll_voter, :from_booth, poll: poll) }
|
|
end
|
|
|
|
it "returns registered users with no demographic data" do
|
|
expect(stats.total_no_demographic_data).to eq 1
|
|
end
|
|
end
|
|
|
|
context "more participants in recounts than registered participants" do
|
|
before do
|
|
create(:poll_recount, :from_booth, poll: poll, total_amount: 3)
|
|
2.times { create(:poll_voter, :from_booth, poll: poll) }
|
|
end
|
|
|
|
it "returns registered users with no demographic data plus users not registered" do
|
|
expect(stats.total_no_demographic_data).to eq 2
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#channels" do
|
|
context "no participants" do
|
|
it "returns no channels" do
|
|
expect(stats.channels).to eq []
|
|
end
|
|
end
|
|
|
|
context "only participants from web" do
|
|
before { create(:poll_voter, :from_web, poll: poll) }
|
|
|
|
it "returns the web channel" do
|
|
expect(stats.channels).to eq ["web"]
|
|
end
|
|
end
|
|
|
|
context "only participants from booth" do
|
|
before do
|
|
create(:poll_recount, :from_booth, poll: poll, total_amount: 1)
|
|
end
|
|
|
|
it "returns the booth channel" do
|
|
expect(stats.channels).to eq ["booth"]
|
|
end
|
|
end
|
|
|
|
context "only participants from letter" do
|
|
before { create(:poll_voter, origin: "letter", poll: poll) }
|
|
|
|
it "returns the web channel" do
|
|
expect(stats.channels).to eq ["letter"]
|
|
end
|
|
end
|
|
|
|
context "participants from all channels" do
|
|
before do
|
|
create(:poll_voter, :from_web, poll: poll)
|
|
create(:poll_recount, :from_booth, poll: poll, total_amount: 1)
|
|
create(:poll_voter, origin: "letter", poll: poll)
|
|
end
|
|
|
|
it "returns all channels" do
|
|
expect(stats.channels).to eq %w[web booth letter]
|
|
end
|
|
end
|
|
end
|
|
end
|