Beispiel #1
0
def sign_up_0_test(request):
    driver = WebDriverManager.launch_browser()

    # Reset course data in Diablo and Kaltura
    test_data = util.parse_sign_up_test_data()
    util.reset_test_data(test_data[0])

    # Define the course data for the test
    section = Section(test_data[0])
    recording_schedule = RecordingSchedule(section)

    # Define page objects
    login_page = LoginPage(driver)
    ouija_page = OuijaBoardPage(driver)
    sign_up_page = SignUpPage(driver)

    session = request.node
    try:
        for item in session.items:
            cls = item.getparent(pytest.Class)
            setattr(cls.obj, 'section', section)
            setattr(cls.obj, 'recording_schedule', recording_schedule)
            setattr(cls.obj, 'driver', driver)
            setattr(cls.obj, 'login_page', login_page)
            setattr(cls.obj, 'ouija_page', ouija_page)
            setattr(cls.obj, 'sign_up_page', sign_up_page)
        yield
    finally:
        WebDriverManager.quit_browser(driver)
Beispiel #2
0
class TestCourseCancellation:

    # INITIALIZE TESTS

    test_data = util.get_test_script_course('test_course_cancellation')
    section = util.get_test_section(test_data)
    meeting = section.meetings[0]
    recording_schedule = RecordingSchedule(section)

    def test_disable_jobs(self):
        self.login_page.load_page()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.disable_all_jobs()

    def test_delete_old_diablo_and_kaltura(self):
        self.kaltura_page.log_in_via_calnet()
        self.kaltura_page.reset_test_data(self.term, self.recording_schedule)
        util.reset_sign_up_test_data(self.section)
        self.recording_schedule.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    def test_admin_emails_pre_run(self):
        self.jobs_page.load_page()
        self.jobs_page.run_admin_emails_job()

    def test_instructor_emails_pre_run(self):
        self.jobs_page.run_instructor_emails_job()

    def test_queued_emails_pre_run(self):
        self.jobs_page.run_queued_emails_job()

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_delete_old_email(self):
        self.email_page.log_in()
        self.email_page.delete_all_messages()

    # COURSE IS CANCELLED BEFORE SIGN-UP

    def test_deleted_pre_signup(self):
        util.delete_section(self.section)

    def test_deleted_pre_signup_no_search_result(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_deleted_pre_sign_up_no_admin_approve(self):
        self.sign_up_page.load_page(self.section)
        assert self.sign_up_page.is_canceled()
        assert not self.sign_up_page.is_present(SignUpPage.APPROVE_BUTTON)
        assert not self.sign_up_page.is_present(
            SignUpPage.SELECT_PUBLISH_TYPE_INPUT)
        assert not self.sign_up_page.is_present(SignUpPage.SEND_INVITE_BUTTON)

    def test_deleted_pre_signup_no_teacher_result(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth(self.section.instructors[0].uid)
        self.ouija_page.wait_for_title_contains('Eligible for Capture')
        assert not self.ouija_page.is_present(
            OuijaBoardPage.course_row_link_locator(self.section))

    def test_deleted_pre_signup_no_teacher_approve(self):
        self.sign_up_page.load_page(self.section)
        assert self.sign_up_page.is_canceled()
        assert not self.sign_up_page.is_present(SignUpPage.APPROVE_BUTTON)
        assert not self.sign_up_page.is_present(
            SignUpPage.SELECT_PUBLISH_TYPE_INPUT)

    # COURSE IS RESTORED AND SCHEDULED

    def test_restored_pre_sign_up(self):
        util.restore_section(self.section)

    def test_approve(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.sign_up_page.click_agree_checkbox()
        self.sign_up_page.click_approve_button()
        msg = 'This course is currently queued for scheduling. Recordings will be scheduled in an hour or less. Approved by you.'
        self.sign_up_page.wait_for_approvals_msg(msg)
        self.recording_schedule.recording_type = RecordingType.SCREENCAST
        self.recording_schedule.publish_type = PublishType.BCOURSES
        self.recording_schedule.approval_status = RecordingApprovalStatus.APPROVED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.QUEUED_FOR_SCHEDULING

    def test_kaltura_job(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()

    def test_kaltura_schedule_id(self):
        util.get_kaltura_id(self.recording_schedule, self.term)

    def test_kaltura_blackouts(self):
        self.jobs_page.run_blackouts_job()

    # COURSE IS CANCELLED AGAIN

    def test_delete_scheduled(self):
        util.delete_section(self.section)

    def test_course_page_cancelled(self):
        self.sign_up_page.load_page(self.section)
        assert self.sign_up_page.is_canceled()

    def test_course_changes(self):
        self.changes_page.load_page()
        self.changes_page.wait_for_results()
        assert self.changes_page.is_course_row_present(self.section)
        assert self.changes_page.is_course_canceled(self.section)

    def test_search_cancelled(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is True
        assert self.ouija_page.course_row_status_el(
            self.section).text.strip() == 'Canceled'

    def test_admin_emails_job(self):
        self.jobs_page.load_page()
        self.jobs_page.run_admin_emails_job()

    def test_instructor_emails_job(self):
        self.jobs_page.run_instructor_emails_job()

    def test_queued_emails_job(self):
        self.jobs_page.run_queued_emails_job()

    # UNSCHEDULE CANCELED COURSE

    def test_admin_unsched_canceled(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.confirm_unscheduling_ineligible(
            self.recording_schedule)

    def test_changes_page_canceled_unsched(self):
        self.sign_up_page.click_course_changes_link()
        self.changes_page.wait_for_results()
        assert not self.changes_page.is_course_row_present(self.section)

    def test_no_kaltura_series_canceled_unsched(self):
        self.kaltura_page.load_event_edit_page(
            self.recording_schedule.series_id)
        self.kaltura_page.wait_for_title('Access Denied - UC Berkeley - Test')

    def test_unsched_again_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is False

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_admin_email_canceled_ineligible(self):
        subj = f'Course Capture Admin: {self.section.code} has moved to CANCELED'
        email = Email(msg_type=None, subject=subj, sender=None)
        assert self.email_page.is_message_delivered(email)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_instructor_email_canceled_ineligible(self):
        subj = f'Your course {self.section.code} is no longer eligible for Course Capture'
        email = Email(msg_type=None, subject=subj, sender=None)
        assert self.email_page.is_message_delivered(email)
Beispiel #3
0
class TestSignUp1:

    test_data = util.get_test_script_course('test_sign_up_1')
    section = Section(test_data)
    meeting = section.meetings[0]
    recording_schedule = RecordingSchedule(section)
    site = CanvasSite(
        code=f'XENA SignUp1 - {section.code}',
        name=f'XENA SignUp1 - {section.code}',
        site_id=None,
    )

    # DELETE PRE-EXISTING DATA

    def test_disable_jobs(self):
        self.login_page.load_page()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_queued_emails_job()
        self.jobs_page.disable_all_jobs()

    def test_delete_old_diablo_and_kaltura(self):
        self.kaltura_page.log_in_via_calnet()
        self.kaltura_page.reset_test_data(self.term, self.recording_schedule)
        util.set_meeting_location(self.section, self.meeting)
        util.reset_sign_up_test_data(self.test_data)
        self.recording_schedule.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    def test_run_initial_canvas_job(self):
        self.jobs_page.load_page()
        self.jobs_page.run_canvas_job()

    def test_delete_old_canvas_sites(self):
        self.canvas_page.delete_section_sites(self.section)
        self.jobs_page.load_page()
        self.jobs_page.run_canvas_job()

    def test_delete_old_email(self):
        self.email_page.log_in()
        self.email_page.delete_all_messages()

    # CHECK FILTERS - NOT INVITED

    def test_not_invited_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_not_invited_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_not_invited_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_not_invited_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_not_invited_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # RUN JOBS AND VERIFY INVITE

    def test_send_invite_email(self):
        self.jobs_page.load_page()
        self.jobs_page.run_invitations_job()
        self.jobs_page.run_queued_emails_job()

    def test_receive_invite_email(self):
        self.recording_schedule.approval_status = RecordingApprovalStatus.INVITED
        subj = f'Invitation {self.section.term.name} {self.section.code} (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_delivered(expected_message)

    # CHECK FILTERS - INVITED

    def test_invited_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_invited_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_invited_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_invited_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_invited_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # ADMIN HITS SIGN UP PAGE

    def test_load_sign_up_page(self):
        self.sign_up_page.load_page(self.section)

    # VERIFY STATIC COURSE SIS DATA

    def test_visible_ccn(self):
        assert self.sign_up_page.visible_ccn() == self.section.ccn

    def test_visible_course_title(self):
        assert self.sign_up_page.visible_course_title() == self.section.title

    def test_visible_instructors(self):
        instructor_names = [
            f'{i.first_name} {i.last_name}' for i in self.section.instructors
        ]
        assert self.sign_up_page.visible_instructors() == instructor_names

    def test_visible_meeting_days(self):
        term_dates = f'{SignUpPage.expected_term_date_str(self.meeting.start_date, self.meeting.end_date)}'
        last_date = f'(Final recording scheduled for {SignUpPage.expected_final_record_date_str(self.meeting, self.section.term)}.)'
        assert self.sign_up_page.visible_meeting_days(
        )[0] == f'{self.meeting.days}\n\n{term_dates}\n{last_date}'

    def test_visible_meeting_time(self):
        assert self.sign_up_page.visible_meeting_time(
        )[0] == f'{self.meeting.start_time} - {self.meeting.end_time}'

    def test_visible_room(self):
        assert self.sign_up_page.visible_rooms()[0] == self.meeting.room.name

    def test_no_visible_site_ids(self):
        assert len(self.sign_up_page.visible_course_site_ids()) == 0

    def test_visible_listings(self):
        listing_codes = [li.code for li in self.section.listings]
        assert self.sign_up_page.visible_cross_listing_codes() == listing_codes

    # VERIFY AVAILABLE OPTIONS

    def test_rec_type_text(self):
        assert self.sign_up_page.is_present(
            SignUpPage.RECORDING_TYPE_TEXT) is False

    def test_publish_type_text(self):
        assert self.sign_up_page.is_present(
            SignUpPage.PUBLISH_TYPE_TEXT) is True

    def test_rec_type_pre_selected(self):
        self.recording_schedule.recording_type = RecordingType.SCREENCAST
        assert self.sign_up_page.default_rec_type(
        ) == self.recording_schedule.recording_type.value['option']

    def test_publish_options(self):
        self.sign_up_page.hit_escape()
        self.sign_up_page.click_publish_type_input()
        visible_opts = self.sign_up_page.visible_menu_options()
        assert visible_opts == [
            PublishType.BCOURSES.value, PublishType.KALTURA.value
        ]

    def test_approve_disabled_no_pub_type(self):
        assert self.sign_up_page.element(
            SignUpPage.APPROVE_BUTTON).get_attribute('disabled') == 'true'

    # SELECT OPTIONS, APPROVE

    def test_choose_publish_type(self):
        self.sign_up_page.hit_escape()
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.recording_schedule.publish_type = PublishType.BCOURSES

    def test_no_agree_terms(self):
        assert not self.sign_up_page.is_present(SignUpPage.AGREE_TO_TERMS_CBX)

    def test_queue_for_schedule(self):
        self.sign_up_page.click_approve_button()
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.QUEUED_FOR_SCHEDULING

    def test_queue_confirmation(self):
        self.sign_up_page.wait_for_queued_confirmation()

    # VERIFY OUIJA FILTER

    def test_queued_filter_all(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_queued_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_queued_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_queued_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_queued_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_queued_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_queued_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_queued_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_queued_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_queued_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # RUN KALTURA SCHEDULING JOB AND OBTAIN SERIES ID

    def test_kaltura_job(self):
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()

    def test_kaltura_schedule_id(self):
        util.get_kaltura_id(self.recording_schedule, self.term)

    # VERIFY SERIES IN DIABLO

    def test_room_series(self):
        self.rooms_page.load_page()
        self.rooms_page.find_room(self.meeting.room)
        self.rooms_page.click_room_link(self.meeting.room)
        self.room_page.wait_for_series_row(self.recording_schedule)

    def test_room_series_link(self):
        expected = f'{self.section.code}, {self.section.number} ({self.term.name})'
        assert self.room_page.series_row_kaltura_link_text(
            self.recording_schedule) == expected

    def test_room_series_start(self):
        start = self.meeting.expected_recording_dates(self.section.term)[0]
        assert self.room_page.series_row_start_date(
            self.recording_schedule) == start

    def test_room_series_end(self):
        last_date = self.meeting.expected_recording_dates(
            self.section.term)[-1]
        assert self.room_page.series_row_end_date(
            self.recording_schedule) == last_date

    def test_room_series_days(self):
        assert self.room_page.series_row_days(
            self.recording_schedule) == self.meeting.days.replace(' ', '')

    def test_series_recordings(self):
        self.room_page.expand_series_row(self.recording_schedule)
        expected = self.meeting.expected_recording_dates(self.section.term)
        visible = self.room_page.series_recording_start_dates(
            self.recording_schedule)
        app.logger.info(f'Missing: {list(set(expected) - set(visible))}')
        app.logger.info(f'Unexpected: {list(set(visible) - set(expected))} ')
        assert visible == expected

    def test_series_blackouts(self):
        expected = self.meeting.expected_blackout_dates(self.section.term)
        visible = self.room_page.series_recording_blackout_dates(
            self.recording_schedule)
        app.logger.info(f'Missing: {list(set(expected) - set(visible))}')
        app.logger.info(f'Unexpected: {list(set(visible) - set(expected))} ')
        assert visible == expected

    def test_open_printable(self):
        self.room_printable_page.open_printable_schedule()

    def test_printable_course(self):
        expected = f'{self.section.code}, {self.section.number}'
        assert self.room_printable_page.visible_course(
            self.section) == expected

    def test_printable_instructors(self):
        expected = [
            f'{inst.first_name} {inst.last_name} ({inst.uid})'
            for inst in self.section.instructors
        ]
        assert self.room_printable_page.visible_instructors(
            self.section) == expected

    def test_printable_days(self):
        expected = [f'{self.meeting.days}']
        assert self.room_printable_page.visible_days(self.section) == expected

    def test_printable_times(self):
        dates = f'{self.meeting.start_date.strftime("%b %-d, %Y")} - {self.meeting.end_date.strftime("%b %-d, %Y")}'
        times = f'{self.meeting.start_time} - {self.meeting.end_time}'
        assert self.room_printable_page.visible_times(
            self.section) == [f'{dates}\n{times}']

    def test_printable_rec_type(self):
        expected = self.recording_schedule.recording_type.value['selection']
        assert self.room_printable_page.visible_recording_type(
            self.section) == expected

    def test_close_printable(self):
        self.room_printable_page.close_printable_schedule()

    # VERIFY OUIJA FILTER

    def test_scheduled_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_scheduled_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_scheduled_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_scheduled_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_scheduled_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # VERIFY SERIES IN KALTURA

    def test_click_series_link(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.click_kaltura_series_link(self.recording_schedule)
        self.kaltura_page.wait_for_delete_button()

    def test_series_title(self):
        expected = f'{self.section.code}, {self.section.number} ({self.term.name})'
        assert self.kaltura_page.visible_series_title() == expected

    def test_series_desc(self):
        course = f'{self.section.code}, {self.section.number} ({self.term.name})'
        instr = f'{self.section.instructors[0].first_name} {self.section.instructors[0].last_name}'
        copy = f'Copyright ©{self.term.name[-4:]} UC Regents; all rights reserved.'
        expected = f'{course} is taught by {instr}. {copy}'
        assert self.kaltura_page.visible_series_desc() == expected

    def test_series_collab_count(self):
        assert len(self.kaltura_page.collaborator_rows()) == len(
            self.section.instructors)

    def test_series_collab_rights(self):
        for instr in self.section.instructors:
            assert self.kaltura_page.collaborator_perm(instr) == 'Co-Editor'

    def test_series_publish_status(self):
        assert self.kaltura_page.is_private()

    def test_kaltura_no_course_site(self):
        assert len(self.kaltura_page.publish_category_els()) == 0

    def test_recur_weekly(self):
        self.kaltura_page.open_recurrence_modal()
        assert self.kaltura_page.is_weekly_checked()

    def test_recur_frequency(self):
        assert self.kaltura_page.visible_weekly_frequency() == '1'

    def test_recur_monday(self):
        checked = self.kaltura_page.is_mon_checked()
        assert checked if 'MO' in self.meeting.days else not checked

    def test_recur_tuesday(self):
        checked = self.kaltura_page.is_tue_checked()
        assert checked if 'TU' in self.meeting.days else not checked

    def test_recur_wednesday(self):
        checked = self.kaltura_page.is_wed_checked()
        assert checked if 'WE' in self.meeting.days else not checked

    def test_recur_thursday(self):
        checked = self.kaltura_page.is_thu_checked()
        assert checked if 'TH' in self.meeting.days else not checked

    def test_recur_friday(self):
        checked = self.kaltura_page.is_fri_checked()
        assert checked if 'FR' in self.meeting.days else not checked

    def test_recur_saturday(self):
        assert not self.kaltura_page.is_sat_checked()

    def test_recur_sunday(self):
        assert not self.kaltura_page.is_sun_checked()

    def test_start_date(self):
        start = util.get_kaltura_term_date_str(
            self.meeting.expected_recording_dates(self.section.term)[0])
        assert self.kaltura_page.visible_start_date() == start

    def test_end_date(self):
        end = util.get_kaltura_term_date_str(
            self.meeting.expected_recording_dates(self.section.term)[-1])
        assert self.kaltura_page.visible_end_date() == end

    def test_start_time(self):
        start = self.meeting.get_berkeley_start_time()
        visible_start = datetime.strptime(
            self.kaltura_page.visible_start_time(), '%I:%M %p')
        assert visible_start == start

    def test_end_time(self):
        end = self.meeting.get_berkeley_end_time()
        visible_end = datetime.strptime(self.kaltura_page.visible_end_time(),
                                        '%I:%M %p')
        assert visible_end == end

    def test_close_kaltura_window(self):
        self.kaltura_page.close_window_and_switch()

    # VERIFY EMAIL

    def test_send_schedule_conf_email(self):
        self.jobs_page.load_page()
        self.jobs_page.run_queued_emails_job()

    def test_receive_schedule_conf_email(self):
        subj = f'Your course, {self.section.code}, has been scheduled for Course Capture'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_delivered(expected_message)

    # INSTRUCTOR VISITS SIGN-UP PAGE AND APPROVES

    def test_instructor_login(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.log_out()
        self.login_page.load_page()
        self.login_page.dev_auth(self.section.instructors[0].uid)
        self.ouija_page.wait_for_title_containing(
            f'Your {self.section.term.name} Course')

    def test_sign_up_link(self):
        self.ouija_page.click_sign_up_page_link(self.section)
        self.sign_up_page.wait_for_diablo_title(
            f'{self.section.code}, {self.section.number}')

    def test_scheduled_status(self):
        msg = 'Recordings have been scheduled but we need approval from you.'
        self.sign_up_page.wait_for_approvals_msg(msg)

    def test_selected_rec_type(self):
        self.sign_up_page.wait_for_element(SignUpPage.RECORDING_TYPE_SCHEDULED,
                                           util.get_short_timeout())
        assert self.sign_up_page.scheduled_rec_type(
        ) == self.recording_schedule.recording_type.value['selection']

    def test_selected_pub_type(self):
        assert self.sign_up_page.scheduled_publish_type(
        ) == self.recording_schedule.publish_type.value

    def test_instructor_agree_terms(self):
        self.sign_up_page.click_agree_checkbox()

    def test_approve(self):
        self.sign_up_page.click_approve_button()
        self.recording_schedule.approval_status = RecordingApprovalStatus.APPROVED

    def test_confirmation(self):
        self.sign_up_page.wait_for_approvals_msg('Approved by you.')

    # VERIFY OUIJA FILTER

    def test_approved_filter_all(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_approved_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_approved_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_approved_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_approved_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # CREATE COURSE SITE

    def test_create_course_site(self):
        self.canvas_page.log_in()
        self.canvas_page.provision_site(self.section, [self.section.ccn],
                                        self.site)

    def test_enable_media_gallery(self):
        if self.canvas_page.is_tool_configured(
                app.config['CANVAS_MEDIA_GALLERY_TOOL']):
            self.canvas_page.load_site(self.site.site_id)
            self.canvas_page.enable_media_gallery(self.site)
            self.canvas_page.click_media_gallery_tool()
        else:
            app.logger.info('Media Gallery is not properly configured')
            raise

    def test_enable_my_media(self):
        if self.canvas_page.is_tool_configured(
                app.config['CANVAS_MY_MEDIA_TOOL']):
            self.canvas_page.load_site(self.site.site_id)
            self.canvas_page.enable_my_media(self.site)
            self.canvas_page.click_my_media_tool()
        else:
            app.logger.info('My Media is not properly configured')
            raise

    def test_run_canvas_and_kaltura_jobs(self):
        self.jobs_page.load_page()
        self.jobs_page.run_canvas_job()
        self.jobs_page.run_kaltura_job()

    def test_visible_site_ids(self):
        self.sign_up_page.load_page(self.section)
        assert self.sign_up_page.visible_course_site_ids() == [
            site.site_id for site in self.section.sites
        ]

    # VERIFY SITE IN KALTURA SERIES

    def test_load_kaltura_series(self):
        self.kaltura_page.load_event_edit_page(
            self.recording_schedule.series_id)
        self.kaltura_page.wait_for_delete_button()

    def test_kaltura_published_status(self):
        self.kaltura_page.wait_for_publish_category_el()
        assert self.kaltura_page.is_published()

    def test_kaltura_course_site_count(self):
        assert len(self.kaltura_page.publish_category_els()) == 1

    def test_kaltura_course_site(self):
        assert self.kaltura_page.is_publish_category_present(self.site)
Beispiel #4
0
class TestCourseRoomChanges:
    real_test_data = util.get_test_script_course('test_course_changes_real')
    fake_test_data = util.get_test_script_course('test_course_changes_fake')
    faker_test_data = util.get_test_script_course('test_course_changes_faker')
    fakest_test_data = util.get_test_script_course(
        'test_course_changes_fakest')
    real_section = util.get_test_section(real_test_data)
    real_meeting = real_section.meetings[0]
    fake_section = Section(fake_test_data)
    fake_meeting = fake_section.meetings[0]
    faker_section = Section(faker_test_data)
    faker_meeting = faker_section.meetings[0]
    fakest_section = Section(fakest_test_data)
    fakest_meeting = fakest_section.meetings[0]
    recording_sched = RecordingSchedule(real_section)

    def test_disable_jobs(self):
        self.login_page.load_page()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.disable_all_jobs()

    def test_delete_old_diablo_and_kaltura(self):
        self.kaltura_page.log_in_via_calnet()
        self.kaltura_page.reset_test_data(self.term, self.recording_sched)
        util.reset_sign_up_test_data(self.real_section)
        self.recording_sched.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_sched.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    def test_admin_emails_pre_run(self):
        self.jobs_page.load_page()
        self.jobs_page.run_admin_emails_job()

    def test_instructor_emails_pre_run(self):
        self.jobs_page.run_instructor_emails_job()

    def test_queued_emails_pre_run(self):
        self.jobs_page.run_queued_emails_job()

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_delete_old_email(self):
        self.email_page.log_in()
        self.email_page.delete_all_messages()

    def test_sign_up(self):
        self.ouija_page.load_page()
        self.ouija_page.log_out()
        self.login_page.dev_auth(self.real_section.instructors[0].uid)
        self.ouija_page.click_sign_up_page_link(self.real_section)
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.sign_up_page.click_agree_checkbox()
        self.sign_up_page.click_approve_button()

    def test_schedule_recordings(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()
        util.get_kaltura_id(self.recording_sched, self.term)

    # SCHEDULED COURSE MOVES TO ANOTHER ELIGIBLE ROOM

    def test_move_to_alt_eligible_room(self):
        util.set_meeting_location(self.real_section, self.fakest_meeting)

    def test_run_admin_email_job_alt_eligible_room(self):
        self.jobs_page.run_admin_emails_job()

    def test_run_instr_email_job_alt_eligible_room(self):
        self.jobs_page.run_instructor_emails_job()

    def test_run_queued_email_job_alt_eligible_room(self):
        self.jobs_page.run_queued_emails_job()

    def test_changes_page_summary_alt_eligible_room(self):
        self.jobs_page.click_course_changes_link()
        self.changes_page.wait_for_course_row(self.real_section)
        expected = 'Room is obsolete.'
        actual = self.changes_page.scheduled_card_summary(self.real_section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_changes_page_old_elig_room(self):
        expected = f'{self.real_meeting.room.name}'
        actual = self.changes_page.scheduled_card_old_room(self.real_section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_changes_page_new_elig_room(self):
        expected = f'{self.fakest_meeting.room.name}'
        actual = self.changes_page.current_card_schedule(self.real_section,
                                                         list_node=None,
                                                         detail_node=None)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    # SCHEDULED COURSE MOVES TO INELIGIBLE ROOM

    def test_move_to_ineligible_room(self):
        util.set_meeting_location(self.real_section, self.fake_meeting)

    def test_run_admin_email_job_ineligible_room(self):
        self.jobs_page.run_admin_emails_job()

    def test_run_instr_email_job_ineligible_room(self):
        self.jobs_page.run_instructor_emails_job()

    def test_run_queued_email_job_ineligible_room(self):
        self.jobs_page.run_queued_emails_job()

    def test_changes_page_summary(self):
        self.jobs_page.click_course_changes_link()
        self.changes_page.wait_for_course_row(self.real_section)
        expected = 'Room is obsolete.'
        actual = self.changes_page.scheduled_card_summary(self.real_section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_changes_page_old_room(self):
        expected = f'{self.real_meeting.room.name}'
        actual = self.changes_page.scheduled_card_old_room(self.real_section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_changes_page_new_room(self):
        expected = f'{self.fake_meeting.room.name}'
        actual = self.changes_page.current_card_schedule(self.real_section,
                                                         list_node=None,
                                                         detail_node=None)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_admin_unsched_ineligible_room(self):
        self.sign_up_page.load_page(self.real_section)
        self.sign_up_page.confirm_unscheduling_ineligible(self.recording_sched)

    def test_changes_page_ineligible_room_unsched(self):
        self.sign_up_page.click_course_changes_link()
        self.changes_page.wait_for_results()
        assert not self.changes_page.is_course_row_present(self.real_section)

    def test_no_kaltura_series_ineligible_room(self):
        self.kaltura_page.load_event_edit_page(self.recording_sched.series_id)
        self.kaltura_page.wait_for_title('Access Denied - UC Berkeley - Test')

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_admin_email_ineligible_room(self):
        subj = f'Course Capture Admin: {self.real_section.code} has moved to {self.fake_meeting.room.name}'
        email = Email(msg_type=None, subject=subj, sender=None)
        assert self.email_page.is_message_delivered(email)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_instructor_email_ineligible_room(self):
        subj = f'Your course {self.real_section.code} is no longer eligible for Course Capture'
        email = Email(msg_type=None, subject=subj, sender=None)
        assert self.email_page.is_message_delivered(email)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_instructor_email_alt_eligible_room(self):
        subj = f'Your course {self.real_section.code} is no longer eligible for Course Capture'
        email = Email(msg_type=None, subject=subj, sender=None)
        assert len(self.email_page.message_rows(email)) == 1

    # ROOM REMOVED

    def test_reset_data_null_test(self):
        util.reset_sign_up_test_data(self.real_section)
        self.recording_sched.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_sched.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    def test_sign_up_null_test(self):
        self.ouija_page.load_page()
        self.ouija_page.log_out()
        self.login_page.dev_auth(self.real_section.instructors[0].uid)
        self.ouija_page.click_sign_up_page_link(self.real_section)
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.sign_up_page.click_agree_checkbox()
        self.sign_up_page.click_approve_button()

    def test_schedule_recordings_null_test(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()
        util.get_kaltura_id(self.recording_sched, self.term)

    def test_move_to_null_room(self):
        self.faker_meeting.room = None
        util.change_course_room(self.real_section,
                                old_room=self.real_meeting.room,
                                new_room=None)

    def test_run_admin_email_job_null_room(self):
        self.jobs_page.load_page()
        self.jobs_page.run_admin_emails_job()

    def test_run_instr_email_job_null_room(self):
        self.jobs_page.run_instructor_emails_job()

    def test_run_queued_email_job_null_room(self):
        self.jobs_page.run_queued_emails_job()

    def test_null_room_changes_page_summary(self):
        self.jobs_page.click_course_changes_link()
        self.changes_page.wait_for_results()
        assert not self.changes_page.is_course_row_present(self.real_section)
class TestWeirdTypeD:

    test_data = util.get_test_script_course('test_weird_type_d')
    section = util.get_test_section(test_data)
    meeting_0 = section.meetings[0]
    meeting_1 = section.meetings[1]
    recording_schedule = RecordingSchedule(section)

    def test_disable_jobs(self):
        self.login_page.load_page()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.disable_all_jobs()

    def test_delete_old_diablo_and_kaltura(self):
        if util.get_kaltura_id(self.recording_schedule, self.section.term):
            self.kaltura_page.log_in_via_calnet()
            self.kaltura_page.reset_test_data(self.term,
                                              self.recording_schedule)
        util.reset_sign_up_test_data(self.section)
        self.recording_schedule.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_delete_old_email(self):
        self.email_page.log_in()
        self.email_page.delete_all_messages()

    # COURSE APPEARS ON 'NOT INVITED' FILTER

    def test_not_invited_filter_not_invited(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_not_invited_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_not_invited_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    # RUN JOBS AND VERIFY NO INVITE

    def test_no_invite_button(self):
        self.ouija_page.click_sign_up_page_link(self.section)
        self.sign_up_page.wait_for_diablo_title(
            f'{self.section.code}, {self.section.number}')
        assert not self.sign_up_page.is_present(SignUpPage.SEND_INVITE_BUTTON)

    def test_send_invite_email(self):
        self.jobs_page.load_page()
        self.jobs_page.run_invitations_job()
        self.jobs_page.run_queued_emails_job()
        self.recording_schedule.approval_status = RecordingApprovalStatus.INVITED

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_receive_invite_email(self):
        subj = f'Invitation {self.section.term.name} {self.section.code} (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert not self.email_page.is_message_delivered(expected_message)

    # INSTRUCTOR LOGS IN

    def test_home_page(self):
        self.ouija_page.load_page()
        self.ouija_page.log_out()
        self.login_page.dev_auth(self.section.instructors[0].uid)
        self.ouija_page.wait_for_title_containing(
            f'Your {self.section.term.name} Course')

    def test_sign_up_link(self):
        self.ouija_page.click_sign_up_page_link(self.section)
        self.sign_up_page.wait_for_diablo_title(
            f'{self.section.code}, {self.section.number}')

    # VERIFY STATIC COURSE SIS DATA

    def test_visible_ccn(self):
        assert self.sign_up_page.visible_ccn() == self.section.ccn

    def test_visible_course_title(self):
        assert self.sign_up_page.visible_course_title() == self.section.title

    def test_visible_instructors(self):
        instructor = self.section.instructors[0]
        instructor_names = [f'{instructor.first_name} {instructor.last_name}']
        assert self.sign_up_page.visible_instructors() == instructor_names

    def test_visible_meeting_0_days(self):
        term_dates = f'{SignUpPage.expected_term_date_str(self.meeting_0.record_start, self.meeting_0.record_end)}'
        assert term_dates in self.sign_up_page.visible_meeting_days()[0]

    def test_visible_meeting_0_time(self):
        assert self.sign_up_page.visible_meeting_time(
        )[0] == f'{self.meeting_0.start_time} - {self.meeting_0.end_time}'

    def test_visible_meeting_0_room(self):
        assert self.sign_up_page.visible_rooms()[0] == self.meeting_0.room.name

    def test_visible_meeting_1_days(self):
        term_dates = f'{SignUpPage.expected_term_date_str(self.meeting_1.record_start, self.meeting_1.record_end)}'
        assert term_dates in self.sign_up_page.visible_meeting_days()[1]

    def test_visible_meeting_1_time(self):
        assert self.sign_up_page.visible_meeting_time(
        )[1] == f'{self.meeting_1.start_time} - {self.meeting_1.end_time}'

    def test_visible_meeting_1_room(self):
        assert self.sign_up_page.visible_rooms()[1] == self.meeting_1.room.name

    # COURSE CANNOT BE SCHEDULED

    def test_no_auto_scheduling(self):
        assert self.sign_up_page.is_present(SignUpPage.NO_AUTO_SCHED_MSG)
        assert not self.sign_up_page.is_present(SignUpPage.APPROVE_BUTTON)
class TestCourseScheduleChanges:
    real_test_data = util.get_test_script_course('test_course_changes_real')
    fake_test_data = util.get_test_script_course('test_course_changes_fake')
    faker_test_data = util.get_test_script_course('test_course_changes_faker')
    real_section = util.get_test_section(real_test_data)
    real_meeting = real_section.meetings[0]
    fake_section = Section(fake_test_data)
    fake_meeting = fake_section.meetings[0]
    faker_section = Section(faker_test_data)
    faker_meeting = faker_section.meetings[0]
    recording_sched = RecordingSchedule(real_section)

    def test_disable_jobs(self):
        self.login_page.load_page()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.disable_all_jobs()

    def test_delete_old_diablo_and_kaltura(self):
        self.kaltura_page.log_in_via_calnet()
        self.kaltura_page.reset_test_data(self.term, self.recording_sched)
        util.reset_sign_up_test_data(self.real_section)
        self.recording_sched.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_sched.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    def test_admin_emails_pre_run(self):
        self.jobs_page.load_page()
        self.jobs_page.run_admin_emails_job()

    def test_instructor_emails_pre_run(self):
        self.jobs_page.run_instructor_emails_job()

    def test_queued_emails_pre_run(self):
        self.jobs_page.run_queued_emails_job()

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_delete_old_email(self):
        self.email_page.log_in()
        self.email_page.delete_all_messages()

    def test_sign_up(self):
        self.ouija_page.load_page()
        self.ouija_page.log_out()
        self.login_page.dev_auth(self.real_section.instructors[0].uid)
        self.ouija_page.click_sign_up_page_link(self.real_section)
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.sign_up_page.click_agree_checkbox()
        self.sign_up_page.click_approve_button()

    def test_schedule_recordings(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()
        util.get_kaltura_id(self.recording_sched, self.term)

    def test_run_admin_email_job_post_scheduling(self):
        self.jobs_page.run_admin_emails_job()

    def test_run_queued_email_job_post_scheduling(self):
        self.jobs_page.run_queued_emails_job()

    # SCHEDULED COURSE CHANGES MEETING TIME

    def test_set_fake_meeting_time(self):
        util.set_course_meeting_time(self.real_section, self.fake_meeting)

    def test_run_admin_email_job_with_new_times(self):
        self.jobs_page.load_page()
        self.jobs_page.run_admin_emails_job()

    def test_run_queued_email_job_with_new_times(self):
        self.jobs_page.run_queued_emails_job()

    def test_changes_page_summary(self):
        self.jobs_page.click_course_changes_link()
        self.changes_page.wait_for_course_row(self.real_section)
        expected = 'Times are obsolete.'
        actual = self.changes_page.scheduled_card_summary(self.real_section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_changes_page_old_room(self):
        expected = self.real_meeting.room.name
        actual = self.changes_page.scheduled_card_old_room(self.real_section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_changes_page_old_sched(self):
        dates = self.real_meeting.expected_recording_dates(
            self.real_section.term)
        start = dates[0]
        end = dates[-1]
        dates = f'{start.strftime("%Y-%m-%d")} to {end.strftime("%Y-%m-%d")}'
        days = self.real_meeting.days.replace(' ', '').replace(',', '')
        days_times = f'{days}, {CourseChangesPage.meeting_time_str(self.real_meeting)}'
        expected = f'{dates}{days_times}'.upper()
        actual = self.changes_page.scheduled_card_old_schedule(
            self.real_section).upper()
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_changes_page_new_sched(self):
        dates = self.real_meeting.expected_recording_dates(
            self.real_section.term)
        start = dates[0]
        end = dates[-1]
        dates = f'{start.strftime("%Y-%m-%d")} to {end.strftime("%Y-%m-%d")}'
        days = self.real_meeting.days.replace(' ', '').replace(',', '')
        days_times = f'{days}, {CourseChangesPage.meeting_time_str(self.fake_meeting)}'
        expected = f'{dates}{days_times}'.upper()
        actual = self.changes_page.current_card_schedule(
            self.real_section, 1, 2).upper()
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_admin_email_received(self):
        subj = f'Course Capture Admin: {self.real_section.code} schedule change'
        email = Email(msg_type=None, subject=subj, sender=None)
        assert self.email_page.is_message_delivered(email)

    def test_admin_unsched_new_times(self):
        self.sign_up_page.load_page(self.real_section)
        self.sign_up_page.confirm_unscheduling(self.recording_sched)

    def test_changes_page_unsched(self):
        self.sign_up_page.click_course_changes_link()
        self.changes_page.wait_for_results()
        assert not self.changes_page.is_course_row_present(self.real_section)

    def test_admin_resched_new_times(self):
        self.sign_up_page.load_page(self.real_section)
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.sign_up_page.click_approve_button()

    def test_run_jobs_with_resched(self):
        self.sign_up_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()

    def test_verify_old_kaltura_series_gone(self):
        self.kaltura_page.load_event_edit_page(self.recording_sched.series_id)
        self.kaltura_page.wait_for_title('Access Denied - UC Berkeley - Test')

    def test_verify_new_kaltura_series_id(self):
        util.get_kaltura_id(self.recording_sched, self.term)

    def test_verify_new_kaltura_series(self):
        self.sign_up_page.load_page(self.real_section)
        self.sign_up_page.click_kaltura_series_link(self.recording_sched)
        self.kaltura_page.wait_for_delete_button()
        expected = f'{self.real_section.code}, {self.real_section.number} ({self.real_section.term.name})'
        assert self.kaltura_page.visible_series_title() == expected

    def test_verify_new_kaltura_days(self):
        self.kaltura_page.open_recurrence_modal()
        mon_checked = self.kaltura_page.is_mon_checked()
        tue_checked = self.kaltura_page.is_tue_checked()
        wed_checked = self.kaltura_page.is_wed_checked()
        thu_checked = self.kaltura_page.is_thu_checked()
        fri_checked = self.kaltura_page.is_fri_checked()
        assert mon_checked if 'MO' in self.real_meeting.days else not mon_checked
        assert tue_checked if 'TU' in self.real_meeting.days else not tue_checked
        assert wed_checked if 'WE' in self.real_meeting.days else not wed_checked
        assert thu_checked if 'TH' in self.real_meeting.days else not thu_checked
        assert fri_checked if 'FR' in self.real_meeting.days else not fri_checked
        assert not self.kaltura_page.is_sat_checked()
        assert not self.kaltura_page.is_sun_checked()

    def test_verify_new_kaltura_times(self):
        start = self.fake_meeting.get_berkeley_start_time()
        visible_start = datetime.strptime(
            self.kaltura_page.visible_start_time(), '%I:%M %p')
        assert visible_start == start
        end = self.fake_meeting.get_berkeley_end_time()
        visible_end = datetime.strptime(self.kaltura_page.visible_end_time(),
                                        '%I:%M %p')
        assert visible_end == end

    # SCHEDULED COURSE MEETING START/END AND MEETING DAYS/TIMES CHANGE TO NULL

    def test_set_null_start_end_dates(self):
        self.faker_meeting.start_date = None
        self.faker_meeting.end_date = None
        util.update_course_start_end_dates(self.real_section,
                                           self.real_meeting.room,
                                           start=None,
                                           end=None)

    def test_set_null_meeting_days(self):
        self.faker_meeting.days = None
        util.set_course_meeting_days(self.real_section, self.faker_meeting)

    def test_set_null_meeting_times(self):
        self.faker_meeting.start_time = None
        self.faker_meeting.end_time = None
        util.set_course_meeting_time(self.real_section, self.faker_meeting)

    def test_run_admin_email_job_with_null_dates(self):
        self.jobs_page.load_page()
        self.jobs_page.run_admin_emails_job()

    def test_run_queued_email_job_with_null_dates(self):
        self.jobs_page.run_queued_emails_job()

    def test_changes_page_summary_with_null_dates(self):
        self.jobs_page.click_course_changes_link()
        self.changes_page.wait_for_course_row(self.real_section)
        expected = 'Dates and times are obsolete.'
        actual = self.changes_page.scheduled_card_summary(self.real_section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_changes_page_null_dates_old_sched(self):
        dates = self.real_meeting.expected_recording_dates(
            self.real_section.term)
        start = dates[0]
        end = dates[-1]
        dates = f'{start.strftime("%Y-%m-%d")} to {end.strftime("%Y-%m-%d")}'
        days = self.real_meeting.days.replace(' ', '').replace(',', '')
        days_times = f'{days}, {CourseChangesPage.meeting_time_str(self.fake_meeting)}'
        expected = f'{dates}{days_times}'.upper()
        actual = self.changes_page.scheduled_card_old_schedule(
            self.real_section).upper()
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_changes_page_null_dates_new_sched(self):
        expected = 'TO, -'
        actual = self.changes_page.current_card_schedule(
            self.real_section, 1, 2).upper()
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_null_dates_admin_email_received(self):
        subj = f'Course Capture Admin: {self.real_section.code} schedule change'
        email = Email(msg_type=None, subject=subj, sender=None)
        assert self.email_page.is_message_delivered(email)

    def test_admin_unsched_null_dates(self):
        self.sign_up_page.load_page(self.real_section)
        self.sign_up_page.confirm_unscheduling(self.recording_sched)

    def test_changes_page_null_dates_unsched(self):
        self.sign_up_page.click_course_changes_link()
        self.changes_page.wait_for_results()
        assert not self.changes_page.is_course_row_present(self.real_section)
Beispiel #7
0
class TestCrossListings:

    test_data = util.get_test_script_course('test_x_listings')
    sections = util.get_test_x_listed_sections(test_data)
    section = sections[0]
    x_listed_section = sections[1]
    meeting = section.meetings[0]
    recording_schedule = RecordingSchedule(section)
    site_1 = CanvasSite(
        code=f'XENA X-Listing One - {section.code}',
        name=f'XENA X-Listing One - {section.code}',
        site_id=None,
    )
    site_2 = CanvasSite(
        code=f'XENA X-Listing Two - {x_listed_section.code}',
        name=f'XENA X-Listing Two - {x_listed_section.code}',
        site_id=None,
    )

    # DELETE PRE-EXISTING DATA AND MAKE SURE THE CROSS-LISTED COURSE IS IN A ROOM WITH A KALTURA RESOURCE

    def test_disable_jobs(self):
        self.login_page.load_page()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_queued_emails_job()
        self.jobs_page.run_canvas_job()
        self.jobs_page.disable_all_jobs()

    def test_delete_old_kaltura_series(self):
        self.kaltura_page.log_in_via_calnet()
        self.kaltura_page.reset_test_data(self.term, self.recording_schedule)

    def test_delete_old_canvas_sites(self):
        ids = []
        for section in self.sections:
            ids.append(self.canvas_page.delete_section_sites(section))
        if any(ids):
            self.jobs_page.load_page()
            self.jobs_page.run_canvas_job()

    def test_delete_old_diablo_data(self):
        util.reset_sign_up_test_data(self.section)
        util.delete_sis_sections_rows(self.x_listed_section)
        util.add_sis_sections_rows(self.x_listed_section)
        self.recording_schedule.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_delete_old_email(self):
        self.email_page.log_in()
        self.email_page.delete_all_messages()

    # CREATE A COURSE SITE FOR EACH OF THE LISTINGS

    def test_create_course_site_one(self):
        self.canvas_page.provision_site(self.section, [self.section.ccn],
                                        self.site_1)

    def test_enable_media_gallery_1(self):
        if self.canvas_page.is_tool_configured(
                app.config['CANVAS_MEDIA_GALLERY_TOOL']):
            self.canvas_page.load_site(self.site_1.site_id)
            self.canvas_page.enable_media_gallery(self.site_1)
            self.canvas_page.click_media_gallery_tool()
        else:
            app.logger.info('Media Gallery is not properly configured')
            raise

    def test_enable_my_media_1(self):
        if self.canvas_page.is_tool_configured(
                app.config['CANVAS_MY_MEDIA_TOOL']):
            self.canvas_page.load_site(self.site_1.site_id)
            self.canvas_page.enable_my_media(self.site_1)
            self.canvas_page.click_my_media_tool()
        else:
            app.logger.info('My Media is not properly configured')
            raise

    def test_create_course_site_two(self):
        self.canvas_page.provision_site(self.x_listed_section,
                                        [self.x_listed_section.ccn],
                                        self.site_2)

    def test_enable_media_gallery_2(self):
        if self.canvas_page.is_tool_configured(
                app.config['CANVAS_MEDIA_GALLERY_TOOL']):
            self.canvas_page.load_site(self.site_2.site_id)
            self.canvas_page.enable_media_gallery(self.site_2)
            self.canvas_page.click_media_gallery_tool()
        else:
            app.logger.info('Media Gallery is not properly configured')
            raise

    def test_enable_my_media_2(self):
        if self.canvas_page.is_tool_configured(
                app.config['CANVAS_MY_MEDIA_TOOL']):
            self.canvas_page.load_site(self.site_2.site_id)
            self.canvas_page.enable_my_media(self.site_2)
            self.canvas_page.click_my_media_tool()
        else:
            app.logger.info('My Media is not properly configured')
            raise

    def test_run_canvas_job(self):
        self.jobs_page.load_page()
        self.jobs_page.run_canvas_job()

    def test_visible_site_ids(self):
        self.sign_up_page.load_page(self.section)
        assert self.sign_up_page.visible_course_site_ids() == [
            self.site_1.site_id, self.site_2.site_id
        ]

    # INSTRUCTORS FOLLOW SIGN UP WORKFLOW

    def test_instructor_home(self):
        self.ouija_page.load_page()
        self.ouija_page.log_out()
        self.login_page.dev_auth(self.section.instructors[0].uid)
        self.ouija_page.wait_for_course_results()
        for section in self.sections:
            assert section.code in self.ouija_page.course_row_code_el(
                self.section).get_attribute('innerText')

    def test_hit_listing(self):
        self.sign_up_page.hit_url(self.x_listed_section.term.id,
                                  self.x_listed_section.ccn)
        self.sign_up_page.wait_for_404()

    def test_view_sign_up_page(self):
        self.ouija_page.load_instructor_view()
        self.ouija_page.click_sign_up_page_link(self.section)
        self.sign_up_page.wait_for_diablo_title(
            f'{self.section.code}, {self.section.number}')
        assert self.sign_up_page.visible_heading(
        ) == f'{self.section.code}, {self.section.number}'

    def test_verify_sign_up_page_listings(self):
        expected = [
            f'{self.x_listed_section.code}, {self.x_listed_section.number}'
        ]
        visible = self.sign_up_page.visible_cross_listing_codes()
        assert visible == expected

    def test_approve_inst_1(self):
        self.sign_up_page.select_publish_type(PublishType.KALTURA.value)
        self.sign_up_page.click_agree_checkbox()
        self.sign_up_page.click_approve_button()

    def test_approve_inst_2(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth(self.section.instructors[1].uid)
        self.ouija_page.click_sign_up_page_link(self.section)
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.sign_up_page.click_agree_checkbox()
        self.sign_up_page.click_approve_button()
        self.recording_schedule.approval_status = RecordingApprovalStatus.APPROVED

    def test_schedule_recordings(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()
        util.get_kaltura_id(self.recording_schedule, self.term)

    def test_click_series_link(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.click_kaltura_series_link(self.recording_schedule)
        self.kaltura_page.wait_for_delete_button()

    def test_series_title(self):
        listing_codes = [
            f'{listing.code}, {self.section.number}'
            for listing in self.section.listings
        ]
        listing_codes.append(f'{self.section.code}, {self.section.number}')
        for code in listing_codes:
            assert code in self.kaltura_page.visible_series_title()

    def test_kaltura_publish_status(self):
        self.kaltura_page.wait_for_publish_category_el()
        assert self.kaltura_page.is_published()

    def test_kaltura_course_site_count_two(self):
        assert len(self.kaltura_page.publish_category_els()) == 4

    def test_kaltura_course_sites(self):
        assert self.kaltura_page.is_publish_category_present(self.site_1)
        assert self.kaltura_page.is_publish_category_present(self.site_2)

    # VERIFY AUTO-EMAILS

    def test_send_emails(self):
        self.jobs_page.load_page()
        self.jobs_page.run_invitations_job()
        self.jobs_page.run_instructor_emails_job()
        self.jobs_page.run_queued_emails_job()
        self.recording_schedule.approval_status = RecordingApprovalStatus.INVITED

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_invite_inst_1(self):
        subj = f'Invitation {self.section.term.name} {self.section.code} (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_delivered(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_invite_inst_2(self):
        subj = f'Invitation {self.section.term.name} {self.section.code} (To: {self.section.instructors[1].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_present(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_no_dupe_invite_inst_1(self):
        subj = f'Invitation {self.section.term.name} {self.section.listings[0].code} (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert not self.email_page.is_message_present(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_awaiting_approval_inst_1(self):
        subj = f'Course Capture: {self.section.code} waiting on approval (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_present(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_no_awaiting_approval_inst_2(self):
        subj = f'Course Capture: {self.section.code} waiting on approval (To: {self.section.instructors[1].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert not self.email_page.is_message_present(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_no_dupe_awaiting_approval_inst_1(self):
        subj = f'Course Capture: {self.section.listings[0].code} waiting on approval (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert not self.email_page.is_message_present(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_notify_of_changes_inst_1(self):
        subj = f'Changes to your Course Capture settings for {self.section.code} (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_present(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_no_notify_of_changes_inst_2(self):
        subj = f'Changes to your Course Capture settings for {self.section.code} (To: {self.section.instructors[1].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert not self.email_page.is_message_present(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_no_dupe_notify_of_changes_inst_1(self):
        subj = f'Changes to your Course Capture settings for {self.section.listings[0].code} (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert not self.email_page.is_message_present(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_schedule_conf_inst_1(self):
        subj = f'Your course, {self.section.code}, has been scheduled for Course Capture (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_present(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_schedule_conf_inst_2(self):
        subj = f'Your course, {self.section.code}, has been scheduled for Course Capture (To: {self.section.instructors[1].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_present(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_no_dupe_schedule_conf_inst_1(self):
        subj = f'Your course, {self.section.listings[0].code}, has been scheduled for Course Capture (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert not self.email_page.is_message_present(expected_message)

    # DELETE SECONDARY LISTING

    def test_delete_secondary_listing(self):
        util.delete_section(self.x_listed_section)

    def test_not_canceled(self):
        self.sign_up_page.load_page(self.section)
        assert not self.sign_up_page.is_canceled()

    def test_no_x_listing(self):
        assert not self.sign_up_page.visible_cross_listing_ccns()

    def test_no_course_changes(self):
        self.changes_page.load_page()
        self.changes_page.wait_for_results()
        assert not self.changes_page.is_course_row_present(self.section)

    # RESTORE SECONDARY LISTING

    def test_restore_secondary(self):
        util.restore_section(self.x_listed_section)

    def test_restored_x_listing(self):
        self.sign_up_page.load_page(self.section)
        expected = [
            f'{self.x_listed_section.code}, {self.x_listed_section.number}'
        ]
        visible = self.sign_up_page.visible_cross_listing_codes()
        assert visible == expected

    # DELETE PRIMARY LISTING

    def test_delete_primary_listing(self):
        util.delete_section(self.section)

    def test_canceled(self):
        self.sign_up_page.load_page(self.section)
        assert self.sign_up_page.is_canceled()

    def test_x_listing(self):
        expected = [
            f'{self.x_listed_section.code}, {self.x_listed_section.number}'
        ]
        visible = self.sign_up_page.visible_cross_listing_codes()
        assert visible == expected

    def test_course_changes(self):
        self.changes_page.load_page()
        self.changes_page.wait_for_results()
        assert self.changes_page.is_course_row_present(self.section)
Beispiel #8
0
class TestUnschedule:

    test_data = util.get_test_script_course('test_unschedule')
    section = Section(test_data)
    recording_schedule = RecordingSchedule(section)

    # DELETE PRE-EXISTING DATA

    def test_disable_jobs(self):
        self.login_page.load_page()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.disable_all_jobs()

    def test_delete_old_kaltura_series(self):
        self.kaltura_page.log_in_via_calnet()
        self.kaltura_page.reset_test_data(self.term, self.recording_schedule)

    def test_delete_old_diablo_data(self):
        util.reset_sign_up_test_data(self.test_data)
        util.set_meeting_location(self.section, self.section.meetings[0])
        self.recording_schedule.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    # ADMIN QUEUES COURSE FOR SCHEDULING AND UN-SCHEDULES PRIOR TO SERIES CREATION IN KALTURA

    def test_admin_approve(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.select_rec_type(
            RecordingType.SCREENCAST.value['option'])
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.sign_up_page.click_approve_button()

    def test_admin_queued_for_scheduling(self):
        self.sign_up_page.wait_for_approvals_msg(
            'This course is currently queued for scheduling')

    def test_unschedule_queued_cancel(self):
        self.sign_up_page.cancel_unscheduling()

    def test_unschedule_queued(self):
        self.sign_up_page.confirm_unscheduling(self.recording_schedule)

    def test_unschedule_queued_opted_out(self):
        assert self.sign_up_page.is_opted_out()

    def test_unschedule_queued_job_run(self):
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()
        assert not util.get_kaltura_id(self.recording_schedule, self.term)

    # VERIFY FILTERS

    def test_unsched_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_unsched_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_unsched_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_unsched_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_unsched_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_unsched_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_unsched_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_unsched_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_unsched_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # INSTRUCTOR SIGNS UP AND RECORDINGS ARE QUEUED FOR SCHEDULING

    def test_hit_sign_up(self):
        self.ouija_page.load_page()
        self.ouija_page.log_out()
        self.login_page.dev_auth(self.section.instructors[0].uid)
        self.ouija_page.click_sign_up_page_link(self.section)

    def test_sign_up(self):
        self.sign_up_page.select_rec_type(RecordingType.VIDEO.value['option'])
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.sign_up_page.click_agree_checkbox()
        self.sign_up_page.click_approve_button()

    def test_confirmation(self):
        self.sign_up_page.wait_for_approvals_msg(
            'This course is currently queued for scheduling')

    def test_schedule_recordings(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()
        util.get_kaltura_id(self.recording_schedule, self.term)

    # SERIES IS CREATED IN KALTURA

    def test_click_series_link(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.click_kaltura_series_link(self.recording_schedule)
        self.kaltura_page.wait_for_delete_button()

    def test_series_title(self):
        expected = f'{self.section.code}, {self.section.number} ({self.term.name})'
        assert self.kaltura_page.visible_series_title() == expected

    def test_close_kaltura_window(self):
        self.kaltura_page.close_window_and_switch()

    # ADMIN UN-SCHEDULES THE COURSE

    def test_unschedule_confirm(self):
        self.sign_up_page.confirm_unscheduling(self.recording_schedule)

    def test_opted_out_sign_up(self):
        assert self.sign_up_page.is_opted_out()

    def test_series_deleted(self):
        self.kaltura_page.load_event_edit_page(
            self.recording_schedule.series_id)
        self.kaltura_page.wait_for_title('Access Denied - UC Berkeley - Test')

    # VERIFY FILTERS

    def test_unsched_again_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_unsched_again_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_unsched_again_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_unsched_again_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_unsched_again_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_unsched_again_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_unsched_again_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_unsched_again_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_unsched_again_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False
class TestCourseInstructorChanges:

    real_test_data = util.get_test_script_course('test_course_changes_real')
    fake_test_data = util.get_test_script_course('test_course_changes_fake')
    real_section = Section(real_test_data)
    real_meeting = real_section.meetings[0]
    fake_section = Section(fake_test_data)
    fake_meeting = fake_section.meetings[0]
    recording_sched = RecordingSchedule(real_section)

    def test_disable_jobs(self):
        self.login_page.load_page()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.disable_all_jobs()

    def test_delete_old_diablo_and_kaltura(self):
        self.kaltura_page.log_in_via_calnet()
        self.kaltura_page.reset_test_data(self.term, self.recording_sched)
        util.reset_sign_up_test_data(self.real_test_data)
        self.recording_sched.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_sched.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    def test_sis_data_refresh_pre_run(self):
        self.jobs_page.load_page()
        self.jobs_page.run_sis_data_refresh_job()

    def test_admin_emails_pre_run(self):
        self.jobs_page.run_admin_emails_job()

    def test_instructor_emails_pre_run(self):
        self.jobs_page.run_instructor_emails_job()

    def test_queued_emails_pre_run(self):
        self.jobs_page.run_queued_emails_job()

    def test_delete_old_email(self):
        self.email_page.log_in()
        self.email_page.delete_all_messages()

    # SCHEDULED COURSE CHANGES INSTRUCTOR

    def test_set_room(self):
        util.set_meeting_location(self.real_section, self.real_meeting)

    def test_set_fake_instr(self):
        util.change_course_instructor(self.fake_section,
                                      self.real_section.instructors[0],
                                      self.fake_section.instructors[0])

    def test_sign_up_with_fake_instr(self):
        self.ouija_page.load_page()
        self.ouija_page.log_out()
        self.login_page.dev_auth(self.fake_section.instructors[0].uid)
        self.ouija_page.click_sign_up_page_link(self.fake_section)
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.sign_up_page.click_agree_checkbox()
        self.sign_up_page.click_approve_button()

    def test_schedule_recordings_with_fake_instr(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()
        util.get_kaltura_id(self.recording_sched, self.term)

    def test_run_sis_job_to_revert_to_real_instr(self):
        self.jobs_page.run_sis_data_refresh_job()

    def test_reset_room(self):
        util.set_meeting_location(self.real_section, self.real_meeting)

    def test_run_admin_email_job_with_instr_change(self):
        self.jobs_page.run_admin_emails_job()

    def test_run_queued_email_job_with_instr_change(self):
        self.jobs_page.run_queued_emails_job()

    def test_changes_page_summary(self):
        self.jobs_page.click_course_changes_link()
        self.changes_page.wait_for_course_row(self.real_section)
        expected = 'Instructors are obsolete.'
        actual = self.changes_page.scheduled_card_summary(self.real_section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_changes_page_old_instructor(self):
        fake_instr_name = f'{self.fake_section.instructors[0].first_name} {self.fake_section.instructors[0].last_name}'
        expected = f'{fake_instr_name} ({self.fake_section.instructors[0].uid})'
        actual = self.changes_page.scheduled_card_old_instructors(
            self.real_section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_changes_page_new_instructor(self):
        real_instr_name = f'{self.real_section.instructors[0].first_name} {self.real_section.instructors[0].last_name}'
        expected = f'{real_instr_name} ({self.real_section.instructors[0].uid})'
        actual = self.changes_page.current_card_instructors(self.real_section,
                                                            node=None)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    # CHECK FILTERS AND ADMIN EMAIL

    def test_not_invited_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.real_section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.real_section) is True

    def test_not_invited_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.real_section).text.strip()
        assert visible_status == self.recording_sched.approval_status.value

    def test_not_invited_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.real_section).text.strip()
        assert visible_status == self.recording_sched.scheduling_status.value

    def test_not_invited_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.real_section) is False

    def test_not_invited_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.real_section) is False

    def test_not_invited_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.real_section) is False

    def test_not_invited_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.real_section) is False

    def test_not_invited_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.real_section) is False

    def test_not_invited_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.real_section) is True

    def test_note_invited_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.real_section) is False

    def test_admin_emails_with_instr_change(self):
        subj = f'Course Capture Admin: {self.real_section.code} Instructor changes'
        email = Email(msg_type=None, subject=subj, sender=None)
        assert self.email_page.is_message_delivered(email)

    # UNSCHEDULE AND RESCHEDULE

    def test_unschedule_confirm(self):
        self.sign_up_page.load_page(self.real_section)
        self.sign_up_page.confirm_unscheduling(self.recording_sched)

    def test_changes_page_course_gone(self):
        self.changes_page.load_page()
        self.changes_page.wait_for_results()
        assert not self.changes_page.is_course_row_present(self.real_section)

    def test_real_instr_approves(self):
        self.ouija_page.load_page()
        self.ouija_page.log_out()
        self.login_page.dev_auth(self.real_section.instructors[0].uid)
        self.ouija_page.click_sign_up_page_link(self.real_section)
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.sign_up_page.click_agree_checkbox()
        self.sign_up_page.click_approve_button()

    def test_update_recordings_with_new_instr(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.changes_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()

    def test_new_series_in_kaltura(self):
        util.get_kaltura_id(self.recording_sched, self.term)
        self.sign_up_page.load_page(self.real_section)
        self.sign_up_page.click_kaltura_series_link(self.recording_sched)
        self.kaltura_page.wait_for_delete_button()

    def test_series_collab_count(self):
        assert len(self.kaltura_page.collaborator_rows()) == len(
            self.real_section.instructors)

    def test_series_collab_rights(self):
        for instr in self.real_section.instructors:
            assert self.kaltura_page.collaborator_perm(instr) == 'Co-Editor'
class TestSignUp0:
    test_data = util.get_test_script_course('test_sign_up_0')
    section = util.get_test_section(test_data)
    meeting = section.meetings[0]
    recording_schedule = RecordingSchedule(section)
    site = CanvasSite(
        code=f'XENA SignUp0 - {section.code}',
        name=f'XENA SignUp0 - {section.code}',
        site_id=None,
    )

    # DELETE PRE-EXISTING DATA

    def test_disable_jobs(self):
        self.login_page.load_page()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_queued_emails_job()
        self.jobs_page.disable_all_jobs()

    def test_create_blackouts(self):
        self.jobs_page.click_blackouts_link()
        self.blackouts_page.delete_all_blackouts()
        self.blackouts_page.create_all_blackouts()

    def test_delete_old_diablo_and_kaltura(self):
        self.kaltura_page.log_in_via_calnet()
        self.kaltura_page.reset_test_data(self.term, self.recording_schedule)
        util.reset_sign_up_test_data(self.section)
        self.recording_schedule.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    def test_run_initial_canvas_job(self):
        self.jobs_page.load_page()
        self.jobs_page.run_canvas_job()

    def test_delete_old_canvas_sites(self):
        self.canvas_page.delete_section_sites(self.section)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_delete_old_email(self):
        self.email_page.log_in()
        self.email_page.delete_all_messages()

    # CREATE COURSE SITE

    def test_create_course_site(self):
        self.canvas_page.provision_site(self.section, [self.section.ccn], self.site)

    def test_enable_media_gallery(self):
        if self.canvas_page.is_tool_configured(app.config['CANVAS_MEDIA_GALLERY_TOOL']):
            self.canvas_page.load_site(self.site.site_id)
            self.canvas_page.enable_media_gallery(self.site)
            self.canvas_page.click_media_gallery_tool()
        else:
            app.logger.info('Media Gallery is not properly configured')
            raise

    def test_enable_my_media(self):
        if self.canvas_page.is_tool_configured(app.config['CANVAS_MY_MEDIA_TOOL']):
            self.canvas_page.load_site(self.site.site_id)
            self.canvas_page.enable_my_media(self.site)
            self.canvas_page.click_my_media_tool()
        else:
            app.logger.info('My Media is not properly configured')
            raise

    def test_run_canvas_job(self):
        self.jobs_page.load_page()
        self.jobs_page.run_canvas_job()

    # CHECK FILTERS - NOT INVITED

    def test_not_invited_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_not_invited_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_not_invited_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_not_invited_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_not_invited_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # RUN JOBS AND VERIFY INVITE

    def test_send_invite_email(self):
        self.jobs_page.load_page()
        self.jobs_page.run_invitations_job()
        self.jobs_page.run_queued_emails_job()
        self.recording_schedule.approval_status = RecordingApprovalStatus.INVITED

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_receive_invite_email(self):
        subj = f'Invitation {self.section.term.name} {self.section.code} (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_delivered(expected_message)

    # CHECK FILTERS - INVITED

    def test_invited_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_invited_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_invited_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_invited_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_invited_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # INSTRUCTOR LOGS IN

    def test_home_page(self):
        self.ouija_page.log_out()
        self.sign_up_page.hit_url(self.term.id, self.section.ccn)
        self.login_page.dev_auth(self.section.instructors[0].uid)
        self.sign_up_page.wait_for_diablo_title(f'{self.section.code}, {self.section.number}')

    # VERIFY STATIC COURSE SIS DATA

    def test_visible_ccn(self):
        assert self.sign_up_page.visible_ccn() == self.section.ccn

    def test_visible_course_title(self):
        assert self.sign_up_page.visible_course_title() == self.section.title

    def test_visible_instructors(self):
        instructor_names = [f'{i.first_name} {i.last_name}' for i in self.section.instructors]
        assert self.sign_up_page.visible_instructors() == instructor_names

    def test_visible_meeting_days(self):
        term_dates = f'{SignUpPage.expected_term_date_str(self.meeting.record_start, self.meeting.record_end)}'
        assert term_dates in self.sign_up_page.visible_meeting_days()[0]

    def test_visible_meeting_time(self):
        assert self.sign_up_page.visible_meeting_time()[0] == f'{self.meeting.start_time} - {self.meeting.end_time}'

    def test_visible_room(self):
        assert self.sign_up_page.visible_rooms()[0] == self.meeting.room.name

    def test_visible_site_ids(self):
        assert self.sign_up_page.visible_course_site_ids() == [site.site_id for site in self.section.sites]

    def test_site_link(self):
        assert self.sign_up_page.external_link_valid(SignUpPage.course_site_link_locator(self.site), self.site.name)

    def test_visible_listings(self):
        listing_codes = [li.code for li in self.section.listings]
        assert self.sign_up_page.visible_cross_listing_codes() == listing_codes

    # VERIFY VARIABLE CONTENT AND EXTERNAL LINKS

    def test_rec_type_text(self):
        assert self.sign_up_page.is_present(SignUpPage.RECORDING_TYPE_TEXT) is True

    def test_publish_type_text(self):
        assert self.sign_up_page.is_present(SignUpPage.PUBLISH_TYPE_TEXT) is True

    def test_overview_link(self):
        title = 'Course Capture | Research, Teaching, and Learning'
        assert self.sign_up_page.external_link_valid(SignUpPage.CC_EXPLAINED_LINK, title) is True

    def test_policies_link(self):
        title = 'Policies | Educational Technology Services'
        assert self.sign_up_page.external_link_valid(SignUpPage.CC_POLICIES_LINK, title) is True

    # VERIFY AVAILABLE OPTIONS AND DISABLED APPROVE BUTTON

    def test_rec_type_options(self):
        self.sign_up_page.click_rec_type_input()
        visible_opts = self.sign_up_page.visible_menu_options()
        expected = [
            RecordingType.SCREENCAST.value['option'], RecordingType.VIDEO_SANS_OPERATOR.value['option'],
            RecordingType.VIDEO_WITH_OPERATOR.value['option'],
        ]
        assert visible_opts == expected

    def test_publish_options(self):
        self.sign_up_page.hit_escape()
        self.sign_up_page.click_publish_type_input()
        visible_opts = self.sign_up_page.visible_menu_options()
        assert visible_opts == [PublishType.BCOURSES.value, PublishType.KALTURA.value]

    def test_approve_disabled_no_selections(self):
        self.sign_up_page.hit_escape()
        assert self.sign_up_page.element(SignUpPage.APPROVE_BUTTON).get_attribute('disabled') == 'true'

    # SELECT OPTIONS, APPROVE

    def test_choose_rec_type(self):
        self.sign_up_page.select_rec_type(RecordingType.VIDEO_WITH_OPERATOR.value['option'])
        self.recording_schedule.recording_type = RecordingType.VIDEO_WITH_OPERATOR

    def test_approve_disabled_no_pub_no_terms(self):
        assert self.sign_up_page.element(SignUpPage.APPROVE_BUTTON).get_attribute('disabled') == 'true'

    def test_choose_publish_type(self):
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.recording_schedule.publish_type = PublishType.BCOURSES

    def test_approve_disabled_no_terms(self):
        assert self.sign_up_page.element(SignUpPage.APPROVE_BUTTON).get_attribute('disabled') == 'true'

    def test_agree_terms(self):
        self.sign_up_page.click_agree_checkbox()

    def test_approve(self):
        self.sign_up_page.click_approve_button()
        self.recording_schedule.approval_status = RecordingApprovalStatus.APPROVED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.QUEUED_FOR_SCHEDULING

    def test_confirmation(self):
        msg = 'This course is currently queued for scheduling. Recordings will be scheduled in an hour or less. Approved by you.'
        self.sign_up_page.wait_for_approvals_msg(msg)

    # VERIFY OUIJA FILTER

    def test_approved_filter_all(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_queued_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_queued_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_approved_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_queued_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_approved_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # RUN KALTURA SCHEDULING JOB AND OBTAIN SERIES ID

    def test_kaltura_job(self):
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()

    def test_kaltura_schedule_id(self):
        util.get_kaltura_id(self.recording_schedule, self.term)

    def test_kaltura_blackouts(self):
        self.jobs_page.run_blackouts_job()

    # VERIFY SERIES IN DIABLO

    def test_room_series(self):
        self.rooms_page.load_page()
        self.rooms_page.find_room(self.meeting.room)
        self.rooms_page.click_room_link(self.meeting.room)
        self.room_page.wait_for_series_row(self.recording_schedule)

    def test_room_series_link(self):
        expected = f'{self.section.code}, {self.section.number} ({self.term.name})'
        assert self.room_page.series_row_kaltura_link_text(self.recording_schedule) == expected

    def test_room_series_start(self):
        start = self.meeting.expected_recording_dates(self.section.term)[0]
        assert self.room_page.series_row_start_date(self.recording_schedule) == start

    def test_room_series_end(self):
        last_date = self.meeting.expected_recording_dates(self.section.term)[-1]
        assert self.room_page.series_row_end_date(self.recording_schedule) == last_date

    def test_room_series_days(self):
        assert self.room_page.series_row_days(self.recording_schedule) == self.meeting.days.replace(' ', '')

    def test_series_recordings(self):
        self.room_page.expand_series_row(self.recording_schedule)
        expected = self.meeting.expected_recording_dates(self.section.term)
        visible = self.room_page.series_recording_start_dates(self.recording_schedule)
        app.logger.info(f'Missing: {list(set(expected) - set(visible))}')
        app.logger.info(f'Unexpected: {list(set(visible) - set(expected))} ')
        expected.reverse()
        assert visible == expected

    def test_series_blackouts(self):
        expected = self.meeting.expected_blackout_dates(self.section.term)
        visible = self.room_page.series_recording_blackout_dates(self.recording_schedule)
        app.logger.info(f'Missing: {list(set(expected) - set(visible))}')
        app.logger.info(f'Unexpected: {list(set(visible) - set(expected))} ')
        expected.reverse()
        assert visible == expected

    def test_open_printable(self):
        self.room_printable_page.open_printable_schedule()

    def test_printable_course(self):
        expected = f'{self.section.code}, {self.section.number}'
        assert self.room_printable_page.visible_course(self.section) == expected

    def test_printable_instructors(self):
        expected = [f'{inst.first_name} {inst.last_name} ({inst.uid})' for inst in self.section.instructors]
        assert self.room_printable_page.visible_instructors(self.section) == expected

    def test_printable_days(self):
        expected = [f'{self.meeting.days}']
        assert self.room_printable_page.visible_days(self.section) == expected

    def test_printable_times(self):
        dates = f'{self.section.term.start_date.strftime("%b %-d, %Y")} - {self.section.term.end_date.strftime("%b %-d, %Y")}'
        times = f'{self.meeting.start_time} - {self.meeting.end_time}'
        assert self.room_printable_page.visible_times(self.section) == [f'{dates}\n{times}']

    def test_printable_rec_type(self):
        expected = self.recording_schedule.recording_type.value['selection']
        assert self.room_printable_page.visible_recording_type(self.section) == expected

    def test_close_printable(self):
        self.room_printable_page.close_printable_schedule()

    # VERIFY OUIJA FILTER

    def test_scheduled_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_scheduled_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_scheduled_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_scheduled_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_scheduled_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # VERIFY SERIES IN KALTURA

    def test_click_series_link(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.click_kaltura_series_link(self.recording_schedule)
        self.kaltura_page.wait_for_delete_button()

    def test_series_title(self):
        expected = f'{self.section.code}, {self.section.number} ({self.term.name})'
        assert self.kaltura_page.visible_series_title() == expected

    def test_series_desc(self):
        course = f'{self.section.code}, {self.section.number} ({self.term.name})'
        instr = f'{self.section.instructors[0].first_name} {self.section.instructors[0].last_name}'
        copy = f"Copyright ©{datetime.strftime(datetime.now(), '%Y')} UC Regents; all rights reserved."
        expected = f'{course} is taught by {instr}. {copy}'
        assert self.kaltura_page.visible_series_desc() == expected

    def test_series_collab_count(self):
        assert len(self.kaltura_page.collaborator_rows()) == len(self.section.instructors)

    def test_series_collab_rights(self):
        for instr in self.section.instructors:
            assert self.kaltura_page.collaborator_perm(instr) == 'Co-Editor, Co-Publisher'

    def test_recur_weekly(self):
        self.kaltura_page.open_recurrence_modal()
        assert self.kaltura_page.is_weekly_checked()

    def test_recur_frequency(self):
        assert self.kaltura_page.visible_weekly_frequency() == '1'

    def test_recur_monday(self):
        checked = self.kaltura_page.is_mon_checked()
        assert checked if 'MO' in self.meeting.days else not checked

    def test_recur_tuesday(self):
        checked = self.kaltura_page.is_tue_checked()
        assert checked if 'TU' in self.meeting.days else not checked

    def test_recur_wednesday(self):
        checked = self.kaltura_page.is_wed_checked()
        assert checked if 'WE' in self.meeting.days else not checked

    def test_recur_thursday(self):
        checked = self.kaltura_page.is_thu_checked()
        assert checked if 'TH' in self.meeting.days else not checked

    def test_recur_friday(self):
        checked = self.kaltura_page.is_fri_checked()
        assert checked if 'FR' in self.meeting.days else not checked

    def test_recur_saturday(self):
        assert not self.kaltura_page.is_sat_checked()

    def test_recur_sunday(self):
        assert not self.kaltura_page.is_sun_checked()

    def test_start_date(self):
        start = util.get_kaltura_term_date_str(self.meeting.expected_recording_dates(self.section.term)[0])
        assert self.kaltura_page.visible_start_date() == start

    def test_end_date(self):
        end = util.get_kaltura_term_date_str(self.meeting.expected_recording_dates(self.section.term)[-1])
        assert self.kaltura_page.visible_end_date() == end

    def test_start_time(self):
        start = self.meeting.get_berkeley_start_time()
        visible_start = datetime.strptime(self.kaltura_page.visible_start_time(), '%I:%M %p')
        assert visible_start == start

    def test_end_time(self):
        end = self.meeting.get_berkeley_end_time()
        visible_end = datetime.strptime(self.kaltura_page.visible_end_time(), '%I:%M %p')
        assert visible_end == end

    def test_series_publish_status(self):
        self.kaltura_page.reload_page()
        self.kaltura_page.wait_for_publish_category_el()
        assert self.kaltura_page.is_published()

    def test_kaltura_course_site_count(self):
        assert len(self.kaltura_page.publish_category_els()) == 2

    def test_kaltura_course_site(self):
        assert self.kaltura_page.is_publish_category_present(self.site)

    def test_close_kaltura_window(self):
        self.kaltura_page.close_window_and_switch()

    # VERIFY EMAIL

    def test_send_schedule_conf_email(self):
        self.jobs_page.load_page()
        self.jobs_page.run_queued_emails_job()

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_receive_schedule_conf_email(self):
        subj = f'Your course, {self.section.code}, has been scheduled for Course Capture'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_delivered(expected_message)
Beispiel #11
0
class TestSignUp2:
    test_data = util.get_test_script_course('test_sign_up_2')
    section = util.get_test_section(test_data)
    meeting = section.meetings[0]
    recording_schedule = RecordingSchedule(section)
    site_1 = CanvasSite(
        code=f'XENA SignUp2A - {section.code}',
        name=f'XENA SignUp2A - {section.code}',
        site_id=None,
    )
    site_2 = CanvasSite(
        code=f'XENA SignUp2B - {section.code}',
        name=f'XENA SignUp2B - {section.code}',
        site_id=None,
    )

    # DELETE PRE-EXISTING DATA

    def test_disable_jobs(self):
        self.login_page.load_page()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_queued_emails_job()
        self.jobs_page.run_canvas_job()
        self.jobs_page.disable_all_jobs()

    def test_create_blackouts(self):
        self.jobs_page.click_blackouts_link()
        self.blackouts_page.delete_all_blackouts()
        self.blackouts_page.create_all_blackouts()

    def test_delete_old_diablo_and_kaltura(self):
        self.kaltura_page.log_in_via_calnet()
        self.kaltura_page.reset_test_data(self.term, self.recording_schedule)
        util.reset_sign_up_test_data(self.section)
        self.recording_schedule.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    def test_run_initial_canvas_job(self):
        self.jobs_page.load_page()
        self.jobs_page.run_canvas_job()

    def test_delete_old_canvas_sites(self):
        site_ids = self.canvas_page.delete_section_sites(self.section)
        if any(site_ids):
            self.jobs_page.load_page()
            self.jobs_page.run_canvas_job()

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_delete_old_email(self):
        self.email_page.log_in()
        self.email_page.delete_all_messages()

    # CHECK FILTERS - NOT INVITED

    def test_not_invited_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_not_invited_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_not_invited_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_not_invited_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_not_invited_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_not_invited_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # RUN JOBS AND VERIFY INVITE

    def test_send_invite_email(self):
        self.jobs_page.load_page()
        self.jobs_page.run_invitations_job()
        self.jobs_page.run_queued_emails_job()
        self.recording_schedule.approval_status = RecordingApprovalStatus.INVITED

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_receive_invite_email_1(self):
        subj = f'Invitation {self.section.term.name} {self.section.code} (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_delivered(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_receive_invite_email_2(self):
        subj = f'Invitation {self.section.term.name} {self.section.code} (To: {self.section.instructors[1].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_delivered(expected_message)

    # CHECK FILTERS - INVITED

    def test_invited_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_invited_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_invited_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_invited_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_invited_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_invited_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # INSTRUCTOR 1 LOGS IN

    def test_home_page_inst_1(self):
        self.ouija_page.log_out()
        self.login_page.dev_auth(self.section.instructors[0].uid)
        self.ouija_page.wait_for_title_containing(f'Your {self.term.name} Course')

    def test_sign_up_link_inst_1(self):
        self.ouija_page.click_sign_up_page_link(self.section)
        self.sign_up_page.wait_for_diablo_title(f'{self.section.code}, {self.section.number}')

    # VERIFY STATIC COURSE SIS DATA

    def test_visible_ccn(self):
        assert self.sign_up_page.visible_ccn() == self.section.ccn

    def test_visible_course_title(self):
        assert self.sign_up_page.visible_course_title() == self.section.title

    def test_visible_instructors(self):
        instructor_names = [f'{i.first_name} {i.last_name}' for i in self.section.instructors]
        assert self.sign_up_page.visible_instructors() == instructor_names

    def test_visible_meeting_days(self):
        term_dates = f'{SignUpPage.expected_term_date_str(self.meeting.record_start, self.meeting.record_end)}'
        assert term_dates in self.sign_up_page.visible_meeting_days()[0]

    def test_visible_meeting_time(self):
        assert self.sign_up_page.visible_meeting_time()[0] == f'{self.meeting.start_time} - {self.meeting.end_time}'

    def test_visible_room(self):
        assert self.sign_up_page.visible_rooms()[0] == self.meeting.room.name

    def test_visible_listings(self):
        listing_codes = [li.code for li in self.section.listings]
        assert self.sign_up_page.visible_cross_listing_codes() == listing_codes

    def test_no_visible_site_ids(self):
        assert len(self.sign_up_page.visible_course_site_ids()) == 0

    # VERIFY AVAILABLE OPTIONS

    def test_rec_type_text(self):
        assert self.sign_up_page.is_present(SignUpPage.RECORDING_TYPE_TEXT) is True

    def test_publish_type_text(self):
        assert self.sign_up_page.is_present(SignUpPage.PUBLISH_TYPE_TEXT) is True

    def test_rec_type_options_inst_1(self):
        self.sign_up_page.click_rec_type_input()
        visible_opts = self.sign_up_page.visible_menu_options()
        expected = [
            RecordingType.SCREENCAST.value['option'], RecordingType.VIDEO_SANS_OPERATOR.value['option'],
            RecordingType.VIDEO_WITH_OPERATOR.value['option'],
        ]
        assert visible_opts == expected

    def test_publish_options_inst_1(self):
        self.sign_up_page.hit_escape()
        self.sign_up_page.click_publish_type_input()
        visible_opts = self.sign_up_page.visible_menu_options()
        assert visible_opts == [PublishType.BCOURSES.value, PublishType.KALTURA.value]

    # SELECT OPTIONS, APPROVE

    def test_pre_approval_msg(self):
        name = f'{self.section.instructors[1].first_name} {self.section.instructors[1].last_name}'
        msg = f'Recordings will be scheduled when we have approvals from you and {name}.'
        self.sign_up_page.wait_for_approvals_msg(msg)

    def test_choose_rec_type_inst_1(self):
        self.sign_up_page.select_rec_type(RecordingType.SCREENCAST.value['option'])
        self.recording_schedule.recording_type = RecordingType.SCREENCAST

    def test_choose_publish_type_inst_1(self):
        self.sign_up_page.select_publish_type(PublishType.KALTURA.value)
        self.recording_schedule.publish_type = PublishType.KALTURA

    def test_agree_terms_inst_1(self):
        self.sign_up_page.click_agree_checkbox()

    def test_approve_inst_1(self):
        self.sign_up_page.click_approve_button()
        self.recording_schedule.approval_status = RecordingApprovalStatus.PARTIALLY_APPROVED

    def test_confirmation_inst_1(self):
        name = f'{self.section.instructors[1].first_name} {self.section.instructors[1].last_name}'
        msg = f'Approved by you. Recordings will be scheduled when we have approval from {name}.'
        self.sign_up_page.wait_for_approvals_msg(msg)

    def test_log_out_inst_1(self):
        self.sign_up_page.log_out()

    # VERIFY OUIJA FILTER

    def test_part_approved_filter_all(self):
        self.login_page.dev_auth()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_queued_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_queued_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_part_approved_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_part_approved_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_part_approved_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_part_approved_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_part_approved_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_part_approved_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_part_approved_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # VERIFY 'WAITING FOR APPROVAL' EMAIL IS SENT TO INSTRUCTOR 1 ONLY

    def test_send_awaiting_approval_email(self):
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_queued_emails_job()

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_receive_awaiting_approval_email_inst_1(self):
        subj = f'Course Capture: {self.section.code} waiting on approval (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_delivered(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_no_receive_awaiting_approval_email_inst_2(self):
        subj = f'Course Capture: {self.section.code} waiting on approval (To: {self.section.instructors[1].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert not self.email_page.is_message_present(expected_message)

    # CREATE COURSE SITE

    def test_create_course_site_one(self):
        self.canvas_page.provision_site(self.section, [self.section.ccn], self.site_1)

    def test_enable_media_gallery(self):
        if self.canvas_page.is_tool_configured(app.config['CANVAS_MEDIA_GALLERY_TOOL']):
            self.canvas_page.load_site(self.site_1.site_id)
            self.canvas_page.enable_media_gallery(self.site_1)
            self.canvas_page.click_media_gallery_tool()
        else:
            app.logger.info('Media Gallery is not properly configured')
            raise

    def test_enable_my_media(self):
        if self.canvas_page.is_tool_configured(app.config['CANVAS_MY_MEDIA_TOOL']):
            self.canvas_page.load_site(self.site_1.site_id)
            self.canvas_page.enable_my_media(self.site_1)
            self.canvas_page.click_my_media_tool()
        else:
            app.logger.info('My Media is not properly configured')
            raise

    def test_run_canvas_job_one(self):
        self.jobs_page.load_page()
        self.jobs_page.run_canvas_job()

    # INSTRUCTOR 2 LOGS IN

    def test_home_page_inst_2(self):
        self.jobs_page.load_page()
        self.jobs_page.log_out()
        self.login_page.dev_auth(self.section.instructors[1].uid)
        self.ouija_page.wait_for_title_containing(f'Your {self.term.name} Course')

    def test_sign_up_link_inst_2(self):
        self.ouija_page.click_sign_up_page_link(self.section)
        self.sign_up_page.wait_for_diablo_title(f'{self.section.code}, {self.section.number}')

    def test_partial_approval_msg(self):
        name = f'{self.section.instructors[0].first_name} {self.section.instructors[0].last_name}'
        msg = f'Approved by {name}. Recordings will be scheduled when we have approval from you.'
        self.sign_up_page.wait_for_approvals_msg(msg)

    def test_visible_site_ids(self):
        self.sign_up_page.load_page(self.section)
        assert self.sign_up_page.visible_course_site_ids() == [site.site_id for site in self.section.sites]

    # VERIFY AVAILABLE OPTIONS

    def test_rec_type_options_inst_2(self):
        self.sign_up_page.click_rec_type_input()
        visible_opts = self.sign_up_page.visible_menu_options()
        expected = [
            RecordingType.SCREENCAST.value['option'], RecordingType.VIDEO_SANS_OPERATOR.value['option'],
            RecordingType.VIDEO_WITH_OPERATOR.value['option'],
        ]
        assert visible_opts == expected

    def test_publish_options_inst_2(self):
        self.sign_up_page.hit_escape()
        self.sign_up_page.click_publish_type_input()
        visible_opts = self.sign_up_page.visible_menu_options()
        assert visible_opts == [PublishType.BCOURSES.value, PublishType.KALTURA.value]

    # CHANGE OPTIONS, APPROVE

    def test_choose_rec_type_inst_2(self):
        self.sign_up_page.select_rec_type(RecordingType.VIDEO_SANS_OPERATOR.value['option'])
        self.recording_schedule.recording_type = RecordingType.VIDEO_SANS_OPERATOR

    def test_choose_publish_type_inst_2(self):
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.recording_schedule.publish_type = PublishType.BCOURSES

    def test_agree_terms_inst_2(self):
        self.sign_up_page.click_agree_checkbox()

    def test_approve_inst_2(self):
        self.sign_up_page.click_approve_button()
        self.recording_schedule.approval_status = RecordingApprovalStatus.APPROVED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.QUEUED_FOR_SCHEDULING

    def test_confirmation_inst_2(self):
        name = f'{self.section.instructors[0].first_name} {self.section.instructors[0].last_name}'
        msg = f'This course is currently queued for scheduling. Recordings will be scheduled in an hour or less. Approved by {name} and you.'
        self.sign_up_page.wait_for_approvals_msg(msg)

    # VERIFY OUIJA FILTER

    def test_approved_filter_all(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_approved_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_approved_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_approved_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_approved_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_approved_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # VERIFY 'NOTIFY INSTRUCTOR OF CHANGES' EMAIL IS SENT TO INSTRUCTOR 1 ONLY

    def test_send_notify_of_changes_email(self):
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_queued_emails_job()

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_receive_notify_of_changes_email_inst_1(self):
        subj = f'Changes to your Course Capture settings for {self.section.code} (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        self.email_page.is_message_delivered(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_no_receive_notify_of_changes_email_inst_2(self):
        subj = f'Changes to your Course Capture settings for {self.section.code} (To: {self.section.instructors[1].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert not self.email_page.is_message_present(expected_message)

    # RUN KALTURA SCHEDULING JOB AND OBTAIN SERIES ID

    def test_run_kaltura_job(self):
        self.jobs_page.load_page()
        self.jobs_page.run_kaltura_job()

    def test_kaltura_schedule_success(self):
        util.get_kaltura_id(self.recording_schedule, self.term)

    def test_kaltura_blackouts(self):
        self.jobs_page.run_blackouts_job()

    # VERIFY SERIES IN DIABLO

    def test_room_series(self):
        self.rooms_page.load_page()
        self.rooms_page.find_room(self.meeting.room)
        self.rooms_page.click_room_link(self.meeting.room)
        self.room_page.wait_for_series_row(self.recording_schedule)

    def test_room_series_link(self):
        expected = f'{self.section.code}, {self.section.number} ({self.term.name})'
        assert self.room_page.series_row_kaltura_link_text(self.recording_schedule) == expected

    def test_room_series_start(self):
        start = self.meeting.expected_recording_dates(self.section.term)[0]
        assert self.room_page.series_row_start_date(self.recording_schedule) == start

    def test_room_series_end(self):
        last_date = self.meeting.expected_recording_dates(self.section.term)[-1]
        assert self.room_page.series_row_end_date(self.recording_schedule) == last_date

    def test_room_series_days(self):
        assert self.room_page.series_row_days(self.recording_schedule) == self.meeting.days.replace(' ', '')

    def test_series_recordings(self):
        self.room_page.expand_series_row(self.recording_schedule)
        expected = self.meeting.expected_recording_dates(self.section.term)
        visible = self.room_page.series_recording_start_dates(self.recording_schedule)
        app.logger.info(f'Missing: {list(set(expected) - set(visible))}')
        app.logger.info(f'Unexpected: {list(set(visible) - set(expected))} ')
        expected.reverse()
        assert visible == expected

    def test_series_blackouts(self):
        expected = self.meeting.expected_blackout_dates(self.section.term)
        visible = self.room_page.series_recording_blackout_dates(self.recording_schedule)
        app.logger.info(f'Missing: {list(set(expected) - set(visible))}')
        app.logger.info(f'Unexpected: {list(set(visible) - set(expected))} ')
        expected.reverse()
        assert visible == expected

    def test_open_printable(self):
        self.room_printable_page.open_printable_schedule()

    def test_printable_course(self):
        expected = f'{self.section.code}, {self.section.number}'
        assert self.room_printable_page.visible_course(self.section) == expected

    def test_printable_instructors(self):
        expected = [f'{inst.first_name} {inst.last_name} ({inst.uid})' for inst in self.section.instructors]
        list.sort(expected)
        visible = self.room_printable_page.visible_instructors(self.section)
        list.sort(visible)
        assert visible == expected

    def test_printable_days(self):
        expected = [f'{self.meeting.days}']
        assert self.room_printable_page.visible_days(self.section) == expected

    def test_printable_times(self):
        dates = f'{self.section.term.start_date.strftime("%b %-d, %Y")} - {self.section.term.end_date.strftime("%b %-d, %Y")}'
        times = f'{self.meeting.start_time} - {self.meeting.end_time}'
        assert self.room_printable_page.visible_times(self.section) == [f'{dates}\n{times}']

    def test_printable_rec_type(self):
        expected = self.recording_schedule.recording_type.value['selection']
        assert self.room_printable_page.visible_recording_type(self.section) == expected

    def test_close_printable(self):
        self.room_printable_page.close_printable_schedule()

    # VERIFY OUIJA FILTER

    def test_scheduled_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_all()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_scheduled_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_scheduled_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_scheduled_filter_no_email(self):
        self.ouija_page.filter_for_do_not_email()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_not_invited(self):
        self.ouija_page.filter_for_not_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_invited(self):
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_partial_approve(self):
        self.ouija_page.filter_for_partially_approved()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_queued(self):
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is False

    def test_scheduled_filter_scheduled(self):
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_scheduled_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # VERIFY SERIES IN KALTURA

    def test_click_series_link(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.click_kaltura_series_link(self.recording_schedule)
        self.kaltura_page.wait_for_delete_button()

    def test_series_title(self):
        expected = f'{self.section.code}, {self.section.number} ({self.term.name})'
        assert self.kaltura_page.visible_series_title() == expected

    def test_series_desc(self):
        course = f'{self.section.code}, {self.section.number} ({self.term.name})'
        instr_1 = f'{self.section.instructors[0].first_name} {self.section.instructors[0].last_name}'
        instr_2 = f'{self.section.instructors[1].first_name} {self.section.instructors[1].last_name}'
        copy = f"Copyright ©{datetime.strftime(datetime.now(), '%Y')} UC Regents; all rights reserved."
        expected = f'{course} is taught by {instr_1} and {instr_2}. {copy}'
        assert self.kaltura_page.visible_series_desc() == expected

    def test_series_collab_count(self):
        assert len(self.kaltura_page.collaborator_rows()) == len(self.section.instructors)

    def test_series_collab_rights(self):
        for instr in self.section.instructors:
            assert self.kaltura_page.collaborator_perm(instr) == 'Co-Editor, Co-Publisher'

    def test_recur_weekly(self):
        self.kaltura_page.open_recurrence_modal()
        assert self.kaltura_page.is_weekly_checked()

    def test_recur_frequency(self):
        assert self.kaltura_page.visible_weekly_frequency() == '1'

    def test_recur_monday(self):
        checked = self.kaltura_page.is_mon_checked()
        assert checked if 'MO' in self.meeting.days else not checked

    def test_recur_tuesday(self):
        checked = self.kaltura_page.is_tue_checked()
        assert checked if 'TU' in self.meeting.days else not checked

    def test_recur_wednesday(self):
        checked = self.kaltura_page.is_wed_checked()
        assert checked if 'WE' in self.meeting.days else not checked

    def test_recur_thursday(self):
        checked = self.kaltura_page.is_thu_checked()
        assert checked if 'TH' in self.meeting.days else not checked

    def test_recur_friday(self):
        checked = self.kaltura_page.is_fri_checked()
        assert checked if 'FR' in self.meeting.days else not checked

    def test_recur_saturday(self):
        assert not self.kaltura_page.is_sat_checked()

    def test_recur_sunday(self):
        assert not self.kaltura_page.is_sun_checked()

    def test_start_date(self):
        start = util.get_kaltura_term_date_str(self.meeting.expected_recording_dates(self.section.term)[0])
        assert self.kaltura_page.visible_start_date() == start

    def test_end_date(self):
        end = util.get_kaltura_term_date_str(self.meeting.expected_recording_dates(self.section.term)[-1])
        assert self.kaltura_page.visible_end_date() == end

    def test_start_time(self):
        start = self.meeting.get_berkeley_start_time()
        visible_start = datetime.strptime(self.kaltura_page.visible_start_time(), '%I:%M %p')
        assert visible_start == start

    def test_end_time(self):
        end = self.meeting.get_berkeley_end_time()
        visible_end = datetime.strptime(self.kaltura_page.visible_end_time(), '%I:%M %p')
        assert visible_end == end

    def test_series_publish_status(self):
        self.kaltura_page.reload_page()
        self.kaltura_page.wait_for_publish_category_el()
        assert self.kaltura_page.is_published()

    def test_kaltura_course_site_count_one(self):
        assert len(self.kaltura_page.publish_category_els()) == 2

    def test_kaltura_course_site_one(self):
        assert self.kaltura_page.is_publish_category_present(self.site_1)

    def test_close_kaltura_window(self):
        self.kaltura_page.close_window_and_switch()

    # VERIFY EMAIL

    def test_send_schedule_conf_email(self):
        self.jobs_page.load_page()
        self.jobs_page.run_queued_emails_job()

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_receive_schedule_conf_email_inst_1(self):
        subj = f'Your course, {self.section.code}, has been scheduled for Course Capture (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_delivered(expected_message)

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_receive_schedule_conf_email_inst_2(self):
        subj = f'Your course, {self.section.code}, has been scheduled for Course Capture (To: {self.section.instructors[1].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_delivered(expected_message)

    # INSTRUCTOR 1 VIEWS APPROVED SIGN UP

    def test_view_approved_inst_1(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.log_out()
        self.login_page.dev_auth(self.section.instructors[0].uid)
        self.ouija_page.click_sign_up_page_link(self.section)
        self.sign_up_page.wait_for_diablo_title(f'{self.section.code}, {self.section.number}')
        name = f'{self.section.instructors[1].first_name} {self.section.instructors[1].last_name}'
        self.sign_up_page.wait_for_approvals_msg(f'Approved by you and {name}.')

    def test_view_scheduled_inst_1(self):
        assert self.sign_up_page.element(SignUpPage.H4_HEADING).text == 'Recordings scheduled'

    # CREATE CANVAS SITE TWO

    def test_create_course_site_two(self):
        self.canvas_page.provision_site(self.section, [self.section.ccn], self.site_2)

    def test_enable_media_gallery_2(self):
        if self.canvas_page.is_tool_configured(app.config['CANVAS_MEDIA_GALLERY_TOOL']):
            self.canvas_page.load_site(self.site_2.site_id)
            self.canvas_page.enable_media_gallery(self.site_2)
            self.canvas_page.click_media_gallery_tool()
        else:
            app.logger.info('Media Gallery is not properly configured')
            raise

    def test_enable_my_media_2(self):
        if self.canvas_page.is_tool_configured(app.config['CANVAS_MY_MEDIA_TOOL']):
            self.canvas_page.load_site(self.site_2.site_id)
            self.canvas_page.enable_my_media(self.site_2)
            self.canvas_page.click_my_media_tool()
        else:
            app.logger.info('My Media is not properly configured')
            raise

    def test_run_canvas_job_site_two(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_canvas_job()
        self.jobs_page.run_kaltura_job()

    def test_two_visible_site_ids(self):
        self.sign_up_page.load_page(self.section)
        assert self.sign_up_page.visible_course_site_ids() == [site.site_id for site in self.section.sites]

    # VERIFY SITES IN KALTURA SERIES

    def test_load_kaltura_series(self):
        self.kaltura_page.load_event_edit_page(self.recording_schedule.series_id)
        self.kaltura_page.wait_for_delete_button()

    def test_kaltura_published_status(self):
        self.kaltura_page.wait_for_publish_category_el()
        assert self.kaltura_page.is_published()

    def test_kaltura_course_site_count_two(self):
        assert len(self.kaltura_page.publish_category_els()) == 3

    def test_kaltura_course_site_both(self):
        assert self.kaltura_page.is_publish_category_present(self.site_1)
        assert self.kaltura_page.is_publish_category_present(self.site_2)

    # DELETE COURSE SITE 1

    def test_delete_course_site(self):
        self.canvas_page.delete_site(self.site_1.site_id)
        self.section.sites.remove(self.site_1)

    def test_run_jobs(self):
        self.jobs_page.load_page()
        self.jobs_page.run_canvas_job()
        self.jobs_page.run_kaltura_job()

    def test_one_visible_site_id(self):
        self.sign_up_page.load_page(self.section)
        assert self.sign_up_page.visible_course_site_ids() == [site.site_id for site in self.section.sites]

    # VERIFY SITES IN KALTURA SERIES

    def test_load_kaltura_series_again(self):
        self.kaltura_page.load_event_edit_page(self.recording_schedule.series_id)
        self.kaltura_page.wait_for_delete_button()

    def test_kaltura_course_site_count_still_two(self):
        self.kaltura_page.wait_for_publish_category_el()
        assert len(self.kaltura_page.publish_category_els()) == 3

    def test_kaltura_course_site_still_both(self):
        assert self.kaltura_page.is_publish_category_present(self.site_1)
        assert self.kaltura_page.is_publish_category_present(self.site_2)
class TestWeirdTypeB:

    # Initial course data
    test_data = util.get_test_script_course('test_weird_type_b')
    section = util.get_test_section(test_data)
    meeting_physical = section.meetings[0]
    meeting_online = section.meetings[1]
    instructor_0 = section.instructors[0]
    room_0 = meeting_physical.room
    recording_schedule = RecordingSchedule(section)

    # Course changes data
    test_data_changes = util.get_test_script_course(
        'test_weird_type_b_changes')
    section_changes = Section(test_data_changes)
    meeting_physical_changes = section_changes.meetings[0]
    meeting_online_changes = section_changes.meetings[1]
    instructor_1 = section_changes.instructors[0]
    room_1 = meeting_physical_changes.room
    recording_schedule_changes = RecordingSchedule(section_changes)

    def test_disable_jobs(self):
        self.login_page.load_page()
        self.login_page.dev_auth()
        self.ouija_page.click_jobs_link()
        self.jobs_page.disable_all_jobs()

    def test_admin_emails_pre_run(self):
        self.jobs_page.run_admin_emails_job()

    def test_instructor_emails_pre_run(self):
        self.jobs_page.run_instructor_emails_job()

    def test_queued_emails_pre_run(self):
        self.jobs_page.run_queued_emails_job()

    def test_create_blackouts(self):
        self.jobs_page.click_blackouts_link()
        self.blackouts_page.delete_all_blackouts()
        self.blackouts_page.create_all_blackouts()

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_delete_old_email(self):
        self.email_page.log_in()
        self.email_page.delete_all_messages()

    def test_delete_old_diablo_and_kaltura(self):
        self.kaltura_page.log_in_via_calnet()
        self.kaltura_page.reset_test_data(self.term, self.recording_schedule)
        util.reset_sign_up_test_data(self.section)
        self.recording_schedule.approval_status = RecordingApprovalStatus.NOT_INVITED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.NOT_SCHEDULED

    # COURSE APPEARS ON 'NOT INVITED' FILTER

    def test_not_invited_filter_not_invited(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_not_invited_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_not_invited_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    # RUN JOBS AND VERIFY INVITE

    def test_send_invite_email(self):
        self.jobs_page.load_page()
        self.jobs_page.run_invitations_job()
        self.jobs_page.run_queued_emails_job()
        self.recording_schedule.approval_status = RecordingApprovalStatus.INVITED

    @pytest.mark.skipif(app.config['SKIP_EMAILS'], reason='Check email')
    def test_receive_invite_email(self):
        subj = f'Invitation {self.section.term.name} {self.section.code} (To: {self.section.instructors[0].email})'
        expected_message = Email(msg_type=None, sender=None, subject=subj)
        assert self.email_page.is_message_delivered(expected_message)

    # COURSE APPEARS ON 'INVITED' FILTER

    def test_invited_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_invited()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_invited_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_invited_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    # INSTRUCTOR LOGS IN

    def test_home_page(self):
        self.ouija_page.log_out()
        self.login_page.dev_auth(self.instructor_0.uid)
        self.ouija_page.wait_for_title_containing(
            f'Your {self.section.term.name} Course')

    def test_sign_up_link(self):
        self.ouija_page.click_sign_up_page_link(self.section)
        self.sign_up_page.wait_for_diablo_title(
            f'{self.section.code}, {self.section.number}')

    # VERIFY STATIC COURSE SIS DATA

    def test_visible_ccn(self):
        assert self.sign_up_page.visible_ccn() == self.section.ccn

    def test_visible_course_title(self):
        assert self.sign_up_page.visible_course_title() == self.section.title

    def test_visible_instructors(self):
        instructor_names = [
            f'{self.instructor_0.first_name} {self.instructor_0.last_name}'
        ]
        assert self.sign_up_page.visible_instructors() == instructor_names

    def test_visible_meeting_days(self):
        term_dates = f'{SignUpPage.expected_term_date_str(self.meeting_physical.record_start, self.meeting_physical.record_end)}'
        assert term_dates in self.sign_up_page.visible_meeting_days()[0]
        assert len(self.sign_up_page.visible_meeting_days()) == 1

    def test_visible_meeting_time(self):
        assert self.sign_up_page.visible_meeting_time(
        )[0] == f'{self.meeting_physical.start_time} - {self.meeting_physical.end_time}'
        assert len(self.sign_up_page.visible_meeting_time()) == 1

    def test_visible_room(self):
        assert self.sign_up_page.visible_rooms(
        )[0] == self.meeting_physical.room.name
        assert len(self.sign_up_page.visible_rooms()) == 1

    # SELECT OPTIONS, APPROVE

    def test_set_rec_type(self):
        self.recording_schedule.recording_type = RecordingType.SCREENCAST

    def test_choose_publish_type(self):
        self.sign_up_page.select_publish_type(PublishType.BCOURSES.value)
        self.recording_schedule.publish_type = PublishType.BCOURSES

    def test_agree_terms(self):
        self.sign_up_page.click_agree_checkbox()

    def test_approve(self):
        self.sign_up_page.click_approve_button()
        self.recording_schedule.approval_status = RecordingApprovalStatus.APPROVED
        self.recording_schedule.scheduling_status = RecordingSchedulingStatus.QUEUED_FOR_SCHEDULING

    def test_confirmation(self):
        msg = 'This course is currently queued for scheduling.'
        self.sign_up_page.wait_for_approvals_msg(msg)

    # COURSE APPEARS ON 'QUEUED' FILTER

    def test_approved_filter_all(self):
        self.sign_up_page.log_out()
        self.login_page.dev_auth()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_queued_for_scheduling()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_queued_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_queued_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    # RUN KALTURA SCHEDULING JOB AND OBTAIN SERIES ID

    def test_kaltura_job(self):
        self.ouija_page.click_jobs_link()
        self.jobs_page.run_kaltura_job()

    def test_kaltura_schedule_id(self):
        util.get_kaltura_id(self.recording_schedule, self.term)

    def test_kaltura_blackouts(self):
        self.jobs_page.run_blackouts_job()

    # VERIFY SERIES IN DIABLO

    def test_room_series(self):
        self.rooms_page.load_page()
        self.rooms_page.find_room(self.meeting_physical.room)
        self.rooms_page.click_room_link(self.meeting_physical.room)
        self.room_page.wait_for_series_row(self.recording_schedule)

    def test_room_series_link(self):
        expected = f'{self.section.code}, {self.section.number} ({self.term.name})'
        assert self.room_page.series_row_kaltura_link_text(
            self.recording_schedule) == expected

    def test_room_series_start(self):
        start = self.meeting_physical.expected_recording_dates(
            self.section.term)[0]
        assert self.room_page.series_row_start_date(
            self.recording_schedule) == start

    def test_room_series_end(self):
        last_date = self.meeting_physical.expected_recording_dates(
            self.section.term)[-1]
        assert self.room_page.series_row_end_date(
            self.recording_schedule) == last_date

    def test_room_series_days(self):
        assert self.room_page.series_row_days(
            self.recording_schedule) == self.meeting_physical.days.replace(
                ' ', '')

    def test_series_recordings(self):
        self.room_page.expand_series_row(self.recording_schedule)
        expected = self.meeting_physical.expected_recording_dates(
            self.section.term)
        visible = self.room_page.series_recording_start_dates(
            self.recording_schedule)
        app.logger.info(f'Missing: {list(set(expected) - set(visible))}')
        app.logger.info(f'Unexpected: {list(set(visible) - set(expected))} ')
        expected.reverse()
        assert visible == expected

    def test_series_blackouts(self):
        expected = self.meeting_physical.expected_blackout_dates(
            self.section.term)
        visible = self.room_page.series_recording_blackout_dates(
            self.recording_schedule)
        app.logger.info(f'Missing: {list(set(expected) - set(visible))}')
        app.logger.info(f'Unexpected: {list(set(visible) - set(expected))} ')
        expected.reverse()
        assert visible == expected

    # COURSE APPEARS ON 'SCHEDULED' FILTER

    def test_scheduled_filter_all(self):
        self.ouija_page.load_page()
        self.ouija_page.search_for_course_code(self.section)
        self.ouija_page.filter_for_scheduled()
        assert self.ouija_page.is_course_in_results(self.section) is True

    def test_scheduled_approval_status(self):
        visible_status = self.ouija_page.course_row_approval_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.approval_status.value

    def test_scheduled_sched_status(self):
        visible_status = self.ouija_page.course_row_sched_status_el(
            self.section).text.strip()
        assert visible_status == self.recording_schedule.scheduling_status.value

    def test_scheduled_filter_weird(self):
        self.ouija_page.filter_for_scheduled_weird()
        assert self.ouija_page.is_course_in_results(self.section) is False

    # VERIFY SERIES IN KALTURA

    def test_click_series_link(self):
        self.sign_up_page.load_page(self.section)
        self.sign_up_page.click_kaltura_series_link(self.recording_schedule)
        self.kaltura_page.wait_for_delete_button()

    def test_series_title(self):
        expected = f'{self.section.code}, {self.section.number} ({self.term.name})'
        assert self.kaltura_page.visible_series_title() == expected

    def test_series_collab_count(self):
        assert len(self.kaltura_page.collaborator_rows()) == len(
            self.section.instructors)

    def test_series_collab_rights(self):
        for instr in self.section.instructors:
            assert self.kaltura_page.collaborator_perm(
                instr) == 'Co-Editor, Co-Publisher'

    def test_recur_weekly(self):
        self.kaltura_page.open_recurrence_modal()
        assert self.kaltura_page.is_weekly_checked()

    def test_recur_frequency(self):
        assert self.kaltura_page.visible_weekly_frequency() == '1'

    def test_recur_monday(self):
        checked = self.kaltura_page.is_mon_checked()
        assert checked if 'MO' in self.meeting_physical.days else not checked

    def test_recur_tuesday(self):
        checked = self.kaltura_page.is_tue_checked()
        assert checked if 'TU' in self.meeting_physical.days else not checked

    def test_recur_wednesday(self):
        checked = self.kaltura_page.is_wed_checked()
        assert checked if 'WE' in self.meeting_physical.days else not checked

    def test_recur_thursday(self):
        checked = self.kaltura_page.is_thu_checked()
        assert checked if 'TH' in self.meeting_physical.days else not checked

    def test_recur_friday(self):
        checked = self.kaltura_page.is_fri_checked()
        assert checked if 'FR' in self.meeting_physical.days else not checked

    def test_recur_saturday(self):
        assert not self.kaltura_page.is_sat_checked()

    def test_recur_sunday(self):
        assert not self.kaltura_page.is_sun_checked()

    def test_start_date(self):
        start = util.get_kaltura_term_date_str(
            self.meeting_physical.expected_recording_dates(
                self.section.term)[0])
        assert self.kaltura_page.visible_start_date() == start

    def test_end_date(self):
        end = util.get_kaltura_term_date_str(
            self.meeting_physical.expected_recording_dates(
                self.section.term)[-1])
        assert self.kaltura_page.visible_end_date() == end

    def test_start_time(self):
        start = self.meeting_physical.get_berkeley_start_time()
        visible_start = datetime.strptime(
            self.kaltura_page.visible_start_time(), '%I:%M %p')
        assert visible_start == start

    def test_end_time(self):
        end = self.meeting_physical.get_berkeley_end_time()
        visible_end = datetime.strptime(self.kaltura_page.visible_end_time(),
                                        '%I:%M %p')
        assert visible_end == end

    def test_close_kaltura_window(self):
        self.kaltura_page.close_window_and_switch()

    # INSTRUCTOR REMOVED

    def test_remove_instructor(self):
        util.change_course_instructor(self.section,
                                      old_instructor=self.instructor_0,
                                      new_instructor=None)

    def test_instr_removed_summary(self):
        self.jobs_page.click_course_changes_link()
        self.changes_page.wait_for_course_row(self.section)
        expected = 'Instructors are obsolete.'
        actual = self.changes_page.scheduled_card_summary(self.section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_instr_removed_former_instr(self):
        expected = f'{self.instructor_0.first_name} {self.instructor_0.last_name} ({self.instructor_0.uid})'
        actual = self.changes_page.scheduled_card_old_instructors(self.section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    # INSTRUCTOR ADDED

    def test_add_instructor(self):
        util.change_course_instructor(self.section,
                                      old_instructor=None,
                                      new_instructor=self.instructor_1)

    def test_instr_changed_summary(self):
        self.changes_page.load_page()
        self.changes_page.wait_for_course_row(self.section)
        expected = 'Instructors are obsolete.'
        actual = self.changes_page.scheduled_card_summary(self.section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_instr_changed_former_instr(self):
        expected = f'{self.instructor_0.first_name} {self.instructor_0.last_name} ({self.instructor_0.uid})'
        actual = self.changes_page.scheduled_card_old_instructors(self.section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_instr_changed_new_instr(self):
        expected = f'{self.instructor_1.first_name} {self.instructor_1.last_name} ({self.instructor_1.uid})'
        actual = self.changes_page.scheduled_card_new_instructors(self.section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_instr_changed_current_card(self):
        expected = f'{self.instructor_1.first_name} {self.instructor_1.last_name} ({self.instructor_1.uid})'
        actual = self.changes_page.current_card_instructors(self.section, 1)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    # START / END DATES CHANGE FOR ELIGIBLE SECTION

    def test_change_dates(self):
        start = self.meeting_physical_changes.start_date
        end = self.meeting_physical_changes.end_date
        util.update_course_start_end_dates(self.section,
                                           self.meeting_physical.room, start,
                                           end)

    def test_dates_changed_summary(self):
        self.changes_page.load_page()
        self.changes_page.wait_for_course_row(self.section)
        expected = 'Instructors and dates are obsolete.'
        actual = self.changes_page.scheduled_card_summary(self.section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_dates_changed_former_sched_room(self):
        expected = self.meeting_physical.room.name
        actual = self.changes_page.scheduled_card_old_room(self.section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_dates_changed_former_sched_dates(self):
        dates = self.meeting_physical.expected_recording_dates(
            self.section.term)
        start = dates[0]
        end = dates[-1]
        dates = f'{start.strftime("%Y-%m-%d")} to {end.strftime("%Y-%m-%d")}'
        times = CourseChangesPage.meeting_time_str(self.meeting_physical)
        days_times = f'{self.meeting_physical.days.replace(" ", "").replace(",", "")}, {times}'
        expected = f'{dates}{days_times}'.upper()
        actual = self.changes_page.scheduled_card_old_schedule(
            self.section).upper()
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_dates_changed_current_physical_room(self):
        expected = self.meeting_physical.room.name
        actual = self.changes_page.current_card_schedule(self.section, 1, 1)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_dates_changed_current_physical_dates(self):
        dates = self.meeting_physical_changes.expected_recording_dates(
            self.section.term)
        start = dates[0]
        end = dates[-1]
        dates = f'{start.strftime("%Y-%m-%d")} to {end.strftime("%Y-%m-%d")}'
        days = self.meeting_physical_changes.days.replace(' ',
                                                          '').replace(',', '')
        times = CourseChangesPage.meeting_time_str(
            self.meeting_physical_changes)
        expected = f'{dates}{days}, {times}'.upper()
        actual = self.changes_page.current_card_schedule(self.section, 1,
                                                         2).upper()
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_dates_changed_current_online_room(self):
        expected = self.meeting_online_changes.room.name
        actual = self.changes_page.current_card_schedule(self.section, 2, 1)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_dates_changed_current_online_dates(self):
        start = self.meeting_online_changes.start_date
        end = self.meeting_online_changes.end_date
        dates = f'{start.strftime("%Y-%m-%d")} to {end.strftime("%Y-%m-%d")}'
        days = self.meeting_online_changes.days.replace(' ',
                                                        '').replace(',', '')
        times = CourseChangesPage.meeting_time_str(self.meeting_online_changes)
        expected = f'{dates}{days}, {times}'.upper()
        actual = self.changes_page.current_card_schedule(self.section, 2,
                                                         2).upper()
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    # ROOM REMOVED

    def test_remove_room(self):
        util.change_course_room(self.section,
                                old_room=self.room_0,
                                new_room=None)

    def test_room_removed_summary(self):
        self.changes_page.load_page()
        self.changes_page.wait_for_course_row(self.section)
        expected = 'Instructors and room are obsolete.'
        actual = self.changes_page.scheduled_card_summary(self.section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_room_removed_former_room(self):
        actual = self.changes_page.scheduled_card_old_room(self.section)
        app.logger.info(f'Expecting: {self.room_0.name}')
        app.logger.info(f'Actual: {actual}')
        assert self.room_0.name in actual

    def test_room_removed_current_card(self):
        actual = self.changes_page.current_card_schedule(self.section,
                                                         list_node=None,
                                                         detail_node=1)
        app.logger.info(f'Expecting: {self.meeting_online.room.name}')
        app.logger.info(f'Actual: {actual}')
        assert self.meeting_online.room.name in actual

    # ROOM ADDED

    def test_add_room(self):
        util.change_course_room(self.section,
                                old_room=None,
                                new_room=self.room_1)

    def test_room_changed_summary(self):
        self.changes_page.load_page()
        self.changes_page.wait_for_course_row(self.section)
        expected = 'Instructors and room are obsolete.'
        actual = self.changes_page.scheduled_card_summary(self.section)
        app.logger.info(f'Expecting: {expected}')
        app.logger.info(f'Actual: {actual}')
        assert expected in actual

    def test_room_changed_former_room(self):
        actual = self.changes_page.scheduled_card_old_room(self.section)
        app.logger.info(f'Expecting: {self.room_0.name}')
        app.logger.info(f'Actual: {actual}')
        assert self.room_0.name in actual

    def test_room_changed_current_card(self):
        actual_physical = self.changes_page.current_card_schedule(
            self.section, list_node=None, detail_node=1)
        actual_online = self.changes_page.current_card_schedule(self.section,
                                                                list_node=None,
                                                                detail_node=2)
        app.logger.info(
            f'Expecting: {self.meeting_online.room.name} and {self.meeting_physical_changes.room.name}'
        )
        app.logger.info(f'Actual: {actual_physical} and {actual_online}')
        assert self.meeting_online.room.name in actual_online
        assert self.meeting_physical_changes.room.name in actual_physical