You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sqm-dashboards/spec/lib/tasks/survey_rake_spec.rb

320 lines
11 KiB

require 'rails_helper'
describe "survey:attempt_questions" do
include_context "rake"
it 'should have environment as a prerequisite' do
expect(subject.prerequisites).to include("environment")
end
describe "basic flow" do
let(:now) {
n = DateTime.now
n += 1.day until n.on_weekday?
return n
}
let(:ready_recipient_schedule) { double('ready recipient schedule', attempt_question: nil) }
let(:recipient_schedules) { double("recipient schedules", ready: [ready_recipient_schedule]) }
let(:active_schedule) { double("active schedule", recipient_schedules: recipient_schedules) }
it "finds all active schedules" do
date = ActiveSupport::TimeZone["UTC"].parse(now.strftime("%Y-%m-%dT20:00:00%z"))
Timecop.freeze(date)
expect(ready_recipient_schedule).to receive(:attempt_question)
expect(active_schedule).to receive(:recipient_schedules)
expect(Schedule).to receive(:active).and_return([active_schedule])
subject.invoke
end
it "works only on weekdays" do
now = DateTime.now
now += 1.day until now.on_weekend?
date = ActiveSupport::TimeZone["UTC"].parse(now.strftime("%Y-%m-%dT20:00:00%z"))
Timecop.freeze(date)
expect(ready_recipient_schedule).to_not receive(:attempt_question)
subject.invoke
end
end
describe "complex flow" do
let(:now) {
n = DateTime.now
n += 1.day until n.on_weekday?
return n
}
let!(:school) { School.create!(name: 'School') }
let!(:recipients) { create_recipients(school, 3) }
let!(:recipient_list) do
school.recipient_lists.create!(name: 'Parents', recipient_ids: recipients.map(&:id).join(','))
end
let!(:category) { Category.create(name: 'Category') }
let!(:questions) { create_questions(3, category) }
let!(:question_list) do
QuestionList.create!(name: 'Parent Questions', question_ids: questions.map(&:id).join(','))
end
let!(:schedule) do
Schedule.create!(
name: 'Parent Schedule',
recipient_list_id: recipient_list.id,
question_list: question_list,
frequency_hours: 24 * 7,
start_date: Time.new,
end_date: 1.year.from_now,
time: 1200
)
end
describe 'First attempt not at specified time' do
before :each do
now = DateTime.new
now += 1.day until now.on_weekend?
date = ActiveSupport::TimeZone["UTC"].parse(now.strftime("%Y-%m-%dT19:00:00%z"))
Timecop.freeze(date) { subject.invoke }
end
it 'should not create any attempts' do
expect(Attempt.count).to eq(0)
end
end
describe 'First attempt at specified time' do
before :each do
date = ActiveSupport::TimeZone["UTC"].parse(now.strftime("%Y-%m-%dT20:00:00%z"))
Timecop.freeze(date) { subject.invoke }
end
it 'should create the first attempt for each recipient' do
recipients.each do |recipient|
recipient.reload
expect(recipient.attempts.count).to eq(1)
attempt = recipient.attempts.first
expect(attempt.sent_at).to be_present
expect(attempt.answer_index).to be_nil
end
end
end
describe 'Second Attempts' do
before :each do
recipients.each do |recipient|
recipient_schedule = schedule.recipient_schedules.for_recipient(recipient).first
recipient_schedule.attempt_question
end
end
describe 'Immediate' do
before :each do
subject.invoke
end
it 'should do nothing' do
recipients.each do |recipient|
recipient.reload
expect(recipient.attempts.count).to eq(1)
end
end
end
describe 'A Week Later' do
before :each do
recipients[1].attempts.first.update_attributes(
answer_index: 4,
responded_at: Time.new
)
Timecop.freeze(now + 7) { subject.invoke }
end
it 'should resend the first question if unanswered by a recipient' do
[recipients[0], recipients[2]].each do |recipient|
recipient.reload
expect(recipient.attempts.count).to eq(1)
attempt = recipient.attempts.last
expect(attempt.sent_at).to be > 1.day.ago
expect(attempt.answer_index).to be_nil
end
end
it 'should create the second attempt with a new question for each recipient who has answered the first question' do
recipient = recipients[1]
recipient.reload
expect(recipient.attempts.count).to eq(2)
attempt = recipient.attempts.last
expect(attempt.sent_at).to be_present
expect(attempt.answer_index).to be_nil
first_attempt = recipient.attempts.first
expect(first_attempt.question).to_not eq(attempt.question)
end
end
describe 'And Then A Recipient Answers The First Attempt' do
before :each do
recipients[1].attempts.first.save_response(answer_index: 4)
Timecop.freeze(now + 7)
recipients.each do |recipient|
recipient_schedule = schedule.recipient_schedules.for_recipient(recipient).first
recipient_schedule.attempt_question
end
@existing_message_count = FakeSMS.messages.length
Timecop.freeze(now + 8)
recipients[2].attempts.first.save_response(answer_index: 3)
subject.invoke
end
it 'should create the second attempt with a new question for each recipient who just answered the first question' do
recipient = recipients[2]
recipient.reload
expect(recipient.attempts.count).to eq(2)
attempt = recipient.attempts.last
expect(attempt.sent_at).to be_present
expect(attempt.answer_index).to be_nil
first_attempt = recipient.attempts.first
expect(first_attempt.question).to_not eq(attempt.question)
end
it 'should not send anything to anyone else' do
expect(FakeSMS.messages.length).to eq(@existing_message_count + 1)
expect(recipients[0].attempts.count).to eq(1)
expect(recipients[1].attempts.count).to eq(2)
end
end
end
describe 'Multiple Students In A Family' do
before :each do
3.times do |i|
recipients[1].students.create(name: "Student#{i}")
end
end
let(:students_recipient) { recipients[1] }
let(:students_recipient_schedule) {
recipient_schedule = students_recipient.recipient_schedules.for_schedule(schedule).first
}
describe 'With A FOR_CHILD Question Is Asked' do
let!(:date) { ActiveSupport::TimeZone["UTC"].parse(now.strftime("%Y-%m-%dT20:00:00%z")) }
before :each do
questions.first.update_attributes(for_recipient_students: true)
Timecop.freeze(date) { subject.invoke }
end
it 'should create one attempt per recipient regardless of students' do
expect(FakeSMS.messages.length).to eq(3)
recipients.each do |recipient|
expect(recipient.attempts.count).to eq(1)
end
end
it 'should store queued questions when an attempt is made on first student' do
expect(students_recipient_schedule.queued_question_ids).to be_present
queued_question_ids = students_recipient_schedule.queued_question_ids.split(/,/)
expect(queued_question_ids.length).to eq(1)
expect(queued_question_ids.first).to eq("#{questions[0].id}")
end
it 'should set the next_attempt_at to now when attempt is made on first student' do
students_recipient.attempts.last.save_response(answer_index: 3)
expect(students_recipient_schedule.reload.next_attempt_at).to eq(Time.new)
end
it 'should set the next_attempt_at to now when attempt is made on second student' do
students_recipient.attempts.last.save_response(answer_index: 3)
expect{students_recipient_schedule.attempt_question}.to change{students_recipient.attempts.count}.by(1)
expect(students_recipient_schedule.reload.queued_question_ids).to be_present
attempt = students_recipient.attempts.last
expect(attempt.student).to eq(students_recipient.students[1])
attempt.save_response(answer_index: 4)
expect(students_recipient_schedule.reload.next_attempt_at).to eq(Time.new)
end
it 'should set the next_attempt_at in the future when an attempt is made on last student' do
students_recipient.attempts.last.save_response(answer_index: 3)
expect{students_recipient_schedule.attempt_question}.to change{students_recipient.attempts.count}.by(1)
expect(students_recipient_schedule.reload.queued_question_ids).to be_present
attempt = students_recipient.attempts.last
expect(attempt.student).to eq(students_recipient.students[1])
Timecop.freeze(date + 1.day)
attempt.save_response(answer_index: 4)
expect(students_recipient_schedule.reload.next_attempt_at).to eq(date + 1.day)
expect{students_recipient_schedule.attempt_question}.to change{students_recipient.attempts.count}.by(1)
expect(students_recipient_schedule.reload.queued_question_ids).to be_nil
expect(students_recipient_schedule.reload.next_attempt_at).to_not eq(date + (60 * 60 * schedule.frequency_hours))
attempt = students_recipient.attempts.last
expect(attempt.student).to eq(students_recipient.students[2])
Timecop.freeze(date + 2.days)
attempt.save_response(answer_index: 2)
expect(students_recipient_schedule.reload.next_attempt_at).to_not eq(date + 2.days)
end
it 'should mention the students name in the text'
it 'resends the question about the same student if not responded to'
it 'still sends when no students are present'
it 'doesnt store any queued_question_ids when no students are present'
it 'doesnt store any queued_question_ids when just one student is present'
end
describe 'With A General Question Is Asked' do
before :each do
subject.invoke
end
it 'should not queue up an questions regardless of how many students there are'
it 'should not mention the students name in the text'
end
end
describe 'Opted Out Recipient' do
before :each do
recipients[1].update_attributes(opted_out: true)
date = ActiveSupport::TimeZone["UTC"].parse(now.strftime("%Y-%m-%dT20:00:00%z"))
Timecop.freeze(date) { subject.invoke }
end
it 'should create the first attempt for each recipient' do
recipients.each_with_index do |recipient, index|
recipient.reload
if index == 1
expect(recipient.attempts.count).to eq(0)
expect(recipient.attempts.first).to be_nil
else
expect(recipient.attempts.count).to eq(1)
attempt = recipient.attempts.first
expect(attempt.sent_at).to be_present
expect(attempt.answer_index).to be_nil
end
end
end
end
end
end