move all DelayedJob Alert code into separate class
fixes CNVS-12411 test-plan: regression test all alerts Change-Id: Ie954c3c6c3f034fce130774c5c6e4e1515b02049 Reviewed-on: https://gerrit.instructure.com/33339 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Simon Williams <simon@instructure.com> QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Simon Williams <simon@instructure.com>
This commit is contained in:
parent
339dc7a41f
commit
bb244d1f86
|
@ -32,6 +32,32 @@ class Alert < ActiveRecord::Base
|
|||
|
||||
before_save :infer_defaults
|
||||
|
||||
def resolve_recipients(student_id, teachers = nil)
|
||||
include_student = false
|
||||
include_teacher = false
|
||||
include_teachers = false
|
||||
admin_roles = []
|
||||
self.recipients.try(:each) do |recipient|
|
||||
case
|
||||
when recipient == :student
|
||||
include_student = true
|
||||
when recipient == :teachers
|
||||
include_teachers = true
|
||||
when recipient.is_a?(String)
|
||||
admin_roles << recipient
|
||||
else
|
||||
raise "Unsupported recipient type!"
|
||||
end
|
||||
end
|
||||
|
||||
recipients = []
|
||||
|
||||
recipients << student_id if include_student
|
||||
recipients.concat(Array(teachers)) if teachers.present? && include_teachers
|
||||
recipients.concat context.account_users.where(:membership_type => admin_roles).uniq.pluck(:user_id) if context_type == 'Account' && !admin_roles.empty?
|
||||
recipients.uniq
|
||||
end
|
||||
|
||||
def infer_defaults
|
||||
self.repetition = nil if self.repetition.blank?
|
||||
end
|
||||
|
@ -64,102 +90,4 @@ class Alert < ActiveRecord::Base
|
|||
end
|
||||
self.criteria.replace(values)
|
||||
end
|
||||
|
||||
def resolve_recipients(student_id, teachers = nil)
|
||||
include_student = false
|
||||
include_teacher = false
|
||||
include_teachers = false
|
||||
admin_roles = []
|
||||
self.recipients.try(:each) do |recipient|
|
||||
case
|
||||
when recipient == :student
|
||||
include_student = true
|
||||
when recipient == :teachers
|
||||
include_teachers = true
|
||||
when recipient.is_a?(String)
|
||||
admin_roles << recipient
|
||||
else
|
||||
raise "Unsupported recipient type!"
|
||||
end
|
||||
end
|
||||
|
||||
recipients = []
|
||||
|
||||
recipients << student_id if include_student
|
||||
recipients.concat(Array(teachers)) if teachers.present? && include_teachers
|
||||
recipients.concat context.account_users.where(:membership_type => admin_roles).uniq.pluck(:user_id) if context_type == 'Account' && !admin_roles.empty?
|
||||
recipients.uniq
|
||||
end
|
||||
|
||||
def self.process
|
||||
Account.root_accounts.active.find_each do |account|
|
||||
next unless account.settings[:enable_alerts]
|
||||
self.send_later_if_production_enqueue_args(:evaluate_for_root_account, { :priority => Delayed::LOW_PRIORITY }, account)
|
||||
end
|
||||
end
|
||||
|
||||
def self.evaluate_for_root_account(account)
|
||||
return unless account.settings[:enable_alerts]
|
||||
alerts_cache = {}
|
||||
account.associated_courses.where(:workflow_state => 'available').find_each do |course|
|
||||
alerts_cache[course.account_id] ||= course.account.account_chain.map { |a| a.alerts.all }.flatten
|
||||
self.evaluate_for_course(course, alerts_cache[course.account_id])
|
||||
end
|
||||
end
|
||||
|
||||
def self.evaluate_for_course(course, account_alerts)
|
||||
return unless course.available?
|
||||
|
||||
alerts = Array.new(account_alerts || [])
|
||||
alerts.concat course.alerts.all
|
||||
return if alerts.empty?
|
||||
|
||||
student_enrollments = course.student_enrollments.active
|
||||
student_ids = student_enrollments.map(&:user_id)
|
||||
return if student_ids.empty?
|
||||
|
||||
teacher_enrollments = course.instructor_enrollments.active
|
||||
teacher_ids = teacher_enrollments.map(&:user_id)
|
||||
return if teacher_ids.empty?
|
||||
|
||||
teacher_student_mapper = Courses::TeacherStudentMapper.new(student_enrollments, teacher_enrollments)
|
||||
|
||||
# Evaluate all the criteria for each user for each alert
|
||||
today = Time.now.beginning_of_day
|
||||
|
||||
alert_checkers = {}
|
||||
|
||||
alerts.each do |alert|
|
||||
student_ids.each do |user_id|
|
||||
matches = true
|
||||
|
||||
alert.criteria.each do |criterion|
|
||||
alert_checker = alert_checkers[criterion.criterion_type] ||= Alerts.const_get(criterion.criterion_type).new(course, student_ids, teacher_ids)
|
||||
matches = !alert_checker.should_not_receive_message?(user_id, criterion.threshold.to_i)
|
||||
break unless matches
|
||||
end
|
||||
|
||||
cache_key = [alert, user_id].cache_key
|
||||
if matches
|
||||
last_sent = Rails.cache.fetch(cache_key)
|
||||
if last_sent.blank?
|
||||
elsif alert.repetition.blank?
|
||||
matches = false
|
||||
else
|
||||
matches = last_sent + alert.repetition.days <= today
|
||||
end
|
||||
end
|
||||
if matches
|
||||
Rails.cache.write(cache_key, today)
|
||||
|
||||
send_alert(alert, alert.resolve_recipients(user_id, teacher_student_mapper.teachers_for_student(user_id)), student_enrollments.to_ary.find { |enrollment| enrollment.user_id == user_id } )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.send_alert(alert, user_ids, student_enrollment)
|
||||
notification = Notification.by_name("Alert")
|
||||
notification.create_message(alert, user_ids, {:asset_context => student_enrollment})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
module Alerts
|
||||
class DelayedAlertSender
|
||||
def self.process
|
||||
Account.root_accounts.active.find_each do |account|
|
||||
next unless account.settings[:enable_alerts]
|
||||
self.send_later_if_production_enqueue_args(:evaluate_for_root_account, { :priority => Delayed::LOW_PRIORITY }, account)
|
||||
end
|
||||
end
|
||||
|
||||
def self.evaluate_for_root_account(account)
|
||||
return unless account.settings[:enable_alerts]
|
||||
alerts_cache = {}
|
||||
account.associated_courses.where(:workflow_state => 'available').find_each do |course|
|
||||
alerts_cache[course.account_id] ||= course.account.account_chain.map { |a| a.alerts.all }.flatten
|
||||
self.evaluate_for_course(course, alerts_cache[course.account_id])
|
||||
end
|
||||
end
|
||||
|
||||
def self.evaluate_for_course(course, account_alerts)
|
||||
return unless course.available?
|
||||
|
||||
alerts = Array.new(account_alerts || [])
|
||||
alerts.concat course.alerts.all
|
||||
return if alerts.empty?
|
||||
|
||||
student_enrollments = course.student_enrollments.active
|
||||
student_ids = student_enrollments.map(&:user_id)
|
||||
return if student_ids.empty?
|
||||
|
||||
teacher_enrollments = course.instructor_enrollments.active
|
||||
teacher_ids = teacher_enrollments.map(&:user_id)
|
||||
return if teacher_ids.empty?
|
||||
|
||||
teacher_student_mapper = Courses::TeacherStudentMapper.new(student_enrollments, teacher_enrollments)
|
||||
|
||||
# Evaluate all the criteria for each user for each alert
|
||||
today = Time.now.beginning_of_day
|
||||
|
||||
alert_checkers = {}
|
||||
|
||||
alerts.each do |alert|
|
||||
student_ids.each do |user_id|
|
||||
matches = true
|
||||
|
||||
alert.criteria.each do |criterion|
|
||||
alert_checker = alert_checkers[criterion.criterion_type] ||= Alerts.const_get(criterion.criterion_type).new(course, student_ids, teacher_ids)
|
||||
matches = !alert_checker.should_not_receive_message?(user_id, criterion.threshold.to_i)
|
||||
break unless matches
|
||||
end
|
||||
|
||||
cache_key = [alert, user_id].cache_key
|
||||
if matches
|
||||
last_sent = Rails.cache.fetch(cache_key)
|
||||
if last_sent.blank?
|
||||
elsif alert.repetition.blank?
|
||||
matches = false
|
||||
else
|
||||
matches = last_sent + alert.repetition.days <= today
|
||||
end
|
||||
end
|
||||
if matches
|
||||
Rails.cache.write(cache_key, today)
|
||||
|
||||
send_alert(alert, alert.resolve_recipients(user_id, teacher_student_mapper.teachers_for_student(user_id)), student_enrollments.to_ary.find { |enrollment| enrollment.user_id == user_id } )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.send_alert(alert, user_ids, student_enrollment)
|
||||
notification = Notification.by_name("Alert")
|
||||
notification.create_message(alert, user_ids, {:asset_context => student_enrollment})
|
||||
end
|
||||
end
|
||||
end
|
|
@ -94,9 +94,9 @@ if Delayed::Stats.enabled?
|
|||
end
|
||||
end
|
||||
|
||||
Delayed::Periodic.cron 'Alert.process', '30 11 * * *', :priority => Delayed::LOW_PRIORITY do
|
||||
Delayed::Periodic.cron 'Alerts::DelayedAlertSender.process', '30 11 * * *', :priority => Delayed::LOW_PRIORITY do
|
||||
Shard.with_each_shard do
|
||||
Alert.process
|
||||
Alerts::DelayedAlertSender.process
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -71,470 +71,5 @@ describe Alert do
|
|||
alert.save.should be_false
|
||||
end
|
||||
end
|
||||
|
||||
context "basic evaluation" do
|
||||
it "should not trigger any alerts for unpublished courses" do
|
||||
course = mock('Course')
|
||||
course.stubs(:available?, false)
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(course, nil)
|
||||
end
|
||||
|
||||
it "should not trigger any alerts for courses with no alerts" do
|
||||
course = mock('Course')
|
||||
course.stubs(:available?).returns(true)
|
||||
course.stubs(:alerts).returns(stub(:all => []))
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(course, nil)
|
||||
end
|
||||
|
||||
it "should not trigger any alerts when there are no students in the class" do
|
||||
course = Account.default.courses.create!
|
||||
course.offer!
|
||||
course.alerts.create!(:recipients => [:student], :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(course, nil)
|
||||
end
|
||||
|
||||
it "should not trigger any alerts when there are no teachers in the class" do
|
||||
course_with_student(:active_course => 1)
|
||||
@course.alerts.create!(:recipients => [:student], :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should not trigger any alerts in subsequent courses" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
@course.alerts.create!(:recipients => [:student], :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
@course.start_at = Time.now - 30.days
|
||||
account_alerts = []
|
||||
|
||||
Alert.evaluate_for_course(@course, account_alerts)
|
||||
|
||||
account_alerts.should == []
|
||||
end
|
||||
end
|
||||
|
||||
context 'repetition' do
|
||||
it "should not keep sending alerts when repetition is nil" do
|
||||
enable_cache do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
@course.alerts.create!(:recipients => [:student], :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything).once
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
|
||||
it "should not keep sending alerts when run on the same day" do
|
||||
enable_cache do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
@course.alerts.create!(:recipients => [:student], :repetition => 1, :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything).once
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
|
||||
it "should keep sending alerts for daily repetition" do
|
||||
enable_cache do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
alert = @course.alerts.create!(:recipients => [:student], :repetition => 1, :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
@course.start_at = Time.now - 30.days
|
||||
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything).twice
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
# update sent_at
|
||||
Rails.cache.write([alert, @user.id].cache_key, (Time.now - 1.day).beginning_of_day)
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'interaction' do
|
||||
it "should not alert for new courses" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert for old courses" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should not alert for submission comments" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user)
|
||||
SubmissionComment.create!(:submission => @submission, :comment => 'some comment', :author => @teacher, :recipient => @user)
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert for old submission comments" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user)
|
||||
SubmissionComment.create!(:submission => @submission, :comment => 'some comment', :author => @teacher, :recipient => @user) do |sc|
|
||||
sc.created_at = Time.now - 30.days
|
||||
end
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should not alert for conversation messages" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@conversation = @teacher.initiate_conversation([@user])
|
||||
@conversation.add_message("hello")
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert for old conversation messages" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@conversation = @teacher.initiate_conversation([@student, user])
|
||||
message = @conversation.add_message("hello")
|
||||
message.created_at = Time.now - 30.days
|
||||
message.save!
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student], :repetition => 1)
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
Alert.expects(:send_alert).with(anything, [ @student.id ], anything).twice
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
# create a generated message
|
||||
@conversation.add_participants([user])
|
||||
@conversation.messages.length.should == 2
|
||||
|
||||
# it should still alert, ignoring the new message
|
||||
# update sent_at so it will send again
|
||||
Rails.cache.write([alert, @student.id].cache_key, (Time.now - 5.days).beginning_of_day)
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
|
||||
it "memoizes alert checker creation" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user)
|
||||
SubmissionComment.create!(:submission => @submission, :comment => 'some comment', :author => @teacher, :recipient => @user) do |sc|
|
||||
sc.created_at = Time.now - 30.days
|
||||
end
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
|
||||
mock_interaction = stub(should_not_receive_message?: true)
|
||||
Alerts::Interaction.expects(:new).once.returns(mock_interaction)
|
||||
|
||||
Alert.evaluate_for_course(@course, [alert])
|
||||
end
|
||||
|
||||
context 'ungraded count' do
|
||||
it "should not alert for no submissions" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedCount', :threshold => 1)
|
||||
alert.save!
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedCount', :threshold => 1)
|
||||
alert.save!
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
|
||||
context 'ungraded timespan' do
|
||||
it "should not alert for no submissions" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedTimespan', :threshold => 1)
|
||||
alert.save!
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should not alert for submission within the threshold" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedTimespan', :threshold => 7)
|
||||
alert.save!
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
@submission.update_attribute(:submitted_at, Time.now - 30.days);
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedTimespan', :threshold => 7)
|
||||
alert.save!
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert for multiple submissions when one matches and one doesn't" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
@submission.update_attribute(:submitted_at, Time.now - 30.days);
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
@submission.update_attribute(:submitted_at, Time.now - 30.days);
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedTimespan', :threshold => 7)
|
||||
alert.save!
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
|
||||
context 'user notes' do
|
||||
before do
|
||||
course_with_teacher(:active_all => 1)
|
||||
root_account = @course.root_account
|
||||
root_account.enable_user_notes = true
|
||||
root_account.save!
|
||||
end
|
||||
|
||||
it "should not alert for new courses" do
|
||||
student_in_course(:active_all => 1)
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UserNote', :threshold => 7)
|
||||
alert.save!
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert for old courses" do
|
||||
student_in_course(:active_all => 1)
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UserNote', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should not alert when a note exists" do
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
UserNote.create!(:creator => @teacher, :user => @user)
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UserNote', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert when an old note exists" do
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
UserNote.create!(:creator => @teacher, :user => @user) { |un| un.created_at = Time.now - 30.days }
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UserNote', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "notification alert info" do
|
||||
before do
|
||||
Notification.create!(:name => 'Alert')
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@pseudonym = mock('Pseudonym')
|
||||
@pseudonym.stubs(:destroyed?).returns(false)
|
||||
Pseudonym.stubs(:find_by_user_id).returns(@pseudonym)
|
||||
a = @user.communication_channels.create(:path => "a@example.com")
|
||||
a.confirm!
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
end
|
||||
|
||||
it "should tell you what the alert is about timespan" do
|
||||
@submission.update_attribute(:submitted_at, Time.now - 30.days);
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedTimespan', :threshold => 7)
|
||||
alert.save!
|
||||
@mock_notification.expects(:create_message).with do |alert, _, _|
|
||||
alert.criteria.first.criterion_type.should == 'UngradedTimespan'
|
||||
end
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should tell you what the alert is about count" do
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedCount', :threshold => 1)
|
||||
alert.save!
|
||||
@mock_notification.expects(:create_message).with do |alert, _, _|
|
||||
alert.criteria.first.criterion_type.should == 'UngradedCount'
|
||||
end
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should tell you what the alert is about note" do
|
||||
root_account = @course.root_account
|
||||
root_account.enable_user_notes = true
|
||||
root_account.save!
|
||||
|
||||
UserNote.create!(:creator => @teacher, :user => @user) { |un| un.created_at = Time.now - 30.days }
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UserNote', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with do |alert, _, _|
|
||||
alert.criteria.first.criterion_type.should == 'UserNote'
|
||||
end
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should tell you what the alert is about interaction" do
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with do |alert, _, _|
|
||||
alert.criteria.first.criterion_type.should == 'Interaction'
|
||||
end
|
||||
|
||||
Alert.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,494 @@
|
|||
#
|
||||
# Copyright (C) 2014 Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper.rb')
|
||||
|
||||
module Alerts
|
||||
describe DelayedAlertSender do
|
||||
|
||||
before do
|
||||
@mock_notification = Notification.new
|
||||
Notification.stubs(:by_name).returns(@mock_notification)
|
||||
end
|
||||
|
||||
context "basic evaluation" do
|
||||
it "should not trigger any alerts for unpublished courses" do
|
||||
course = mock('Course')
|
||||
course.stubs(:available?, false)
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(course, nil)
|
||||
end
|
||||
|
||||
it "should not trigger any alerts for courses with no alerts" do
|
||||
course = mock('Course')
|
||||
course.stubs(:available?).returns(true)
|
||||
course.stubs(:alerts).returns(stub(:all => []))
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(course, nil)
|
||||
end
|
||||
|
||||
it "should not trigger any alerts when there are no students in the class" do
|
||||
course = Account.default.courses.create!
|
||||
course.offer!
|
||||
course.alerts.create!(:recipients => [:student], :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(course, nil)
|
||||
end
|
||||
|
||||
it "should not trigger any alerts when there are no teachers in the class" do
|
||||
course_with_student(:active_course => 1)
|
||||
@course.alerts.create!(:recipients => [:student], :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should not trigger any alerts in subsequent courses" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
@course.alerts.create!(:recipients => [:student], :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
@course.start_at = Time.now - 30.days
|
||||
account_alerts = []
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, account_alerts)
|
||||
|
||||
account_alerts.should == []
|
||||
end
|
||||
end
|
||||
|
||||
context 'repetition' do
|
||||
it "should not keep sending alerts when repetition is nil" do
|
||||
enable_cache do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
@course.alerts.create!(:recipients => [:student], :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything).once
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
|
||||
it "should not keep sending alerts when run on the same day" do
|
||||
enable_cache do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
@course.alerts.create!(:recipients => [:student], :repetition => 1, :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything).once
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
|
||||
it "should keep sending alerts for daily repetition" do
|
||||
enable_cache do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
alert = @course.alerts.create!(:recipients => [:student], :repetition => 1, :criteria => [{:criterion_type => 'Interaction', :threshold => 7}])
|
||||
@course.start_at = Time.now - 30.days
|
||||
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything).twice
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
# update sent_at
|
||||
Rails.cache.write([alert, @user.id].cache_key, (Time.now - 1.day).beginning_of_day)
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'interaction' do
|
||||
it "should not alert for new courses" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert for old courses" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should not alert for submission comments" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user)
|
||||
SubmissionComment.create!(:submission => @submission, :comment => 'some comment', :author => @teacher, :recipient => @user)
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert for old submission comments" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user)
|
||||
SubmissionComment.create!(:submission => @submission, :comment => 'some comment', :author => @teacher, :recipient => @user) do |sc|
|
||||
sc.created_at = Time.now - 30.days
|
||||
end
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should not alert for conversation messages" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@conversation = @teacher.initiate_conversation([@user])
|
||||
@conversation.add_message("hello")
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert for old conversation messages" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@conversation = @teacher.initiate_conversation([@student, user])
|
||||
message = @conversation.add_message("hello")
|
||||
message.created_at = Time.now - 30.days
|
||||
message.save!
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student], :repetition => 1)
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
DelayedAlertSender.expects(:send_alert).with(anything, [@student.id], anything).twice
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
# create a generated message
|
||||
@conversation.add_participants([user])
|
||||
@conversation.messages.length.should == 2
|
||||
|
||||
# it should still alert, ignoring the new message
|
||||
# update sent_at so it will send again
|
||||
Rails.cache.write([alert, @student.id].cache_key, (Time.now - 5.days).beginning_of_day)
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
|
||||
it "memoizes alert checker creation" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user)
|
||||
SubmissionComment.create!(:submission => @submission, :comment => 'some comment', :author => @teacher, :recipient => @user) do |sc|
|
||||
sc.created_at = Time.now - 30.days
|
||||
end
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
|
||||
mock_interaction = stub(should_not_receive_message?: true)
|
||||
Alerts::Interaction.expects(:new).once.returns(mock_interaction)
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, [alert])
|
||||
end
|
||||
|
||||
context 'ungraded count' do
|
||||
it "should not alert for no submissions" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedCount', :threshold => 1)
|
||||
alert.save!
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedCount', :threshold => 1)
|
||||
alert.save!
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
|
||||
context 'ungraded timespan' do
|
||||
it "should not alert for no submissions" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
student_in_course(:active_all => 1)
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedTimespan', :threshold => 1)
|
||||
alert.save!
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should not alert for submission within the threshold" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedTimespan', :threshold => 7)
|
||||
alert.save!
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
@submission.update_attribute(:submitted_at, Time.now - 30.days);
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedTimespan', :threshold => 7)
|
||||
alert.save!
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert for multiple submissions when one matches and one doesn't" do
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
@submission.update_attribute(:submitted_at, Time.now - 30.days);
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
@submission.update_attribute(:submitted_at, Time.now - 30.days);
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedTimespan', :threshold => 7)
|
||||
alert.save!
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
|
||||
context 'user notes' do
|
||||
before do
|
||||
course_with_teacher(:active_all => 1)
|
||||
root_account = @course.root_account
|
||||
root_account.enable_user_notes = true
|
||||
root_account.save!
|
||||
end
|
||||
|
||||
it "should not alert for new courses" do
|
||||
student_in_course(:active_all => 1)
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UserNote', :threshold => 7)
|
||||
alert.save!
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert for old courses" do
|
||||
student_in_course(:active_all => 1)
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UserNote', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should not alert when a note exists" do
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
::UserNote.create!(:creator => @teacher, :user => @user)
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UserNote', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
Notification.any_instance.expects(:create_message).never
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should alert when an old note exists" do
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
::UserNote.create!(:creator => @teacher, :user => @user) { |un| un.created_at = Time.now - 30.days }
|
||||
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UserNote', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with(anything, [@user.id], anything)
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
|
||||
context "notification alert info" do
|
||||
before do
|
||||
Notification.create!(:name => 'Alert')
|
||||
course_with_teacher(:active_all => 1)
|
||||
@teacher = @user
|
||||
@user = nil
|
||||
student_in_course(:active_all => 1)
|
||||
@pseudonym = mock('Pseudonym')
|
||||
@pseudonym.stubs(:destroyed?).returns(false)
|
||||
Pseudonym.stubs(:find_by_user_id).returns(@pseudonym)
|
||||
a = @user.communication_channels.create(:path => "a@example.com")
|
||||
a.confirm!
|
||||
@assignment = @course.assignments.new(:title => "some assignment")
|
||||
@assignment.workflow_state = "published"
|
||||
@assignment.save
|
||||
@submission = @assignment.submit_homework(@user, :body => 'body')
|
||||
end
|
||||
|
||||
it "should tell you what the alert is about timespan" do
|
||||
@submission.update_attribute(:submitted_at, Time.now - 30.days);
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedTimespan', :threshold => 7)
|
||||
alert.save!
|
||||
@mock_notification.expects(:create_message).with do |alert, _, _|
|
||||
alert.criteria.first.criterion_type.should == 'UngradedTimespan'
|
||||
end
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should tell you what the alert is about count" do
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UngradedCount', :threshold => 1)
|
||||
alert.save!
|
||||
@mock_notification.expects(:create_message).with do |alert, _, _|
|
||||
alert.criteria.first.criterion_type.should == 'UngradedCount'
|
||||
end
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should tell you what the alert is about note" do
|
||||
root_account = @course.root_account
|
||||
root_account.enable_user_notes = true
|
||||
root_account.save!
|
||||
|
||||
::UserNote.create!(:creator => @teacher, :user => @user) { |un| un.created_at = Time.now - 30.days }
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'UserNote', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with do |alert, _, _|
|
||||
alert.criteria.first.criterion_type.should == 'UserNote'
|
||||
end
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
|
||||
it "should tell you what the alert is about interaction" do
|
||||
alert = @course.alerts.build(:recipients => [:student])
|
||||
alert.criteria.build(:criterion_type => 'Interaction', :threshold => 7)
|
||||
alert.save!
|
||||
@course.start_at = Time.now - 30.days
|
||||
@mock_notification.expects(:create_message).with do |alert, _, _|
|
||||
alert.criteria.first.criterion_type.should == 'Interaction'
|
||||
end
|
||||
|
||||
DelayedAlertSender.evaluate_for_course(@course, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue