demarches-normaliennes/spec/controllers/stats_controller_spec.rb

356 lines
14 KiB
Ruby
Raw Normal View History

require 'spec_helper'
describe StatsController, type: :controller do
describe "#last_four_months_hash" do
context "while a regular user is logged in" do
before do
2018-01-23 17:15:42 +01:00
FactoryBot.create(:procedure, :created_at => 6.months.ago, :updated_at => 6.months.ago)
FactoryBot.create(:procedure, :created_at => 2.months.ago, :updated_at => 62.days.ago)
FactoryBot.create(:procedure, :created_at => 2.months.ago, :updated_at => 62.days.ago)
FactoryBot.create(:procedure, :created_at => 2.months.ago, :updated_at => 31.days.ago)
2018-10-25 15:11:12 +02:00
FactoryBot.create(:procedure, :created_at => 2.months.ago, :updated_at => Time.zone.now)
@controller = StatsController.new
allow(@controller).to receive(:administration_signed_in?).and_return(false)
end
let (:association) { Procedure.all }
subject { @controller.send(:last_four_months_hash, association, :updated_at) }
2018-01-15 18:54:57 +01:00
it do
expect(subject).to match_array([
[I18n.l(62.days.ago.beginning_of_month, format: "%B %Y"), 2],
[I18n.l(31.days.ago.beginning_of_month, format: "%B %Y"), 1]
])
2018-01-15 18:54:57 +01:00
end
end
context "while a super admin is logged in" do
before do
2018-01-23 17:15:42 +01:00
FactoryBot.create(:procedure, :updated_at => 6.months.ago)
FactoryBot.create(:procedure, :updated_at => 45.days.ago)
FactoryBot.create(:procedure, :updated_at => 1.day.ago)
FactoryBot.create(:procedure, :updated_at => 1.day.ago)
@controller = StatsController.new
allow(@controller).to receive(:administration_signed_in?).and_return(true)
end
let (:association) { Procedure.all }
subject { @controller.send(:last_four_months_hash, association, :updated_at) }
2018-01-15 18:54:57 +01:00
it do
expect(subject).to eq([
[I18n.l(45.days.ago.beginning_of_month, format: "%B %Y"), 1],
2018-03-06 13:44:29 +01:00
[I18n.l(1.day.ago.beginning_of_month, format: "%B %Y"), 2]
2017-06-12 14:10:49 +02:00
])
2018-01-15 18:54:57 +01:00
end
end
end
describe '#cumulative_hash' do
before do
2018-10-25 15:21:06 +02:00
Timecop.freeze(Time.zone.local(2016, 10, 2))
2018-01-23 17:15:42 +01:00
FactoryBot.create(:procedure, :created_at => 55.days.ago, :updated_at => 43.days.ago)
FactoryBot.create(:procedure, :created_at => 45.days.ago, :updated_at => 40.days.ago)
FactoryBot.create(:procedure, :created_at => 45.days.ago, :updated_at => 20.days.ago)
FactoryBot.create(:procedure, :created_at => 15.days.ago, :updated_at => 20.days.ago)
FactoryBot.create(:procedure, :created_at => 15.days.ago, :updated_at => 1.hour.ago)
end
after { Timecop.return }
let (:association) { Procedure.all }
context "while a super admin is logged in" do
before { allow(@controller).to receive(:administration_signed_in?).and_return(true) }
subject { @controller.send(:cumulative_hash, association, :updated_at) }
2018-01-15 19:02:12 +01:00
it do
expect(subject).to eq({
Time.utc(2016, 8, 1) => 2,
Time.utc(2016, 9, 1) => 4,
Time.utc(2016, 10, 1) => 5
})
2018-01-15 19:02:12 +01:00
end
end
context "while a super admin is not logged in" do
before { allow(@controller).to receive(:administration_signed_in?).and_return(false) }
subject { @controller.send(:cumulative_hash, association, :updated_at) }
2018-01-15 19:02:12 +01:00
it do
expect(subject).to eq({
Time.utc(2016, 8, 1) => 2,
Time.utc(2016, 9, 1) => 4
})
2018-01-15 19:02:12 +01:00
end
end
end
describe "#dossier_instruction_mean_time" do
# Month-2: mean 3 days
# procedure_1: mean 2 days
# dossier_p1_a: 3 days
# dossier_p1_b: 1 days
# procedure_2: mean 4 days
# dossier_p2_a: 4 days
#
# Month-1: mean 5 days
# procedure_1: mean 5 days
# dossier_p1_c: 5 days
before do
2018-01-23 17:15:42 +01:00
procedure_1 = FactoryBot.create(:procedure)
procedure_2 = FactoryBot.create(:procedure)
dossier_p1_a = FactoryBot.create(:dossier,
:procedure => procedure_1,
:en_construction_at => 2.months.ago.beginning_of_month,
:processed_at => 2.months.ago.beginning_of_month + 3.days)
2018-01-23 17:15:42 +01:00
dossier_p1_b = FactoryBot.create(:dossier,
:procedure => procedure_1,
:en_construction_at => 2.months.ago.beginning_of_month,
2018-03-06 13:44:29 +01:00
:processed_at => 2.months.ago.beginning_of_month + 1.day)
2018-01-23 17:15:42 +01:00
dossier_p1_c = FactoryBot.create(:dossier,
:procedure => procedure_1,
2018-03-06 13:44:29 +01:00
:en_construction_at => 1.month.ago.beginning_of_month,
:processed_at => 1.month.ago.beginning_of_month + 5.days)
2018-01-23 17:15:42 +01:00
dossier_p2_a = FactoryBot.create(:dossier,
:procedure => procedure_2,
2018-03-06 13:44:29 +01:00
:en_construction_at => 2.months.ago.beginning_of_month,
:processed_at => 2.months.ago.beginning_of_month + 4.days)
# Write directly in the DB to avoid the before_validation hook
Dossier.update_all(state: Dossier.states.fetch(:accepte))
@expected_hash = {
2018-10-01 14:03:05 +02:00
(2.months.ago.beginning_of_month).to_s => 3.0,
(1.month.ago.beginning_of_month).to_s => 5.0
}
end
2018-08-28 14:50:44 +02:00
let (:association) { Dossier.state_not_brouillon }
subject { StatsController.new.send(:dossier_instruction_mean_time, association) }
it { expect(subject).to eq(@expected_hash) }
end
describe "#dossier_filling_mean_time" do
# Month-2: mean 30 minutes
# procedure_1: mean 20 minutes
# dossier_p1_a: 30 minutes
# dossier_p1_b: 10 minutes
# procedure_2: mean 40 minutes
# dossier_p2_a: 80 minutes, for twice the fields
#
# Month-1: mean 50 minutes
# procedure_1: mean 50 minutes
# dossier_p1_c: 50 minutes
before do
2018-01-23 17:15:42 +01:00
procedure_1 = FactoryBot.create(:procedure, :with_type_de_champ, :types_de_champ_count => 24)
procedure_2 = FactoryBot.create(:procedure, :with_type_de_champ, :types_de_champ_count => 48)
dossier_p1_a = FactoryBot.create(:dossier,
:procedure => procedure_1,
:created_at => 2.months.ago.beginning_of_month,
:en_construction_at => 2.months.ago.beginning_of_month + 30.minutes,
:processed_at => 2.months.ago.beginning_of_month + 1.day)
2018-01-23 17:15:42 +01:00
dossier_p1_b = FactoryBot.create(:dossier,
:procedure => procedure_1,
:created_at => 2.months.ago.beginning_of_month,
:en_construction_at => 2.months.ago.beginning_of_month + 10.minutes,
:processed_at => 2.months.ago.beginning_of_month + 1.day)
2018-01-23 17:15:42 +01:00
dossier_p1_c = FactoryBot.create(:dossier,
:procedure => procedure_1,
2018-03-06 13:44:29 +01:00
:created_at => 1.month.ago.beginning_of_month,
:en_construction_at => 1.month.ago.beginning_of_month + 50.minutes,
:processed_at => 1.month.ago.beginning_of_month + 1.day)
2018-01-23 17:15:42 +01:00
dossier_p2_a = FactoryBot.create(:dossier,
:procedure => procedure_2,
2018-03-06 13:44:29 +01:00
:created_at => 2.months.ago.beginning_of_month,
:en_construction_at => 2.months.ago.beginning_of_month + 80.minutes,
:processed_at => 2.months.ago.beginning_of_month + 1.day)
# Write directly in the DB to avoid the before_validation hook
Dossier.update_all(state: Dossier.states.fetch(:accepte))
@expected_hash = {
2018-10-01 14:03:05 +02:00
(2.months.ago.beginning_of_month).to_s => 30.0,
(1.month.ago.beginning_of_month).to_s => 50.0
}
end
2018-08-28 14:50:44 +02:00
let (:association) { Dossier.state_not_brouillon }
subject { StatsController.new.send(:dossier_filling_mean_time, association) }
it { expect(subject).to eq(@expected_hash) }
end
2017-05-09 17:09:35 +02:00
describe "#satisfaction_usagers" do
before do
# Test the stats on October 2018 where the 1st, 8th, 15th, 22th and 29th are conveniently Mondays
# Current week: 1 negative feedback
Timecop.freeze(Time.zone.local(2018, 10, 22, 12, 00)) { create(:feedback, :unhappy) }
# Last week: 3 positive, 1 negative
Timecop.freeze(Time.zone.local(2018, 10, 21, 12, 00)) { create(:feedback, :unhappy) }
Timecop.freeze(Time.zone.local(2018, 10, 19, 12, 00)) { create(:feedback, :happy) }
Timecop.freeze(Time.zone.local(2018, 10, 17, 12, 00)) { create(:feedback, :happy) }
Timecop.freeze(Time.zone.local(2018, 10, 15, 12, 00)) { create(:feedback, :happy) }
# N-2 week: 2 positive, 2 negative
Timecop.freeze(Time.zone.local(2018, 10, 14, 12, 00)) { create(:feedback, :unhappy) }
Timecop.freeze(Time.zone.local(2018, 10, 12, 12, 00)) { create(:feedback, :happy) }
Timecop.freeze(Time.zone.local(2018, 10, 10, 12, 00)) { create(:feedback, :unhappy) }
Timecop.freeze(Time.zone.local(2018, 10, 8, 12, 00)) { create(:feedback, :happy) }
# N-3 week: 1 positive, 3 negative
Timecop.freeze(Time.zone.local(2018, 10, 1, 12, 00)) { create(:feedback, :unhappy) }
Timecop.freeze(Time.zone.local(2018, 10, 3, 12, 00)) { create(:feedback, :happy) }
Timecop.freeze(Time.zone.local(2018, 10, 5, 12, 00)) { create(:feedback, :unhappy) }
Timecop.freeze(Time.zone.local(2018, 10, 7, 12, 00)) { create(:feedback, :unhappy) }
end
subject(:stats) do
Timecop.freeze(Time.zone.local(2018, 10, 28, 12, 00)) {
StatsController.new.send(:satisfaction_usagers)
}
end
it 'returns one set of values for each kind of feedback' do
expect(stats.count).to eq 3
expect(stats.map { |g| g[:name] }).to contain_exactly('Satisfaits', 'Neutres', 'Mécontents')
end
it 'returns weekly ratios between a given feedback and all feedback' do
happy_data = stats.find { |g| g[:name] == 'Satisfaits' }[:data]
expect(happy_data.values[0]).to eq 0
expect(happy_data.values[1]).to eq 0
expect(happy_data.values[2]).to eq 0
expect(happy_data.values[3]).to eq 25.0
expect(happy_data.values[4]).to eq 50.0
expect(happy_data.values[5]).to eq 75.0
unhappy_data = stats.find { |g| g[:name] == 'Mécontents' }[:data]
expect(unhappy_data.values[0]).to eq 0
expect(unhappy_data.values[1]).to eq 0
expect(unhappy_data.values[2]).to eq 0
expect(unhappy_data.values[3]).to eq 75.0
expect(unhappy_data.values[4]).to eq 50.0
expect(unhappy_data.values[5]).to eq 25.0
end
it 'excludes values still in the current week' do
unhappy_data = stats.find { |g| g[:name] == 'Mécontents' }[:data]
expect(unhappy_data.values).not_to include(100.0)
end
end
2017-05-09 17:09:35 +02:00
describe '#avis_usage' do
let!(:dossier) { create(:dossier) }
let!(:avis_with_dossier) { create(:avis) }
let!(:dossier2) { create(:dossier) }
2018-10-25 15:11:12 +02:00
before { Timecop.freeze(Time.zone.now) }
after { Timecop.return }
2017-05-09 17:09:35 +02:00
subject { StatsController.new.send(:avis_usage) }
2018-03-06 13:44:29 +01:00
it { expect(subject).to match([[3.weeks.ago.to_i, 0], [2.weeks.ago.to_i, 0], [1.week.ago.to_i, 33.33]]) }
2017-05-09 17:09:35 +02:00
end
describe "#avis_average_answer_time" do
before do
Timecop.freeze(Time.zone.local(2016, 10, 2))
# 1 week ago
create(:avis, answer: "voila ma réponse", created_at: 1.week.ago + 1.day, updated_at: 1.week.ago + 2.days) # 1 day
create(:avis, created_at: 1.week.ago + 2.days)
# 2 weeks ago
2018-03-06 13:44:29 +01:00
create(:avis, answer: "voila ma réponse", created_at: 2.weeks.ago + 1.day, updated_at: 2.weeks.ago + 2.days) # 1 day
create(:avis, answer: "voila ma réponse2", created_at: 2.weeks.ago + 3.days, updated_at: 1.week.ago + 6.days) # 10 days
create(:avis, answer: "voila ma réponse2", created_at: 2.weeks.ago + 2.days, updated_at: 1.week.ago + 6.days) # 11 days
create(:avis, created_at: 2.weeks.ago + 1.day, updated_at: 2.weeks.ago + 2.days)
# 3 weeks ago
create(:avis, answer: "voila ma réponse2", created_at: 3.weeks.ago + 1.day, updated_at: 3.weeks.ago + 2.days) # 1 day
create(:avis, answer: "voila ma réponse2", created_at: 3.weeks.ago + 1.day, updated_at: 1.week.ago + 5.days) # 18 day
end
after { Timecop.return }
subject { StatsController.new.send(:avis_average_answer_time) }
it { expect(subject.count).to eq(3) }
it { is_expected.to include [1.week.ago.to_i, 1.0] }
2018-03-06 13:44:29 +01:00
it { is_expected.to include [2.weeks.ago.to_i, 7.33] }
it { is_expected.to include [3.weeks.ago.to_i, 9.5] }
end
describe '#avis_answer_percentages' do
let!(:avis) { create(:avis, created_at: 2.days.ago) }
let!(:avis2) { create(:avis, answer: 'answer', created_at: 2.days.ago) }
let!(:avis3) { create(:avis, answer: 'answer', created_at: 2.days.ago) }
subject { StatsController.new.send(:avis_answer_percentages) }
2018-10-25 15:11:12 +02:00
before { Timecop.freeze(Time.zone.now) }
after { Timecop.return }
2018-03-06 13:44:29 +01:00
it { is_expected.to match [[3.weeks.ago.to_i, 0], [2.weeks.ago.to_i, 0], [1.week.ago.to_i, 66.67]] }
end
2017-06-15 14:42:48 +02:00
describe '#motivation_usage_dossier' do
let!(:dossier) { create(:dossier, processed_at: 1.week.ago, motivation: "Motivation") }
let!(:dossier2) { create(:dossier, processed_at: 1.week.ago) }
let!(:dossier3) { create(:dossier, processed_at: 1.week.ago) }
2018-10-25 15:11:12 +02:00
before { Timecop.freeze(Time.zone.now) }
after { Timecop.return }
2017-06-15 14:42:48 +02:00
subject { StatsController.new.send(:motivation_usage_dossier) }
2018-03-06 13:44:29 +01:00
it { expect(subject).to match([[I18n.l(3.weeks.ago.end_of_week, format: '%d/%m/%Y'), 0], [I18n.l(2.weeks.ago.end_of_week, format: '%d/%m/%Y'), 0], [I18n.l(1.week.ago.end_of_week, format: '%d/%m/%Y'), 33.33]]) }
2017-06-15 14:42:48 +02:00
end
describe '#motivation_usage_procedure' do
let!(:dossier) { create(:dossier, processed_at: 1.week.ago, motivation: "Motivation") }
2017-06-15 14:42:48 +02:00
let!(:dossier1) { create(:dossier, processed_at: 1.week.ago, motivation: "Motivation", procedure: dossier.procedure) }
let!(:dossier2) { create(:dossier, processed_at: 1.week.ago) }
let!(:dossier3) { create(:dossier, processed_at: 1.week.ago) }
2018-10-25 15:11:12 +02:00
before { Timecop.freeze(Time.zone.now) }
after { Timecop.return }
2017-06-15 14:42:48 +02:00
subject { StatsController.new.send(:motivation_usage_procedure) }
2018-03-06 13:44:29 +01:00
it { expect(subject).to match([[I18n.l(3.weeks.ago.end_of_week, format: '%d/%m/%Y'), 0], [I18n.l(2.weeks.ago.end_of_week, format: '%d/%m/%Y'), 0], [I18n.l(1.week.ago.end_of_week, format: '%d/%m/%Y'), 33.33]]) }
2017-06-15 14:42:48 +02:00
end
describe "#cloned_from_library_procedures_ratio" do
let!(:procedure1) { create(:procedure, created_at: 3.weeks.ago) }
let!(:procedure2) { create(:procedure, created_at: 2.weeks.ago) }
let!(:procedure3) { create(:procedure, created_at: 2.weeks.ago, cloned_from_library: true) }
2018-10-25 15:11:12 +02:00
before { Timecop.freeze(Time.zone.now) }
after { Timecop.return }
subject { StatsController.new.send(:cloned_from_library_procedures_ratio) }
let(:result) do
[
[I18n.l(3.weeks.ago.end_of_week, format: '%d/%m/%Y'), 0],
[I18n.l(2.weeks.ago.end_of_week, format: '%d/%m/%Y'), 50.0],
[I18n.l(1.week.ago.end_of_week, format: '%d/%m/%Y'), 0]
]
end
it { expect(subject).to match(result) }
end
end