def _send_invitation_email(self, section_id): SentEmail.create( section_id=section_id, recipient_uid=get_instructor_uids(section_id=section_id, term_id=self.term_id)[0], template_type='invitation', term_id=self.term_id, )
def test_has_obsolete_meeting_dates(self, client, admin_session): """Admins can see meeting date changes that might disrupt scheduled recordings.""" with test_approvals_workflow(app): meeting = get_eligible_meeting(section_id=section_1_id, term_id=self.term_id) obsolete_meeting_end_date = '2020-04-01' assert meeting['endDate'] != obsolete_meeting_end_date Scheduled.create( instructor_uids=get_instructor_uids(term_id=self.term_id, section_id=section_1_id), kaltura_schedule_id=random.randint(1, 10), meeting_days=meeting['days'], meeting_end_date=obsolete_meeting_end_date, meeting_end_time=meeting['endTime'], meeting_start_date=meeting['startDate'], meeting_start_time=meeting['startTime'], publish_type_='kaltura_my_media', recording_type_='presentation_audio', room_id=Room.get_room_id(section_id=section_1_id, term_id=self.term_id), section_id=section_1_id, term_id=self.term_id, ) std_commit(allow_test_environment=True) api_json = self._api_course_changes(client, term_id=self.term_id) course = _find_course(api_json=api_json, section_id=section_1_id) assert course assert course['scheduled']['hasObsoleteRoom'] is False assert course['scheduled']['hasObsoleteDates'] is True assert course['scheduled']['hasObsoleteTimes'] is False assert course['scheduled']['hasObsoleteInstructors'] is False
def test_has_obsolete_instructors(self, client, admin_session): """Admins can see instructor changes that might disrupt scheduled recordings.""" with test_approvals_workflow(app): meeting = get_eligible_meeting(section_id=section_1_id, term_id=self.term_id) instructor_uids = get_instructor_uids(term_id=self.term_id, section_id=section_1_id) # Course has multiple instructors; we will schedule using only one instructor UID. assert len(instructor_uids) > 1 scheduled_with_uid = instructor_uids[0] Scheduled.create( instructor_uids=[scheduled_with_uid], kaltura_schedule_id=random.randint(1, 10), meeting_days=meeting['days'], meeting_end_date=get_recording_end_date(meeting), meeting_end_time=meeting['endTime'], meeting_start_date=get_recording_start_date(meeting, return_today_if_past_start=True), meeting_start_time=meeting['startTime'], publish_type_='kaltura_my_media', recording_type_='presenter_audio', room_id=Room.get_room_id(section_id=section_1_id, term_id=self.term_id), section_id=section_1_id, term_id=self.term_id, ) std_commit(allow_test_environment=True) api_json = self._api_course_changes(client, term_id=self.term_id) course = _find_course(api_json=api_json, section_id=section_1_id) assert course assert course['scheduled']['hasObsoleteRoom'] is False assert course['scheduled']['hasObsoleteDates'] is False assert course['scheduled']['hasObsoleteTimes'] is False assert course['scheduled']['hasObsoleteInstructors'] is True assert len(course['instructors']) == 2 assert len(course['scheduled']['instructors']) == 1 assert course['scheduled']['instructors'][0]['uid'] == scheduled_with_uid
def test_course_with_partial_approval(self, client, admin_session): """Course with two instructors and one approval.""" with test_approvals_workflow(app): # If course has approvals but not scheduled then it will show up in the feed. approved_by_uid = get_instructor_uids(section_id=section_1_id, term_id=self.term_id)[0] room_id = Room.get_room_id(section_id=section_1_id, term_id=self.term_id) Approval.create( approved_by_uid=approved_by_uid, approver_type_='instructor', publish_type_='kaltura_my_media', recording_type_='presentation_audio', room_id=room_id, section_id=section_1_id, term_id=self.term_id, ) std_commit(allow_test_environment=True) api_json = api_get_course( client, term_id=self.term_id, section_id=section_1_id, ) assert [i['uid'] for i in api_json['instructors']] == ['10001', '10002'] approvals = api_json['approvals'] assert len(approvals) == 1 assert approved_by_uid == approvals[0]['approvedBy']['uid'] assert api_json['approvalStatus'] == 'Partially Approved' assert api_json['schedulingStatus'] == 'Not Scheduled' assert api_json['meetings']['eligible'][0]['room']['id'] == room_id assert api_json['meetings']['eligible'][0]['room']['location'] == 'Barrows 106'
def test_admin_alert_multiple_meeting_patterns(self): """Emails admin if course is scheduled with weird start/end dates.""" with test_approvals_workflow(app): with enabled_job(job_key=AdminEmailsJob.key()): term_id = app.config['CURRENT_TERM_ID'] section_id = 50014 room_id = Room.find_room('Barker 101').id # The course has two instructors. instructor_uid = get_instructor_uids(section_id=section_id, term_id=term_id)[0] approval = Approval.create( approved_by_uid=instructor_uid, approver_type_='instructor', publish_type_='kaltura_my_media', recording_type_='presenter_audio', room_id=room_id, section_id=section_id, term_id=term_id, ) # Uh oh! Only one of them has been scheduled. meeting = get_eligible_meeting(section_id=section_id, term_id=term_id) Scheduled.create( instructor_uids=[instructor_uid], kaltura_schedule_id=random.randint(1, 10), meeting_days=meeting['days'], meeting_end_date=get_recording_end_date(meeting), meeting_end_time=meeting['endTime'], meeting_start_date=get_recording_start_date( meeting, return_today_if_past_start=True), meeting_start_time=meeting['startTime'], publish_type_=approval.publish_type, recording_type_=approval.recording_type, room_id=room_id, section_id=section_id, term_id=term_id, ) courses = SisSection.get_courses_scheduled_nonstandard_dates( term_id=term_id) course = next( (c for c in courses if c['sectionId'] == section_id), None) assert course # Message queued but not sent. admin_uid = app.config['EMAIL_DIABLO_ADMIN_UID'] AdminEmailsJob(simply_yield).run() queued_messages = QueuedEmail.query.filter_by( section_id=section_id).all() assert len(queued_messages) == 1 for queued_message in queued_messages: assert '2020-08-26 to 2020-10-02' in queued_message.message # Message sent. QueuedEmailsJob(simply_yield).run() emails_sent = SentEmail.get_emails_sent_to(uid=admin_uid) assert len(emails_sent) == 1 assert emails_sent[ 0].template_type == 'admin_alert_multiple_meeting_patterns' assert emails_sent[0].section_id == section_id
def test_approval_by_instructors(self, app, client, fake_auth): """Instructor can submit approval if s/he is teaching the requested course.""" with test_approvals_workflow(app): instructor_uids = get_instructor_uids(section_id=section_1_id, term_id=self.term_id) fake_auth.login(instructor_uids[0]) api_approve( client, publish_type='kaltura_my_media', recording_type='presentation_audio', section_id=section_1_id, ) std_commit(allow_test_environment=True) fake_auth.login(instructor_uids[1]) api_approve( client, publish_type='kaltura_media_gallery', recording_type='presentation_audio', section_id=section_1_id, ) std_commit(allow_test_environment=True) QueuedEmailsJob(app.app_context).run() # First instructor was notified 1) that second instructor needed to approve; 2) that second instructor made changes. emails_sent = SentEmail.get_emails_sent_to(instructor_uids[0]) assert len(emails_sent) == 2 for email in emails_sent: assert email.section_id == section_1_id assert email.term_id == self.term_id assert emails_sent[0].template_type == 'waiting_for_approval' assert emails_sent[1].template_type == 'notify_instructor_of_changes' # Second instructor received no notifications. assert len(SentEmail.get_emails_sent_to(instructor_uids[1])) == 0 fake_auth.login(admin_uid) api_json = api_get_course( client, term_id=self.term_id, section_id=section_1_id, ) assert api_json['meetings']['eligible'][0]['room']['location'] == 'Barrows 106' instructor_uids = [i['uid'] for i in api_json['instructors']] assert instructor_uids == instructor_uids approvals_ = api_json['approvals'] assert len(approvals_) == 2 assert approvals_[0]['approvedBy']['uid'] == instructor_uids[0] assert approvals_[0]['publishType'] == 'kaltura_my_media' assert approvals_[1]['approvedBy']['uid'] == instructor_uids[1] assert approvals_[1]['publishType'] == 'kaltura_media_gallery' assert approvals_[1]['recordingType'] == 'presentation_audio' assert approvals_[1]['recordingTypeName'] == 'Presentation and Audio' assert api_json['hasNecessaryApprovals'] is True assert api_json['scheduled'] is None
def test_alert_admin_of_instructor_change(self): """Emails admin when a scheduled course gets a new instructor.""" with test_approvals_workflow(app): with enabled_job(job_key=AdminEmailsJob.key()): term_id = app.config['CURRENT_TERM_ID'] section_id = 50005 room_id = Room.find_room('Barker 101').id # The course has two instructors. instructor_1_uid, instructor_2_uid = get_instructor_uids( section_id=section_id, term_id=term_id) approval = Approval.create( approved_by_uid=instructor_1_uid, approver_type_='instructor', course_display_name= f'term_id:{term_id} section_id:{section_id}', publish_type_='kaltura_my_media', recording_type_='presenter_audio', room_id=room_id, section_id=section_id, term_id=term_id, ) # Uh oh! Only one of them has been scheduled. meeting = get_eligible_meeting(section_id=section_id, term_id=term_id) Scheduled.create( course_display_name= f'term_id:{term_id} section_id:{section_id}', instructor_uids=[instructor_1_uid], kaltura_schedule_id=random.randint(1, 10), meeting_days=meeting['days'], meeting_end_date=get_recording_end_date(meeting), meeting_end_time=meeting['endTime'], meeting_start_date=get_recording_start_date( meeting, return_today_if_past_start=True), meeting_start_time=meeting['startTime'], publish_type_=approval.publish_type, recording_type_=approval.recording_type, room_id=room_id, section_id=section_id, term_id=term_id, ) admin_uid = app.config['EMAIL_DIABLO_ADMIN_UID'] email_count = _get_email_count(admin_uid) # Message queued but not sent. AdminEmailsJob(simply_yield).run() assert _get_email_count(admin_uid) == email_count queued_messages = QueuedEmail.query.filter_by( template_type='admin_alert_instructor_change').all() assert len(queued_messages) == 1 for snippet in [ 'LAW 23', 'Old instructor(s) Regan MacNeil', 'New instructor(s) Regan MacNeil, Burke Dennings' ]: assert snippet in queued_messages[0].message # Message sent. QueuedEmailsJob(simply_yield).run() assert _get_email_count(admin_uid) == email_count + 1
def test_unauthorized(self, client, fake_auth): """Instructors cannot unschedule courses.""" instructor_uids = get_instructor_uids(section_id=section_1_id, term_id=self.term_id) fake_auth.login(instructor_uids[0]) self._api_unschedule( client, term_id=self.term_id, section_id=section_1_id, expected_status_code=401, )
def _create_approval(self, section_id): Approval.create( approved_by_uid=get_instructor_uids(section_id=section_id, term_id=self.term_id)[0], approver_type_='instructor', publish_type_='kaltura_my_media', recording_type_='presentation_audio', room_id=Room.get_room_id(section_id=section_id, term_id=self.term_id), section_id=section_id, term_id=self.term_id, )
def test_not_authorized(self, client, fake_auth): """Deny access if user is not an admin.""" instructor_uids = get_instructor_uids(section_id=section_1_id, term_id=self.term_id) fake_auth.login(instructor_uids[0]) api_get_course( client, term_id=self.term_id, section_id=section_3_id, expected_status_code=403, )
def test_unauthorized(self, client, fake_auth): """Instructors cannot modify preferences.""" instructor_uids = get_instructor_uids(section_id=section_1_id, term_id=self.term_id) fake_auth.login(instructor_uids[0]) self._api_opt_out_update( client, term_id=self.term_id, section_id=section_1_id, opt_out=True, expected_status_code=401, )
def test_instructor_already_approved(self, client, fake_auth): """Instructor can submit his/her approval only once.""" with test_approvals_workflow(app): instructor_uids = get_instructor_uids(section_id=section_1_id, term_id=self.term_id) fake_auth.login(instructor_uids[0]) for expected_status_code in [200, 403]: api_approve( client, publish_type='kaltura_my_media', recording_type='presentation_audio', section_id=section_1_id, expected_status_code=expected_status_code, )
def test_date_time_format(self, client, fake_auth): """Dates and times are properly formatted for front-end display.""" instructor_uids = get_instructor_uids(section_id=section_2_id, term_id=self.term_id) fake_auth.login(instructor_uids[0]) api_json = api_get_course( client, term_id=self.term_id, section_id=section_2_id, ) assert api_json['meetings']['ineligible'][0]['daysFormatted'] == ['MO', 'WE', 'FR'] assert api_json['meetings']['ineligible'][0]['startTimeFormatted'] == '3:00 pm' assert api_json['meetings']['ineligible'][0]['endTimeFormatted'] == '3:59 pm' assert api_json['meetings']['ineligible'][0]['location'] == 'Wheeler 150' assert api_json['nonstandardMeetingDates'] is False assert api_json['meetingType'] == 'A'
def test_alert_admin_of_room_change(self, db_session): """Emails admin when a scheduled course gets a room change.""" with test_approvals_workflow(app): with enabled_job(job_key=AdminEmailsJob.key()): term_id = app.config['CURRENT_TERM_ID'] section_id = 50004 approved_by_uid = '10004' the_old_room = 'Wheeler 150' scheduled_in_room = Room.find_room(the_old_room) approval = Approval.create( approved_by_uid=approved_by_uid, approver_type_='instructor', publish_type_='kaltura_media_gallery', recording_type_='presenter_audio', room_id=scheduled_in_room.id, section_id=section_id, term_id=term_id, ) meeting = get_eligible_meeting(section_id=section_id, term_id=term_id) Scheduled.create( instructor_uids=get_instructor_uids(term_id=term_id, section_id=section_id), kaltura_schedule_id=random.randint(1, 10), meeting_days=meeting['days'], meeting_end_date=get_recording_end_date(meeting), meeting_end_time=meeting['endTime'], meeting_start_date=get_recording_start_date( meeting, return_today_if_past_start=True), meeting_start_time=meeting['startTime'], publish_type_=approval.publish_type, recording_type_=approval.recording_type, room_id=scheduled_in_room.id, section_id=section_id, term_id=term_id, ) admin_uid = app.config['EMAIL_DIABLO_ADMIN_UID'] # Message queued, then sent. AdminEmailsJob(simply_yield).run() QueuedEmailsJob(simply_yield).run() emails_sent = SentEmail.get_emails_sent_to(uid=admin_uid) assert len(emails_sent) == 1 assert emails_sent[0].section_id == section_id assert emails_sent[ 0].template_type == 'admin_alert_room_change'
def test_partially_approved_filter(self, client, admin_session): """Partially approved: Eligible, invited course with 1+ approvals, but not ALL instructors have approved.""" with test_approvals_workflow(app): for section_id in [section_1_id, section_6_id, section_7_id]: # Assert multiple instructors assert len(get_instructor_uids(section_id=section_id, term_id=self.term_id)) > 1 # Send invites self._send_invitation_email(section_id) if section_id == section_1_id: # If course is "approved" by admin only then it will NOT show up on the partially-approval list. Approval.create( approved_by_uid=admin_uid, approver_type_='admin', publish_type_='kaltura_my_media', recording_type_='presentation_audio', room_id=Room.get_room_id(section_id=section_id, term_id=self.term_id), section_id=section_id, term_id=self.term_id, ) else: # Approval by first instructor only self._create_approval(section_id) # Feed will include both scheduled and not scheduled. for section_id in [section_1_id, section_7_id]: mock_scheduled(section_id=section_id, term_id=self.term_id) # Unschedule one of them Approval.delete(section_id=section_7_id, term_id=self.term_id) Scheduled.delete(section_id=section_7_id, term_id=self.term_id) std_commit(allow_test_environment=True) api_json = self._api_courses(client, term_id=self.term_id, filter_='Partially Approved') assert len(api_json) == 1 course = _find_course(api_json=api_json, section_id=section_6_id) assert course assert course['label'] == 'LAW 23, LEC 002' assert course['approvalStatus'] == 'Partially Approved' assert course['schedulingStatus'] == 'Not Scheduled'
def test_unauthorized(self, client, fake_auth): """Instructors cannot view courses report.""" instructor_uids = get_instructor_uids(section_id=section_1_id, term_id=self.term_id) fake_auth.login(instructor_uids[0]) self._api_courses_report(client, term_id=self.term_id, expected_status_code=401)
def test_not_authorized(self, client, fake_auth): """Deny access if user is not an admin.""" instructor_uids = get_instructor_uids(section_id=section_1_id, term_id=app.config['CURRENT_TERM_ID']) fake_auth.login(instructor_uids[0]) self._api_courses_csv(client, expected_status_code=401)
def test_not_authorized(self, client, fake_auth): instructor_uids = get_instructor_uids(section_id=section_1_id, term_id=self.term_id) fake_auth.login(instructor_uids[0]) self._api_courses(client, term_id=self.term_id, expected_status_code=401)