Ejemplo n.º 1
0
class TestEpicName(unittest.TestCase):
    """Product.Epic - Epic Text."""

    def setUp(self):
        """Pretest settings."""

        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(
                use_env_vars=True,
                pasta_user=self.ps,
                capabilities=self.desired_capabilities
            )
        else:
            self.teacher = Teacher(
                use_env_vars=True
            )

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(
                job_id=str(self.teacher.driver.session_id),
                **self.ps.test_updates
            )
        try:
            self.teacher.delete()
        except:
            pass

    # Case CaseID - Story# - UserType
    @pytest.mark.skipif(str(CaseID) not in TESTS, reason='Excluded')
    def test_usertype_storytext_CaseID(self):
        """Story Text.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 'product.epic.story' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'product',
            'product.epic',
            'product.epic.story',
            'CaseID'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    def test_teacher_able_to_search_within_the_book_7629(self):
        """Able to search within the book.

        Steps:
        Go to tutor-qa
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click "Online Book" in the header
        Enter search words into the search engine next to the "Contents" button

        Expected Result:
        The search word is highlighted in yellow within the text and is bolded
        within the table of contents
        """
        self.ps.test_updates['name'] = 'cc1.05.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.05', 'cc1.05.005', '7629']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        teacher = Teacher(
            existing_driver=self.student.driver,
            username=os.getenv('TEACHER_USER'),
            password=os.getenv('TEACHER_PASSWORD'),
            pasta_user=self.ps,
            capabilities=self.desired_capabilities,
        )
        teacher.login()
        teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard/")]').click()
        teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a//span[contains(text(),"Online Book")]'))).click()
        window_with_book = teacher.driver.window_handles[1]
        teacher.driver.switch_to_window(window_with_book)
        assert('cnx' in teacher.current_url()), \
            'Not viewing the textbook PDF'
        teacher.page.wait_for_page_load()
        teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//input[@placeholder="Search this book"]'
                 ))).send_keys('balance' + Keys.ENTER)
        # make sure the search worked
        # still passes if no results found and it says: No matching results...
        teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="result-count"]')))
        teacher.delete()
        self.ps.test_updates['passed'] = True
class TestImproveCourseManagement(unittest.TestCase):
    """T2.07 - Improve Course Management."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(use_env_vars=True,
                               pasta_user=self.ps,
                               capabilities=self.desired_capabilities)
        self.admin = Admin(use_env_vars=True,
                           pasta_user=self.ps,
                           capabilities=self.desired_capabilities,
                           existing_driver=self.teacher.driver)

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        self.admin = None
        try:
            self.teacher.delete()
        except:
            pass

    def test_view_stats_admin(self):
        """
        Log in as Admin
        Click on User Menu for drop-down
        Click on 'Admin' on user menu
        Click "Stats"
        Click "Concept Coach"
        ***The user is presented with Concept Coach Statistics (t2.07.01)***

        Corresponds to...
        t2.07.01
        :return:
        """
        # t2.07.01 --> The user is presented with Concept Coach Statistics
        self.admin.login()
        self.admin.goto_admin_control()
        self.admin.sleep(5)
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Stats'))).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Concept Coach'))).click()

        assert ('/stats/concept_coach' in self.admin.current_url()), \
            'Not viewing Concept Coach stats'
class TestEpicName(unittest.TestCase):
    """Product.Epic - Epic Text."""

    def setUp(self):
        """Pretest settings."""

        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.teacher.delete()
        except:
            pass

    # Case CaseID - Story# - UserType
    @pytest.mark.skipif(str(CaseID) not in TESTS, reason='Excluded')
    def test_usertype_storytext_CaseID(self):
        """Story Text.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 'product.epic.story' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'product',
            'product.epic',
            'product.epic.story',
            'CaseID'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    def test_teacher_able_to_search_within_the_book_7629(self):
        """Able to search within the book.

        Steps:
        Go to tutor-qa
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click "Online Book" in the header
        Enter search words into the search engine next to the "Contents" button

        Expected Result:
        The search word is highlighted in yellow within the text and is bolded
        within the table of contents
        """
        self.ps.test_updates["name"] = "cc1.05.005" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["cc1", "cc1.05", "cc1.05.005", "7629"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        teacher = Teacher(
            existing_driver=self.student.driver,
            username=os.getenv("TEACHER_USER"),
            password=os.getenv("TEACHER_PASSWORD"),
            pasta_user=self.ps,
            capabilities=self.desired_capabilities,
        )
        teacher.login()
        teacher.driver.find_element(By.XPATH, '//a[contains(@href,"/cc-dashboard/")]').click()
        teacher.wait.until(
            expect.visibility_of_element_located((By.XPATH, '//a//span[contains(text(),"Online Book")]'))
        ).click()
        window_with_book = teacher.driver.window_handles[1]
        teacher.driver.switch_to_window(window_with_book)
        assert "cnx" in teacher.current_url(), "Not viewing the textbook PDF"
        teacher.page.wait_for_page_load()
        teacher.wait.until(
            expect.visibility_of_element_located((By.XPATH, '//input[@placeholder="Search this book"]'))
        ).send_keys("balance" + Keys.ENTER)
        # make sure the search worked
        # still passes if no results found and it says: No matching results...
        teacher.wait.until(expect.visibility_of_element_located((By.XPATH, '//div[@class="result-count"]')))
        teacher.delete()
        self.ps.test_updates["passed"] = True
class TestImproveLoginRegistrationEnrollment(unittest.TestCase):
    """CC2.09 - Improve Login, Registration, Enrollment."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(
                use_env_vars=True,
                pasta_user=self.ps,
                capabilities=self.desired_capabilities
            )
            self.student = Student(
                use_env_vars=True,
                existing_driver=self.teacher.driver,
                pasta_user=self.ps,
                capabilities=self.desired_capabilities
            )
        else:
            self.teacher = Teacher(
                use_env_vars=True
            )
            self.student = Student(
                use_env_vars=True,
                existing_driver=self.teacher.driver,
            )

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(
                job_id=str(self.teacher.driver.session_id),
                **self.ps.test_updates
            )
        self.student = None
        try:
            self.teacher.delete()
        except:
            pass

    def get_enrollemnt_code(self, number=0):
        """
        Steps:
        Sign in as teacher
        Click on a Concept Coach course
        Click on "Course Settings and Roster" from the user menu
        Click "Your Student Enrollment Code"

        Return value: code, enrollemnt_url
            code - enrollment code
            enrollemnt_url - url of book for course
        """
        self.teacher.login()
        if number != 0:
            cc_courses = self.teacher.find_all(
                By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
            )
            cc_courses[number].click()
        else:
            self.teacher.find(
                By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
            ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        self.teacher.find(
            By.XPATH, '//span[contains(text(),"Your student enrollment code")]'
        ).click()
        self.teacher.sleep(1)
        code = self.teacher.find(
            By.XPATH, '//p[@class="code"]'
        ).text
        enrollement_url = self.teacher.find(
            By.XPATH, '//textarea'
        ).text
        enrollement_url = enrollement_url.split('\n')[5]
        self.teacher.find(
            By.XPATH, '//button[@class="close"]'
        ).click()
        self.teacher.sleep(0.5)
        self.teacher.logout()
        return code, enrollement_url

    def create_user(self, start_num, end_num):
        """
        creates a new user and return the username
        """
        self.student.get("http://accounts-qa.openstax.org")
        num = str(randint(start_num, end_num))
        self.student.find(By.LINK_TEXT, 'Sign up').click()
        self.student.find(
            By.ID, 'identity-login-button').click()
        self.student.find(
            By.ID, 'signup_first_name').send_keys('first_name_001')
        self.student.find(
            By.ID, 'signup_last_name').send_keys('last_name_001')
        self.student.find(
            By.ID, 'signup_email_address').send_keys('*****@*****.**')
        self.student.find(
            By.ID, 'signup_username').send_keys('automated_09_'+num)
        self.student.find(
            By.ID, 'signup_password'
        ).send_keys(os.getenv('STUDENT_PASSWORD'))
        self.student.find(
            By.ID, 'signup_password_confirmation'
        ).send_keys(os.getenv('STUDENT_PASSWORD'))
        self.student.find(By.ID, 'signup_i_agree').click()
        self.student.find(
            By.ID, 'create_account_submit').click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Sign out')
            )
        ).click()
        print('automated_09_'+num)
        return 'automated_09_'+num

    '''
    # 14820 - 001 - Teacher | Register for teaching a CC course as new faculty
    @pytest.mark.skipif(str(14820) not in TESTS, reason='Excluded')
    def test_teacher_register_for_teaching_cc_course_as_new_facult_14820(self):
        """Register for teaching a CC course as new faculty.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc2.09.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.001', '14820']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    '''

    # 14819 - 002 - Teacher | Register for teaching a CC course as
    # returning faculty for the same book
    @pytest.mark.skipif(str(14819) not in TESTS, reason='Excluded')
    def test_teacher_register_for_teaching_cc_course_as_returning_14819(self):
        """Register for teaching a CC course as returning faculty.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click "Course Settings and Roster" from the user menu
        Click "Add Section"
        Create a name when prompted
        Click "Add"
        Click on the sections from previous semesters
        Click "Archive Section"

        Expected Result:
        A new section is added and the old sections are archived
        """
        self.ps.test_updates['name'] = 'cc2.09.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.002', '14819']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        # add a new section
        new_section_name = "new_section_" + str(randint(100, 999))
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[contains(@class,"add-period")]//button')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//input[@type="text"]')
            )
        ).send_keys(new_section_name)
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[@class="modal-content"]//button/span[text()="Add"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + new_section_name + '"]')
            )
        )
        # revove old section
        old_section_name = self.teacher.find(By.XPATH, '//a[@role="tab"]').text
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + old_section_name + '"]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(@class,"archive-period")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@role="tooltip"]//button' +
                 '//span[contains(text(),"Archive")]')
            )
        ).click()
        self.teacher.sleep(2)
        archived = self.teacher.driver.find_elements(
            By.XPATH,
            '//li//a[@role="tab" and text()="' + old_section_name + '"]')
        assert(len(archived) == 0), ' not archived'

        # arhive new section and re-add old section as clean-up
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + new_section_name + '"]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(@class,"archive-period")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@role="tooltip"]//button' +
                 '//span[contains(text(),"Archive")]')
            )
        ).click()

        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@class,"view-archived-periods")]//button')
            )
        ).click()
        periods = self.teacher.driver.find_elements(
            By.XPATH, '//div[@class="modal-content"]//tbody//tr'
        )
        for period in periods:
            try:
                period.find_element(
                    By.XPATH, ".//td[text()='" + old_section_name + "']")
                period.find_element(
                    By.XPATH,
                    ".//td//span[contains(@class,'restore-period')]//button"
                ).click()
                break
            except NoSuchElementException:
                if period == periods[-1]:
                    raise Exception

        self.ps.test_updates['passed'] = True

    # 14759 - 003 - Student | Sign up and enroll in a CC course
    @pytest.mark.skipif(str(14759) not in TESTS, reason='Excluded')
    def test_teacher_sign_up_and_enroll_in_a_cc_course_14759(self):
        """Sign up and enroll in a CC course.

        Steps:
        Sign in as teacher
        Click on a Concept Coach course
        Click on "Course Settings and Roster" from the user menu
        Click "Your Student Enrollment Code"
        Copy and paste the URL into an incognito window
        Click "Jump to Concept Coach"
        Click "Launch Concept Coach"
        Click Sign Up
        Click Sign up with a password
        Fill in the required fields
        Click "Create Account"
        Enter the numerical enrollment code you get from the teacher
        Click "Enroll"
        Enter school issued ID, OR skip this step for now

        Expected Result:
        The user is presented with a message that confirms enrollment
        Is redirected to the CC assignment
        """
        self.ps.test_updates['name'] = 'cc2.09.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.003', '14759']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        code, enrollement_url = self.get_enrollemnt_code()
        rand_username = self.create_user(100, 999)
        self.student.get(enrollement_url)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]')
            )
        ).click()
        self.student.page.wait_for_page_load()
        self.student.find(
            By.XPATH, '//div[text()="Sign in"]'
        ).click()
        self.student.sleep(0.5)
        login_window = self.student.driver.window_handles[1]
        cc_window = self.student.driver.window_handles[0]
        self.student.driver.switch_to_window(login_window)
        print(rand_username)
        self.student.find(
            By.ID, 'auth_key').send_keys(rand_username)
        print(self.student.password)
        self.student.find(
            By.ID, 'password').send_keys(self.student.password)
        self.student.find(
            By.XPATH, '//button[text()="Sign in"]').click()
        try:
            self.student.find(By.ID, "i_agree").click()
            self.student.find(By.ID, "agreement_submit").click()
            self.student.find(By.ID, "i_agree").click()
            self.student.find(By.ID, "agreement_submit").click()
        except NoSuchElementException:
            pass
        self.student.driver.switch_to_window(cc_window)
        self.student.sleep(1)
        self.student.find(
            By.XPATH, '//input[@placeholder="enrollment code"]'
        ).send_keys(code)
        self.student.find(
            By.XPATH, '//button/span[text()="Enroll"]'
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[@class="skip"]')
            )
        ).click()
        # check for confirmation message
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//*[contains(text(),"You have successfully joined")]')
            )
        )

        self.ps.test_updates['passed'] = True

    # 14862 - 004 - Student | Sign in and enroll in a CC course
    @pytest.mark.skipif(str(14862) not in TESTS, reason='Excluded')
    def test_teacher_sign_in_and_enroll_in_a_cc_course_14862(self):
        """Sign in and enroll in a CC course.

        Steps:
        Sign in as teacher100
        Click on a Concept Coach course
        Click on "Course Settings and Roster" from the user menu
        Click "Your Student Enrollment Code"
        Copy and paste the URL into an incognito window
        Click "Jump to Concept Coach"
        Click "Launch Concept Coach"
        Click Sign In
        Sign in as student71
        Enter the numerical enrollment code you get from the teacher
        Click "Enroll"
        Enter school issued ID, OR skip this step for now

        Expected Result:
        The user is presented with a message that confirms enrollment
        Is redirected to the CC assignment
        """
        self.ps.test_updates['name'] = 'cc2.09.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.004', '14862']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        code, enrollement_url = self.get_enrollemnt_code()
        # use a new student so that when run a second time no issues
        # with student already being enrolled in course
        rand_username = self.create_user(100, 999)
        self.student.get(enrollement_url)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]')
            )
        ).click()
        self.student.page.wait_for_page_load()
        self.student.find(
            By.XPATH, '//div[text()="Sign in"]'
        ).click()
        self.student.sleep(0.5)
        login_window = self.student.driver.window_handles[1]
        cc_window = self.student.driver.window_handles[0]
        self.student.driver.switch_to_window(login_window)
        self.student.find(
            By.ID, 'auth_key').send_keys(rand_username)
        self.student.find(
            By.ID, 'password').send_keys(self.student.password)
        self.student.find(
            By.XPATH, '//button[text()="Sign in"]').click()
        try:
            self.student.find(By.ID, "i_agree").click()
            self.student.find(By.ID, "agreement_submit").click()
            self.student.find(By.ID, "i_agree").click()
            self.student.find(By.ID, "agreement_submit").click()
        except NoSuchElementException:
            pass
        self.student.driver.switch_to_window(cc_window)
        self.student.sleep(1)
        self.student.find(
            By.XPATH, '//input[@placeholder="enrollment code"]'
        ).send_keys(code)
        self.student.find(
            By.XPATH, '//button/span[text()="Enroll"]'
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[@class="skip"]')
            )
        ).click()
        # check for confirmation message
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//*[contains(text(),"You have successfully joined")]')
            )
        )

        self.ps.test_updates['passed'] = True

    # 14771 - 005 - User | View a message that says you need an enrollment code
    # before signing up
    @pytest.mark.skipif(str(14771) not in TESTS, reason='Excluded')
    def test_user_view_a_message_that_says_you_need_an_enrollment_14771(self):
        """View a message that says you need an enrollment code before signing up.

        Steps:
        Sign in as teacher100
        Click on a Concept Coach course
        Click on "Course Settings and Roster" from the user menu
        Click "Your Student Enrollment Code"
        Copy and paste the URL into an incognito window
        Click "Jump to Concept Coach"
        Click "Launch Concept Coach"

        Expected Result:
        The user is presented with a message that says "Sign up with your
        enrollment code. If you don't have an enrollment code, contact your
        instructor."
        """
        self.ps.test_updates['name'] = 'cc2.09.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.005', '14771']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        code, enrollement_url = self.get_enrollemnt_code()
        self.student.get(enrollement_url)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//p[@class="code-required"]')
            )
        )

        self.ps.test_updates['passed'] = True

    # 14821 - 006 - Student | Jump to CC from the top of the reading
    @pytest.mark.skipif(str(14821) not in TESTS, reason='Excluded')
    def test_student_jump_to_cc_from_the_top_of_the_reading_14821(self):
        """Jump to CC from the top of the reading.

        Steps:
        If the user has more than one course, click on a CC course name
        Click on a non-introductory section
        Click "Jump to Concept Coach"

        Expected Result:
        The screen jumps to the "Launch Concept Coach" button
        """
        self.ps.test_updates['name'] = 'cc2.09.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.006', '14821']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.login()
        self.student.find(
            By.XPATH, '//a[contains(@href,"cnx")]'      # possibly change
        ).click()
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button//span[text()="Contents"]')
            )
        ).click()
        self.student.sleep(0.5)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//span[@class="chapter-number" and text()="1.1"]')
            )
        ).click()
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]')
            )
        )

        self.ps.test_updates['passed'] = True

    # 14822 - 007 - Teacher | Jump to CC from the top of the reading
    @pytest.mark.skipif(str(14822) not in TESTS, reason='Excluded')
    def test_teacher_jump_to_cc_from_the_top_of_the_reading_14822(self):
        """Jump to CC from the top of the reading.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Online Book"
        Click on a non-introductory section
        Click "Jump to Concept Coach"

        Expected Result:
        The screen jumps to the "Launch Concept Coach" button
        """
        self.ps.test_updates['name'] = 'cc2.09.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.007', '14822']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        # open book
        self.teacher.driver.find_element(
            By.XPATH, '//a//span[contains(text(),"Online Book")]'
        ).click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        assert('cnx' in self.teacher.current_url()), \
            'Not viewing the textbook PDF'
        # get to non-introductory section of book
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button//span[text()="Contents"]')
            )
        ).click()
        self.student.sleep(0.5)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//span[@class="chapter-number" and text()="1.1"]')
            )
        ).click()
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]')
            )
        )
        self.ps.test_updates['passed'] = True

    # 107585 - 008 - Teacher | Register and enroll in a CC course without a
    # username
    @pytest.mark.skipif(str(107585) not in TESTS, reason='Excluded')
    def test_teacher_jump_to_cc_from_the_top_of_the_reading_107585(self):
        """Register and enroll in a CC course thout a username.

        Steps:
        [Get an enrollment link from a teacher in course settings and roster]
        Go to link
        Click orange "Jump to Concept Coach" button
        Click "Enroll in This Course"
        Click "sign Up and Enroll"

        [In the new window'
        Select 'Student' from the 'I am a' drop down menu
        Enter an email into the email text box
        Click 'Next'
        [an email with a pin is sent, log onto email and get pin]
        Enter Pin into text box
        Click 'Confirm'
        Enter password [staxly16] into password text box
        Re-Enter password in confirm password text box
        Click Submit
        Enter first name into the 'First Name' text box
        Enter last name into the 'Last Name' text box
        Enter school into 'School' text box
        Click the checkbox for 'I Agree' for the Terms of Use and the Privacy
        Policy
        Click 'Create Account'

        Click the checkbox and click 'I Agree' for the Terms of Use
        Click the checkbox and click 'I Agree' for the Privacy Policy

        Expected Result:
        Pop-up box for account creation is closed.
        New user is logged into Concept Coach.
        """
        self.ps.test_updates['name'] = 'cc2.09.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc2',
            'cc2.09',
            'cc2.09.008',
            '107585'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
class TestTrainingAndSupportingTeachersAndStudents(unittest.TestCase):
    """CC1.14 - Training and Supporting Teachers and Students."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.student = Student(
            use_env_vars=True,
            existing_driver=self.teacher.driver,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        self.student = None
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7704 - 001 - System | Concept Coach Zendesk is web-accessible
    @pytest.mark.skipif(str(7704) not in TESTS, reason='Excluded')
    def test_system_concept_coach_zendesk_is_web_accessible_7704(self):
        """Concept Coach Zendesk is web-accesible.

        Steps:
        Log in to Tutor as teacher
        If more then one course, click on a concept coach course
        In user menu in top right of header, click 'Get Help'

        Expected Result:
        In a new window or tab, zendesk help is opened
        """
        self.ps.test_updates['name'] = 'cc1.14.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.14',
            'cc1.14.001',
            '7704'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard/")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Get Help'
        ).click()
        # change to window with help center
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]'
        )
        assert('support' in self.teacher.current_url()), 'not at help center'

        self.ps.test_updates['passed'] = True

    # Case C7705 - 002 - Teacher | Can access user support
    @pytest.mark.skipif(str(7705) not in TESTS, reason='Excluded')
    def test_teacher_can_access_user_support_7705(self):
        """Can access user support.

        Steps:
        Click on the user menu
        Click on the Get Help option

        Expected Result:
        In a new tab or window Zendesk is opened
        """
        self.ps.test_updates['name'] = 'cc1.14.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.14',
            'cc1.14.002',
            '7705'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard/")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Get Help'
        ).click()
        # change to window with help center
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]'
        )
        assert('support' in self.teacher.current_url()), 'not at help center'

        self.ps.test_updates['passed'] = True

    # Case C7706 - 003 - Student | Can access user support
    @pytest.mark.skipif(str(7706) not in TESTS, reason='Excluded')
    def test_student_can_access_user_support_7706(self):
        """Can access user support.

        Steps:
        Click on the user menu
        Click on the Get Help option

        Expected Result:
        In a new tab or window zendesk is opened
        """
        self.ps.test_updates['name'] = 'cc1.14.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.14',
            'cc1.14.003',
            '7706'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.login()
        self.student.open_user_menu()
        self.student.find(
            By.LINK_TEXT, 'Get Help'
        ).click()
        # change to window with help center
        window_with_help = self.student.driver.window_handles[1]
        self.student.driver.switch_to_window(window_with_help)
        self.student.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]'
        )
        assert('support' in self.student.current_url()), 'not at help center'
        self.ps.test_updates['passed'] = True

    # Case C7707 - 004 - Non-user | Submit support questions
    @pytest.mark.skipif(str(7707) not in TESTS, reason='Excluded')
    def test_nonuser_submit_support_questions_7707(self):
        """Submit support questions.

        Steps:
        Go to the Concept Coach landing page
        click support in the header
        enter text into the search box
        click contact us
        fillout form
        click Submit

        Expected Result:
        'Message sent' displayed in help box
        """
        self.ps.test_updates['name'] = 'cc1.14.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.14',
            'cc1.14.004',
            '7707'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.sleep(1)
        # number hardcoded because condenses at different size than tutor
        if self.teacher.driver.get_window_size()['width'] < 1105:
            element = self.teacher.wait.until(
                expect.visibility_of_element_located(
                    (By.XPATH, '//label[@for="mobileNavToggle"]')
                )
            )
            actions = ActionChains(self.teacher.driver)
            # use action chain because it is clicking to the wrong elemnt
            actions.move_to_element(element)
            actions.click()
            actions.perform()
        support = self.teacher.find(
            By.LINK_TEXT, 'support'
        )
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(support)
        actions.click()
        actions.perform()
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'searchAskInput'
        ).send_keys('fake_question')
        self.teacher.find(
            By.ID, 'searchAskButton'
        ).click()
        self.teacher.find(
            By.LINK_TEXT, 'Contact Us'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//input[contains(@id,"contactUsForm:firstName")]'
        ).send_keys('qa')
        self.teacher.find(
            By.XPATH, '//input[contains(@id,"contactUsForm:lastName")]'
        ).send_keys('test')
        self.teacher.find(
            By.XPATH, '//input[contains(@id,"contactUsForm:email")]'
        ).send_keys('*****@*****.**')
        self.teacher.find(
            By.XPATH, '//div[@class="submit-container"]//input'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//p[contains(text(),"Thank you")]')
            )
        )
        self.ps.test_updates['passed'] = True

    # Case C7708 - 005 - Teacher | Submit support questions
    @pytest.mark.skipif(str(7708) not in TESTS, reason='Excluded')
    def test_teacher_submit_support_questions_7708(self):
        """Submit support questions.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If user has more than one course, click on a Concept Coach course
        Click the user menu in the right corner of the header
        Click "Get Help"
        Click "Submit a request"
        Fill out all the necessary text fields
        Click "Submit"

        Expected Result:
        The user submits support questions
        """
        self.ps.test_updates['name'] = 'cc1.14.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.14',
            'cc1.14.005',
            '7708'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard/")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Get Help'
        ).click()
        # change to window with help center
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]'
        )
        assert('support' in self.teacher.current_url()), 'not at help center'
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'searchAskInput'
        ).send_keys('fake_question')
        self.teacher.find(
            By.ID, 'searchAskButton'
        ).click()
        self.teacher.find(
            By.LINK_TEXT, 'Contact Us'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//input[contains(@id,"contactUsForm:firstName")]'
        ).send_keys('qa')
        self.teacher.find(
            By.XPATH, '//input[contains(@id,"contactUsForm:lastName")]'
        ).send_keys('test')
        self.teacher.find(
            By.XPATH, '//input[contains(@id,"contactUsForm:email")]'
        ).send_keys('*****@*****.**')
        self.teacher.find(
            By.XPATH, '//div[@class="submit-container"]//input'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//p[contains(text(),"Thank you")]')
            )
        )
        self.ps.test_updates['passed'] = True

    # Case C7709 - 006 - Student | Submit support questions
    @pytest.mark.skipif(str(7709) not in TESTS, reason='Excluded')
    def test_student_submit_support_questions_7709(self):
        """Submit support questions.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account in the username and password text boxes
        Click on the 'Sign in' button
        Click the user menu in the right corner of the header
        Click "Get Help"
        Click "Submit a request"
        Fill out all the necessary text fields
        Click "Submit"

        Expected Result:
        The user submits support questions
        """
        self.ps.test_updates['name'] = 'cc1.14.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.14',
            'cc1.14.006',
            '7709'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.login()
        self.student.open_user_menu()
        self.student.find(
            By.LINK_TEXT, 'Get Help'
        ).click()
        # change to window with help center
        window_with_help = self.student.driver.window_handles[1]
        self.student.driver.switch_to_window(window_with_help)
        self.student.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]'
        )
        assert('support' in self.student.current_url()), 'not at help center'
        self.student.page.wait_for_page_load()
        self.student.find(
            By.ID, 'searchAskInput'
        ).send_keys('fake_question')
        self.student.find(
            By.ID, 'searchAskButton'
        ).click()
        self.student.find(
            By.LINK_TEXT, 'Contact Us'
        ).click()
        self.student.page.wait_for_page_load()
        self.student.find(
            By.XPATH, '//input[contains(@id,"contactUsForm:firstName")]'
        ).send_keys('qa')
        self.student.find(
            By.XPATH, '//input[contains(@id,"contactUsForm:lastName")]'
        ).send_keys('test')
        self.student.find(
            By.XPATH, '//input[contains(@id,"contactUsForm:email")]'
        ).send_keys('*****@*****.**')
        self.student.find(
            By.XPATH, '//div[@class="submit-container"]//input'
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//p[contains(text(),"Thank you")]')
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7710 - 007 - Teacher | View instructions on how to use CC
    @pytest.mark.skipif(str(7710) not in TESTS, reason='Excluded')
    def test_teacher_view_instructions_on_how_to_use_cc_7710(self):
        """View instructions on how to use Concept Coach.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If user has more than one course, click on a Concept Coach course
        Click the user menu in the right corner of the header
        Click "Get Help"
        Click "Getting Started Guide"
        * Click on the pdf link
            OR
        * Click "Getting Started" from the user menu

        Expected Result:
        The user is presented with a guide to use CC
        """
        self.ps.test_updates['name'] = 'cc1.14.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.14',
            'cc1.14.007',
            '7710'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard/")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Getting Started'
        ).click()
        self.teacher.find(
            By.XPATH, '//h3[contains(text(),"Getting Started")]'
        ).click()
        assert('help' in self.teacher.current_url()), 'not at help center'

        self.ps.test_updates['passed'] = True

    # Case C7711 - 008 - Student | View instructions on how to use CC
    @pytest.mark.skipif(str(7711) not in TESTS, reason='Excluded')
    def test_student_view_instructions_on_how_to_use_cc_7711(self):
        """View instructions on how to use Concept Coach.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account in the username and password text boxes
        Click on the 'Sign in' button
        Click the user menu in the right corner of the header
        Click "Get Help"
        Scroll down to the questions under "Students"

        Expected Result:
        The user is presented with instructions on how to use CC
        """
        self.ps.test_updates['name'] = 'cc1.14.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.14',
            'cc1.14.008',
            '7711'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.login()
        self.student.open_user_menu()
        self.student.find(
            By.LINK_TEXT, 'Get Help'
        ).click()
        # change to window with help center
        window_with_help = self.student.driver.window_handles[1]
        self.student.driver.switch_to_window(window_with_help)
        self.student.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]'
        )
        assert('support' in self.student.current_url()), 'not at help center'
        self.ps.test_updates['passed'] = True

    # Case C7712 - 009 - Teacher | View instructions on how to assign CC
    @pytest.mark.skipif(str(7712) not in TESTS, reason='Excluded')
    def test_teacher_view_instructions_on_how_to_assign_cc_7712(self):
        """View instructions on how to use Concept Coach.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If user has more than one course, click on a Concept Coach course
        Click the user menu in the right corner of the header
        Click "Get Help"

        Expected Result:
        Taken to Zendesk in a new window or tab
        Assorted help is displayed
        """
        self.ps.test_updates['name'] = 'cc1.14.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.14',
            'cc1.14.009',
            '7712'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard/")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Get Help'
        ).click()
        # change to window with help center
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]'
        )
        assert('support' in self.teacher.current_url()), 'not at help center'

        self.ps.test_updates['passed'] = True

    # Case C7713 - 010 - Student | Get help during account registration
    @pytest.mark.skipif(str(7713) not in TESTS, reason='Excluded')
    def test_student_get_help_during_account_registration_7713(self):
        """View instructions on how to use Concept Coach.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc1.14.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.14',
            'cc1.14.010',
            '7713'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7714 - 011 - Teacher | View instructions for Legacy users
    # transitioning to Concept Coach
    @pytest.mark.skipif(str(7714) not in TESTS, reason='Excluded')
    def test_teacher_view_instructions_for_legacy_users_transition_7714(self):
        """View instructions for Legacy users transitioning to Concept Coach.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc1.14.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.14',
            'cc1.14.011',
            '7714'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
Ejemplo n.º 8
0
class TestScoresReportingTeacher(unittest.TestCase):
    def setUp(self):
        """Pretest Settings"""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(use_env_vars=True,
                               pasta_user=self.ps,
                               capabilities=self.desired_capabilities)
        self.teacher.login()

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    @pytest.mark.skipif(str(1) not in TESTS, reason='Excluded')
    def test_score_stuff(self):
        """
        Go to https://tutor-qa.openstax.org/
            Login with the account [ teacher01 | password]
            If the user has more than one course, select a Tutor course
            Click "Student Scores" from user menu
            ***The user is presented with the overall score column (t2.08.05)
            ***

            Click "number"
            ***Overall score percentage does not change format when selecting Number in the Percentage/Number toggle (t2.08.06)
            ***

            Scroll to a reading assignment
            ***The user is presented with progress icon but no score (t2.08.07)***


            Click on the info icon next to "Class Performance"
            ***The info icon displays a definition of how class and overall scores are calculated (t2.08.08)***

            Scroll until an assignment with an orange triangle is found
            Click on the orange triangle in the upper right corner of a progress cell
            Click "Accept late score" for a homework, OR Click "Accept late progress" for a reading
            ***The late score replaces the score at due date (t2.08.09)***
            ***The progress icon changes to reflect the last worked progress (t2.08.11)***

            Scroll until an assignment with a gray triangle is found
            Click on the gray triangle in the upper right corner of a progress cell
            Click "Use this score" for a homework OR "Use this Progress" for a reading
            ***The score is converted back to the score at due date (t2.08.10)***

            Click "Export"
            ***The teacher should be presented with their students' scores for each section taught (t1.13.03)***

            Click on the "Export" button
            ***Spreadsheet of scores is generating (t1.23.03)***
            ***External assignments are not included in the scores export t2.08.14***

            Select destination for saved spreadsheet in the pop up
            Click on the "Save" Button on the pop up
            ***Spreadsheet of scores is saved to chosen destination as an xlsx file
            (t1.23.4) ***

            Expected result:

            ***Corresponds to ***
            t1.23.03 --> 04
            t2.10 - 6,7
            T2.08 - 5--> 11, 14
            """
        ### ARE WE JUST GONNA HARD CODE THE COURSE?
        ### MAYBE THERE'S ANTOEHR WAY WE CAN ASSIGN IT?
        self.teacher.select_course(appearance='college_physics')

        assert('course' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.teacher.find(By.PARTIAL_LINK_TEXT, 'Student Scores').click()

        assert('scores' in self.teacher.current_url()), \
            'Not viewing Student Scores'

        # t2.08.05 --> The user is presented with the overall score column (t2.08.05)

        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, "//div[@class='overall-header-cell']")))

        #t2.08.06 --> Overall score percentage does not change format
        # when selecting Number in the Percentage/Number toggle

        overall_average1 = self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, "//div[contains(@class,'overall-average')]"
                 "//span"))).text

        self.teacher.find(
            By.XPATH, "//button[contains(@class,'btn btn-sm btn-default')"
            "and contains(text(),'number')]").click()

        overall_average2 = self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, "//div[contains(@class,'overall-average')]"
                 "//span"))).text

        assert (overall_average1 == overall_average2), \
            'Overall average is not the same between percentage and number'

        ### ADD A SCROLLING FEATURE HERE??

        # t2.08.07 -->  The user is presented with progress icon but no score

        # t2.08.08 --> The info icon displays a definition of how class and overall scores are calculated

        self.teacher.find(
            By.XPATH,
            "//i[@class='tutor-icon fa fa-info-circle clickable']").click()
        self.teacher.sleep(2)
        self.teacher.find(By.XPATH, "//div[@class='popover-content']")

        # t2.08.09 --> The late score replaces the score at due date
        found = False

        scrollbar = self.teacher.find(
            By.XPATH, "//div[@class='ScrollbarLayout_main " +
            "ScrollbarLayout_mainHorizontal public_Scrollbar_main " +
            "public_Scrollbar_mainOpaque']")
        scrollbar.click()

        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(scrollbar)
        actions.click(scrollbar)
        actions.perform()

        newbar = self.teacher.find(
            By.XPATH, "//div[@class='ScrollbarLayout_main " +
            "ScrollbarLayout_mainHorizontal public_Scrollbar_main " +
            "public_Scrollbar_mainOpaque public_Scrollbar_mainActive']")

        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(newbar)
        actions.click(newbar)
        actions.perform()
        scrolls = 0
        # Four arrow rights bring a new assignment into view, try to bring
        # Bring three new assignments into view at a time
        p = False

        for num in range(100):
            for num1 in range(12):
                newbar.send_keys(Keys.ARROW_RIGHT)
            if len(
                    self.teacher.driver.find_elements_by_xpath(
                        "//div[@class='late-caret']")) > 0:
                for num2 in range(5):
                    newbar.send_keys(Keys.ARROW_RIGHT)
                while not found:
                    try:
                        caret = self.teacher.find(
                            By.XPATH, "//div[@class='late-caret']")

                        try:
                            parent = caret.find_element_by_xpath(
                                "..").find_element_by_xpath("..")
                        except:
                            pass
                        try:
                            worked = parent.find_element_by_class_name(
                                "worked")
                        except:
                            pass
                        try:
                            not_started = worked.find_elements_by_class_name(
                                "not-started")
                        except:
                            pass

                        try:
                            if len(worked.find_elements_by_tag_name(
                                    'path')) > 0:
                                p = True

                        except:
                            pass

                        caret1 = caret.find_element_by_xpath("..")

                        self.teacher.sleep(3)
                        caret.click()

                        self.teacher.find(
                            By.XPATH,
                            "//button[@class='late-button btn btn-default']"
                        ).click()
                        found = True
                        break

                    except:

                        if scrolls == 20:
                            break
                        try:
                            scrollbar = self.teacher.find(
                                By.XPATH,
                                "//div[@class='ScrollbarLayout_main " +
                                "ScrollbarLayout_mainVertical " +
                                "public_Scrollbar_main']")

                            scrollbar.click()

                        except:
                            pass

                        newbar = self.teacher.find(
                            By.XPATH, "//div[@class='ScrollbarLayout_main " +
                            "ScrollbarLayout_mainVertical " +
                            "public_Scrollbar_main " +
                            "public_Scrollbar_mainActive']")

                        actions = ActionChains(self.teacher.driver)
                        actions.move_to_element(newbar)
                        actions.click(newbar)
                        actions.perform()
                        for i in range(3):
                            scrolls += 1
                            newbar.send_keys(Keys.ARROW_DOWN)
                break

        revert = False
        diff = False

        lates = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='late-caret accepted']")

        if len(not_started) > 0:
            slice_late = worked.find_elements_by_tag_name('circle')
            assert(slice_late[0].get_attribute('class') == 'slice late'), \
                'No change in the display of progress bar'
            diff = True

        # Case if assignment was partially complete before due date
        else:
            assert (p)
            assert(len(worked.find_elements_by_tag_name('path')) == 0), \
                'No change'

            diff = True

        if found:
            for item in lates:
                try:
                    item.click()
                    self.teacher.find(
                        By.XPATH,
                        "//button[@class='late-button btn btn-default']"
                    ).click()
                    revert = True
                    break

                except:
                    pass

        item = worked.find_element_by_xpath(
            "//div[@class='late-caret accepted']")

        item.click()
        self.teacher.find(
            By.XPATH,
            "//button[@class='late-button btn btn-default']").click()
        revert = True

        self.teacher.sleep(5)
        assert (found), \
            'Not found'

        assert (revert), \
            'Didnt revert'

        # t2.08.10 --> The score is converted back to the score at due date
        scrollbar.click()

        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(scrollbar)
        actions.click(scrollbar)
        actions.perform()

        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(newbar)
        actions.click(newbar)
        actions.perform()
        scrolls = 0

        # Four arrow rights bring a new assignment into view, try to bring
        # Bring three new assignments into view at a time

        for num in range(100):
            for num1 in range(12):
                newbar.send_keys(Keys.ARROW_RIGHT)
            if len(
                    self.teacher.driver.find_elements_by_xpath(
                        "//div[@class='late-caret accepted']")) > 0:
                for num2 in range(3):
                    newbar.send_keys(Keys.ARROW_RIGHT)
                while not found:
                    try:

                        caret = self.teacher.find(
                            By.XPATH, "//div[@class='late-caret accepted']")
                        self.teacher.sleep(2)
                        caret.click()
                        self.teacher.sleep(5)

                        self.teacher.find(
                            By.XPATH,
                            "//button[@class='late-button btn btn-default']"
                        ).click()
                        self.teacher.sleep(5)
                        """
                        self.teacher.find_elements_by_xpath(
                            By.XPATH, "//div[@class='late-caret accepted']"
                        )[index].click()
        
                        self.teacher.find(
                            By.XPATH,
                            "//button[@class='late-button btn btn-default']"
                        ).click()
                        """
                        found = True
                        break

                    except:

                        if scrolls == 20:
                            break
                        try:
                            scrollbar = self.teacher.find(
                                By.XPATH,
                                "//div[@class='ScrollbarLayout_main " +
                                "ScrollbarLayout_mainVertical " +
                                "public_Scrollbar_main']")

                            scrollbar.click()

                        except:
                            pass

                        newbar = self.teacher.find(
                            By.XPATH, "//div[@class='ScrollbarLayout_main " +
                            "ScrollbarLayout_mainVertical " +
                            "public_Scrollbar_main " +
                            "public_Scrollbar_mainActive']")

                        actions = ActionChains(self.teacher.driver)
                        actions.move_to_element(newbar)
                        actions.click(newbar)
                        actions.perform()
                        for i in range(1):
                            scrolls += 1
                            newbar.send_keys(Keys.ARROW_DOWN)

                break

        lates = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='late-caret']")

        revert = False
        if found:
            for item in lates:
                try:
                    item.click()
                    self.teacher.find(
                        By.XPATH,
                        "//button[@class='late-button btn btn-default']"
                    ).click()
                    revert = True
                    break

                except:
                    pass

        self.teacher.sleep(5)
        assert (found), \
            'Not found'

        assert (revert), \
            'Didnt revert'

        # t2.08.11  --> The progress icon changes to reflect the last worked progress

        #  Setup scrollbar for scrolling
        scrollbar = self.teacher.find(
            By.XPATH, "//div[@class='ScrollbarLayout_main " +
            "ScrollbarLayout_mainHorizontal public_Scrollbar_main " +
            "public_Scrollbar_mainOpaque']")
        scrollbar.click()

        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(scrollbar)
        actions.click(scrollbar)
        actions.perform()

        newbar = self.teacher.find(
            By.XPATH, "//div[@class='ScrollbarLayout_main " +
            "ScrollbarLayout_mainHorizontal public_Scrollbar_main " +
            "public_Scrollbar_mainOpaque public_Scrollbar_mainActive']")
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(newbar)
        actions.click(newbar)
        actions.perform()
        scrolls = 0

        p = False
        for i in range(6):
            newbar.send_keys(Keys.PAGE_UP)
        self.teacher.sleep(3)
        # Four arrow rights bring a new assignment into view, try to bring
        # Bring three new assignments into view at a time
        for num in range(100):
            for num1 in range(12):
                newbar.send_keys(Keys.ARROW_RIGHT)
            if len(
                    self.teacher.driver.find_elements_by_xpath(
                        "//div[@class='late-caret']")) > 0:
                for num2 in range(3):
                    newbar.send_keys(Keys.ARROW_RIGHT)

                while not found:
                    try:
                        caret = self.teacher.find(
                            By.XPATH, "//div[@class='late-caret']")

                        try:
                            parent = caret.find_element_by_xpath(
                                "..").find_element_by_xpath("..")
                        except:
                            pass
                        try:
                            worked = parent.find_element_by_class_name(
                                "worked")
                        except:
                            pass
                        try:
                            not_started = worked.find_elements_by_class_name(
                                "not-started")
                        except:
                            pass

                        try:
                            if len(worked.find_elements_by_tag_name(
                                    'path')) > 0:
                                p = True

                        except:
                            pass

                        caret1 = caret.find_element_by_xpath("..")

                        caret1.click()
                        self.teacher.find(
                            By.XPATH,
                            "//button[@class='late-button btn btn-default']"
                        ).click()
                        found = True
                        break

                    # Scroll down if the late assignment is not immediately
                    # visible, continue to scroll until found
                    except:

                        if scrolls == 20:
                            break
                        try:
                            scrollbar = self.teacher.find(
                                By.XPATH,
                                "//div[@class='ScrollbarLayout_main " +
                                "ScrollbarLayout_mainVertical " +
                                "public_Scrollbar_main']")

                            scrollbar.click()

                        except:
                            pass

                        newbar = self.teacher.find(
                            By.XPATH, "//div[@class='ScrollbarLayout_main " +
                            "ScrollbarLayout_mainVertical " +
                            "public_Scrollbar_main " +
                            "public_Scrollbar_mainActive']")

                        actions = ActionChains(self.teacher.driver)
                        actions.move_to_element(newbar)
                        actions.click(newbar)
                        actions.perform()
                        for i in range(1):
                            scrolls += 1
                            newbar.send_keys(Keys.ARROW_DOWN)

                break

        revert = False
        diff = False

        # Case if assignment was not started at all before due date
        if len(not_started) > 0:
            slice_late = worked.find_elements_by_tag_name('circle')
            assert (slice_late[0].get_attribute('class') == 'slice late'), \
                'No change'

            diff = True

        # Case if assignment was partially complete before due date
        else:
            assert (p)
            assert (len(worked.find_elements_by_tag_name('path')) == 0), \
                'No change'

            diff = True

        assert (diff), \
            'No change'

        item = worked.find_element_by_xpath(
            "//div[@class='late-caret accepted']")

        item.click()
        self.teacher.find(
            By.XPATH,
            "//button[@class='late-button btn btn-default']").click()
        revert = True

        self.teacher.sleep(5)
        assert (found), \
            'Not found'

        assert (revert), \
            'Didnt revert'
        # t1.23.03 --> Spreadsheet of scores is generating
        # The teacher should be presented with their students' scores for each section taught

        # t2.08.14 --> External assignments are not included in the scores export

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@class,"export-button-buttons")]//button'
                 ))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="export-button"]//button[text()="Export"]')))
        coursename = self.teacher.driver.find_element(
            By.XPATH, '//div[@class="course-name"]').text
        coursename = coursename.replace(' ', '_') + "_Scores"
        home = os.getenv("HOME")
        files = os.listdir(home + '/Downloads')
        for i in range(len(files)):
            if (coursename in files[i]) and (files[i][-5:] == '.xlsx'):
                break
            else:
                if i == len(files) - 1:
                    raise Exception

    # t1.23.04 --> Spreadsheet of scores is saved to chosen destination as an xlsx file

        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@class,"export-button-buttons")]//button'
                 ))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="export-button"]//button[text()="Export"]')))
        coursename = self.teacher.driver.find_element(
            By.XPATH, '//div[@class="course-name"]').text
        coursename = coursename.replace(' ', '_') + "_Scores"
        home = os.getenv("HOME")
        files = os.listdir(home + '/Downloads')
        for i in range(len(files)):
            if (coursename in files[i]) and (files[i][-5:] == '.xlsx'):
                break
            else:
                if i == len(files) - 1:
                    raise Exception
Ejemplo n.º 9
0
class TestTutorWorksWithCNX(unittest.TestCase):
    """T1.27 - Tutor works with CNX."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.teacher.delete()
        except:
            pass

    # Case C8182 - 001 - System | CNX needs to handle LaTeX in Exercises
    @pytest.mark.skipif(str(8182) not in TESTS, reason='Excluded')
    def test_system_cnx_needs_to_handle_latex_in_exercises_8182(self):
        """CNX needs to handle LaTeX in Exercises.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't1.27.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.27',
            't1.27.001',
            '8182'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C8183 - 002 - System | CNX pulls exercises from Tutor
    @pytest.mark.skipif(str(8183) not in TESTS, reason='Excluded')
    def test_system_cnx_pulls_exercises_from_tutor_8183(self):
        """Story Text.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't1.27.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.27',
            't1.27.002',
            '8183'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
class TestStudentsWorkAssignments(unittest.TestCase):
    """CC1.08 - Students Work Assignments."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(username=os.getenv('TEACHER_USER_CC'),
                                   password=os.getenv('TEACHER_PASSWORD'),
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
        else:
            self.teacher = Teacher(
                username=os.getenv('TEACHER_USER_CC'),
                password=os.getenv('TEACHER_PASSWORD'),
            )
        self.teacher.login()
        if 'cc-dashboard' not in self.teacher.current_url():
            courses = self.teacher.find_all(By.CLASS_NAME,
                                            'tutor-booksplash-course-item')
            assert (courses), 'No courses found.'
            if not isinstance(courses, list):
                courses = [courses]
            course_id = randint(0, len(courses) - 1)
            self.course = courses[course_id].get_attribute('data-title')
            self.teacher.select_course(title=self.course)
        self.teacher.goto_course_roster()
        try:
            section = self.teacher.find_all(
                By.XPATH, '//*[contains(@class,"nav-tabs")]//a')
            if isinstance(section, list):
                section = '%s' % section[randint(0, len(section) - 1)].text
            else:
                section = '%s' % section.text
        except Exception:
            section = '%s' % randint(100, 999)
            self.teacher.add_course_section(section)
        self.code = self.teacher.get_enrollment_code(section)
        print('Course Phrase: ' + self.code)
        self.book_url = self.teacher.find(
            By.XPATH,
            '//a[span[contains(text(),"Online Book")]]').get_attribute('href')
        self.teacher.find(By.CSS_SELECTOR, 'button.close').click()
        self.teacher.sleep(0.5)
        self.teacher.logout()
        self.teacher.sleep(1)
        self.student = Student(use_env_vars=True,
                               existing_driver=self.teacher.driver)
        self.first_name = Assignment.rword(6)
        self.last_name = Assignment.rword(8)
        self.email = self.first_name + '.' \
            + self.last_name \
            + '@tutor.openstax.org'

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7691 - 001 - Student | Selects an exercise answer
    @pytest.mark.skipif(str(7691) not in TESTS, reason='Excluded')
    def test_student_select_an_exercise_answer_7691(self):
        """Select an exercise answer."""
        self.ps.test_updates['name'] = 'cc1.08.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.001', '7691']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.get(self.book_url)
        self.student.sleep(2)
        self.student.find_all(By.XPATH, '//a[@class="nav next"]')[0].click()
        self.student.page.wait_for_page_load()
        try:
            widget = self.student.find(By.ID, 'coach-wrapper')
        except:
            self.student.find_all(By.XPATH,
                                  '//a[@class="nav next"]')[0].click()
            self.student.page.wait_for_page_load()
            try:
                self.student.sleep(1)
                widget = self.student.find(By.ID, 'coach-wrapper')
            except:
                self.student.find_all(By.XPATH,
                                      '//a[@class="nav next"]')[0].click()
                self.student.page.wait_for_page_load()
                self.student.sleep(1)
                widget = self.student.find(By.ID, 'coach-wrapper')
        Assignment.scroll_to(self.student.driver, widget)
        self.student.find(
            By.XPATH,
            '//button[span[contains(text(),"Launch Concept Coach")]]').click()
        self.student.sleep(1.5)
        base_window = self.student.driver.window_handles[0]
        self.student.find(By.CSS_SELECTOR, 'div.sign-up').click()
        self.student.sleep(3)
        popup = self.student.driver.window_handles[1]
        self.student.driver.switch_to_window(popup)
        self.student.find(By.LINK_TEXT, 'Sign up').click()
        self.student.find(By.ID, 'identity-login-button').click()
        self.student.find(By.ID,
                          'signup_first_name').send_keys(self.first_name)
        self.student.find(By.ID, 'signup_last_name').send_keys(self.last_name)
        self.student.find(By.ID, 'signup_email_address').send_keys(self.email)
        self.student.find(By.ID, 'signup_username').send_keys(self.last_name)
        self.student.find(By.ID,
                          'signup_password').send_keys(self.student.password)
        self.student.find(By.ID, 'signup_password_confirmation').send_keys(
            self.student.password)
        self.student.find(By.ID, 'create_account_submit').click()
        self.student.find(By.ID, 'i_agree').click()
        self.student.find(By.ID, 'agreement_submit').click()
        self.student.find(By.ID, 'i_agree').click()
        self.student.find(By.ID, 'agreement_submit').click()
        self.student.driver.switch_to_window(base_window)
        self.student.find(
            By.XPATH,
            '//input[contains(@label,"Enter the enrollment code")]').send_keys(
                self.code)
        self.student.sleep(2)
        self.student.find(By.CSS_SELECTOR, 'button.enroll').click()
        self.student.sleep(2)
        self.student.find(By.CSS_SELECTOR,
                          'div.field input.form-control').send_keys(
                              self.last_name)
        self.student.find(By.CSS_SELECTOR, 'button.async-button').click()
        self.student.sleep(5)
        try:
            self.student.find(By.XPATH, '//button[text()="Continue"]').click()
        except:
            print('Two-step message not seen.')
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH,
                 '//div[@class="openstax-question"]//textarea'))).send_keys(
                     chomsky())
        self.student.find(By.CSS_SELECTOR, 'button.async-button').click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="answer-letter"]')))
        answers = self.student.find_all(By.CSS_SELECTOR, 'div.answer-letter')
        answers[randint(0, len(answers) - 1)].click()
        self.student.find(By.CSS_SELECTOR, 'button.async-button').click()
        self.student.find(By.CSS_SELECTOR, 'button.async-button').click()

        self.ps.test_updates['passed'] = True

    # Case C7692 - 002 - Student | After answering an exercise feedback
    # is presented
    @pytest.mark.skipif(str(7692) not in TESTS, reason='Excluded')  # NOQA
    def test_student_after_answering_an_exercise_feedback_7692(self):
        """View section completion report.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click the 'Answer' button
        Click a multiple choice answer
        Click the 'Submit' button

        Expected Result:
        The correct answer is displayed and feedback is given.
        """
        self.ps.test_updates['name'] = 'cc1.08.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.002', '7692']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        # //span[@class='title section']
        # get the 21 drop downs in toc

        #    By.PARTIAL_LINK_TEXT, "Macro Econ").click()
        self.student.select_course(appearance='macro_economics')
        self.student.sleep(5)
        self.student.find(By.XPATH, "//button[@class='toggle btn']").click()
        self.student.sleep(3)

        finished = False

        # Expand all the chapters in the table of contents
        chapters = self.student.driver.find_elements_by_xpath(
            "//span[@class='title section']")
        chapters.pop(0)
        for chapter in chapters:
            chapter.click()

        # Get all sections, excluding the preface
        sections = self.student.driver.find_elements_by_xpath(
            "//a/span[@class='title']")
        sections.pop(0)

        self.student.sleep(2)

        length = len(sections)

        for num in range(length):

            sections = self.student.driver.find_elements_by_xpath(
                "//a/span[@class='title']")
            sections.pop(0)
            sections[num].click()
            self.student.sleep(3)

            if 'Introduction-to' not in self.student.current_url():
                # Jump to the Concept Coach widget and open Concept Coach
                self.student.find(
                    By.XPATH,
                    "//div[@class='jump-to-cc']/a[@class='btn']").click()
                self.student.sleep(2)
                self.student.find(
                    By.XPATH,
                    "//button[@class='btn btn-lg btn-primary']").click()
                self.student.sleep(2)

                # If this section has been completed already,
                # leave and go to the next section
                breadcrumbs = self.student.driver.find_elements_by_xpath(
                    "//div[@class='task-breadcrumbs']/span")

                breadcrumbs[-1].click()
                self.student.sleep(3)

                if len(
                        self.student.driver.find_elements_by_xpath(
                            "//div[@class='card-body coach-coach-review-completed'][1]"
                        )) > 0:
                    self.student.find(
                        By.XPATH, "//a/button[@class='btn-plain " +
                        "-coach-close btn btn-default']").click()

                # Else, go through questions until a blank one is found
                # and answer the question
                else:
                    for question in breadcrumbs:
                        question.click()

                        if len(
                                self.student.driver.find_elements_by_xpath(
                                    "//div[@class='question-feedback bottom']")
                        ) > 0:
                            continue

                        else:
                            while len(
                                    self.student.driver.find_elements_by_xpath(
                                        "//div[@class='question-feedback bottom']"
                                    )) == 0:

                                if len(
                                        self.student.driver.
                                        find_elements_by_xpath(
                                            "//button[@class='btn btn-default']"
                                        )) > 0:
                                    self.student.find(
                                        By.XPATH,
                                        "//button[@class='btn btn-default']"
                                    ).click()
                                    continue

                                # Free response
                                if self.student.find(
                                        By.XPATH,
                                        "//button[@class='async-button " +
                                        "continue btn btn-primary']"
                                ).text == 'Answer':
                                    self.student.find(
                                        By.XPATH, "//textarea").send_keys(
                                            'An answer for this textarea')
                                    self.student.find(
                                        By.XPATH,
                                        "//button[@class='async-button " +
                                        "continue btn btn-primary']").click()
                                    self.student.sleep(3)

                                # Multiple Choice
                                elif self.student.find(
                                        By.XPATH,
                                        "//button[@class='async-button " +
                                        "continue btn btn-primary']"
                                ).text == 'Submit':
                                    answers = self.student.driver.find_elements(  # NOQA
                                        By.CLASS_NAME, 'answer-letter')
                                    self.student.sleep(0.8)
                                    rand = randint(0, len(answers) - 1)
                                    answer = chr(ord('a') + rand)
                                    Assignment.scroll_to(
                                        self.student.driver, answers[0])
                                    if answer == 'a':
                                        self.student.driver.execute_script(
                                            'window.scrollBy(0, -160);')
                                    elif answer == 'd':
                                        self.student.driver.execute_script(
                                            'window.scrollBy(0, 160);')
                                    answers[rand].click()

                                    self.student.find(
                                        By.XPATH,
                                        "//button[@class='async-button " +
                                        "continue btn btn-primary']").click()
                                    self.student.sleep(3)

                                    finished = True

                        break

            if finished:
                break

        self.student.sleep(5)
        self.student.find(By.XPATH, "//div[@class='question-feedback bottom']")

        self.ps.test_updates['passed'] = True

    # Case C7693 - 003 - System | Assessments are from the current module
    @pytest.mark.skipif(str(7693) not in TESTS, reason='Excluded')  # NOQA
    def test_system_assessments_are_from_the_current_module_7693(self):
        """Assessment is from the current module.

        Steps:


        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc1.08.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.003', '7693']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7694 - 004 - System | Spaced practice assessments are from
    # previously worked modules
    @pytest.mark.skipif(str(7694) not in TESTS, reason='Excluded')  # NOQA
    def test_system_spaced_practice_assessments_are_from_previo_7694(self):
        """Spaced practice assessments are from previousy worked modules.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Select a non-introductory section
        Click Jump to Concept Coach
        Click Launch Concept Coach
        Go through the assessments until you get to the Spaced Practice

        Expected Result:
        The section number beneath the text box is from a previous section
        """
        self.ps.test_updates['name'] = 'cc1.08.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.004', '7694']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7695 - 005 - System | Modules without assessments do not display
    # the Concept Coach widget
    @pytest.mark.skipif(str(7695) not in TESTS, reason='Excluded')  # NOQA
    def test_system_modules_without_assessments_do_not_display_7695(self):
        """Module without assessments does not display the CC widget.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Click on an introductory section

        Expected Result:
        The Concept Coach widget does not appear.
        """
        self.ps.test_updates['name'] = 'cc1.08.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.005', '7695']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.select_course(appearance='macro_economics')
        self.student.sleep(5)
        self.student.find(By.XPATH, "//button[@class='toggle btn']").click()
        self.student.sleep(3)

        # Expand all the chapters in the table of contents
        chapters = self.student.driver.find_elements_by_xpath(
            "//span[@class='title section']")
        chapters.pop(0)
        for chapter in chapters:
            chapter.click()

        # Get all sections, excluding the preface
        sections = self.student.driver.find_elements_by_xpath(
            "//a/span[@class='title']")
        sections.pop(0)

        self.student.sleep(2)

        length = len(sections)

        for num in range(length):

            sections = self.student.driver.find_elements_by_xpath(
                "//a/span[@class='title']")
            sections.pop(0)
            sections[num].click()
            self.student.sleep(3)

            if 'Introduction-to' in self.student.current_url():
                # Jump to the Concept Coach widget and open Concept Coach
                count = self.student.driver.find_elements_by_xpath(
                    "//div[@class='jump-to-cc']/a[@class='btn']")
                self.student.sleep(2)

                assert (len(count) == 0), "Intro should not have CC widget"
                break

        self.ps.test_updates['passed'] = True

    # Case C7696 - 006 - Student | Assignment is assistive technology friendly
    @pytest.mark.skipif(str(7696) not in TESTS, reason='Excluded')  # NOQA
    def test_student_assignment_is_assistive_technology_friendly_7696(self):
        """Assignment is assistive technology friendly.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click the 'Answer' button
        Type a, b, c, or d

        Expected Result:
        A multiple choice answer matching the letter typed should be selected.
        """
        self.ps.test_updates['name'] = 'cc1.08.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.006', '7696']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.select_course(appearance='macro_economics')
        self.student.sleep(5)
        self.student.find(By.XPATH, "//button[@class='toggle btn']").click()
        self.student.sleep(3)

        finished = False

        # Expand all the chapters in the table of contents
        chapters = self.student.driver.find_elements_by_xpath(
            "//span[@class='title section']")
        chapters.pop(0)
        for chapter in chapters:
            chapter.click()

        # Get all sections, excluding the preface
        sections = self.student.driver.find_elements_by_xpath(
            "//a/span[@class='title']")
        sections.pop(0)

        self.student.sleep(2)

        length = len(sections)

        for num in range(length):

            sections = self.student.driver.find_elements_by_xpath(
                "//a/span[@class='title']")
            sections.pop(0)
            sections[num].click()
            self.student.sleep(3)

            if 'Introduction-to' not in self.student.current_url():
                # Jump to the Concept Coach widget and open Concept Coach
                self.student.find(
                    By.XPATH,
                    "//div[@class='jump-to-cc']/a[@class='btn']").click()
                self.student.sleep(2)
                self.student.find(
                    By.XPATH,
                    "//button[@class='btn btn-lg btn-primary']").click()
                self.student.sleep(2)

                # If this section has been completed already,
                # leave and go to the next section
                breadcrumbs = self.student.driver.find_elements_by_xpath(
                    "//div[@class='task-breadcrumbs']/span")

                breadcrumbs[-1].click()
                self.student.sleep(3)

                if len(
                        self.student.driver.find_elements_by_xpath(
                            "//div[@class='card-body coach-coach-review-completed'][1]"
                        )) > 0:
                    self.student.find(
                        By.XPATH, "//a/button[@class='btn-plain " +
                        "-coach-close btn btn-default']").click()

                # Else, go through questions until a blank one is found
                # and answer the question
                else:
                    for question in breadcrumbs:
                        question.click()

                        if len(
                                self.student.driver.find_elements_by_xpath(
                                    "//div[@class='question-feedback bottom']")
                        ) > 0:
                            continue

                        else:
                            while len(
                                    self.student.driver.find_elements_by_xpath(
                                        "//div[@class='question-feedback bottom']"
                                    )) == 0:

                                if len(
                                        self.student.driver.
                                        find_elements_by_xpath(
                                            "//button[@class='btn btn-default']"
                                        )) > 0:
                                    self.student.find(
                                        By.XPATH,
                                        "//button[@class='btn btn-default']"
                                    ).click()
                                    continue

                                # Free response
                                if self.student.find(
                                        By.XPATH,
                                        "//button[@class='async-button " +
                                        "continue btn btn-primary']"
                                ).text == 'Answer':
                                    self.student.find(
                                        By.XPATH, "//textarea").send_keys(
                                            'An answer for this textarea')
                                    self.student.find(
                                        By.XPATH,
                                        "//button[@class='async-button " +
                                        "continue btn btn-primary']").click()
                                    self.student.sleep(3)

                                # Multiple Choice
                                elif self.student.find(
                                        By.XPATH,
                                        "//button[@class='async-button " +
                                        "continue btn btn-primary']"
                                ).text == 'Submit':
                                    action = ActionChains(self.student.driver)
                                    action.send_keys('c')
                                    action.perform()

                                    self.student.find(
                                        By.XPATH,
                                        "//div[@class='answers-answer " +
                                        "answer-checked']")
                                    self.student.sleep(3)

                                    finished = True
                                    break

                        break

            if finished:
                break

        self.student.sleep(5)

        self.student.sleep(3)

        self.ps.test_updates['passed'] = True

    # Case C7697 - 007 - Student | Display the assignment summary
    # after completing the assignment
    @pytest.mark.skipif(str(7697) not in TESTS, reason='Excluded')  # NOQA
    def test_student_display_the_assignment_summary_after_completin_7697(self):
        """Display the assignment summary after completing the assignment.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click a multiple choice answer
        Click the 'Submit' button
        After answering the last question, click the 'Next Question' button

        Expected Result:
        The summary is displayed
        """
        self.ps.test_updates['name'] = 'cc1.08.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.007', '7697']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.select_course(appearance='macro_economics')
        self.student.sleep(5)
        self.student.find(By.XPATH, "//button[@class='toggle btn']").click()
        self.student.sleep(3)

        finished = False

        # Expand all the chapters in the table of contents
        chapters = self.student.driver.find_elements_by_xpath(
            "//span[@class='title section']")
        chapters.pop(0)
        for chapter in chapters:
            chapter.click()

        # Get all sections, excluding the preface
        sections = self.student.driver.find_elements_by_xpath(
            "//a/span[@class='title']")
        sections.pop(0)

        self.student.sleep(2)

        length = len(sections)

        for num in range(length):

            sections = self.student.driver.find_elements_by_xpath(
                "//a/span[@class='title']")
            sections.pop(0)
            sections[num].click()
            self.student.sleep(3)

            if 'Introduction-to' not in self.student.current_url():
                # Jump to the Concept Coach widget and open Concept Coach
                self.student.find(
                    By.XPATH,
                    "//div[@class='jump-to-cc']/a[@class='btn']").click()
                self.student.sleep(2)
                self.student.find(
                    By.XPATH,
                    "//button[@class='btn btn-lg btn-primary']").click()
                self.student.sleep(2)

                # If this section has been completed already,
                # leave and go to the next section
                breadcrumbs = self.student.driver.find_elements_by_xpath(
                    "//div[@class='task-breadcrumbs']/span")

                breadcrumbs[-1].click()
                self.student.sleep(3)

                if len(
                        self.student.driver.find_elements_by_xpath(
                            "//div[@class='card-body coach-coach-review-completed'][1]"
                        )) > 0:
                    self.student.find(
                        By.XPATH, "//a/button[@class='btn-plain " +
                        "-coach-close btn btn-default']").click()

                # Else, go through questions until a blank one is found
                # and answer the question
                else:
                    for question in breadcrumbs:
                        question.click()

                        if len(
                                self.student.driver.find_elements_by_xpath(
                                    "//div[@class='question-feedback bottom']")
                        ) > 0:
                            if len(
                                    self.student.driver.find_elements_by_xpath(
                                        "//div[@class='card-body coach-" +
                                        "coach-review-completed'][1]")) > 0:
                                finished = True
                            continue

                        else:
                            while len(
                                    self.student.driver.find_elements_by_xpath(
                                        "//div[@class='question-feedback bottom']"
                                    )) == 0:
                                # Free response

                                if len(
                                        self.student.driver.
                                        find_elements_by_xpath(
                                            "//button[@class='btn btn-default']"
                                        )) > 0:
                                    self.student.find(
                                        By.XPATH,
                                        "//button[@class='btn btn-default']"
                                    ).click()
                                    continue

                                if self.student.find(
                                        By.XPATH,
                                        "//button[@class='async-button " +
                                        "continue btn btn-primary']"
                                ).text == 'Answer':
                                    self.student.find(
                                        By.XPATH, "//textarea").send_keys(
                                            'An answer for this textarea')
                                    self.student.find(
                                        By.XPATH,
                                        "//button[@class='async-button " +
                                        "continue btn btn-primary']").click()
                                    self.student.sleep(3)

                                # Multiple Choice
                                elif self.student.find(
                                        By.XPATH,
                                        "//button[@class='async-button " +
                                        "continue btn btn-primary']"
                                ).text == 'Submit':
                                    answers = self.student.driver.find_elements(  # NOQA
                                        By.CLASS_NAME, 'answer-letter')
                                    self.student.sleep(0.8)
                                    rand = randint(0, len(answers) - 1)
                                    answer = chr(ord('a') + rand)
                                    Assignment.scroll_to(
                                        self.student.driver, answers[0])
                                    if answer == 'a':
                                        self.student.driver.execute_script(
                                            'window.scrollBy(0, -160);')
                                    elif answer == 'd':
                                        self.student.driver.execute_script(
                                            'window.scrollBy(0, 160);')
                                    answers[rand].click()

                                    self.student.find(
                                        By.XPATH,
                                        "//button[@class='async-button " +
                                        "continue btn btn-primary']").click()
                                    self.student.sleep(3)

            if finished:
                break

        self.student.sleep(5)

        self.ps.test_updates['passed'] = True

    # Case C7698 - 008 - Student | The exercise ID is visible within
    # the assessment pane
    @pytest.mark.skipif(str(7698) not in TESTS, reason='Excluded')  # NOQA
    def test_student_exercise_id_is_visible_within_the_assessment_7698(self):
        """The exercise ID is visible within the assessment pane.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page

        Expected Result:
        The exercise ID is visivle on the exercise.
        """
        self.ps.test_updates['name'] = 'cc1.08.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.008', '7698']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.select_course(appearance='macro_economics')
        self.student.sleep(5)
        self.student.find(By.XPATH, "//button[@class='toggle btn']").click()
        self.student.sleep(3)

        # Expand all the chapters in the table of contents
        chapters = self.student.driver.find_elements_by_xpath(
            "//span[@class='title section']")
        chapters.pop(0)
        for chapter in chapters:
            chapter.click()

        # Get all sections, excluding the preface
        sections = self.student.driver.find_elements_by_xpath(
            "//a/span[@class='title']")
        sections.pop(0)

        self.student.sleep(2)

        length = len(sections)

        for num in range(length):

            sections = self.student.driver.find_elements_by_xpath(
                "//a/span[@class='title']")
            sections.pop(0)
            sections[num].click()
            self.student.sleep(3)

            if 'Introduction-to' not in self.student.current_url():
                # Jump to the Concept Coach widget and open Concept Coach
                self.student.find(
                    By.XPATH,
                    "//div[@class='jump-to-cc']/a[@class='btn']").click()
                self.student.sleep(2)
                self.student.find(
                    By.XPATH,
                    "//button[@class='btn btn-lg btn-primary']").click()
                self.student.sleep(2)

                # View summary
                breadcrumbs = self.student.driver.find_elements_by_xpath(
                    "//div[@class='task-breadcrumbs']/span")

                breadcrumbs[-1].click()
                self.student.sleep(3)

                # Verify the first question has an exercise ID
                breadcrumbs[2].click()

                self.student.find(
                    By.XPATH,
                    "//span[@class='exercise-identifier-link']/span[2]")

                break

        self.student.sleep(5)

        self.ps.test_updates['passed'] = True

    # Case C7699 - 009 - Student | Able to refer an assessment to OpenStax
    # via Errata Form
    @pytest.mark.skipif(str(7699) not in TESTS, reason='Excluded')  # NOQA
    def test_student_able_to_refer_an_assessment_to_openstax_7699(self):
        """Able to refer to an assessment to OpenStax via Errata form.

        Steps:
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Click the 'Report an error' link

        Expected Result:
        User is taken to the Errata form with the exercise ID prefilled
        """
        self.ps.test_updates['name'] = 'cc1.08.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.009', '7699']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.select_course(appearance='macro_economics')
        self.student.sleep(5)
        self.student.find(By.XPATH, "//button[@class='toggle btn']").click()
        self.student.sleep(3)

        # Expand all the chapters in the table of contents
        chapters = self.student.driver.find_elements_by_xpath(
            "//span[@class='title section']")
        chapters.pop(0)
        for chapter in chapters:
            chapter.click()

        # Get all sections, excluding the preface
        sections = self.student.driver.find_elements_by_xpath(
            "//a/span[@class='title']")
        sections.pop(0)

        self.student.sleep(2)

        length = len(sections)

        for num in range(length):

            sections = self.student.driver.find_elements_by_xpath(
                "//a/span[@class='title']")
            sections.pop(0)
            sections[num].click()
            self.student.sleep(3)

            if 'Introduction-to' not in self.student.current_url():
                # Jump to the Concept Coach widget and open Concept Coach
                self.student.find(
                    By.XPATH,
                    "//div[@class='jump-to-cc']/a[@class='btn']").click()
                self.student.sleep(2)
                self.student.find(
                    By.XPATH,
                    "//button[@class='btn btn-lg btn-primary']").click()
                self.student.sleep(2)

                # View summary
                breadcrumbs = self.student.driver.find_elements_by_xpath(
                    "//div[@class='task-breadcrumbs']/span")

                breadcrumbs[-1].click()
                self.student.sleep(3)

                # Verify the first question has an exercise ID
                breadcrumbs[2].click()

                self.student.find(
                    By.XPATH,
                    "//span[@class='exercise-identifier-link']/a").click()

                self.student.driver.switch_to.window(
                    self.student.driver.window_handles[-1])

                assert("google" in self.student.current_url()), \
                    'Not viewing the errata form'

                break

        self.student.sleep(5)

        self.ps.test_updates['passed'] = True

    # Case C7700 - 010 - Student | Able to work an assignment on an
    # Apple tablet device
    @pytest.mark.skipif(str(7700) not in TESTS, reason='Excluded')  # NOQA
    def test_student_able_to_work_an_assignment_on_an_apple_tablet_7700(self):
        """Able to work an assignment on an Apple tablet device.

        Steps:
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click a multiple choice answer
        Click the 'Submit' button

        Expected Result:
        Answer is successfully submitted.
        """
        self.ps.test_updates['name'] = 'cc1.08.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.010', '7700']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7701 - 011 - Student | Able to work an assignment on an
    # Android tablet device
    @pytest.mark.skipif(str(7701) not in TESTS, reason='Excluded')  # NOQA
    def test_student_able_to_work_an_assignment_on_android_tablet_7701(self):
        """Able to work an assignment on an Android tablet device.

        Steps:
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click a multiple choice answer
        Click the 'Submit' button

        Expected Result:
        Answer is successfully submitted.
        """
        self.ps.test_updates['name'] = 'cc1.08.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.011', '7701']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7702 - 012 - Student | Able to work an assignment on a
    # Windows tablet device
    @pytest.mark.skipif(str(7701) not in TESTS, reason='Excluded')  # NOQA
    def test_student_able_to_work_an_assignment_on_windows_tablet_7702(self):
        """Able to work an assignment on a WIndows tablet device.

        Steps:
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click a multiple choice answer
        Click the 'Submit' button

        Expected Result:
        Answer is successfully submitted.
        """
        self.ps.test_updates['name'] = 'cc1.08.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.08', 'cc1.08.012', '7702']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    '''
    # Case C7703 - 013 - Student | Sees product error modals
    @pytest.mark.skipif(str(7703) not in TESTS, reason='Excluded')  # NOQA
    def test_student_sees_product_error_modals_7703(self):
        """See product error modals.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 'cc1.08.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.013',
            '7703'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    '''

    # Case C100131 - 014 - Student | Work a two-step assessment
    @pytest.mark.skipif(str(100131) not in TESTS, reason='Excluded')  # NOQA
    def test_student_work_a_two_step_assessment_100131(self):
        """Work a two-step assessment.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 'cc1.08.014' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1', 'cc1.08', 'cc1.08.014', '100131'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C100132 - 015 - Student | Work a multiple-choice-only assessment
    @pytest.mark.skipif(str(100132) not in TESTS, reason='Excluded')  # NOQA
    def test_student_work_a_multiple_choice_only_assessment_100132(self):
        """Work a multiple-choice-only assessment.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 'cc1.08.015' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1', 'cc1.08', 'cc1.08.015', '100132'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
Ejemplo n.º 11
0
class TestGuideMonitorSupportAndTrainUsers(unittest.TestCase):
    """T2.18 - Guide, Monitor, Support, and Train Users."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(use_env_vars=True,
                               pasta_user=self.ps,
                               capabilities=self.desired_capabilities)

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                           **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    # 14752 - 001 - User | In-app Notification of downtime
    @pytest.mark.skipif(str(14752) not in TESTS, reason='Excluded')
    def test_user_inapp_notification_of_downtime_14752(self):
        """In-app Notification of downtime.

        Steps:

        Go to Tutor
        Log in as admin
        Click "Admin" from the user menu
        Click "System Setting"
        Click "Notifications"
        Enter a new notification into the text box
        Click "Add"
        Log out of admin
        Log in as teacher01

        Expected Result:
        An orange header with the notification pops up when you sign in
        """
        self.ps.test_updates['name'] = 't2.18.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.001', '14752']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14751 - 002 - Teacher | Directed to a "No Courses" page when not in any
    # courses yet
    @pytest.mark.skipif(str(14751) not in TESTS, reason='Excluded')
    def test_teacher_directed_to_a_no_courses_page_when_not_in_any_14751(self):
        """Directed to a "No Courses" page when not in any courses yet.

        Steps:
        Go to tutor-qa.openstax.org
        Sign in as demo_teacher; password

        Expected Result:
        The message "We cannot find an OpenStax course associated with your
        account" displays with help links below
        """
        self.ps.test_updates['name'] = 't2.18.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.002', '14751']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58279 - 003 - Teacher | View "Getting Started with Tutor" Guide
    @pytest.mark.skipif(str(58279) not in TESTS, reason='Excluded')
    def test_teacher_view_getting_started_with_tutor_guide_58279(self):
        """View "Getting Started with Tutor" Guide.

        Steps:
        Click "Tutor Instructors. Get help"

        Expected Result:
        Tutor Help Center opens in another tab with the Getting Started guide
        """
        self.ps.test_updates['name'] = 't2.18.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.003', '58279']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58280 - 004 - Teacher | Access Tutor Help Center after registering for
    # a course
    @pytest.mark.skipif(str(58280) not in TESTS, reason='Excluded')
    def test_teacher_access_tutor_help_center_after_registering_58280(self):
        """Access Tutor Help Center after registering for a course.

        Steps:
        Go to Tutor
        Sign in as teacher01
        Click on a Tutor course if the user is in more than one
        Click "Get Help" from the user menu in the upper right corner of the
            screen

        Expected Result:
        The user is presented with the Tutor Help Center
        """
        self.ps.test_updates['name'] = 't2.18.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.004', '58280']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58284 - 005 - Teacher | Submit a question
    @pytest.mark.skipif(str(58284) not in TESTS, reason='Excluded')
    def test_teacher_submit_a_question_58284(self):
        """Submit a question.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter

        Expected Result:
        The user is presented with search results
        """
        self.ps.test_updates['name'] = 't2.18.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.005', '58284']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58352 - 006 - Teacher | View "Contact Us" button after submitting a
    # question
    @pytest.mark.skipif(str(58352) not in TESTS, reason='Excluded')
    def test_teacher_view_contact_us_button_after_submitting_quest_58352(self):
        """View "Contact Us" button after submitting a question.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Scroll to the bottom of the screen

        Expected Result:
        "Contact Us" button exists
        """
        self.ps.test_updates['name'] = 't2.18.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.006', '58352']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58288 - 007 - Teacher | View an article after submitting a question
    @pytest.mark.skipif(str(58288) not in TESTS, reason='Excluded')
    def test_teacher_view_an_article_after_submitting_a_question_58288(self):
        """View an article after submitting a question.

        Steps:

        Click "Get Help" from the user menu in the upper right corner of the
        screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result

        Expected Result:
        The user is presented with an article containing answer to the question
        """
        self.ps.test_updates['name'] = 't2.18.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.007', '58288']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58313 - 008 - Teacher | Indicate that the article was helpful
    @pytest.mark.skipif(str(58313) not in TESTS, reason='Excluded')
    def test_teacher_indicate_that_the_article_was_helpful_58313(self):
        """Indicate that the article was helpful.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "Yes"

        Expected Result:
        A message that says "Thanks for your feedback!" is displayed
        """
        self.ps.test_updates['name'] = 't2.18.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.008', '58313']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58314 - 009 - Teacher | Negative feedback renders a feedback popup box
    @pytest.mark.skipif(str(58314) not in TESTS, reason='Excluded')
    def test_teacher_negative_feedback_renders_feedback_popup_box_58314(self):
        """Negative feedback renders a feedback popup box.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"

        Expected Result:
        The user is presented with a popup box that allows them to input
        feedback
        """
        self.ps.test_updates['name'] = 't2.18.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.009', '58314']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58315 - 010 - Teacher | Submit feedback for an article
    @pytest.mark.skipif(str(58315) not in TESTS, reason='Excluded')
    def test_teacher_submit_feedback_for_an_article_58315(self):
        """Submit feedback for an article.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        Enter feedback into the box that pops up
        Click "Submit"

        Expected Result:
        A message that says "Thanks for your feedback!" is displayed in the box
        """
        self.ps.test_updates['name'] = 't2.18.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.010', '58315']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58322 - 011 - Teacher | Close window after submitting feedback for an
    # article
    @pytest.mark.skipif(str(58322) not in TESTS, reason='Excluded')
    def test_teacher_close_window_after_submitting_feedback_for_58322(self):
        """Close window after submitting feedback for an article.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        Enter feedback into the box that pops up
        Click "Submit"
        Click "Close window"

        Expected Result:
        The popup box closes and the message "Thanks for your feedback"
        displays beneath "Feedback"
        """
        self.ps.test_updates['name'] = 't2.18.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.011', '58322']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58316 - 012 - Teacher | Cancel feedback
    @pytest.mark.skipif(str(58316) not in TESTS, reason='Excluded')
    def test_teacher_cancel_feedback_before_making_changes_58316(self):
        """Cancel feedback.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        [optional] Enter feedback into the text box
        Click "Cancel"

        Expected Result:
        The popup box closes
        """
        self.ps.test_updates['name'] = 't2.18.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.012', '58316']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58318 - 013 - Teacher | View related articles
    @pytest.mark.skipif(str(58318) not in TESTS, reason='Excluded')
    def test_teacher_view_related_articles_58318(self):
        """View related articles.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Related Articles"
        Click on one of the articles (if any)

        Expected Result:
        The user is presented with the related article
        """
        self.ps.test_updates['name'] = 't2.18.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.013', '58318']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58319 - 014 - Teacher | Submit a question to Customer Support
    @pytest.mark.skipif(str(58319) not in TESTS, reason='Excluded')
    def test_teacher_submit_a_question_to_customer_support_58319(self):
        """Submit a question to Customer Support.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        CLick "Search" or press enter
        Click on a search result
        Scroll to the bottom of the page
        CLick "Contact Us"
        Fill out the required fields
        Enter "Submit"

        Expected Result:
        The message "Thank you for your message! We'll be back to you within
        one business day" is displayed
        """
        self.ps.test_updates['name'] = 't2.18.014' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.014', '58319']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14755 - 015 - Teacher | View guided tutorials of Tutor
    @pytest.mark.skipif(str(14755) not in TESTS, reason='Excluded')
    def test_teacher_view_guided_tutorials_of_concept_coach_14755(self):
        """View guided tutorials of Tutor.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.18.015' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.015', '14755']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14750 - 016 - Student | Directed to a "No Courses" page when not in any
    # courses yet
    @pytest.mark.skipif(str(14750) not in TESTS, reason='Excluded')
    def test_student_directed_to_a_no_courses_page_when_not_in_any_14750(self):
        """Directed to a "No Courses" page when not in any courses yet.

        Steps:
        Go to Tutor
        Log in as qa_student_37003

        Expected Result:
        The message "We cannot find an OpenStax course associated with your
        account" displays with help links
        """
        self.ps.test_updates['name'] = 't2.18.016' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.016', '14750']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58336 - 017 - Student | View "Getting Started with Tutor" Guide
    @pytest.mark.skipif(str(58336) not in TESTS, reason='Excluded')
    def test_student_view_getting_started_with_tutor_guide_58336(self):
        """View "Getting Started with Tutor" Guide.

        Steps:
        Click "Tutor Students. Get help"

        Expected Result:
        Tutor Help Center opens in another tab with the Getting Started guide
        """
        self.ps.test_updates['name'] = 't2.18.017' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.017', '58336']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58337 - 018 - Student | Access Tutor Help Center after registering for a
    # course
    @pytest.mark.skipif(str(58337) not in TESTS, reason='Excluded')
    def test_student_access_tutor_help_center_after_registering_58337(self):
        """Access Tutor Help Center after registering for a course.

        Steps:
        Go to Tutor
        Sign in as student01
        Click on a Tutor course if the user is in more than one
        Click "Get Help" from the user menu in the upper right corner of the
            screen

        Expected Result:
        The user is presented with the Tutor Help Center
        """
        self.ps.test_updates['name'] = 't2.18.018' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.018', '58337']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58338 - 019 - Student | Submit a question
    @pytest.mark.skipif(str(58338) not in TESTS, reason='Excluded')
    def test_student_submit_a_question_58338(self):
        """Submit a question.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter

        Expected Result:
        The user is presented with search results
        """
        self.ps.test_updates['name'] = 't2.18.019' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.019', '58338']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58353 - 020 - Student | View "Contact Us" button after submitting a
    # question
    @pytest.mark.skipif(str(58353) not in TESTS, reason='Excluded')
    def test_student_view_contact_us_button_after_submitting_quest_58353(self):
        """View "Contact Us" button after submitting a question.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Scroll to the bottom of the page

        Expected Result:
        "Contact Us" button exists
        """
        self.ps.test_updates['name'] = 't2.18.020' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.020', '58353']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58339 - 021 - Student | View an article after submitting a question
    @pytest.mark.skipif(str(58339) not in TESTS, reason='Excluded')
    def test_student_view_an_article_after_submitting_a_question_58339(self):
        """View an article after submitting a question.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result

        Expected Result:
        The user is presented with an article containing answer to the question
        """
        self.ps.test_updates['name'] = 't2.18.021' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.021', '58339']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58340 - 022 - Student | Indicate that the article was helpful
    @pytest.mark.skipif(str(58340) not in TESTS, reason='Excluded')
    def test_student_indicate_that_the_article_was_helpful_58340(self):
        """Indicate that the article was helpful.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "Yes"

        Expected Result:
        A message that says "Thanks for your feedback!" is displayed
        """
        self.ps.test_updates['name'] = 't2.18.022' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.022', '58340']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58341 - 023 - Student | Negative feedback renders a feedback popup box
    @pytest.mark.skipif(str(58341) not in TESTS, reason='Excluded')
    def test_student_negative_feedback_renders_feedback_popup_box_58341(self):
        """Negative feedback renders a feedback popup box.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"

        Expected Result:
        The user is presented with a popup box that allows them to input
        feedback
        """
        self.ps.test_updates['name'] = 't2.18.023' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.023', '58341']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58342 - 024 - Student | Submit feedback for an article
    @pytest.mark.skipif(str(58342) not in TESTS, reason='Excluded')
    def test_student_submit_feedback_for_an_article_58342(self):
        """Submit feedback for an article.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        Enter feedback into the box that pops up
        Click "Submit"

        Expected Result:
        A message that says "Thanks for your feedback!" is displayed in the box
        """
        self.ps.test_updates['name'] = 't2.18.024' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.024', '58342']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58343 - 025 - Student | Close window after submitting feedback for an
    # article
    @pytest.mark.skipif(str(58343) not in TESTS, reason='Excluded')
    def test_student_close_window_after_submitting_feedback_for_58343(self):
        """Close window after submitting feedback for an article.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        Enter feedback into the box that pops up
        Click "Submit"
        Click "Close window"

        Expected Result:
        The popup box closes and the message "Thanks for your feedback"
        displays beneath "Feedback"
        """
        self.ps.test_updates['name'] = 't2.18.025' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.025', '58343']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58344 - 026 - Student | Cancel feedback
    @pytest.mark.skipif(str(58344) not in TESTS, reason='Excluded')
    def test_student_cancel_feedback_58344(self):
        """Cancel feedback.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        [optional] Enter feedback into text box
        Click "Cancel"

        Expected Result:
        The popup box closes
        """
        self.ps.test_updates['name'] = 't2.18.026' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.026', '58344']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58346 - 027 - Student | View related articles
    @pytest.mark.skipif(str(58346) not in TESTS, reason='Excluded')
    def test_student_view_related_articles_58346(self):
        """View related articles.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Related Articles"
        Click on one of the articles (if any)

        Expected Result:
        The user is presented with the related article
        """
        self.ps.test_updates['name'] = 't2.18.027' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.027', '58346']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58347 - 028 - Student | Submit a question to Customer Support
    @pytest.mark.skipif(str(58347) not in TESTS, reason='Excluded')
    def test_student_submit_a_question_to_customer_support_58347(self):
        """Submit a question to Customer Support.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to the bottom of the page
        Click "Contact Us"
        Fill out the required fields
        Enter "Submit"

        Expected Result:
        The message "Thank you for your message! We'll be back to you within
        one business day" is displayed
        """
        self.ps.test_updates['name'] = 't2.18.028' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.028', '58347']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 58348 - 029 - Student | View guided tutorials of Tutor
    @pytest.mark.skipif(str(58348) not in TESTS, reason='Excluded')
    def test_student_view_guided_tutorials_of_concept_coach_58348(self):
        """View guided tutorial of Tutor.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.18.029' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.18', 't2.18.029', '58348']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
class TestViewClassScores(unittest.TestCase):
    """T1.23 - View Class Scores."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(use_env_vars=True,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
        else:
            self.teacher = Teacher(use_env_vars=True)

        self.wait = WebDriverWait(self.teacher.driver, Assignment.WAIT_TIME)

        self.teacher.login()

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    @pytest.mark.skipif(str(1) not in TESTS, reason='Excluded')
    def test_homework_assignment_from_scores(self):
        '''
        Go to https://tutor-qa.openstax.org/
        Click on the 'Login' button
        Enter the teacher user account [ teacher01 | password ] in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a Tutor course name

        Click on the "Student Scores" button
        Click on the tab for the chosen period
        Click on the "Review" button under the selected homework assignment.
        ***Displays students progress on chosen assignment for
        selected period, actual questions, and question results. (T1.23.13)***
        ***Period tabs are displayed. (t1.23.18)***
        ***Each question has a correct response displayed (t1.23.21)***
        ***Assessment pane shows interleaved class stats (t1.23.23)***
        ***Screen is moved down to selected section of homework. (t1.23.17)***


        Click "Back to Scores" button
        Click on score cell for chosen student and homework assignment (student must have started the hw)
        Click on a breadcrumb of selected section of homework.
        ***Teacher view of student work shown. Teacher can go through different
        questions with either the "Next Question"
        button, or breadcrumbs. Students answers are shown for questions they have worked. (t1.23.25)***

        Expected Results:

        Corresponds to...
        t1.23. 13,17,18,21,23,25
        '''
        # go to Student Scores
        self.teacher.select_course(
            appearance='college_physics'
        )  # might have to change the course appearance
        self.teacher.goto_student_scores()

        # self.teacher.find(
        #     By.LINK_TEXT, 'Student Scores').click()
        # self.teacher.wait.until(
        #     expect.visibility_of_element_located(
        #         (By.XPATH, '//span[contains(text(), "Student Scores")]')
        #     )
        # ).click()
        ###  UNNECESSARY CODE COMMENTED? ^

        #(t1.23.13 --> Displays students progress on chosen assignment for
        # selected period, actual questions, and question results.

        # go to the Review Metrics of a HW by clicking 'Review'

        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//span[contains(@class, "tab-item-period-name")]'))).click()

        bar = 0
        scroll_width = 1
        scroll_total_size = 1
        # scroll bar might not be there
        try:
            scroll_bar = self.teacher.find(
                By.XPATH,
                '//div[contains(@class,"ScrollbarLayout_faceHorizontal")]')
            scroll_width = scroll_bar.size['width']

            scroll_total_size = self.teacher.find(
                By.XPATH,
                '//div[contains(@class,"ScrollbarLayout_mainHorizontal")]'
            ).size['width']
            bar = scroll_width
        except:
            pass

        while (bar < scroll_total_size):
            try:
                self.teacher.find(
                    By.XPATH, '//span[@class="review-link"]' +
                    '//a[contains(text(),"Review")]').click()
                assert ('metrics' in self.teacher.current_url()), \
                    'Not viewing homework assignment summary'
                break
            except:
                bar += scroll_width
                if scroll_total_size <= bar:
                    print("No HWs for this class :(")
                    raise Exception
                # drag scroll bar instead of scrolling
                actions = ActionChains(self.teacher.driver)
                actions.move_to_element(scroll_bar)
                actions.click_and_hold()
                actions.move_by_offset(scroll_width, 0)
                actions.release()
                actions.perform()

        # (t1.23.18) --> Period tabs are displayed.
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//ul[contains(@role,"tablist")]' +
                 '//span[contains(@class,"tab-item-period-name")]')))

        # (t1.23.21) --> Each question has a correct response displayed
        correct_answers = self.teacher.driver.find_elements(
            By.XPATH, '//div[contains(@class,"answer-correct")]')
        questions = self.teacher.driver.find_elements(
            By.XPATH, '//span[contains(@class,"openstax-breadcrumbs")]')
        assert (len(correct_answers) == len(questions)), \
            "number of correct answers not equal to the number of questions"

        # (t1.23.23) --> Assessment pane shows interleaved class stats (t1.23.23)
        ### PRETTY SURE T1.23.23 IS ALREADY COVERED

        # (t1.23.17) --> Screen is moved down to selected section of homework. (t1.23.17)
        sections = self.teacher.driver.find_elements(
            By.XPATH, '//span[contains(@class,"breadcrumbs")]')
        sections[-1].click()
        self.teacher.sleep(2)
        assert (expect.visibility_of_element_located(
            (By.XPATH,
             "//div[contains(@data-section,'%s')]" % str(len(sections) - 1))))

        # (t1.23.25) --> Teacher view of student work shown. Teacher can go through different
        # questions with either the "Next Question" button, or breadcrumbs.
        # Students answers are shown for questions they have worked. (t1.23.25)***

        ### GOT UP TO HERE ON TESTING! SUBSEQUENT CODE MIGHT NOT WORK

        # go back to student scores
        self.teacher.find(By.XPATH, '//span[contains(@title,"Menu")]').click()
        self.teacher.find(By.LINK_TEXT, 'Student Scores').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//span[contains(text(), "Student Scores")]'))).click()

        # look for a student that's worked a homework
        # click on their score to review the homework

        while (bar < scroll_total_size):
            try:
                self.teacher.find(
                    By.XPATH,
                    "//div[contains(@class,'score')]//a[@data-assignment-type='homework']"
                ).click()
                break

            # except (NoSuchElementException,
            #         ElementNotVisibleException,
            #         WebDriverException)

            except:
                bar += scroll_width
                if scroll_total_size <= bar:
                    print("No worked HWs for this class :(")
                    raise Exception
                # drag scroll bar instead of scrolling
                actions = ActionChains(self.teacher.driver)
                actions.move_to_element(scroll_bar)
                actions.click_and_hold()
                actions.move_by_offset(scroll_width, 0)
                actions.release()
                actions.perform()

        # make sure that we're reviewing the hw
        assert ('step' in self.teacher.current_url()), \
            'Not viewing student work for homework'

        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(@class,"breadcrumbs")]')))
        sections = self.teacher.find_all(
            By.XPATH, '//span[contains(@class,"breadcrumbs")]')
        section = sections[-1]
        section.click()
        chapter = section.get_attribute("data-chapter")
        assert (self.teacher.driver.find_element(
            By.XPATH, '//span[contains(text(),"' +
                      chapter + '")]').is_displayed()), \
            'chapter not displayed'
class TestStudentsWorkAssignments(unittest.TestCase):
    """CC1.08 - Students Work Assignments."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            username=os.getenv('TEACHER_USER_CC'),
            password=os.getenv('TEACHER_PASSWORD'),
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.teacher.login()
        if 'cc-dashboard' not in self.teacher.current_url():
            courses = self.teacher.find_all(
                By.CLASS_NAME,
                'tutor-booksplash-course-item'
            )
            assert(courses), 'No courses found.'
            if not isinstance(courses, list):
                courses = [courses]
            course_id = randint(0, len(courses) - 1)
            self.course = courses[course_id].get_attribute('data-title')
            self.teacher.select_course(title=self.course)
        self.teacher.goto_course_roster()
        try:
            section = self.teacher.find_all(
                By.XPATH,
                '//*[contains(@class,"nav-tabs")]//a'
            )
            if isinstance(section, list):
                section = '%s' % section[randint(0, len(section) - 1)].text
            else:
                section = '%s' % section.text
        except Exception:
            section = '%s' % randint(100, 999)
            self.teacher.add_course_section(section)
        self.code = self.teacher.get_enrollment_code(section)
        print('Course Phrase: ' + self.code)
        self.book_url = self.teacher.find(
            By.XPATH, '//a[span[contains(text(),"Online Book")]]'
        ).get_attribute('href')
        self.teacher.find(By.CSS_SELECTOR, 'button.close').click()
        self.teacher.sleep(0.5)
        self.teacher.logout()
        self.teacher.sleep(1)
        self.student = Student(use_env_vars=True,
                               existing_driver=self.teacher.driver)
        self.first_name = Assignment.rword(6)
        self.last_name = Assignment.rword(8)
        self.email = self.first_name + '.' \
            + self.last_name \
            + '@tutor.openstax.org'

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7691 - 001 - Student | Selects an exercise answer
    @pytest.mark.skipif(str(7691) not in TESTS, reason='Excluded')
    def test_student_select_an_exercise_answer_7691(self):
        """Select an exercise answer."""
        self.ps.test_updates['name'] = 'cc1.08.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.001',
            '7691'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.get(self.book_url)
        self.student.sleep(2)
        self.student.find_all(By.XPATH, '//a[@class="nav next"]')[0].click()
        self.student.page.wait_for_page_load()
        try:
            widget = self.student.find(By.ID, 'coach-wrapper')
        except:
            self.student.find_all(By.XPATH,
                                  '//a[@class="nav next"]')[0].click()
            self.student.page.wait_for_page_load()
            try:
                self.student.sleep(1)
                widget = self.student.find(By.ID, 'coach-wrapper')
            except:
                self.student.find_all(By.XPATH,
                                      '//a[@class="nav next"]')[0].click()
                self.student.page.wait_for_page_load()
                self.student.sleep(1)
                widget = self.student.find(By.ID, 'coach-wrapper')
        Assignment.scroll_to(self.student.driver, widget)
        self.student.find(
            By.XPATH,
            '//button[span[contains(text(),"Launch Concept Coach")]]'
        ).click()
        self.student.sleep(1.5)
        base_window = self.student.driver.window_handles[0]
        self.student.find(By.CSS_SELECTOR, 'div.sign-up').click()
        self.student.sleep(3)
        popup = self.student.driver.window_handles[1]
        self.student.driver.switch_to_window(popup)
        self.student.find(By.LINK_TEXT, 'Sign up').click()
        self.student.find(By.ID, 'identity-login-button').click()
        self.student.find(
            By.ID,
            'signup_first_name'
        ).send_keys(self.first_name)
        self.student.find(By.ID, 'signup_last_name').send_keys(self.last_name)
        self.student.find(By.ID, 'signup_email_address').send_keys(self.email)
        self.student.find(By.ID, 'signup_username').send_keys(self.last_name)
        self.student.find(
            By.ID,
            'signup_password'
        ).send_keys(self.student.password)
        self.student.find(
            By.ID,
            'signup_password_confirmation'
        ).send_keys(self.student.password)
        self.student.find(By.ID, 'create_account_submit').click()
        self.student.find(By.ID, 'i_agree').click()
        self.student.find(By.ID, 'agreement_submit').click()
        self.student.find(By.ID, 'i_agree').click()
        self.student.find(By.ID, 'agreement_submit').click()
        self.student.driver.switch_to_window(base_window)
        self.student.find(
            By.XPATH,
            '//input[contains(@label,"Enter the enrollment code")]'
        ).send_keys(self.code)
        self.student.sleep(2)
        self.student.find(By.CSS_SELECTOR, 'button.enroll').click()
        self.student.sleep(2)
        self.student.find(
            By.CSS_SELECTOR,
            'div.field input.form-control'
        ).send_keys(self.last_name)
        self.student.find(By.CSS_SELECTOR, 'button.async-button').click()
        self.student.sleep(5)
        try:
            self.student.find(By.XPATH, '//button[text()="Continue"]').click()
        except:
            print('Two-step message not seen.')
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH,
                 '//div[@class="openstax-question"]//textarea')
            )
        ).send_keys(chomsky())
        self.student.find(By.CSS_SELECTOR, 'button.async-button').click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="answer-letter"]')
            )
        )
        answers = self.student.find_all(By.CSS_SELECTOR, 'div.answer-letter')
        answers[randint(0, len(answers) - 1)].click()
        self.student.find(By.CSS_SELECTOR, 'button.async-button').click()
        self.student.find(By.CSS_SELECTOR, 'button.async-button').click()

        self.ps.test_updates['passed'] = True

    # Case C7692 - 002 - Student | After answering an exercise feedback
    # is presented
    @pytest.mark.skipif(str(7692) not in TESTS, reason='Excluded')  # NOQA
    def test_student_after_answering_an_exercise_feedback_7692(self):
        """View section completion report.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click the 'Answer' button
        Click a multiple choice answer
        Click the 'Submit' button

        Expected Result:
        The correct answer is displayed and feedback is given.
        """
        self.ps.test_updates['name'] = 'cc1.08.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.002',
            '7692'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7693 - 003 - System | Assessments are from the current module
    @pytest.mark.skipif(str(7693) not in TESTS, reason='Excluded')  # NOQA
    def test_system_assessments_are_from_the_current_module_7693(self):
        """Assessment is from the current module.

        Steps:


        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc1.08.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.003',
            '7693'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7694 - 004 - System | Spaced practice assessments are from
    # previously worked modules
    @pytest.mark.skipif(str(7694) not in TESTS, reason='Excluded')  # NOQA
    def test_system_spaced_practice_assessments_are_from_previo_7694(self):
        """Spaced practice assessments are from previousy worked modules.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Select a non-introductory section
        Click Jump to Concept Coach
        Click Launch Concept Coach
        Go through the assessments until you get to the Spaced Practice

        Expected Result:
        The section number beneath the text box is from a previous section
        """
        self.ps.test_updates['name'] = 'cc1.08.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.004',
            '7694'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7695 - 005 - System | Modules without assessments do not display
    # the Concept Coach widget
    @pytest.mark.skipif(str(7695) not in TESTS, reason='Excluded')  # NOQA
    def test_system_modules_without_assessments_do_not_display_7695(self):
        """Module without assessments does not display the CC widget.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Click on an introductory section

        Expected Result:
        The Concept Coach widget does not appear.
        """
        self.ps.test_updates['name'] = 'cc1.08.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.005',
            '7695'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7696 - 006 - Student | Assignment is assistive technology friendly
    @pytest.mark.skipif(str(7696) not in TESTS, reason='Excluded')  # NOQA
    def test_student_assignment_is_assistive_technology_friendly_7696(self):
        """Assignment is assistive technology friendly.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click the 'Answer' button
        Type a, b, c, or d

        Expected Result:
        A multiple choice answer matching the letter typed should be selected.
        """
        self.ps.test_updates['name'] = 'cc1.08.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.006',
            '7696'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7697 - 007 - Student | Display the assignment summary
    # after completing the assignment
    @pytest.mark.skipif(str(7697) not in TESTS, reason='Excluded')  # NOQA
    def test_student_display_the_assignment_summary_after_completin_7697(self):
        """Display the assignment summary after completing the assignment.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click a multiple choice answer
        Click the 'Submit' button
        After answering the last question, click the 'Next Question' button

        Expected Result:
        The summary is displayed
        """
        self.ps.test_updates['name'] = 'cc1.08.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.007',
            '7697'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7698 - 008 - Student | The exercise ID is visible within
    # the assessment pane
    @pytest.mark.skipif(str(7698) not in TESTS, reason='Excluded')  # NOQA
    def test_student_exercise_id_is_visible_within_the_assessment_7698(self):
        """The exercise ID is visible within the assessment pane.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page

        Expected Result:
        The exercise ID is visivle on the exercise.
        """
        self.ps.test_updates['name'] = 'cc1.08.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.008',
            '7698'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7699 - 009 - Student | Able to refer an assessment to OpenStax
    # via Errata Form
    @pytest.mark.skipif(str(7699) not in TESTS, reason='Excluded')  # NOQA
    def test_student_able_to_refer_an_assessment_to_openstax_7699(self):
        """Able to refer to an assessment to OpenStax via Errata form.

        Steps:
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Click the 'Report an error' link

        Expected Result:
        User is taken to the Errata form with the exercise ID prefilled
        """
        self.ps.test_updates['name'] = 'cc1.08.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.009',
            '7699'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7700 - 010 - Student | Able to work an assignment on an
    # Apple tablet device
    @pytest.mark.skipif(str(7700) not in TESTS, reason='Excluded')  # NOQA
    def test_student_able_to_work_an_assignment_on_an_apple_tablet_7700(self):
        """Able to work an assignment on an Apple tablet device.

        Steps:
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click a multiple choice answer
        Click the 'Submit' button

        Expected Result:
        Answer is successfully submitted.
        """
        self.ps.test_updates['name'] = 'cc1.08.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.010',
            '7700'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7701 - 011 - Student | Able to work an assignment on an
    # Android tablet device
    @pytest.mark.skipif(str(7701) not in TESTS, reason='Excluded')  # NOQA
    def test_student_able_to_work_an_assignment_on_android_tablet_7701(self):
        """Able to work an assignment on an Android tablet device.

        Steps:
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click a multiple choice answer
        Click the 'Submit' button

        Expected Result:
        Answer is successfully submitted.
        """
        self.ps.test_updates['name'] = 'cc1.08.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.011',
            '7701'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7702 - 012 - Student | Able to work an assignment on a
    # Windows tablet device
    @pytest.mark.skipif(str(7701) not in TESTS, reason='Excluded')  # NOQA
    def test_student_able_to_work_an_assignment_on_windows_tablet_7702(self):
        """Able to work an assignment on a WIndows tablet device.

        Steps:
        Click the 'Contents' button to open the table of contents
        Click on a chapter
        Click on a non-introductory section
        Click the 'Launch Concept Coach' button at the bottom of the page
        Type text into the 'Enter your response' text box
        Click a multiple choice answer
        Click the 'Submit' button

        Expected Result:
        Answer is successfully submitted.
        """
        self.ps.test_updates['name'] = 'cc1.08.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.012',
            '7702'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7703 - 013 - Student | Sees product error modals
    @pytest.mark.skipif(str(7703) not in TESTS, reason='Excluded')  # NOQA
    def test_student_sees_product_error_modals_7703(self):
        """See product error modals.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 'cc1.08.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.08',
            'cc1.08.013',
            '7703'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
class TestImproveLoginRegistrationEnrollment(unittest.TestCase):
    """CC2.09 - Improve Login, Registration, Enrollment."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.student = Student(
            use_env_vars=True,
            existing_driver=self.teacher.driver,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.student.delete()
        except:
            pass
        try:
            self.teacher.delete()
        except:
            pass

    def get_enrollemnt_code(self, number=0):
        """
        Steps:
        Sign in as teacher
        Click on a Concept Coach course
        Click on "Course Settings and Roster" from the user menu
        Click "Your Student Enrollment Code"

        Return value: code, enrollemnt_url
            code - enrollment code
            enrollemnt_url - url of book for course
        """
        self.teacher.login()
        if number != 0:
            cc_courses = self.teacher.find_all(
                By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
            )
            cc_courses[number].click()
        else:
            self.teacher.find(
                By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
            ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        self.teacher.find(
            By.XPATH, '//span[contains(text(),"Your student enrollment code")]'
        ).click()
        self.teacher.sleep(1)
        code = self.teacher.find(
            By.XPATH, '//p[@class="code"]'
        ).text
        enrollement_url = self.teacher.find(
            By.XPATH, '//textarea'
        ).text
        enrollement_url = enrollement_url.split('\n')[5]
        self.teacher.find(
            By.XPATH, '//button[@class="close"]'
        ).click()
        self.teacher.sleep(0.5)
        self.teacher.logout()
        return code, enrollement_url

    def create_user(self, start_num, end_num):
        """
        creates a new user and return the username
        """
        self.student.get("http://accounts-qa.openstax.org")
        num = str(randint(start_num, end_num))
        self.student.find(By.LINK_TEXT, 'Sign up').click()
        self.student.find(
            By.ID, 'identity-login-button').click()
        self.student.find(
            By.ID, 'signup_first_name').send_keys('first_name_001')
        self.student.find(
            By.ID, 'signup_last_name').send_keys('last_name_001')
        self.student.find(
            By.ID, 'signup_email_address').send_keys('*****@*****.**')
        self.student.find(
            By.ID, 'signup_username').send_keys('automated_09_'+num)
        self.student.find(
            By.ID, 'signup_password'
        ).send_keys(os.getenv('STUDENT_PASSWORD'))
        self.student.find(
            By.ID, 'signup_password_confirmation'
        ).send_keys(os.getenv('STUDENT_PASSWORD'))
        self.student.find(By.ID, 'signup_i_agree').click()
        self.student.find(
            By.ID, 'create_account_submit').click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Sign out')
            )
        ).click()
        print('automated_09_'+num)
        return 'automated_09_'+num

    # 14820 - 001 - Teacher | Register for teaching a CC course as new faculty
    @pytest.mark.skipif(str(14820) not in TESTS, reason='Excluded')
    def test_teacher_register_for_teaching_cc_course_as_new_facult_14820(self):
        """Register for teaching a CC course as new faculty.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc2.09.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.001', '14820']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14819 - 002 - Teacher | Register for teaching a CC course as
    # returning faculty for the same book
    @pytest.mark.skipif(str(14819) not in TESTS, reason='Excluded')
    def test_teacher_register_for_teaching_cc_course_as_returning_14819(self):
        """Register for teaching a CC course as returning faculty.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click "Course Settings and Roster" from the user menu
        Click "Add Section"
        Create a name when prompted
        Click "Add"
        Click on the sections from previous semesters
        Click "Archive Section"

        Expected Result:
        A new section is added and the old sections are archived
        """
        self.ps.test_updates['name'] = 'cc2.09.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.002', '14819']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        # add a new section
        new_section_name = "new_section_" + str(randint(100, 999))
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[contains(@class,"add-period")]//button')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//input[@type="text"]')
            )
        ).send_keys(new_section_name)
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[@class="modal-content"]//button/span[text()="Add"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + new_section_name + '"]')
            )
        )
        # revove old section
        old_section_name = self.teacher.find(By.XPATH, '//a[@role="tab"]').text
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + old_section_name + '"]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(@class,"archive-period")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@role="tooltip"]//button' +
                 '//span[contains(text(),"Archive")]')
            )
        ).click()
        self.teacher.sleep(2)
        archived = self.teacher.driver.find_elements(
            By.XPATH,
            '//li//a[@role="tab" and text()="' + old_section_name + '"]')
        assert(len(archived) == 0), ' not archived'

        # arhive new section and re-add old section as clean-up
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + new_section_name + '"]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(@class,"archive-period")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@role="tooltip"]//button' +
                 '//span[contains(text(),"Archive")]')
            )
        ).click()

        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@class,"view-archived-periods")]//button')
            )
        ).click()
        periods = self.teacher.driver.find_elements(
            By.XPATH, '//div[@class="modal-content"]//tbody//tr'
        )
        for period in periods:
            try:
                period.find_element(
                    By.XPATH, ".//td[text()='" + old_section_name + "']")
                period.find_element(
                    By.XPATH,
                    ".//td//span[contains(@class,'restore-period')]//button"
                ).click()
                break
            except NoSuchElementException:
                if period == periods[-1]:
                    raise Exception

        self.ps.test_updates['passed'] = True

    # 14759 - 003 - Student | Sign up and enroll in a CC course
    @pytest.mark.skipif(str(14759) not in TESTS, reason='Excluded')
    def test_teacher_sign_up_and_enroll_in_a_cc_course_14759(self):
        """Sign up and enroll in a CC course.

        Steps:
        Sign in as teacher
        Click on a Concept Coach course
        Click on "Course Settings and Roster" from the user menu
        Click "Your Student Enrollment Code"
        Copy and paste the URL into an incognito window
        Click "Jump to Concept Coach"
        Click "Launch Concept Coach"
        Click Sign Up
        Click Sign up with a password
        Fill in the required fields
        Click "Create Account"
        Enter the numerical enrollment code you get from the teacher
        Click "Enroll"
        Enter school issued ID, OR skip this step for now

        Expected Result:
        The user is presented with a message that confirms enrollment
        Is redirected to the CC assignment
        """
        self.ps.test_updates['name'] = 'cc2.09.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.003', '14759']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        code, enrollement_url = self.get_enrollemnt_code()
        rand_username = self.create_user(100, 999)
        self.student.get(enrollement_url)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]')
            )
        ).click()
        self.student.page.wait_for_page_load()
        self.student.find(
            By.XPATH, '//div[text()="Sign in"]'
        ).click()
        self.student.sleep(0.5)
        login_window = self.student.driver.window_handles[1]
        cc_window = self.student.driver.window_handles[0]
        self.student.driver.switch_to_window(login_window)
        print(rand_username)
        self.student.find(
            By.ID, 'auth_key').send_keys(rand_username)
        print(self.student.password)
        self.student.find(
            By.ID, 'password').send_keys(self.student.password)
        self.student.find(
            By.XPATH, '//button[text()="Sign in"]').click()
        try:
            self.student.find(By.ID, "i_agree").click()
            self.student.find(By.ID, "agreement_submit").click()
            self.student.find(By.ID, "i_agree").click()
            self.student.find(By.ID, "agreement_submit").click()
        except NoSuchElementException:
            pass
        self.student.driver.switch_to_window(cc_window)
        self.student.sleep(1)
        self.student.find(
            By.XPATH, '//input[@placeholder="enrollment code"]'
        ).send_keys(code)
        self.student.find(
            By.XPATH, '//button/span[text()="Enroll"]'
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[@class="skip"]')
            )
        ).click()
        # check for confirmation message
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//*[contains(text(),"You have successfully joined")]')
            )
        )

        self.ps.test_updates['passed'] = True

    # 14862 - 004 - Student | Sign in and enroll in a CC course
    @pytest.mark.skipif(str(14862) not in TESTS, reason='Excluded')
    def test_teacher_sign_in_and_enroll_in_a_cc_course_14862(self):
        """Sign in and enroll in a CC course.

        Steps:
        Sign in as teacher100
        Click on a Concept Coach course
        Click on "Course Settings and Roster" from the user menu
        Click "Your Student Enrollment Code"
        Copy and paste the URL into an incognito window
        Click "Jump to Concept Coach"
        Click "Launch Concept Coach"
        Click Sign In
        Sign in as student71
        Enter the numerical enrollment code you get from the teacher
        Click "Enroll"
        Enter school issued ID, OR skip this step for now

        Expected Result:
        The user is presented with a message that confirms enrollment
        Is redirected to the CC assignment
        """
        self.ps.test_updates['name'] = 'cc2.09.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.004', '14862']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        code, enrollement_url = self.get_enrollemnt_code()
        # use a new student so that when run a second time no issues
        # with student already being enrolled in course
        rand_username = self.create_user(100, 999)
        self.student.get(enrollement_url)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]')
            )
        ).click()
        self.student.page.wait_for_page_load()
        self.student.find(
            By.XPATH, '//div[text()="Sign in"]'
        ).click()
        self.student.sleep(0.5)
        login_window = self.student.driver.window_handles[1]
        cc_window = self.student.driver.window_handles[0]
        self.student.driver.switch_to_window(login_window)
        self.student.find(
            By.ID, 'auth_key').send_keys(rand_username)
        self.student.find(
            By.ID, 'password').send_keys(self.student.password)
        self.student.find(
            By.XPATH, '//button[text()="Sign in"]').click()
        try:
            self.student.find(By.ID, "i_agree").click()
            self.student.find(By.ID, "agreement_submit").click()
            self.student.find(By.ID, "i_agree").click()
            self.student.find(By.ID, "agreement_submit").click()
        except NoSuchElementException:
            pass
        self.student.driver.switch_to_window(cc_window)
        self.student.sleep(1)
        self.student.find(
            By.XPATH, '//input[@placeholder="enrollment code"]'
        ).send_keys(code)
        self.student.find(
            By.XPATH, '//button/span[text()="Enroll"]'
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[@class="skip"]')
            )
        ).click()
        # check for confirmation message
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//*[contains(text(),"You have successfully joined")]')
            )
        )

        self.ps.test_updates['passed'] = True

    # 14771 - 005 - User | View a message that says you need an enrollment code
    # before signing up
    @pytest.mark.skipif(str(14771) not in TESTS, reason='Excluded')
    def test_user_view_a_message_that_says_you_need_an_enrollment_14771(self):
        """View a message that says you need an enrollment code before signing up.

        Steps:
        Sign in as teacher100
        Click on a Concept Coach course
        Click on "Course Settings and Roster" from the user menu
        Click "Your Student Enrollment Code"
        Copy and paste the URL into an incognito window
        Click "Jump to Concept Coach"
        Click "Launch Concept Coach"

        Expected Result:
        The user is presented with a message that says "Sign up with your
        enrollment code. If you don't have an enrollment code, contact your
        instructor."
        """
        self.ps.test_updates['name'] = 'cc2.09.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.005', '14771']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        code, enrollement_url = self.get_enrollemnt_code()
        self.student.get(enrollement_url)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//p[@class="code-required"]')
            )
        )

        self.ps.test_updates['passed'] = True

    # 14821 - 006 - Student | Jump to CC from the top of the reading
    @pytest.mark.skipif(str(14821) not in TESTS, reason='Excluded')
    def test_student_jump_to_cc_from_the_top_of_the_reading_14821(self):
        """Jump to CC from the top of the reading.

        Steps:
        If the user has more than one course, click on a CC course name
        Click on a non-introductory section
        Click "Jump to Concept Coach"

        Expected Result:
        The screen jumps to the "Launch Concept Coach" button
        """
        self.ps.test_updates['name'] = 'cc2.09.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.006', '14821']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.login()
        self.student.find(
            By.XPATH, '//a[contains(@href,"cnx")]'      # possibly change
        ).click()
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button//span[text()="Contents"]')
            )
        ).click()
        self.student.sleep(0.5)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//span[@class="chapter-number" and text()="1.1"]')
            )
        ).click()
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]')
            )
        )

        self.ps.test_updates['passed'] = True

    # 14822 - 007 - Teacher | Jump to CC from the top of the reading
    @pytest.mark.skipif(str(14822) not in TESTS, reason='Excluded')
    def test_teacher_jump_to_cc_from_the_top_of_the_reading_14822(self):
        """Jump to CC from the top of the reading.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Online Book"
        Click on a non-introductory section
        Click "Jump to Concept Coach"

        Expected Result:
        The screen jumps to the "Launch Concept Coach" button
        """
        self.ps.test_updates['name'] = 'cc2.09.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.09', 'cc2.09.007', '14822']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        # open book
        self.teacher.driver.find_element(
            By.XPATH, '//a//span[contains(text(),"Online Book")]'
        ).click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        assert('cnx' in self.teacher.current_url()), \
            'Not viewing the textbook PDF'
        # get to non-introductory section of book
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button//span[text()="Contents"]')
            )
        ).click()
        self.student.sleep(0.5)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//span[@class="chapter-number" and text()="1.1"]')
            )
        ).click()
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]')
            )
        )
        self.ps.test_updates['passed'] = True
class TestSimplifyAndImproveReadings(unittest.TestCase):
    """T2.13 - Simplify and Improve Readings."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities["name"] = self.id()
        self.teacher = Teacher(use_env_vars=True, pasta_user=self.ps, capabilities=self.desired_capabilities)
        # create a reading for the student to work
        self.teacher.login()
        self.assignment_name = "t1.18 reading-%s" % randint(100, 999)
        today = datetime.date.today()
        begin = today.strftime("%m/%d/%Y")
        end = (today + datetime.timedelta(days=randint(1, 10))).strftime("%m/%d/%Y")
        self.teacher.add_assignment(
            assignment="reading",
            args={
                "title": self.assignment_name,
                "description": chomsky(),
                "periods": {"all": (begin, end)},
                "reading_list": ["1.1", "1.2"],
                "status": "publish",
            },
        )
        self.teacher.wait.until(
            expect.visibility_of_element_located((By.XPATH, '//div[contains(@class,"calendar-container")]'))
        )
        self.teacher.logout()
        # login as a student to work the reading
        self.student = Student(
            existing_driver=self.teacher.driver,
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities,
        )
        self.student.login()
        self.student.wait.until(expect.visibility_of_element_located((By.LINK_TEXT, "This Week")))
        reading = self.student.driver.find_element(By.XPATH, '//span[text()="%s"]' % self.assignment_name)
        self.teacher.driver.execute_script("return arguments[0].scrollIntoView();", reading)
        self.teacher.driver.execute_script("window.scrollBy(0, -80);")
        reading.click()

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(job_id=str(self.teacher.driver.session_id), **self.ps.test_updates)
        self.student = None
        try:
            self.teacher.delete()
        except:
            pass

    # 14745 - 001 - Student | Relative size and progress are displayed while
    # working a reading assignment
    @pytest.mark.skipif(str(14745) not in TESTS, reason="Excluded")
    def test_student_relative_size_and_progress_are_displayed_whil_14745(self):
        """Size and progress are displayed while working a reading.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a Tutor course name
        Click on a reading assignment
        Click on the right arrow

        Expected Result:
        The progress bar at the top reflects how far along you are as you work
        through the reading assignment
        """
        self.ps.test_updates["name"] = "t2.13.001" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.13", "t2.13.001", "14745"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        self.student.driver.find_element(By.XPATH, '//div[contains(@class,"progress-bar progress-bar-success")]')

        self.ps.test_updates["passed"] = True

    # 14746 - 002 - Student | Access prior milestones in the reading assignment
    # with breadcrumbs
    @pytest.mark.skipif(str(14746) not in TESTS, reason="Excluded")
    def test_student_access_prior_milestones_in_the_reading_assign_14746(self):
        """Access prior milestones in the reading assignment with breadcrumbs.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on a reading assignment
        Click on the icon next to the calendar on the header

        Expected Result:
        The user is presented with prior milestones
        """
        self.ps.test_updates["name"] = "t2.13.002" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.13", "t2.13.002", "14746"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        self.student.find(By.CSS_SELECTOR, "a.paging-control.next").click()
        self.student.sleep(1)
        self.student.find(By.CSS_SELECTOR, "a.milestones-toggle").click()
        self.student.sleep(1)
        cards = self.student.find_all(By.CSS_SELECTOR, 'div[class="milestone"]')
        preview = ""
        if not isinstance(cards, list):
            preview = cards.find_element(By.XPATH, '/div[@class="milestone-preview"]').text
            cards.click()
        else:
            card = randint(0, len(cards) - 1)
            preview = cards[card].find_element(By.XPATH, '/div[@class="milestone-preview"]').text
            cards[card].click()
        # Issue: section titles are not in the content
        preview

        self.ps.test_updates["passed"] = True
class TestImprovePracticeAndForecast(unittest.TestCase):
    """T2.14 - Improve Practice and Forecast."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities["name"] = self.id()
        self.teacher = Teacher(use_env_vars=True, pasta_user=self.ps, capabilities=self.desired_capabilities)

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(job_id=str(self.teacher.driver.session_id), **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    # 14747 - 001 - Teacher | View how much students have practiced
    @pytest.mark.skipif(str(14747) not in TESTS, reason="Excluded")
    def test_teacher_view_how_much_students_have_practiced_14747(self):
        """View how much students have practiced.

        Steps:


        Expected Result:

        """
        self.ps.test_updates["name"] = "t2.14.001" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.14", "t2.14.001", "14747"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 14748 - 002 - Student | View changes in Performance Forecast at the end
    # of a retrieval practice in readings, hw, and previous practice
    @pytest.mark.skipif(str(14748) not in TESTS, reason="Excluded")
    def test_student_view_changes_in_performance_forecast_at_the_14748(self):
        """View changes in Performance Forecast at end of retrieval practice.

        Steps:


        Expected Result:

        """
        self.ps.test_updates["name"] = "t2.14.002" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.14", "t2.14.002", "14748"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 14749 - 003 - Teacher | Assign practice
    @pytest.mark.skipif(str(14749) not in TESTS, reason="Excluded")
    def test_teacher_assign_practice_14749(self):
        """Assign practice.

        Steps:


        Expected Result:

        """
        self.ps.test_updates["name"] = "t2.14.003" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.14", "t2.14.003", "14749"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True
class TestTeacherLoginAndAuthentification(unittest.TestCase):
    """CC1.11 - Teacher Login and Authentification."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(use_env_vars=True,
                               pasta_user=self.ps,
                               capabilities=self.desired_capabilities)
        self.teacher.login()

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                           **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7688 - 001 - Teacher | Log into Concept Coach
    @pytest.mark.skipif(str(7688) not in TESTS, reason='Excluded')
    def test_teacher_log_into_concept_coach_7688(self):
        """Log into Concept Coach.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name

        Expected Result:
        User is taken to the class dashboard.
        """
        self.ps.test_updates['name'] = 'cc1.11.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.11', 'cc1.11.001', '7688']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='macro_economics')
        self.teacher.sleep(5)

        assert('cc-dashboard' in self.teacher.current_url()), \
            'Not viewing the cc dashboard'

        self.ps.test_updates['passed'] = True

    # Case C7689 - 002 - Teacher | Logging out returns to the login page
    @pytest.mark.skipif(str(7689) not in TESTS, reason='Excluded')
    def test_teacher_loggin_out_returns_to_the_login_page_7689(self):
        """Logging out returns to the login page.

        Steps:
        Click the user menu containing the user's name
        Click the 'Log Out' button

        Expected Result:
        User is taken to cc.openstax.org
        """
        self.ps.test_updates['name'] = 'cc1.11.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.11', 'cc1.11.002', '7689']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='macro_economics')
        self.teacher.sleep(5)

        assert('dashboard' in self.teacher.current_url()), \
            'Not viewing the cc dashboard'

        self.teacher.open_user_menu()
        self.teacher.sleep(1)
        self.teacher.find(By.XPATH, "//a/form[@class='-logout-form']").click()

        assert('cc.openstax.org' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.ps.test_updates['passed'] = True

    # Case C7690 - 003 - Teacher | Can log into Tutor and be redirected to CC
    @pytest.mark.skipif(str(7690) not in TESTS, reason='Excluded')
    def test_teacher_can_log_into_tutor_and_be_redirected_to_cc_7690(self):
        """Can log into Tutor and be redirected to Concept Coach.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name

        Expected Result:
        User is taken to the class dashboard
        """
        self.ps.test_updates['name'] = 'cc1.11.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.11', 'cc1.11.003', '7690']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='macro_economics')
        self.teacher.sleep(5)

        assert('cc-dashboard' in self.teacher.current_url()), \
            'Not viewing the cc dashboard'

        self.ps.test_updates['passed'] = True
Ejemplo n.º 18
0
class TestViewClassScores(unittest.TestCase):
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(use_env_vars=True,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
        else:
            self.teacher = Teacher(use_env_vars=True)
        self.wait = WebDriverWait(self.student.driver, Assignment.WAIT_TIME)

        self.teacher.login()

        # go to student scores
        self.teacher.select_course(appearance='biology')
        self.teacher.driver.find_element(By.LINK_TEXT,
                                         'Student Scores').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//span[contains(text(), "Student Scores")]'))).click()

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    @pytest.mark.skipif(str(1) not in TESTS, reason='Excluded')
    def test_review_student_scores(self):
        '''
        Go to https://tutor-qa.openstax.org/
        Click on the 'Login' button
        Enter the teacher user account [ teacher01 | password ] in the username
        and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a Tutor course name

        Click "Student Scores" from the calendar dashboard
        ***The user is presented with scores at due date (t2.10.06)***

        Click on the orange flag in the upper right corner of a progress cell
        for the desired student
        ***The user is presented with the current score (t2.10.07)***

        Period tabs are displayed
        ***Period tabs are displayed (t1.23.02)***

        Click on the tab for the desired period
        ***Scores for selected period are displayed in table (t1.23.01)***

        Click on the name of an arbitrary student
        ***Performance Forecast for selected student is displayed (t1.23.05)***

        Click on the name of the student to open a drop down menu
        In the drop down menu click the name of selected student
        ***Performance Forecast for second selected student is displayed
        (t1.23.06)***

        Click on the info icon next to the student's name
        ***Information about Performance Forecast is displayed. (t1.23.07)***

        Click on the "Return to Scores" button
        ***User at Student scores page on the first tab (t1.23.08)***

        Click on "Student Name" on the table [this will make the names in
        reverse alphabetical order by last name]
        Click on "Student Name" on the table again [this will make the names in
        alphabetical order by last name]
        ***The students are sorted alphabetically by last name. (t1.23.09)***

        Click "Progress" button
        ***Students are sorted by completion of selected assignment.
        (t1.23.10)***

        Click on the tab for selected section
        ***Due date for selected assignment is displayed in the cell below the
        assignment name (t1.23.011)***

        Corresponds to...
        t2.10 06,07
        t1.23 1,3,5 --> 11
        '''

        # t1.23.01 --> Scores for selected period are displayed in table
        assert ('scores' in self.teacher.current_url()), \
            'Not viewing Student Scores'

        # (t1.23.02) --> Period tabs are displayed
        current_period = 0
        period_tabs = self.teacher.wait.until(
            expect.visibility_of_elements_located(
                (By.XPATH,
                 '//span[contains(@class, "tab-item-period-name")]')))
        period_tabs[current_period + 1].click()

        # DO SOMETHING HERE TO WAIT FOR THIS TO BE CLICKABLE
        period_tabs[current_period].click()

        # (t2.10.06) -->  The user is presented with scores at due date
        #  Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="course-scores-container"]')))

        # t2.10.07 --> The user is presented with the current score
        scroll_bar = self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"ScrollbarLayout_faceHorizontal")]')
        scroll_width = scroll_bar.size['width']
        scroll_total_size = self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"ScrollbarLayout_mainHorizontal")]'
        ).size['width']
        bar = scroll_width
        while (bar < scroll_total_size):
            try:
                late_caret = self.teacher.find(
                    By.XPATH, '//div[@class="late-caret accepted"]')
                late_caret.click()
                pie_progress = late_caret.findElement(
                    By.XPATH, "/..//svg[contains(@class,'pie-progress')]")
                print(pie_progress)

                # self.teacher.find(
                #     By.XPATH,
                #     '//div[contains(@class,"late-status")]' +
                #     '//span[text()="due date"]'
                # )
                # break
            except (NoSuchElementException, ElementNotVisibleException,
                    WebDriverException):
                bar += scroll_width
                if scroll_total_size <= bar:
                    print("No Late assignments for this class :(")
                    raise Exception
                # drag scroll bar instead of scrolling
                actions = ActionChains(self.teacher.driver)
                actions.move_to_element(scroll_bar)
                actions.click_and_hold()
                actions.move_by_offset(scroll_width, 0)
                actions.release()
                actions.perform()

        # t1.23.05 --> Performance Forecast for selected student is displayed
        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(@class,"name-cell")]'))).click()
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH,
                 '//span[contains(text(), "Performance Forecast for")]')))

        # (t1.23.06) --> Performance Forecast for second selected student is
        # displayed
        self.teacher.find(By.ID, 'student-selection').click()
        student_select = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(@role, "menuitem")]' +
                 '//span[contains(@class,"-name")]')))

        student_name = student_select.text
        student_select.click()

        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH,
                 '//span[contains(text(), "' + student_name + '")]')))

        # (t1.23.07 --> Information about Performance Forecast is displayed.
        self.teacher.find(By.XPATH,
                          '//button[contains(@class,"info-link")]').click()
        self.teacher.driver.find_element(
            By.XPATH, '//div[contains(@class,"tooltip-inner")]')

        # (t1.23.08 --> User at Student scores page on the first tab
        self.teacher.find(By.LINK_TEXT, 'Return to Scores').click()

        assert('scores' in self.teacher.current_url()), \
            'Not viewing Student Scores'

        # NOTE: ## signifies the selectors that possibly need editing

        # (t1.23.09 --> The students are sorted alphabetically by last name.

        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(text(),"Name and Student ID")]'))).click()

        # WATCH OUT-- THERE'S MULTIPLE HEADER-CELLS
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"header-row")]' +
            '//div[contains(@class,"is-descending")]')

        # self.teacher.find(
        #     By.XPATH, '//div[contains(text(),"Name and Student ID")]')
        # .click() ##
        #
        #
        # self.teacher.find(
        #     By.XPATH,
        #     '//div[contains(@class,"header-cell")]' +
        #     '//div[contains(@class,"is-ascending")]')

        # t1.23.10 --> Students are sorted by completion of selected
        # assignment.

        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[contains(@class,"scores-cell")]' +
                 '//div[contains(text(),"Progress")]'))).click()

        self.teacher.find(
            By.XPATH, '//div[contains(@class,"scores-cell")]' +
            '//div[contains(@class,"is-descending")]')

        # self.teacher.driver.find_element(
        #     By.XPATH,
        #     '//div[contains(@class,"scores-cell")]' + ##
        #     '//div[contains(text(),"Progress")]' ##
        # ).click()
        # self.teacher.driver.find_element(
        #     By.XPATH,
        #     '//div[contains(@class,"scores-cell")]' + ##
        #     '//div[contains(@class,"is-ascending")]') ##

        # t1.23.11 --> Due date for selected assignment is displayed in
        # the cell below the assignment name

        assignment_cell = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@data-assignment-type,"reading")]')))
        assignment_cell.find_element(
            By.XPATH, '//following-sibling::div[contains(@class,"due")]')
Ejemplo n.º 19
0
class TestExercisesTeacher(unittest.TestCase):
    """Tutor | Teacher"""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(use_env_vars=True,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
        else:
            self.teacher = Teacher(use_env_vars=True)
        # self.teacher.login(url='http://exercises-qa.openstax.org')

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    @pytest.mark.skipif(str(162257) not in TESTS, reason='Excluded')
    def test_creating_true_and_false_question_162257(self):
        """
        Go to exercises qa
        Log in as a teacher
        Click "Write a new exercise"
        Click "True/False" button

        Expected result:

        ***User is presented with a page where a True/False question can be
        created***

        Corresponding test cases: T2.12 001, 002

        https://trello.com/c/w4T1eqT4/66-creating-vocabulary-question-and-true-false
        """

        self.ps.test_updates['name'] = \
            'exercises_new_exercise_teacher_162257' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = \
            ['exercises', 'new_exercise', 'teacher', '162257']
        self.ps.test_updates['passed'] = False

        # log into exercises
        self.teacher.login(url=os.getenv('EXERCISES_STAGING'),
                           username=os.getenv('CONTENT_USER'),
                           password=os.getenv('CONTENT_PASSWORD'))
        # Click "Write a new exercise"
        self.teacher.find(By.CSS_SELECTOR, "a[href*='new']").click()
        # Click true false button
        self.teacher.find(By.CSS_SELECTOR, "#input-true-false").click()
        # Verify that user is presented with a page where they can make a true
        # false q
        self.teacher.find(By.CSS_SELECTOR, "textarea")

        self.ps.test_updates['passed'] = True

    @pytest.mark.skipif(str(162258) not in TESTS, reason='Excluded')
    def test_question_library_functionality_162258(self):
        """
        Go to tutor qa
        Log in as a teacher
        Click on a course
        Upper right corner under user menu, click "Question Library"
        Select a section or chapter
        click "Show Questions"
        **User is presented with all the questions for the section or chapter**

        Scroll down to a question, click "Exclude Question"
        ***Observe that Question is excluded***

        Click on the "Reading" tab
        ***Exercises that are only for Reading appear***

        Click on the "Practice" tab @@@@@@@@@@@ Should this be Homework?
        ***Exercises that are only for Practice appear***

        Scroll down
        **Observe that tabs are pinned to the top of the screen when scrolled**

        Click on the section links at the top of the screen
        ***Observe that the screen scrolls to the selected screen***
        Hover over a question and click "Question details"
        Click "Report an error"

        Expected result:

        ***Observe that a new tab with the assessment errata form appears with
        the assessment ID already filled in***

        Corresponding test cases: T2.11 001-007

        https://trello.com/c/SchGDgfL/70-question-library-functionality
        """

        self.ps.test_updates['name'] = \
            'exercises_question_library_teacher_162258' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = \
            ['exercises', 'question_library', 'teacher', '162258']
        self.ps.test_updates['passed'] = False

        self.teacher.login()
        # select random tutor course
        self.teacher.random_course()
        # if Tutor feedback pops up
        try:
            self.teacher.find(
                By.XPATH,
                ".//*[contains(text(),'I won’t be using it')]").click()
        except:
            pass
        # go to question library
        self.teacher.open_user_menu()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.CSS_SELECTOR, "#menu-option-viewQuestionsLibrary")))
        self.teacher.find(By.CSS_SELECTOR,
                          "#menu-option-viewQuestionsLibrary").click()
        # 50/50 coin toss. 0 = chapter, 1 = section(s)
        coin = randint(0, 1)
        # reveal sections
        chaptertitles = self.teacher.find_all(
            By.CSS_SELECTOR, ".chapter-heading.panel-title>a")
        for num in range(1, len(chaptertitles) - 1):
            self.teacher.scroll_to(chaptertitles[num])
            self.teacher.sleep(.2)
            chaptertitles[num].click()
            self.teacher.sleep(.2)

        # choose a random chapter and all its sections
        if coin == 0:
            chapters = self.teacher.find_all(By.CSS_SELECTOR,
                                             ".chapter-checkbox")
            chapternum = randint(0, len(chapters) - 1)
            self.teacher.scroll_to(chapters[chapternum])
            self.teacher.sleep(0.5)
            chapters[chapternum].click()
            self.teacher.sleep(0.5)

        # choose randomly 1-5 sections from anywhere in the book
        elif coin == 1:
            sections = self.teacher.find_all(By.CSS_SELECTOR,
                                             ".section-checkbox")
            randomlist = random.sample(range(len(sections) - 1),
                                       k=randint(1, 5))
            for num in randomlist:
                self.teacher.scroll_to(sections[num])
                self.teacher.sleep(.5)
                sections[num].click()

        # click show questions
        self.teacher.find(By.CSS_SELECTOR, ".btn.btn-primary").click()
        self.teacher.sleep(5)
        # verify questions show up
        readingq = self.teacher.find_all(By.CSS_SELECTOR, ".controls-overlay")
        excludebutton = self.teacher.find_all(By.CSS_SELECTOR,
                                              ".action.exclude")[0]
        # exclude a random question
        self.teacher.scroll_to(excludebutton)
        self.teacher.sleep(1)
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(excludebutton)
        self.teacher.sleep(1)
        actions.perform()
        self.teacher.sleep(2)
        excludebutton.click()
        self.teacher.sleep(.5)
        self.teacher.find(By.CSS_SELECTOR, ".action.include").click()

        # click reading button
        self.teacher.find(By.CSS_SELECTOR, ".reading.btn.btn-default").click()
        self.teacher.page.wait_for_page_load()
        totalq = self.teacher.find_all(By.CSS_SELECTOR, ".controls-overlay")
        # click homework button
        self.teacher.find(By.CSS_SELECTOR, ".homework.btn.btn-default").click()
        homeworkq = self.teacher.find_all(By.CSS_SELECTOR, ".controls-overlay")
        assert (len(totalq) > len(readingq))
        assert (len(totalq) > len(homeworkq))

        # Observe that tabs are pinned to the top of the screen when scrolled
        self.teacher.driver.execute_script("window.scrollTo(0, 0);")
        self.teacher.sleep(3)
        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.sleep(3)
        self.teacher.find(By.XPATH, "//div[@class='section active']")
        self.teacher.find(By.CSS_SELECTOR, ".homework.btn.btn-default")
        self.teacher.find(By.CSS_SELECTOR, ".reading.btn.btn-default")

        # jumps
        jumps = self.teacher.find_all(
            By.XPATH, "//div[@class='sectionizer']/div[@class='section']")
        # Click the section links and verify the page is scrolled
        position = self.teacher.driver.execute_script("return window.scrollY;")
        for button in jumps:
            button.click()
            self.teacher.sleep(1)
            assert(position != self.teacher.driver.execute_script(
                "return window.scrollY;")), \
                'Section link did not jump to next section'
            position = \
                self.teacher.driver.execute_script("return window.scrollY;")
        # details will lead to Question details
        details = self.teacher.find_all(By.CSS_SELECTOR, ".action.details")[0]
        self.teacher.scroll_to(details)
        self.teacher.sleep(1)
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(details)
        self.teacher.sleep(1)
        actions.perform()
        self.teacher.sleep(2)
        details.click()
        self.teacher.find(By.CSS_SELECTOR, ".action.report-error").click()
        details_window = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(details_window)
        self.teacher.page.wait_for_page_load()
        self.teacher.sleep(2)
        self.teacher.find(By.CSS_SELECTOR, ".errata-page.page")

        self.ps.test_updates['passed'] = True

    @pytest.mark.skipif(str(162259) not in TESTS, reason='Excluded')
    def test_creating_multiple_choice_questions_162259(self):
        """
        Go to exercises qa
        Log in as a teacher
        Click "Write a new exercise"
        Enter the video embed link into the Question Stem text box
        ***The video should appear in the box to the right***

        Fill out the required fields
        Click on the box "Order Matters"
        ***User is able to preserve the order of choices***
        Click "Tags"
        Click "Question Type", "DOK", "Blooms", and/or "Time"
        ***The user is able to pull out the dropdown tags***

        Select a choice from the dropdown tags
        ***User is able to select a specific tag and the tag(s) appear in the
        box to the right***

        Check the box that says "Requires Context"
        ***The user is able to specify whether context is required for a
        question and the tag
        "requires-context:true" appears in the box to the right***

        Click "+" next to "CNX Module"
        Enter the CNX Module number
        Click "Save Draft"
        Click "Assets"
        Click "Add new image"
        Select an image
        ***The image and the options "Choose different image" and "Upload"
        should come up***

        Click "Upload"
        ***There shoould be a URL and a "Delete" button)***
        ***The user is presented with uploaded URL in the HTML snippet***
        Click "Delete"
        ***The image is deleted***

        Click "Save Draft", then click "Publish"
        ***Observe message: "Exercise [exercise ID] has published
        successfully")***

        Click "Search"
        Enter the desired exercise ID
        Scroll down to "Detailed Solutions"
        Edit text in the "Detailed Solutions" text box
        Click "Publish"

        Expected Result:

        ***The user is able to edit detailed solutions and the changes are in
        the box to the right***

        Corresponding test cases: T2.11 022-031

        https://trello.com/c/n5VmmdyB/83-creating-multiple-choice-questions
        """

        self.ps.test_updates['name'] = \
            'exercises_new_exercise_teacher_162259' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = \
            ['exercises', 'new_exercise', 'teacher', '162259']
        self.ps.test_updates['passed'] = False

        self.teacher.login(url=os.getenv('EXERCISES_QA'),
                           username=os.getenv('CONTENT_USER'),
                           password=os.getenv('CONTENT_PASSWORD'))
        # click create a new question
        self.teacher.find(By.CSS_SELECTOR, "a[href*='new']").click()
        textboxes = self.teacher.find_all(By.CSS_SELECTOR,
                                          ".question>div>textarea")
        # put embed link into Question Stem text box
        embedlink = '<iframe width="560" height="315" ' + \
            'src="https://www.youtube.com/embed/'
        embedlink += 'QnQe0xW_JY4" frameborder="0" allowfullscreen></iframe>"'
        textboxes[0].send_keys(embedlink)
        # verify that the video appears in the box to the right
        self.teacher.find(By.CSS_SELECTOR, "iframe")
        # fill out the required fields
        answers = self.teacher.find_all(By.CSS_SELECTOR,
                                        ".correct-answer>textarea")
        answers[0].send_keys('answer numero uno')
        answers[1].send_keys('answer numero dos')
        # textboxes[1].send_keys('answer numero tres')
        # click on Order Matters checkbox
        self.teacher.find(By.CSS_SELECTOR, "#input-om").click()

        # Click on Tabs tag
        self.teacher.find(By.CSS_SELECTOR, "#exercise-parts-tab-tags").click()
        # verify that all the dropdowns are clickable
        tagoptions = self.teacher.find_all(By.CSS_SELECTOR, ".form-control")
        for num in range(len(tagoptions)):
            expect.element_to_be_clickable(tagoptions[num])
        # choose an option from a dropdown
        tagoptions[1].click()
        self.teacher.find_all(By.CSS_SELECTOR, "option")[1].click()
        # verify that the tag appears in the box to the right
        self.teacher.find(
            By.XPATH, "//*[@class='exercise-tag' and contains(text(),'type')]")
        self.teacher.find(By.CSS_SELECTOR, ".tag>input").click()
        self.teacher.find(
            By.XPATH,
            "//*[@class='exercise-tag' and contains(text(),'context:true')]")
        # click "+" next to CNX Module
        self.teacher.find_all(By.CSS_SELECTOR, ".fa.fa-plus-circle")[2].click()
        # put in a CNX module
        self.teacher.find(
            By.XPATH,
            ".//*[@class='form-control' and @placeholder]").send_keys(
                '12345678-1234-5788-9123-456798123456')

        # click save draft
        self.teacher.find(By.CSS_SELECTOR,
                          ".async-button.draft.btn.btn-info").click()
        # click assets tab
        self.teacher.find(By.CSS_SELECTOR, "#exercise-parts-tab-assets") \
            .click()
        # Choose image. This is all local -- prob have to edit for diff
        # computer
        IMAGEPATH = "/Users/openstax10/desktop/bee_clip_art_18782.jpg"
        self.teacher.find(By.ID, "file").send_keys(IMAGEPATH)
        # check that Choose different image and Upload buttons are present
        self.teacher.find(By.XPATH,
                          './/*[contains(text(),"Choose different image")]')
        self.teacher.find(By.XPATH, './/*[contains(text(),"Upload")]').click()
        self.teacher.page.wait_for_page_load()
        # check if uploaded url is present
        self.teacher.find(By.CSS_SELECTOR, ".copypaste")
        # check that delete button is present and click it
        self.teacher.find(By.XPATH, './/*[contains(text(),"Delete")]').click()
        self.teacher.sleep(1)

        # click publish
        self.teacher.find(By.CSS_SELECTOR,
                          '.async-button.publish.btn.btn-primary').click()
        self.teacher.sleep(1)
        # confirm that you want to publish
        self.teacher.find(
            By.XPATH,
            './/*[@class="btn btn-primary" and contains(text(),"Publish")]'
        ).click()
        self.teacher.sleep(1)
        # close popup window tellign you ID #
        self.teacher.find(
            By.XPATH,
            './/*[@class="btn btn-primary" and contains(text(),"Close")]'
        ).click()
        # get id
        ID = self.teacher.current_url().split('/')[-1]

        # click search button
        self.teacher.find(By.CSS_SELECTOR,
                          '.btn.btn-danger.back.btn.btn-default').click()
        # enter ID into field
        self.teacher.find(By.CSS_SELECTOR, '.form-control').send_keys(ID)
        self.teacher.find(By.CSS_SELECTOR, '.btn.btn-default.load').click()
        # edit detailed solution
        self.teacher.find(By.XPATH, "//div[4]/textarea") \
            .send_keys('hello edited')
        detailedsol = self.teacher.find(
            By.CSS_SELECTOR,
            '.openstax-has-html.solution').get_attribute('innerHTML')
        # check that the text you inputted into detailed solution is in the
        # box to the right
        assert ('hello edited' == detailedsol)

        self.ps.test_updates['passed'] = True

    @pytest.mark.skipif(str(162260) not in TESTS, reason='Excluded')
    def test_creating_vocabulary_questions_162260(self):
        """
        Go to exercises qa
        Log in with as a teacher
        Click "Write a new exercise"
        Click "New Vocabulary Term" from the header
        Fill out required fields
        Click "Save Draft"
        Click "Publish"
        ***The "Publish" button is whited out and the exercise ID appears in
        the box to the right***

        Click "Search"
        Enter the desired exercise ID
        ***The vocabulary question loads and user is able to review it***

        Enter next text into "Key Term", "Key Term Definition", and
        "Distractors"
        Click "Save Draft"
        Click "Publish"

        Expected result:

        ***The user is able to edit and save a vocabulary question***

        Corresponding test cases: T2.11 035-037

        https://trello.com/c/3j0K6fp0/89-creating-vocabulary-questions
        """

        self.ps.test_updates['name'] = \
            'exercises_new_exercise_teacher_162260' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = \
            ['exercises', 'new_exercise', 'teacher', '162260']
        self.ps.test_updates['passed'] = False

        # logging in with these credentials
        self.teacher.login(url=os.getenv('EXERCISES_QA'),
                           username=os.getenv('CONTENT_USER'),
                           password=os.getenv('CONTENT_PASSWORD'))
        # click create a new question
        self.teacher.find(By.CSS_SELECTOR, "a[href*='new']").click()
        # click New vocabulary question
        self.teacher.find(By.CSS_SELECTOR,
                          ".btn.btn-success.vocabulary.blank").click()
        # enter testing as the key term
        self.teacher.find(By.CSS_SELECTOR, "#key-term").send_keys('testing')
        # enter 'ignore' as the definition
        self.teacher.find(By.CSS_SELECTOR, "#key-term-def").send_keys('ignore')
        # click save draft
        self.teacher.find(By.CSS_SELECTOR,
                          ".async-button.draft.btn.btn-info").click()
        # click publish
        self.teacher.find(By.CSS_SELECTOR,
                          ".async-button.publish.btn.btn-primary").click()
        self.teacher.sleep(1)
        # confirm publish
        self.teacher.find(
            By.XPATH,
            ".//*[@class='btn btn-primary' and contains(text(),'Publish')]"
        ).click()
        self.teacher.sleep(3)
        # get the exercise id
        exerciseid = self.teacher.find_all(
            By.CSS_SELECTOR, ".exercise-tag")[3].get_attribute('innerHTML')[4:]

        # go to search
        self.teacher.find(By.XPATH, ".//*[contains(text(),'Search')]").click()
        # search the exercise id
        self.teacher.find(By.CSS_SELECTOR, ".form-control") \
            .send_keys(exerciseid)
        # click search
        self.teacher.find(By.CSS_SELECTOR, ".btn.btn-default.load").click()
        # confirm key term value is what was inputted originally
        keyterm = self.teacher.find(By.CSS_SELECTOR, "#key-term") \
            .get_attribute('value')
        assert (keyterm == 'testing')
        # write something else for key term
        keyterm = self.teacher.find(By.CSS_SELECTOR, "#key-term")
        keyterm.send_keys(Keys.BACKSPACE * len('testing   '))
        self.teacher.sleep(0.2)
        keyterm.send_keys('test edit')
        # confirm key term def value is what was inputted oirignally
        keytermdef = self.teacher.find(By.CSS_SELECTOR, '#key-term-def') \
            .get_attribute('value')
        assert (keytermdef == 'ignore')
        # write something else for key term def
        keytermdef = self.teacher.find(By.CSS_SELECTOR, "#key-term-def")
        keytermdef.send_keys(Keys.BACKSPACE * len('ignore   '))
        self.teacher.sleep(0.2)
        keytermdef.send_keys('ignore edit')
        # fill in value for distractor
        self.teacher.find_all(By.CSS_SELECTOR,
                              ".form-control")[2].send_keys('im a distractor')
        self.teacher.sleep(3)

        # save as draft
        self.teacher.find(By.CSS_SELECTOR,
                          ".async-button.draft.btn.btn-info").click()
        self.teacher.sleep(1)
        # publish
        self.teacher.find(By.CSS_SELECTOR,
                          ".async-button.publish.btn.btn-primary").click()
        # confirm publish
        self.teacher.find(
            By.XPATH,
            './/*[@class="btn btn-primary" and contains(text(),"Publish")]'
        ).click()
        self.teacher.sleep(2)
        # get new exercise id
        exerciseid = self.teacher.find_all(
            By.CSS_SELECTOR, ".exercise-tag")[3].get_attribute('innerHTML')[4:]
        # click search
        self.teacher.find(By.XPATH, ".//*[contains(text(),'Search')]").click()
        # search the exercise id
        self.teacher.find(By.CSS_SELECTOR, ".form-control") \
            .send_keys(exerciseid)
        self.teacher.find(By.CSS_SELECTOR, ".btn.btn-default.load").click()
        # verify that the value in key term is what was inputted previously
        keyterm = self.teacher.find(By.CSS_SELECTOR, "#key-term") \
            .get_attribute('value')
        assert (keyterm == 'test edit')

        self.ps.test_updates['passed'] = True

    @pytest.mark.skipif(str(162261) not in TESTS, reason='Excluded')
    def test_creating_multipart_question_162261(self):
        """
        Go to exercises qa
        Log in as a teacher
        Click "Write a new exercise"
        Check the box that says "Exercise contains multiple parts"
        Fill out the required fields
        Click "Publish"

        Expected result:

        ***The user gets a confirmation that says "Exercise [exercise ID] has
        published successfully"***

        Corresponding test case: T2.11 045

        https://trello.com/c/8LnE8Qml/162-creating-multi-part-question
        """
        self.ps.test_updates['name'] = \
            'exercises_new_exercise_teacher_162261' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = \
            ['exercises', 'new_exercise', 'teacher', '162261']
        self.ps.test_updates['passed'] = False

        # logging in with these credentials
        self.teacher.login(url=os.getenv('EXERCISES_QA'),
                           username=os.getenv('CONTENT_USER'),
                           password=os.getenv('CONTENT_PASSWORD'))
        # click create a new question
        self.teacher.find(By.CSS_SELECTOR, "a[href*='new']").click()
        # click "Exercise contains multiple parts"
        self.teacher.find(By.CSS_SELECTOR, '#mpq-toggle').click()
        # write in something for question stem
        self.teacher.find(By.CSS_SELECTOR, '.question>div>textarea') \
            .send_keys('test')
        # write in something for Distractor
        self.teacher.find(By.CSS_SELECTOR, '.correct-answer>textarea') \
            .send_keys('ignore')
        # click tab "question 2"
        self.teacher.find(By.CSS_SELECTOR, '#exercise-parts-tab-question-1') \
            .click()
        self.teacher.sleep(1)
        # write in something for question stem
        self.teacher.find_all(By.CSS_SELECTOR,
                              '.question>div>textarea')[2].send_keys('test2')
        # write in something for Distractor
        self.teacher.find_all(
            By.CSS_SELECTOR,
            '.correct-answer>textarea')[2].send_keys('ignore2')
        # click save draft
        self.teacher.find(By.CSS_SELECTOR,
                          '.async-button.draft.btn.btn-info').click()
        # click publish
        self.teacher.find(By.CSS_SELECTOR,
                          '.async-button.publish.btn.btn-primary').click()
        self.teacher.sleep(1)
        # confirm publish
        self.teacher.find(
            By.XPATH,
            ".//*[@class='btn btn-primary' and contains(text(),'Publish')]"
        ).click()
        # confirm message appears
        self.teacher.find(By.CSS_SELECTOR, '.modal-body>b')

        self.ps.test_updates['passed'] = True
class TestConceptCoachWidgetMechanicsAndInfrastructure(unittest.TestCase):
    """CC1.06 - Concept Coach Widget Mechanics and Infrastructure."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                           **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7748 - 001 - Student | View a Concept Coach book and see the widget
    @pytest.mark.skipif(str(7748) not in TESTS, reason='Excluded')
    def test_student_view_a_cc_book_and_see_the_widget_7748(self):
        """View a Concept Coach book and see the widget.

        Steps:
        go to tutor-qa
        login as a student
        click on a concept coach book
        Click on the 'Contents +' button
        Click on the a chapter in the contents
        Click on a section other than the introduction
        Scroll down

        Expected Result:
        Concept Coach widget visible
        """
        self.ps.test_updates['name'] = 'cc1.06.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.06',
            'cc1.06.001',
            '7748'
        ]
        self.ps.test_updates['passed'] = False

        # login and go to cc course
        student = Student(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities,
            username=os.getenv('STUDENT_USER'),
            password=os.getenv('STUDENT_PASSWORD')
        )
        student.login()
        student.driver.find_element(
            By.XPATH, '//a[contains(@href,"cnx.org/contents")]'
        ).click()
        # go to section 1.1 then cc widget
        student.page.wait_for_page_load()
        student.driver.find_element(
            By.XPATH,
            '//button[@class="toggle btn"]//span[contains(text(),"Contents")]'
        ).click()
        student.sleep(0.5)
        student.driver.find_element(
            By.XPATH,
            '//span[@class="chapter-number" and text()="1.1"]'
        ).click()
        student.page.wait_for_page_load()
        student.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        student.driver.find_element(
            By.XPATH,
            '//div[@class="concept-coach-launcher"]'
        )
        student.delete()
        self.ps.test_updates['passed'] = True

    # Case C7749 - 002 - Teacher | View a Concept Coach book and see the widget
    @pytest.mark.skipif(str(7749) not in TESTS, reason='Excluded')
    def test_teacher_view_a_cc_book_and_see_the_widget_7749(self):
        """View a Concept Coach book and see the widget.

        Steps:
        Go to Tutor
        Login as a teacher
        Click on a concept coach book
        Click on 'Online Book' in the header
        Click on the 'Contents +' button
        Click on the a chapter in the contents
        Click on a section other than the introduction
        Scroll down

        Expected Result:
        Concept Coach widget visible
        """
        self.ps.test_updates['name'] = 'cc1.06.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.06',
            'cc1.06.002',
            '7749'
        ]
        self.ps.test_updates['passed'] = False

        # login and go to cc course
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        # open online book
        self.teacher.driver.find_element(
            By.XPATH, '//a//span[contains(text(),"Online Book")]'
        ).click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        assert('cnx' in self.teacher.current_url()), \
            'Not viewing the textbook PDF'
        # go to section 1.1 then cc widget
        self.teacher.page.wait_for_page_load()
        self.teacher.driver.find_element(
            By.XPATH,
            '//button[@class="toggle btn"]//span[contains(text(),"Contents")]'
        ).click()
        self.teacher.sleep(0.5)
        self.teacher.driver.find_element(
            By.XPATH,
            '//span[@class="chapter-number" and text()="1.1"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[@class="concept-coach-launcher"]'
        )
        self.ps.test_updates['passed'] = True

    # Case C7750 - 003 - Student | Doesn't see end-of-page exercise sections
    @pytest.mark.skipif(str(7750) not in TESTS, reason='Excluded')
    def test_student_doesnt_see_end_of_page_exercise_sections_7750(self):
        """Doesn't see end-of-page exercise sections.

        Steps:
        Go to Tutor
        Login as a student
        Click on a concept coach book
        Click on the 'Contents +' button
        Click on the a chapter in the contents
        Click on a section other than the introduction
        Scroll down

        Expected Result:
        End-of-page exercise sections are not displayed.
        """
        self.ps.test_updates['name'] = 'cc1.06.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.06',
            'cc1.06.003',
            '7750'
        ]
        self.ps.test_updates['passed'] = False

        # login and go to cc course
        student = Student(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities,
            username=os.getenv('STUDENT_USER'),
            password=os.getenv('STUDENT_PASSWORD')
        )
        student.login()
        student.driver.find_element(
            By.XPATH, '//a[contains(@href,"cnx.org/contents")]'
        ).click()
        # go to section 1.1 then cc widget
        student.page.wait_for_page_load()
        student.driver.find_element(
            By.XPATH,
            '//button[@class="toggle btn"]//span[contains(text(),"Contents")]'
        ).click()
        student.sleep(0.5)
        student.driver.find_element(
            By.XPATH,
            '//span[@class="chapter-number" and text()="1.1"]'
        ).click()
        student.page.wait_for_page_load()
        questions = student.driver.find_elements(
            By.XPATH,
            '//section[@data-depth="1" and not(@class)]' +
            '//div[@data-type="exercise"]'
        )
        assert(len(questions) == 0), "questions found at the end of chapter"
        student.delete()
        self.ps.test_updates['passed'] = True
Ejemplo n.º 21
0
class TestViewTheCalendarDashboard(unittest.TestCase):
    """T1.13 - View the calendar."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(
                use_env_vars=True,
                pasta_user=self.ps,
                capabilities=self.desired_capabilities
            )
        else:
            self.teacher = Teacher(
                use_env_vars=True
            )
        self.teacher.login()
        self.teacher.select_course(appearance='college_physics')

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(
                job_id=str(self.teacher.driver.session_id),
                **self.ps.test_updates
            )
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7978 - 001 - Teacher | View the calendar dashboard
    @pytest.mark.skipif(str(7978) not in TESTS, reason='Excluded')
    def test_teacher_view_the_calendar_dashboard_7978(self):
        """View the calendar dashboard.

        Steps:
        If the user has more than one course, click on a Tutor course name

        Expected Result:
        The teacher is presented their calendar dashboard.
        """
        self.ps.test_updates['name'] = 't1.13.001' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.001', '7978']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        assert('course' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.ps.test_updates['passed'] = True

    # Case C7979 - 002 - Teacher | View student scores using dashboard button
    @pytest.mark.skipif(str(7979) not in TESTS, reason='Excluded')
    def test_teacher_view_student_scores_using_the_dashboard_button_7979(self):
        """View student scores using the dashboard button.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the 'Student Scores' button

        Expected Result:
        The teacher is presented with the student scores
        """
        self.ps.test_updates['name'] = 't1.13.002' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.002', '7979']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        self.teacher.find(By.LINK_TEXT, 'Student Scores').click()
        assert('scores' in self.teacher.current_url()), \
            'Not viewing student scores'

        self.ps.test_updates['passed'] = True

    # Case C7980 - 003 - Teacher | View student scores using the user menu link
    @pytest.mark.skipif(str(7980) not in TESTS, reason='Excluded')
    def test_teacher_view_student_scores_using_the_user_menu_link_7980(self):
        """View student scores using the user menu link.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the user menu
        Click on the 'Student Scores' link

        Expected Result:
        The teacher is presented with the student scores
        """
        self.ps.test_updates['name'] = 't1.13.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.003', '7980']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        self.teacher.open_user_menu()
        self.teacher.find(By.CLASS_NAME, 'viewScores'). \
            find_element_by_tag_name('a'). \
            click()
        assert('scores' in self.teacher.current_url()), \
            'Not viewing the student scores'

        self.ps.test_updates['passed'] = True

    # Case C7981 - 004 - Teacher | View performance forecast using the
    # dashboard button
    @pytest.mark.skipif(str(7981) not in TESTS, reason='Excluded')
    def test_teacher_view_performance_forecast_using_dash_button_7981(self):
        """View performance forecast using the dashboard button.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the 'Performance Forecast' button on the dashboard

        Expected Result:
        The teacher is presented with the performance forecast
        """
        self.ps.test_updates['name'] = 't1.13.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.004', '7981']
        self.ps.test_updates['passed'] = False

        self.teacher.find(By.LINK_TEXT, 'Performance Forecast').click()
        self.teacher.page.wait_for_page_load()
        assert('guide' in self.teacher.current_url()), \
            'Not viewing the performance forecast'

        self.ps.test_updates['passed'] = True

    # Case C7982 - 005 - Teacher | View performace forecast using
    # the user menu link
    @pytest.mark.skipif(str(7982) not in TESTS, reason='Excluded')
    def test_teacher_view_performance_forecast_using_user_menu_link_7982(self):
        """View performance forecast using the user menu link.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the user menu
        Click on the 'Performance Forecast' link

        Expected Result:
        The teacher is presented with the performance forecast
        """
        self.ps.test_updates['name'] = 't1.13.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.005', '7982']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        self.teacher.open_user_menu()
        self.teacher.find(
            By.XPATH, '//a[@data-name="viewPerformanceGuide"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        assert('guide' in self.teacher.current_url()), \
            'Not viewing the performance forecast'

        self.ps.test_updates['passed'] = True

    # Case C7983 - 006 - Teacher | View a reading assignment summary
    @pytest.mark.skipif(str(7983) not in TESTS, reason='Excluded')
    def test_teacher_view_a_reading_assignment_summary_7983(self):
        """View a reading assignment summary.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Create a reading assignment
        Click on the reading assignment on the calendar

        Expected Result:
        The teacher is presented with the reading assignment summary
        """
        self.ps.test_updates['name'] = 't1.13.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.006', '7983']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(appearance='physics')
        # create an assignment
        assignment_name = 'reading-%s' % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=2)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=5)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(
            assignment='reading',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'reading_list': ['1.1'],
                'status': 'publish',
            }
        )
        # click on assignment
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, '//label[contains(text(), "%s")]' % assignment_name)
            )
        ).click()
        # check that it opened
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH,
                 '//*[@class="modal-title" and ' +
                 'contains(text(), "%s")]' % assignment_name)
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7984 - 007 - Teacher | View a homework assignment summary
    @pytest.mark.skipif(str(7984) not in TESTS, reason='Excluded')
    def test_teacher_view_a_homework_assignment_summary_7984(self):
        """View a homework assignment summary.

        Steps:
        create a homework assignment
        If the user has more than one course, click on a Tutor course name
        Click on a homework assignment on the calendar

        Expected Result:
        The teacher is presented with the homework assignment summary
        """
        self.ps.test_updates['name'] = 't1.13.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.007', '7984']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(appearance='physics')
        # create an assignment
        assignment_name = "homework-%s" % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=2)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=5)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(
            assignment='homework',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'problems': {'1.1': (2, 3), },
                'status': 'publish',
                'feedback': 'immediate'
            }
        )
        # click on assignment
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, '//label[contains(text(), "%s")]' % assignment_name)
            )
        ).click()
        # check that it opened
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH,
                 '//*[@class="modal-title" and ' +
                 'contains(text(), "%s")]' % assignment_name)
            )
        )
        self.ps.test_updates['passed'] = True

    # NOT DONE
    # Case C7985 - 008 - Teacher | View an external assignment summary
    @pytest.mark.skipif(str(7985) not in TESTS, reason='Excluded')
    def test_teacher_view_an_external_assignment_summary_7985(self):
        """View an external assignment summary.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on an external assignment on the calendar

        Expected Result:
        The teacher is presented with the external assignment summary
        """
        self.ps.test_updates['name'] = 't1.13.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.008', '7985']
        self.ps.test_updates['passed'] = False

        # create an assignment
        assignment_name = 'external-%s' % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=0)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=5)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(
            assignment='external',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'url': 'google.com',
                'status': 'publish'
            }
        )
        # click on assignment
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, '//label[contains(text(), "%s")]' % assignment_name)
            )
        ).click()
        # check that it opened
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH,
                 '//*[@class="modal-title" and ' +
                 'contains(text(), "%s")]' % assignment_name)
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7986 - 009 - Teacher | View an event summary
    @pytest.mark.skipif(str(7986) not in TESTS, reason='Excluded')
    def test_teacher_view_an_event_summary_7986(self):
        """View an event summary.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on an event on the calendar

        Expected Result:
        The teacher is presented with the event summary
        """
        self.ps.test_updates['name'] = 't1.13.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.009', '7986']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(appearance='physics')
        # create an assignment
        assignment_name = "homework-%s" % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=2)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=5)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'publish'
            }
        )
        # click on assignment
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, '//label[contains(text(), "%s")]' % assignment_name)
            )
        ).click()
        # check that it opened
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH,
                 '//*[@class="modal-title" and ' +
                 'contains(text(), "%s")]' % assignment_name)
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7987 - 010 - Teacher | Open the refrenece book using the dashboard
    # button
    @pytest.mark.skipif(str(7987) not in TESTS, reason='Excluded')
    def test_teacher_open_the_reference_book_using_dashboard_button_7987(self):
        """Open the refrenece book using the dashboard button.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the 'Browse The Book'button

        Expected Result:
        The teacher is preseneted with the book in a new tab
        """
        self.ps.test_updates['name'] = 't1.13.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.010', '7987']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        self.teacher.driver.find_element(
            By.CSS_SELECTOR,
            '.calendar-header .view-reference-guide'
        ).click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        assert('book' in self.teacher.current_url()), \
            'Not viewing the textbook PDF'

        self.ps.test_updates['passed'] = True

    # Case C7988 - 011 - Teacher | Open the refrenece book using user menu link
    @pytest.mark.skipif(str(7988) not in TESTS, reason='Excluded')
    def test_teacher_open_the_reference_book_using_user_menu_link_7988(self):
        """Open the refrenece book using the user menu link.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the user menu
        Click on the 'Browse the Book' link

        Expected Result:
        The teacher is presented with the book in a new tab
        """
        self.ps.test_updates['name'] = 't1.13.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.011', '7988']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        self.teacher.open_user_menu()
        self.teacher.find(
            By.CSS_SELECTOR,
            '.calendar-header .view-reference-guide'
        ).click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        assert('book' in self.teacher.current_url()), \
            'Not viewing the textbook PDF'

        self.ps.test_updates['passed'] = True

    # Case C7989 - 012 - Teacher | Click on the course name to return to
    # the dashboard
    @pytest.mark.skipif(str(7989) not in TESTS, reason='Excluded')
    def test_teacher_click_course_name_to_return_to_the_dashboard_7989(self):
        """Click on the course name to return to the dashboard.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the 'Performance Forecast' button
        Click on the course name in the header

        Expected Result:
        The teacher is presented with their calendar dashboard
        """
        self.ps.test_updates['name'] = 't1.13.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.012', '7989']
        self.ps.test_updates['passed'] = False

        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT,
            'Performance Forecast'
        ).click()
        self.teacher.find(
            By.CLASS_NAME,
            'course-name'
        ).click()
        assert('course' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.ps.test_updates['passed'] = True

    # Case C7990 - 013 - Teacher | Cick on the OpenStax logo to return to
    # the course picker
    @pytest.mark.skipif(str(7990) not in TESTS, reason='Excluded')
    def test_teacher_click_openstax_logo_to_return_to_course_picker_7990(self):
        """Cick on the OpenStax logo to return to the course picker.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click in the OpenStax logo in the header

        Expected Result:
        The teacher is presented with the course picker
        """
        self.ps.test_updates['name'] = 't1.13.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.013', '7990']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(appearance='physics')
        self.teacher.find(
            By.CLASS_NAME,
            'ui-brand-logo'
        ).click()
        assert('dashboard' in self.teacher.current_url()), \
            'Not viewing the course picker'

        self.ps.test_updates['passed'] = True

    '''
class TestTeacherLoginAndAuthentification(unittest.TestCase):
    """CC1.11 - Teacher Login and Authentification."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.teacher.login()

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7688 - 001 - Teacher | Log into Concept Coach
    @pytest.mark.skipif(str(7688) not in TESTS, reason='Excluded')
    def test_teacher_log_into_concept_coach_7688(self):
        """Log into Concept Coach.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name

        Expected Result:
        User is taken to the class dashboard.
        """
        self.ps.test_updates['name'] = 'cc1.11.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.11',
            'cc1.11.001',
            '7688'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='macro_economics')
        self.teacher.sleep(5)

        assert('cc-dashboard' in self.teacher.current_url()), \
            'Not viewing the cc dashboard'

        self.ps.test_updates['passed'] = True

    # Case C7689 - 002 - Teacher | Logging out returns to the login page
    @pytest.mark.skipif(str(7689) not in TESTS, reason='Excluded')
    def test_teacher_loggin_out_returns_to_the_login_page_7689(self):
        """Logging out returns to the login page.

        Steps:
        Click the user menu containing the user's name
        Click the 'Log Out' button

        Expected Result:
        User is taken to cc.openstax.org
        """
        self.ps.test_updates['name'] = 'cc1.11.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.11',
            'cc1.11.002',
            '7689'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='macro_economics')
        self.teacher.sleep(5)

        assert('dashboard' in self.teacher.current_url()), \
            'Not viewing the cc dashboard'

        self.teacher.open_user_menu()
        self.teacher.sleep(1)
        self.teacher.find(By.XPATH, "//a/form[@class='-logout-form']").click()

        assert('cc.openstax.org' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.ps.test_updates['passed'] = True

    # Case C7690 - 003 - Teacher | Can log into Tutor and be redirected to CC
    @pytest.mark.skipif(str(7690) not in TESTS, reason='Excluded')
    def test_teacher_can_log_into_tutor_and_be_redirected_to_cc_7690(self):
        """Can log into Tutor and be redirected to Concept Coach.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name

        Expected Result:
        User is taken to the class dashboard
        """
        self.ps.test_updates['name'] = 'cc1.11.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.11',
            'cc1.11.003',
            '7690'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='macro_economics')
        self.teacher.sleep(5)

        assert('cc-dashboard' in self.teacher.current_url()), \
            'Not viewing the cc dashboard'

        self.ps.test_updates['passed'] = True
class TestCreateNewQuestionAndAssignmentTypes(unittest.TestCase):
    """T2.12 - Create New Question and Assignment Types."""
    def setUp(self):
        """Pretest settings."""

        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(use_env_vars=True,
                               pasta_user=self.ps,
                               capabilities=self.desired_capabilities)
        self.student = Student(use_env_vars=True,
                               existing_driver=self.teacher.driver,
                               pasta_user=self.ps,
                               capabilities=self.desired_capabilities)

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                           **self.ps.test_updates)
        self.student = None
        try:
            self.teacher.delete()
        except:
            pass

    # 14739 - 001 - Teacher | Vocabulary question is a question type
    @pytest.mark.skipif(str(14739) not in TESTS, reason='Excluded')
    def test_teacher_vocabulary_question_is_a_question_type_14739(self):
        """Vocabulary question is a question type.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher account in the username and password text boxes
        Click on the 'Sign in' button
        Click "Write a new exercise"
        Click "New Vocabulary Term"

        Expected Result:
        The user is presented with a page where a new vocabulary question can
        be created
        """
        self.ps.test_updates['name'] = 't2.12.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.12', 't2.12.001', '14739']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get("https://exercises-qa.openstax.org/")
        # login
        self.teacher.find(
            By.XPATH,
            '//div[@id="account-bar-content"]//a[text()="Sign in"]').click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(By.ID, 'auth_key').send_keys(self.teacher.username)
        self.teacher.find(By.ID, 'password').send_keys(self.teacher.password)
        self.teacher.find(By.XPATH, '//button[text()="Sign in"]').click()
        # create new vocab
        self.teacher.page.wait_for_page_load()
        self.teacher.find(By.XPATH, '//a[@href="/exercises/new"]').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[text()="New Vocabulary Term"]'))).click()
        assert('/vocabulary/new' in self.teacher.current_url()), \
            'not at new vocab page'

        self.ps.test_updates['passed'] = True

    # 14741 - 002 - Teacher | True/False is a question type
    @pytest.mark.skipif(str(14741) not in TESTS, reason='Excluded')
    def test_teacher_truefalse_is_a_question_type_14741(self):
        """True/False is a question type.

        Steps:
        Click "Write a new exercise"
        Click on the "True/False" radio button

        Expected Result:
        The user is presented with a page where a True/False question can be
        created
        """
        self.ps.test_updates['name'] = 't2.12.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.12', 't2.12.002', '14741']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get("https://exercises-qa.openstax.org/")
        # login
        self.teacher.find(
            By.XPATH,
            '//div[@id="account-bar-content"]//a[text()="Sign in"]').click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(By.ID, 'auth_key').send_keys(self.teacher.username)
        self.teacher.find(By.ID, 'password').send_keys(self.teacher.password)
        self.teacher.find(By.XPATH, '//button[text()="Sign in"]').click()
        # create new vocab
        self.teacher.page.wait_for_page_load()
        self.teacher.find(By.XPATH, '//a[@href="/exercises/new"]').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//input[@label="True/False"]'))).click()
        self.teacher.find(By.XPATH, '//span[text()="True/False"]')
        self.ps.test_updates['passed'] = True

    # possibly changed implementation on site
    # no info icon found
    # 14742 - 003 - System | Display embedded videos with attribution and link
    # back to author
    @pytest.mark.skipif(str(14742) not in TESTS, reason='Excluded')
    def test_system_display_embedded_videos_with_attribution_14742(self):
        """Display embedded videos with attribution and a link back to author.

        Steps:
        Go to Tutor
        Click Login
        Sign in as student01
        Click "HS AP Physics LG"
        Click on a homework assignment
        Click through it until you get to a video
        Click on the info icon on the video

        Expected Result:
        Attribution and links are displayed
        """
        self.ps.test_updates['name'] = 't2.12.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.12', 't2.12.003', '14742']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # NOT DONE
    # create hw helper still not working
    # but works for manually created assignemnt, add assignemnt commented out
    # 14743 - 004 - Teacher | Each part of a multi-part question counts as a
    # seperate problem when scored
    @pytest.mark.skipif(str(14743) not in TESTS, reason='Excluded')
    def test_teacher_each_part_of_a_multipart_question_counts_as_14743(self):
        """Multi-part questions count as seperate problems when scored.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Log in as teacher03
        Click "College Introduction to Sociology"
        Go to "Student Scores"
        Pick a homework that has multipart question
        Click "Review"

        Expected Result:
        There is a breadcrumb for each part of a multipart question
        """
        self.ps.test_updates['name'] = 't2.12.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.12', 't2.12.004', '14743']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        # create a hw with a multi part question, and gice it a randomized name
        # ID: 12061@6 is multi part
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//div[@data-appearance="intro_sociology"]' +
            '//a[not(contains(@href,"/cc-dashboard"))]').click()
        assignment_name = "homework-%s" % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=0)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=100)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(assignment='homework',
                                    args={
                                        'title': assignment_name,
                                        'description': 'description',
                                        'periods': {
                                            'all': (begin, end)
                                        },
                                        'problems': {
                                            '1.1': ['12024@10'],
                                        },
                                        'status': 'publish',
                                    })
        self.teacher.open_user_menu()
        self.teacher.find(By.LINK_TEXT, 'Student Scores').click()
        self.teacher.page.wait_for_page_load()
        # can just click the first review because assignemnt just created
        # and should be the most recent one
        self.teacher.find(By.LINK_TEXT, 'Review').click()
        cards = self.teacher.find_all(By.XPATH,
                                      '//div[contains(@class,"card-body")]')
        questions = self.teacher.find_all(
            By.XPATH, '//div[contains(@class,"openstax-question")]')
        breadcrumbs = self.teacher.find_all(
            By.XPATH, '//span[contains(@class,"openstax-breadcrumb")]')
        assert(len(questions) == len(breadcrumbs)), \
            'breadcrumbs and questions not equal'
        assert(len(cards) < len(breadcrumbs)), \
            'multipart question card has multiple questions,' + \
            'not matching up with  breadcrumbs'

        self.ps.test_updates['passed'] = True

    # NOT DONE
    # same issue as above w/ add_homework helper
    # but works for manually created assignemnt
    # (add assignemnt gets commented out, manual assignemnt name added)
    # 14744 - 005 - Student | Each part of a multi-part question counts as a
    # seperate problem when scored
    @pytest.mark.skipif(str(14744) not in TESTS, reason='Excluded')
    def test_student_each_part_of_a_multipart_question_counts_as_14744(self):
        """Multi-part questions count as seperate problems when scored.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Log in as abarnes
        Click "College Introduction to Sociology"
        Click on a homework assignment
        Go through the questions

        Expected Result:
        There is a breadcrumb for each part in the multipart question and the
        progress/score is out of the total number of questions, rather than
        counting the multipart question as one question
        """
        self.ps.test_updates['name'] = 't2.12.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.12', 't2.12.005', '14744']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        # create a hw with a multi part question, and give it a randomized name
        # ID: 12252@5 is multi part
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//div[@data-appearance="intro_sociology"]' +
            '//a[not(contains(@href,"/cc-dashboard"))]').click()
        assignment_name = "homework-%s" % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=0)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=100)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(assignment='homework',
                                    args={
                                        'title': assignment_name,
                                        'description': 'description',
                                        'periods': {
                                            'all': (begin, end)
                                        },
                                        'problems': {
                                            '1.1': ['12024@10'],
                                        },
                                        'status': 'publish',
                                    })
        self.teacher.logout()
        # assignemnt name put here for manual testing
        # assignment_name = 'hw w/ video and multi part question'
        # login as student and go to same class
        self.student.login()
        self.teacher.find(
            By.XPATH, '//div[@data-appearance="intro_sociology"]' +
            '//a[not(contains(@href,"/cc-dashboard"))]').click()
        self.student.page.wait_for_page_load()
        # go to assignment (find my assignemnt_name)
        self.student.find(
            By.XPATH, '//a[contains(@class,"homework workable")]' +
            '//span[text()="' + assignment_name + '"]').click()
        # go through all questions
        breadcrumbs = self.teacher.find_all(
            By.XPATH, '//span[contains(@class,"openstax-breadcrumb")' +
            ' and not(contains(@class,"intro"))' +
            ' and not(contains(@class,"personalized"))'
            ' and not(contains(@class,"end"))]')
        total_questions = 0
        found_multipart = False
        i = 0
        while i < len(breadcrumbs):
            breadcrumbs[i].click()
            try:
                self.student.find(By.XPATH,
                                  '//span[text()="Multi-part question"]')
                found_multipart = True
                questions = self.teacher.find_all(
                    By.XPATH, '//div[contains(@class,"openstax-question")]')
                total_questions += len(questions)
                i += len(questions)
            except NoSuchElementException:
                i += 1
                questions = self.teacher.find_all(
                    By.XPATH, '//div[contains(@class,"openstax-question")]')
                total_questions += len(questions)
        # check that everything worked out
        assert (found_multipart), 'no multipart question found'
        assert(total_questions == len(breadcrumbs)), \
            'breadcrumbs and questions not equal'

        self.ps.test_updates['passed'] = True
class TestRecruitingTeachers(unittest.TestCase):
    """CC1.01 - Recruiting Teachers."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.CONDENSED_WIDTH = 1105

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7751 - 001 - Admin | Recruitment and promo website is available
    @pytest.mark.skipif(str(7751) not in TESTS, reason='Excluded')
    def test_admin_recruitment_and_promo_website_is_available_7751(self):
        """Recruitment and promo website is available.

        Steps:
        Go to the recruitment website ( http://cc.openstax.org/ )

        Expected Result:
        Recruitment website loads and renders
        """
        self.ps.test_updates['name'] = 'cc1.01.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.001',
            '7751'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()

        self.ps.test_updates['passed'] = True

    # Case C7752 - 002 - Teacher | Information about Concept Coach and the
    # pilot are available on the demo site
    @pytest.mark.skipif(str(7752) not in TESTS, reason='Excluded')
    def test_teacher_information_about_cc_is_available_on_demo_site_7752(self):
        """Information about CC and pilot are available on the demo site.

        Steps:
        Go to the recruitment website ( http://cc.openstax.org/ )

        Expected Result:
        Page loads several sections describing Concept Coach
        """
        self.ps.test_updates['name'] = 'cc1.01.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.002',
            '7752'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        self.teacher.find(By.ID, 'who-we-are')

        self.ps.test_updates['passed'] = True

    # Case C7753 - 003 - Teacher | Can interact with a Concept Coach wire frame
    # for each subject
    @pytest.mark.skipif(str(7753) not in TESTS, reason='Excluded')
    def test_teacher_can_interact_with_a_cc_wire_frame_for_subjects_7753(self):
        """Can interact with a Concept Coach wire frame for each subject.

        Steps:
        Go to the recruitment website ( http://cc.openstax.org/)
        Hover over "demos" in the header
        Click "Interactice Demo"
        CLick on a Concept Coach book title

        Expected Result:
        A new tab or window opens rendering the demo content for the selected
        book
        """
        self.ps.test_updates['name'] = 'cc1.01.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.003',
            '7753'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        demo_link = self.teacher.find(
            By.XPATH,
            '//section[@id="interactive-demo"]' +
            '//a[@class="btn" and contains(@href,"cc-mockup")]'
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', demo_link)
        self.teacher.driver.execute_script('window.scrollBy(0, -80);')
        self.teacher.sleep(1)
        demo_link.click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        self.teacher.page.wait_for_page_load()
        assert('http://cc.openstax.org/assets/demos/cc-mockup' in
               self.teacher.current_url()), \
            'not at demo book'
        self.ps.test_updates['passed'] = True

    # # NOT DONE
    # Case C7754 - 004 - Teacher | View a Concept Coach demo video
    @pytest.mark.skipif(str(7754) not in TESTS, reason='Excluded')
    def test_teacher_view_a_concept_coach_demo_video_7754(self):
        """View a Concept Coach demo video.

        Steps:
        Open recruitment website ( http://cc.openstax.org/ )
        Hover over "demos" in the header
        Click "Interactive Demo"
        Click on a Concept Coach book title
        Scroll down until an embedded video pane is displayed
        Click on the right-pointing arrow to play the video

        Expected Result:
        The video loads and plays
        """
        self.ps.test_updates['name'] = 'cc1.01.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.004',
            '7754'
        ]
        self.ps.test_updates['passed'] = False

        raise NotImplementedError(inspect.currentframe().f_code.co_name)
        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        demo_link = self.teacher.find(
            By.XPATH,
            '//section[@id="interactive-demo"]' +
            '//a[@class="btn" and contains(@href,"cc-mockup-physics")]'
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', demo_link)
        self.teacher.driver.execute_script('window.scrollBy(0, -80);')
        self.teacher.sleep(1)
        demo_link.click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        self.teacher.page.wait_for_page_load()
        self.teacher.sleep(2)
        # self.teacher.find(
        #     By.XPATH, '//div[@id="player"]'
        # ).click()
        title = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Inelastic Collisions")]')
            )
        )
        # self.teacher.wait.until(
        #     expect.presence_of_element_located(
        #         (By.ID, 'player')
        #     )
        # )
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(title)
        actions.move_by_offset(0, 300)
        actions.click()
        actions.perform()
        self.teacher.sleep(2)
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"playing-mode")]'
        )
        # actions.perform()
        self.teacher.find(
            By.XPATH,
            '//div[@id="player"]/div[contains(@class,"paused-mode")]'
        )

        self.ps.test_updates['passed'] = True

    # Case C7755 - 005 - Teacher | Sample exercise questions are seen in
    # the wire frames
    @pytest.mark.skipif(str(7755) not in TESTS, reason='Excluded')
    def test_teacher_sample_exercise_questions_are_in_wire_frames_7755(self):
        """Sample exercise questions are seen in the wire frames.

        Steps:
        Open recruitment website ( http://cc.openstax.org/ )
        Hover over "demos" in the header
        Click "Interactive Demo"
        Click on a Concept Coach book title
        Scroll down until the 'CONCEPT COACH' pane is displayed

        Expected Result:
        Demo exercises are rendered and can be answered along with showing
        feedback
        """
        self.ps.test_updates['name'] = 'cc1.01.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.005',
            '7755'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        demo_link = self.teacher.find(
            By.XPATH,
            '//section[@id="interactive-demo"]' +
            '//a[@class="btn" and contains(@href,"cc-mockup-physics")]'
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', demo_link)
        self.teacher.driver.execute_script('window.scrollBy(0, -80);')
        self.teacher.sleep(1)
        demo_link.click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        self.teacher.page.wait_for_page_load()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH, '//span[contains(text(),"JUMP TO CONCEPT COACH")]'
        ).click()
        self.teacher.find(
            By.XPATH, '//div[contains(@data-label,"q1-multiple-choice")]')
        self.teacher.sleep(2)
        answer = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[contains(@data-label,"choice-1b-text")]')
            )
        )
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(answer)
        actions.click()
        actions.perform()
        self.teacher.find(
            By.XPATH, "//div[@data-label='State2']"
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 "//div[@data-label='q1-answer-b']//div[@data-label='next']")
            )
        )
        self.ps.test_updates['passed'] = True

    # Case C7756 - 006 - Teacher | Access Concept Coach help and support before
    # the teacher's course is created
    @pytest.mark.skipif(str(7756) not in TESTS, reason='Excluded')
    def test_teacher_access_cc_support_before_course_is_created_7756(self):
        """Access CC help and support before the teacher's course is created.

        Steps:
        Open the recruitment website ( http://cc.openstax.org/ )
        Click "Support" in the header

        Expected Result:
        A new tab opens with the CC Help Center
        """
        self.ps.test_updates['name'] = 'cc1.01.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.006',
            '7756'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        if self.teacher.driver.get_window_size()['width'] < \
                self.CONDENSED_WIDTH:
            self.teacher.wait.until(
                expect.visibility_of_element_located(
                    (By.XPATH, '//label[@for="mobileNavToggle" and ' +
                     'contains(@class,"fixed")]')
                )
            ).click()
            self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH, '//a[contains(text(),"support")]'
        ).click()
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]'
        )

        self.ps.test_updates['passed'] = True

    # Case C7757 - 007 - Teacher | Teacher registers to use a CC course
    @pytest.mark.skipif(str(7757) not in TESTS, reason='Excluded')
    def test_teacher_teacher_registers_to_use_a_cc_course_7757(self):
        """Teacher registers to use a Concept Coach course.

        Steps:
        Go to the recruitment website ( http://cc.openstax.org )
        Click on the 'sign up now' button

        Expected Result:
        Web form renders
        """
        self.ps.test_updates['name'] = 'cc1.01.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.007',
            '7757'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//section[@id="video2"]//a[@href="/sign-up"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'signup-form'
        )
        self.ps.test_updates['passed'] = True

    # Case C7758 - 008 - Teacher | Teacher uses a web form to sign up for CC
    @pytest.mark.skipif(str(7758) not in TESTS, reason='Excluded')
    def test_teacher_teacher_uses_a_web_form_to_sign_up_for_cc_7758(self):
        """Teacher uses a web form to sign up for Concept Coach.

        Steps:
        Teacher fills out the form

        Expected Result:
        Preconditions pass.
        User is presented with a confirmation message
        """
        self.ps.test_updates['name'] = 'cc1.01.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.008',
            '7758'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//section[@id="video2"]//a[@href="/sign-up"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'signup-form'
        )
        self.teacher.find(
            By.ID, 'first_name'
        ).send_keys('first')
        self.teacher.find(
            By.ID, 'last_name'
        ).send_keys('last')
        self.teacher.find(
            By.ID, 'email'
        ).send_keys('*****@*****.**')
        self.teacher.find(
            By.ID, 'company'
        ).send_keys('school')
        menu = self.teacher.find(
            By.XPATH,
            '//span[@id="book-select"]' +
            '//span[contains(@class,"select2-container--")]'
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', menu)
        self.teacher.driver.execute_script('window.scrollBy(0, -120);')
        self.teacher.sleep(0.5)
        menu.click()
        self.teacher.sleep(0.5)
        self.teacher.find(
            By.XPATH,
            '//li[contains(@class,"select2-results__option")]'
        ).click()
        self.teacher.find(
            By.XPATH, '//input[@maxlength="255" and @required]'
        ).send_keys('25')
        self.teacher.find(
            By.XPATH, '//input[@type="submit"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//h1[contains(text(),"Thank you")]')
            )
        )
        assert('/thank-you' in self.teacher.current_url()), \
            'not at thank you page after submitting form'

        self.ps.test_updates['passed'] = True

    # Case C7759 - 009 - Teacher | Receive error messages if required fields on
    # the sign up form are blank
    @pytest.mark.skipif(str(7759) not in TESTS, reason='Excluded')
    def test_teacher_receive_error_messages_if_required_fields_are_7759(self):
        """Receive error messages if required fields on the sign up form are blank.

        Steps:
        Go to the recruitment website ( http://cc.openstax.org/ )
        Click on the 'sign up now' button
        Submit the form without changing any of the text fields

        Expected Result:
        Receive 'Please fill out this field' error messages in red for
        each blank required field
        """
        self.ps.test_updates['name'] = 'cc1.01.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.009',
            '7759'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//section[@id="video2"]//a[@href="/sign-up"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'signup-form'
        )
        submit = self.teacher.find(
            By.XPATH, '//input[@type="submit"]'
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', submit)
        self.teacher.sleep(0.5)
        submit.click()
        assert('/sign-up' in self.teacher.current_url()), \
            'moved from sign up when submitting with blank required fields'
        self.teacher.find(
            By.XPATH, '//div[contains(text(),"Please fill out this field.")]'
        )

        self.ps.test_updates['passed'] = True

    # Case C7760 - 010 - Teacher | Submit a form to supply required course info
    @pytest.mark.skipif(str(7760) not in TESTS, reason='Excluded')
    def test_teacher_submit_a_form_to_supply_required_course_info_7760(self):
        """Submit a form to supply required course information.

        Steps:
        Go to the recruitment website ( http://cc.openstax.org )
        Click on the 'sign up now' button
        Fill out the intent to participate form
        Submit the form

        Expected Result:
        Web form submits
        Displays a Thank you message panel
        """
        self.ps.test_updates['name'] = 'cc1.01.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.010',
            '7760'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//section[@id="video2"]//a[@href="/sign-up"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'signup-form'
        )
        self.teacher.find(
            By.ID, 'first_name'
        ).send_keys('first')
        self.teacher.find(
            By.ID, 'last_name'
        ).send_keys('last')
        self.teacher.find(
            By.ID, 'email'
        ).send_keys('*****@*****.**')
        self.teacher.find(
            By.ID, 'company'
        ).send_keys('school')
        # choose a book!
        menu = self.teacher.find(
            By.XPATH,
            '//span[@id="book-select"]' +
            '//span[contains(@class,"select2-container--")]'
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', menu)
        self.teacher.driver.execute_script('window.scrollBy(0, -120);')
        self.teacher.sleep(0.5)
        menu.click()
        self.teacher.sleep(0.5)
        self.teacher.find(
            By.XPATH,
            '//li[contains(@class,"select2-results__option")]'
        ).click()
        self.teacher.find(
            By.XPATH, '//input[@maxlength="255" and @required]'
        ).send_keys('25')
        self.teacher.find(
            By.XPATH, '//input[@type="submit"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//h1[contains(text(),"Thank you")]')
            )
        )
        assert('/thank-you' in self.teacher.current_url()), \
            'not at thank you page after submitting form'

        self.ps.test_updates['passed'] = True

    # Case C7761 - 011 - Teacher | Submit co-instructors, classes, names, etc.
    @pytest.mark.skipif(str(7761) not in TESTS, reason='Excluded')
    def test_teacher_submit_coinstructors_classes_names_etc_7761(self):
        """Submit co-instructors, classes, names and other data.

        Steps:
        Go to the recruitment and promo website ( http://cc.openstax.org/ )
        Click on the 'sign up now' button
        Click on the 'Co-Teaching class with a colleague?' circle button
        Enter the co-instructor's (or co-instructors') information
        Enter text into other fields concerning classe, names, etc.

        Expected Result:
        Input box exists for instructor information, class details and
        other data.
        The user is able to input information.
        """
        self.ps.test_updates['name'] = 'cc1.01.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.011',
            '7761'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//section[@id="video2"]//a[@href="/sign-up"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'signup-form'
        )
        option = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[@class="slide-checkbox"]/label')
            )
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', option)
        self.teacher.driver.execute_script('window.scrollBy(0, -120);')
        self.teacher.sleep(0.5)
        option.click()
        textarea = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[@id="coteachcontact"]/textarea')
            )
        )
        textarea.send_keys('co teacher info')
        self.ps.test_updates['passed'] = True

    # Case C7762 - 012 - Teacher | Select the textbook to use in the course
    @pytest.mark.skipif(str(7762) not in TESTS, reason='Excluded')
    def test_teacher_select_the_textbook_to_use_in_the_course_7762(self):
        """Select the textbook to use in the course.

        Steps:
        Go to the recruitment website ( http://cc.openstax.org )
        Click on the 'sign up now' button
        Select the course textbook from the 'Book' dropdown options

        Expected Result:
        Able to select any Concept Coach textbook
        """
        self.ps.test_updates['name'] = 'cc1.01.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.012',
            '7762'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//section[@id="video2"]//a[@href="/sign-up"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'signup-form'
        )
        menu = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//span[@id="book-select"]' +
                 '//span[contains(@class,"select2-container--")]')
            )
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', menu)
        self.teacher.driver.execute_script('window.scrollBy(0, -120);')
        self.teacher.sleep(0.5)
        menu.click()
        self.teacher.sleep(0.5)
        book = self.teacher.find(
            By.XPATH,
            '//li[contains(@class,"select2-results__option")]'
        )
        title = book.text
        book.click()
        self.teacher.sleep(0.5)
        self.teacher.find(
            By.XPATH,
            '//span[contains(@title,"' + title + '") and ' +
            'contains(@class,"select2-selection__rendered")]'
        )
        self.ps.test_updates['passed'] = True

    # Case C7763 - 013 - Teacher | Indicate whether the teacher was recruited
    # by OpenStax
    @pytest.mark.skipif(str(7763) not in TESTS, reason='Excluded')
    def test_teacher_indicate_whether_the_teacher_was_recruited_by_7763(self):
        """Indicate if the teacher was or was not recruited by OpenStax.

        Steps:
        Go to the recruitment and promo website ( http://cc.openstax.org/ )
        Click on the 'sign up now' button ( http://cc.openstax.org/sign-up )
        Enter recruitment information into the 'Anything else we need to know?'
        text box

        Expected Result:
        Able to input recruitment information
        """
        self.ps.test_updates['name'] = 'cc1.01.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.013',
            '7763'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//section[@id="video2"]//a[@href="/sign-up"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'signup-form'
        )
        textarea = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//textarea[@placeholder="Feedback"]')
            )
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', textarea)
        self.teacher.driver.execute_script('window.scrollBy(0, -120);')
        self.teacher.sleep(0.5)
        textarea.send_keys('recuitment info')
        self.ps.test_updates['passed'] = True

    # Case C7764 - 014 - Teacher | Presented a thank you page after registering
    # to use Concept Coach
    @pytest.mark.skipif(str(7764) not in TESTS, reason='Excluded')
    def test_teacher_presented_a_thank_you_page_after_registering_7764(self):
        """Presented a thank you page after registering to use Concept Coach.

        Steps:
        Go to the recruitment website ( http://cc.openstax.org )
        Click on the 'sign up now' button
        Fill out the intent to participate form
        Submit the form

        Expected Result:
        Displays a Thank you message panel
        """
        self.ps.test_updates['name'] = 'cc1.01.014' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.014',
            '7764'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//section[@id="video2"]//a[@href="/sign-up"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'signup-form'
        )
        self.teacher.find(
            By.ID, 'first_name'
        ).send_keys('first')
        self.teacher.find(
            By.ID, 'last_name'
        ).send_keys('last')
        self.teacher.find(
            By.ID, 'email'
        ).send_keys('*****@*****.**')
        self.teacher.find(
            By.ID, 'company'
        ).send_keys('school')
        menu = self.teacher.find(
            By.XPATH,
            '//span[@id="book-select"]' +
            '//span[contains(@class,"select2-container--")]'
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', menu)
        self.teacher.driver.execute_script('window.scrollBy(0, -120);')
        self.teacher.sleep(0.5)
        menu.click()
        self.teacher.sleep(0.5)
        self.teacher.find(
            By.XPATH,
            '//li[contains(@class,"select2-results__option")]'
        ).click()
        self.teacher.find(
            By.XPATH, '//input[@maxlength="255" and @required]'
        ).send_keys('25')
        self.teacher.find(
            By.XPATH, '//input[@type="submit"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//h1[contains(text(),"Thank you")]')
            )
        )
        assert('/thank-you' in self.teacher.current_url()), \
            'not at thank you page after submitting form'

        self.ps.test_updates['passed'] = True

    # Case C7765 - 015 - Teacher | Sign up for an OpenStax Accounts username
    @pytest.mark.skipif(str(7765) not in TESTS, reason='Excluded')
    def test_teacher_sign_up_for_an_openstax_accounts_username_7765(self):
        """Sign up for an OpenStax Accounts username.

        Steps:
        Go to the recruitment website ( http://cc.openstax.org )
        Click on the 'sign up now' button
        Fill out the intent to participate form
        Submit the form

        Expected Result:
        Displays a Thank you message panel
        """
        self.ps.test_updates['name'] = 'cc1.01.015' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.015',
            '7765'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//section[@id="video2"]//a[@href="/sign-up"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'signup-form'
        )
        self.teacher.find(
            By.ID, 'first_name'
        ).send_keys('first')
        self.teacher.find(
            By.ID, 'last_name'
        ).send_keys('last')
        self.teacher.find(
            By.ID, 'email'
        ).send_keys('*****@*****.**')
        self.teacher.find(
            By.ID, 'company'
        ).send_keys('school')
        menu = self.teacher.find(
            By.XPATH,
            '//span[@id="book-select"]' +
            '//span[contains(@class,"select2-container--")]'
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', menu)
        self.teacher.driver.execute_script('window.scrollBy(0, -120);')
        self.teacher.sleep(0.5)
        menu.click()
        self.teacher.sleep(0.5)
        self.teacher.find(
            By.XPATH,
            '//li[contains(@class,"select2-results__option")]'
        ).click()
        self.teacher.find(
            By.XPATH, '//input[@maxlength="255" and @required]'
        ).send_keys('25')
        self.teacher.find(
            By.XPATH, '//input[@type="submit"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//h1[contains(text(),"Thank you")]')
            )
        )
        assert('/thank-you' in self.teacher.current_url()), \
            'not at thank you page after submitting form'

        self.ps.test_updates['passed'] = True

    # Case C7770 - 020 - Admin | Add co-instructors to a course
    @pytest.mark.skipif(str(7770) not in TESTS, reason='Excluded')
    def test_admin_add_coinstructors_to_a_course_7770(self):
        """Add co-instructors to a course.

        Steps:
        Log into Tutor as an admin
        From the user menu, select 'Admin'
        From the 'Course Organization' menu, select 'Courses'
        In the Courses table, find the correct course and click the 'Edit'
            button on the right side of that row
        Click on the 'Teachers' tab
        In the search box, enter the teacher's name or username
        Select the teacher in the list below the search bar or hit the down
            arrow followed by the enter/return key

        Expected Result:
        Co-instructor is linked to the affected course
        """
        self.ps.test_updates['name'] = 'cc1.01.020' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.020',
            '7770'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login(
            username=os.getenv('ADMIN_USER'),
            password=os.getenv('ADMIN_PASSWORD'))
        self.teacher.open_user_menu()
        self.teacher.find(
            By.XPATH, '//a[@role="menuitem" and contains(text(),"Admin")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Course Organization')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Courses')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Edit')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Teachers')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.ID, 'course_teacher')
            )
        ).send_keys('teacher0')
        element = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//ul[contains(@class,"ui-autocomplete")]' +
                 '//li[contains(text(),"(teacher0")]')
            )
        )
        teacher_name = element.text.split(' (')[0]
        element.click()
        # check that the teacher has been added to the table
        print(teacher_name)
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//td[contains(text(),"' + teacher_name + '")]')
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7771 - 021 - Teacher | Login with an Existing OpenStax Account
    @pytest.mark.skipif(str(7771) not in TESTS, reason='Excluded')
    def test_teacher_login_with_an_existing_openstax_account_7771(self):
        """Log in with an Existing OpenStax Accounts username.

        Steps:
        Go to the recruitment website ( http://cc.openstax.org/ )
        Click on faculty login
        You are redirected to the accounts page.
        Enter a username and password
        click on Login.

        Expected Result:
        Login should be successful. It should take you to the teacher course
        picker/dashboard page.
        """
        self.ps.test_updates['name'] = 'cc1.01.021' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.021',
            '7771'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get(self.teacher.url)
        self.teacher.page.wait_for_page_load()
        # check to see if the screen width is normal or condensed
        if self.teacher.driver.get_window_size()['width'] <= \
           self.teacher.CONDENSED_WIDTH:
            # get small-window menu toggle
            is_collapsed = self.teacher.find(
                By.XPATH,
                '//button[contains(@class,"navbar-toggle")]'
            )
            # check if the menu is collapsed and, if yes, open it
            if('collapsed' in is_collapsed.get_attribute('class')):
                is_collapsed.click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Login')
            )
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID,
            'auth_key'
        ).send_keys(self.teacher.username)
        self.teacher.find(
            By.ID,
            'password'
        ).send_keys(self.teacher.password)
        # click on the sign in button
        self.teacher.find(
            By.XPATH,
            '//button[text()="Sign in"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        assert('dashboard' in self.teacher.current_url()),\
            'Not taken to dashboard: %s' % self.teacher.current_url()

        self.ps.test_updates['passed'] = True

    # Case C7772 - 022 - Teacher | Access the Concept Coach course
    @pytest.mark.skipif(str(7772) not in TESTS, reason='Excluded')
    def test_teacher_access_the_cc_course_7772(self):
        """Access the Concept Coach course.

        Steps:
        Once you login you will be taken to a course picker page.
        Click on the course you want to check the dashboard

        Expected Result:
        At Concept Coach teacher dashboard
        """
        self.ps.test_updates['name'] = 'cc1.01.022' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.022',
            '7772'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard/")]'
        ).click()
        assert('cc-dashboard' in self.teacher.current_url()),\
            'Not taken to dashboard: %s' % self.teacher.current_url()

        self.ps.test_updates['passed'] = True

    # Case C7773 - 023 - Admin | Distribute access codes for the course
    @pytest.mark.skipif(str(7773) not in TESTS, reason='Excluded')
    def test_admin_distribute_access_codes_for_the_course_7773(self):
        """Distribute access codes for the teacher's course.

        Steps:
        CC approves a faculty.
        Login as admin
        Click on user menu
        Click on Admin
        Click on Salesforce tab
        Click on import [Do not check the box]
        This will automatically create a course for the teacher created.
        Email is sent to the email id used when signing up with
            the unique course URL.

        Expected Result:
        Instructors are emailed the unique course url to the address provided
        when they signed up.
        """
        self.ps.test_updates['name'] = 'cc1.01.023' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.023',
            '7773'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)
        admin = Admin(
            use_env_vars=True,
            existing_driver=self.teacher.driver,
            # pasta_user=self.ps,
            # capabilities=self.desired_capabilities
        )
        admin.login()
        admin.open_user_menu()
        admin.find(By.LINK_TEXT, 'Admin').click()
        admin.page.wait_for_page_load()
        admin.find(By.LINK_TEXT, 'Salesforce').click()
        admin.page.wait_for_page_load()
        admin.find(
            By.XPATH, '//input[@vale="Import Courses"]'
        ).click()

        self.ps.test_updates['passed'] = True

    # Case C7774 - 024 - Teacher | Access CC help and support during the course
    @pytest.mark.skipif(str(7774) not in TESTS, reason='Excluded')
    def test_teacher_acccess_cc_help_and_support_during_the_course_7774(self):
        """Access Concept Coach help and support during the course.

        Steps:
        Login as teacher
        Click on the course name
        On dashboard click on the name of the teacher
        It drops down and displays several options.
        Click on Get Help

        Expected Result:
        It should open a new tab which shows the openstax.force.com
        """
        self.ps.test_updates['name'] = 'cc1.01.024' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.024',
            '7774'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard/")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Get Help"
        ).click()
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]'
        ).click()

        self.ps.test_updates['passed'] = True

    # Case C7775 - 025 - Teacher | Access CC help and support after course ends
    @pytest.mark.skipif(str(7775) not in TESTS, reason='Excluded')
    def test_teacher_access_cc_help_and_support_after_course_ends_7775(self):
        """Access Concept Coach help and support after the end of the course.

        Steps:
        Login as teacher
        Click on the course name
        On dashboard click on the name of the teacher
        It drops down and displays several options.
        Click on Get Help

        Expected Result:
        It should open a new tab which shows the CC help center
        """
        self.ps.test_updates['name'] = 'cc1.01.025' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.01',
            'cc1.01.025',
            '7775'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Get Help"
        ).click()
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]'
        ).click()

        self.ps.test_updates['passed'] = True
class TestImprovesScoresReporting(unittest.TestCase):
    """CC2.08 - Improves Scores Reporting."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities,
        )
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.teacher.delete()
        except:
            pass

    # 14806 - 001 - Teacher | View student scores as percent complete
    @pytest.mark.skipif(str(14806) not in TESTS, reason='Excluded')
    def test_teacher_view_student_scores_as_percent_complete_14806(self):
        """View student scores as percent complete.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click on the icon in the progress column

        Expected Result:
        Student Scores are presented as percent complete
        """
        self.ps.test_updates['name'] = 'cc2.08.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.001', '14806']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(text(),"View Detailed Scores")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')
            )
        )
        self.teacher.find(
            By.XPATH, '//button[contains(text(),"percentage")]'
        ).click()
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"score")]//a[contains(text(),"%")]')
        self.ps.test_updates['passed'] = True

    # 14807 - 002 - Teacher | View student scores as number of total
    @pytest.mark.skipif(str(14807) not in TESTS, reason='Excluded')
    def test_teacher_view_student_scores_as_number_of_total_14807(self):
        """View student scores as number of total.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click "Number"

        Expected Result:
        Student Scores are presented as "Number of Total"
        """
        self.ps.test_updates['name'] = 'cc2.08.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.002', '14807']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(text(),"View Detailed Scores")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')
            )
        )
        self.teacher.find(
            By.XPATH, '//button[contains(text(),"number")]'
        ).click()
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"score")]//a[contains(text()," of ")]')

        self.ps.test_updates['passed'] = True

    # 14808 - 003 - Teacher | View tooltips on hover
    @pytest.mark.skipif(str(14808) not in TESTS, reason='Excluded')
    def test_teacher_view_tooltips_on_hover_14808(self):
        """View tooltips on hover.

        Steps:
        If the user has more than one course, click on a CC course name
        Hover over the info icons

        Expected Result:
        The user is presented with tooltips
        """
        self.ps.test_updates['name'] = 'cc2.08.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.003', '14808']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(text(),"View Detailed Scores")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')
            )
        )
        self.teacher.find(
            By.XPATH, '//i[@type="info-circle"]').click()
        self.teacher.find(
            By.XPATH,
            '//h3[@class="popover-title" and ' +
            'contains(text(), "Class and Overall Averages")]')
        self.ps.test_updates['passed'] = True

    # 14810 - 004 - Teacher | Sort student scores based on score
    @pytest.mark.skipif(str(14810) not in TESTS, reason='Excluded')
    def test_teacher_sort_student_scores_based_on_score_14810(self):
        """Sort student scores based on score.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click "Score" for the desired assignment

        Expected Result:
        Students are sorted based on score
        """
        self.ps.test_updates['name'] = 'cc2.08.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.004', '14810']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(text(),"View Detailed Scores")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"sortable")]//div[text()="Score"]'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"is-descending")]//div[text()="Score"]'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"is-ascending")]//div[text()="Score"]'
        )
        self.ps.test_updates['passed'] = True

    # 14811 - 005 - Teacher | Sort student scores based on number complete
    @pytest.mark.skipif(str(14811) not in TESTS, reason='Excluded')
    def test_teacher_sort_student_scores_based_on_number_completed_14811(self):
        """Sort student scores based on number complete.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click "Progress" for the desired assignment

        Expected Result:
        Students are sorted based on number completed
        """
        self.ps.test_updates['name'] = 'cc2.08.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.005', '14811']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(text(),"View Detailed Scores")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"sortable")]//div[text()="Progress"]'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"is-descending")]//div[text()="Progress"]'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"is-ascending")]//div[text()="Progress"]'
        )
        self.ps.test_updates['passed'] = True

    # 14668 - 006 - Teacher | All popups in the roster have an X button
    @pytest.mark.skipif(str(14668) not in TESTS, reason='Excluded')
    def test_teacher_all_popups_in_the_roster_have_an_x_button_14668(self):
        """All popups in the roster have an X button.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Course Settings and Roster" from the user menu
        Click "Rename Course," "Change Course Timezone,"
        "View Archived Period," "Add Period," "Rename," and "Get Student
            Enrollment Code"

        Expected Result:
        All pop ups have an X button
        """
        self.ps.test_updates['name'] = 'cc2.08.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.006', '14668']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.find(
            By.XPATH, '//a[text()="Course Settings and Roster"]'
        ).click()
        self.teacher.sleep(1)
        # rename couse
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"Rename Course")]'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]'
        ).click()
        self.teacher.sleep(0.75)
        # course timezone
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"Change Course Timezone")]'
        ).click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]'
        ).click()
        self.teacher.sleep(0.75)
        # add period/section
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"add-period")]//button'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]'
        ).click()
        self.teacher.sleep(0.75)
        # rename period
        self.teacher.find(
            By.XPATH,
            '//span[contains(@class,"rename-period")]//button'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]'
        ).click()
        self.teacher.sleep(0.75)
        # student enrollemnt code
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"Your student enrollment code")]'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]'
        ).click()
        self.teacher.sleep(0.75)
        # View Archived periods
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"View Archived ")]'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]'
        ).click()
        self.ps.test_updates['passed'] = True

    # 14670 - 007 - Teacher | Close popup with X button
    @pytest.mark.skipif(str(14670) not in TESTS, reason='Excluded')
    def test_teacher_close_popup_with_x_button_14670(self):
        """Close popup with X button.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Course Settings and Roster" from the user menu
        Click ONE of the following:
        * Rename Course
        * Change Course Timezone
        * View Archived Period
        * Add Period
        * Rename
        * Get Student Enrollment Code
        Click the X on the pop up

        Expected Result:
        Popup is closed
        """
        self.ps.test_updates['name'] = 'cc2.08.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.007', '14670']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.find(
            By.XPATH, '//a[text()="Course Settings and Roster"]'
        ).click()
        self.teacher.sleep(1)
        # rename couse
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//button//span[contains(text(),"Rename Course")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]')
            )
        ).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(
                By.XPATH, '//div[@class="modal-content"]')
        # course timezone
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"Change Course Timezone")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]')
            )
        ).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(
                By.XPATH, '//div[@class="modal-content"]')
        # add period/section
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"add-period")]//button'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]')
            )
        ).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(
                By.XPATH, '//div[@class="modal-content"]')
        # rename period
        self.teacher.find(
            By.XPATH,
            '//span[contains(@class,"rename-period")]//button'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]')
            )
        ).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(
                By.XPATH, '//div[@class="modal-content"]')
        # student enrollemnt code
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"Your student enrollment code")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]')
            )
        ).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(
                By.XPATH, '//div[@class="modal-content"]')
        # View Archived Periods
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"View Archived")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]')
            )
        ).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(
                By.XPATH, '//div[@class="modal-content"]')

        self.ps.test_updates['passed'] = True

    # 14669 - 008 - Teacher | The icon in the progress column shows info on
    # percentage complete, attempted out of total possible questions, and
    # the date last worked
    @pytest.mark.skipif(str(14669) not in TESTS, reason='Excluded')
    def test_teacher_the_icon_in_the_progress_column_shows_info_14669(self):
        """The icon in the progress column shows info.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click on the icon in the progress column for a completed assignment

        Expected Result:
        Shows information on percentage complete, attempted out of total
        possible questions as well as the date last worked
        """
        self.ps.test_updates['name'] = 'cc2.08.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.008', '14669']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(text(),"View Detailed Scores")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')
            )
        )
        icon = self.teacher.find(
            By.XPATH,
            '//span[contains(@aria-describedby,"scores-cell-info-popover")]')
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(icon)
        actions.perform()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@id,"scores-cell-info-popover")]')
            )
        ).click()
        # more on each individial thing
        self.ps.test_updates['passed'] = True

    # 14812 - 009 - Teacher | Import CC Student Scores export into an LMS
    @pytest.mark.skipif(str(14812) not in TESTS, reason='Excluded')
    def test_teacher_import_cc_student_scores_export_into_an_lms_14812(self):
        """Import CC student scores export into an LMS.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc2.08.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.009', '14812']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14813 - 010 - Teacher | View zeros in exported scores instead of blank
    # cells for incomplete assignments
    @pytest.mark.skipif(str(14813) not in TESTS, reason='Excluded')
    def test_teacher_view_zeros_in_exported_scores_instead_of_blan_14813(self):
        """View zeros in exported scores for incomplete assignments.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click "Export"
        Open the excel file

        Expected Result:
        For incomplete assignments or assignments that are not started,
        there are zeros instead of blank cells
        """
        self.ps.test_updates['name'] = 'cc2.08.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.010', '14813']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(text(),"View Detailed Scores")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')
            )
        )
        self.teacher.find(
            By.XPATH, '//div[@class="export-button"]//button'
        ).click()
        # wait until button return and no longer is loading
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="export-button"]//button' +
                 '/span[text()="Export"]')
            )
        )
        self.teacher.sleep(2)
        coursename = self.teacher.find(
             By.XPATH, '//div[@class="course-name"]').text
        coursename = coursename.replace(' ', '_') + "_Scores"
        home = os.getenv("HOME")
        files = os.listdir(home + '/Downloads')
        file_name = ''
        for i in range(len(files)):
            if (coursename in files[i]) and (files[i][-5:] == '.xlsx'):
                file_name = files[i]
                break
            else:
                if i == len(files)-1:
                    raise Exception
        period = self.teacher.find(
            By.XPATH, '//span[contains(@class,"tab-item-period-name")]').text
        wb = load_workbook(str(home + '/Downloads/' + file_name))
        sheet = wb[period + ' - %']
        rows = sheet.rows
        start_row = float("inf")
        for i in range(len(sheet.rows)):
            if rows[i][0].value == 'First Name':
                start_row = i
            if i >= start_row:
                if rows[i][4].value == 0:
                    # found that 0% is being used istead of blanks
                    break
                elif rows[i+1][4].value is None:
                    print('empty cell instead of 0%')
                    raise Exception
        self.ps.test_updates['passed'] = True

    # 14814 - 011 - Teacher | Green check icon is displayed for completed
    # assignments
    @pytest.mark.skipif(str(14814) not in TESTS, reason='Excluded')
    def test_teacher_green_check_icon_is_displayed_for_completed_14814(self):
        """Green check icon is displayed for completed assignments.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores

        Expected Result:
        Green check icon is displayed for completed assignments
        """
        self.ps.test_updates['name'] = 'cc2.08.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.011', '14814']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(text(),"View Detailed Scores")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')
            )
        )
        # scroll to find a green checkmark
        assignments = self.teacher.find_all(
            By.XPATH,
            "//span[contains(@aria-describedby,'header-cell-title')]")

        for i in range(len(assignments)//4):
            try:
                self.teacher.find(
                    By.XPATH,
                    '//span[contains(@class,"trig")]' +
                    '//*[contains(@class,"finished")]')
                break
            except (NoSuchElementException, ElementNotVisibleException):
                if i >= (len(assignments)//4)-1:
                    print("completed assignments for this period")
                    raise Exception
                # try to drag scroll bar instead of scrolling
                scroll_bar = self.teacher.find(
                    By.XPATH,
                    '//div[contains(@class,"ScrollbarLayout_faceHorizontal")]')
                actions = ActionChains(self.teacher.driver)
                actions.move_to_element(scroll_bar)
                actions.click_and_hold()
                actions.move_by_offset(50, 0)
                actions.release()
                actions.perform()

        self.ps.test_updates['passed'] = True

    # 14815 - 012 - Teacher | The class average info icon displays a definition
    # about scores from completed assignments
    @pytest.mark.skipif(str(14815) not in TESTS, reason='Excluded')
    def test_teacher_class_average_info_icon_displays_definition_14815(self):
        """The class average info icon displays a definition.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores
        Click on the info icon next to "Class Average"

        Expected Result:
        The class average info icon displays a definition about scores from
        completed assignments
        """
        self.ps.test_updates['name'] = 'cc2.08.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.012', '14815']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(text(),"View Detailed Scores")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')
            )
        )
        self.teacher.find(
            By.XPATH, '//i[@type="info-circle"]').click()
        self.teacher.find(
            By.XPATH,
            '//h3[@class="popover-title" and ' +
            'contains(text(), "Class and Overall Averages")]')

        self.ps.test_updates['passed'] = True

    # 14816 - 013 - Teacher | View the overall score column
    @pytest.mark.skipif(str(14816) not in TESTS, reason='Excluded')
    def test_teacher_view_the_overall_score_column_14816(self):
        """View the overall score column.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores

        Expected Result:
        User is presented with the overall score column next to student names
        """
        self.ps.test_updates['name'] = 'cc2.08.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.013', '14816']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(text(),"View Detailed Scores")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')
            )
        )
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"overall-header-cell")]')

        self.ps.test_updates['passed'] = True
class TestAdminAndTeacherCourseSetup(unittest.TestCase):
    """CC1.10 - Admin and Teacher Course Setup."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.admin = Admin(
            use_env_vars=True,
            existing_driver=self.teacher.driver,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.admin.driver = None
            self.teacher.delete()
        except:
            pass

    # Case C7715 - 001 - Admin | Send course setup data from Sales Force
    @pytest.mark.skipif(str(7715) not in TESTS, reason='Excluded')
    def test_admin_send_course_setup_data_from_sales_force_7715(self):
        """Send course setup data from Sales Force.

        Steps:
        Go to tutor-staging.openstax.org and login as admin
        Click on the user menu
        Select the Admin option
        Click on Salesforce on the header

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc1.10.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.001',
            '7715'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.admin.login()
        self.admin.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Admin'
        ).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Salesforce')
            )
        ).click()
        assert('salesforce' in self.admin.current_url()), 'not at salesforce'

        self.ps.test_updates['passed'] = True

    # Case C7716 - 002 - System | Course registration codes are emailed to the
    # teacher once the course is set up
    @pytest.mark.skipif(str(7716) not in TESTS, reason='Excluded')
    def test_system_registration_codes_are_emailed_to_teacher_7716(self):
        """Registration codes are emailed to teacher once the course is set up.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc1.10.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.002',
            '7716'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7717 - 003 - Teacher | Use a teacher registration code to access
    # their course
    @pytest.mark.skipif(str(7717) not in TESTS, reason='Excluded')
    def test_teacher_use_teacher_registration_code_to_access_course_7717(self):
        """Use a teacher registration code to access their course.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc1.10.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.003',
            '7717'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7718 - 004 - Teacher | Create course periods
    @pytest.mark.skipif(str(7718) not in TESTS, reason='Excluded')
    def test_teacher_create_course_periods_7718(self):
        """Create course periods.

        Steps:
        go to Tutor
        Log in as a teacher
        Click on a Concept Coach book
        Click on the user menu
        Select course roster
        Click "+ Add section"
        Enter a section name into the section Name text box

        Expected Result:
        New course section created
        """
        self.ps.test_updates['name'] = 'cc1.10.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.004',
            '7718'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[contains(@class,"add-period")]//button')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//input[@type="text"]')
            )
        ).send_keys('test_period')
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[@class="modal-content"]//button/span[text()="Add"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="test_period"]')
            )
        )
        self.ps.test_updates['passed'] = True

    # Case C7719 - 005 - Teacher | View student enrollment code for
    # course period
    @pytest.mark.skipif(str(7719) not in TESTS, reason='Excluded')
    def test_teacher_view_student_enrollment_code_for_course_period_7719(self):
        """View the student enrollment code for a course period.

        Steps:
        Go to Tutor
        Log in as a teacher
        Click on a Concept Coach book
        Click on the user menu
        Select course roster
        Click on tab for selected section
        Click 'Get Student Enrollment Code'

        Expected Result:
        Student Enrollment code displayed along with instruction teacher can
        send to students on how to use enrollment code
        """
        self.ps.test_updates['name'] = 'cc1.10.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.005',
            '7719'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//button[contains(@class,"show-enrollment-code")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="enrollment-code"]')
            )
        )
        self.ps.test_updates['passed'] = True

    # Case C7720 - 006 - Teacher | Rename a course period
    @pytest.mark.skipif(str(7720) not in TESTS, reason='Excluded')
    def test_teacher_rename_a_course_period_7720(self):
        """Rename a course period.

        Steps:
        Go to Tutor
        Log in as a teacher
        Click on a Concept Coach book
        Click on the user menu
        Select course roster
        Click on tab for selected section
        Click 'Rename section'
        Enter new section name into the section Name text box
        Click on the 'Rename' button

        Expected Result:
        Section is renamed
        """
        self.ps.test_updates['name'] = 'cc1.10.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.006',
            '7720'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        period_name = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab"]')
            )
        ).text
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(@class,"rename-period")]//button')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//input[@type="text"]')
            )
        ).send_keys('_EDIT')
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[@class="modal-content"]//button/span[text()="Rename"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + period_name + '_EDIT"]')
            )
        )
        # then set it back to what it was before
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(@class,"rename-period")]//button')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//input[@type="text"]')
            )
        ).send_keys(Keys.BACK_SPACE * 5)
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[@class="modal-content"]//button/span[text()="Rename"]'
        ).click()

        self.ps.test_updates['passed'] = True

    # Case C7721 - 007 - Teacher | Archive an empty period
    @pytest.mark.skipif(str(7721) not in TESTS, reason='Excluded')
    def test_teacher_remove_an_empty_period_7721(self):
        """Remove an empty period.

        Steps:
        Go to Tutor
        Log in as a teacher
        Click on a Concept Coach book
        Click on the user menu
        Select course roster
        Click on tab for selected empty section
        Click 'Archive section'
        Click on the 'Archive' button

        Expected Result:
        Section is archived
        """
        self.ps.test_updates['name'] = 'cc1.10.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.007',
            '7721'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        section_name = 'test_' + str(randint(0, 1000))
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        # create an empty section
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[contains(@class,"add-period")]//button')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//input[@type="text"]')
            )
        ).send_keys(section_name)
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[@class="modal-content"]//button/span[text()="Add"]'
        ).click()
        # archive the section just created
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + section_name + '"]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(@class,"archive-period")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@role="tooltip"]//button' +
                 '//span[contains(text(),"Archive")]')
            )
        ).click()
        self.teacher.sleep(2)
        archived = self.teacher.driver.find_elements(
            By.XPATH, '//li//a[@role="tab" and text()="' + section_name + '"]')
        assert(len(archived) == 0), ' not archived'
        self.ps.test_updates['passed'] = True

    # Case C7722 - 008 - Teacher | Archive a non-empty period
    @pytest.mark.skipif(str(7722) not in TESTS, reason='Excluded')
    def test_teacher_archive_a_nonempty_periods_7722(self):
        """Error message displayed if attempting to remove a non-empty period.

        Steps:
        Go to Tutor
        Log in as a teacher
        Click on a Concept Coach book
        Click on the user menu
        Select course roster
        Click on tab for selected non-empty section
        Click 'Archive section'
        Click Archive

        Expected Result:
        Section is archived
        """
        self.ps.test_updates['name'] = 'cc1.10.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.008',
            '7722'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        # name of period to archive (first tab)
        period_name = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab"]')
            )
        ).text
        # archive the section
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + period_name + '"]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(@class,"archive-period")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@role="tooltip"]//button' +
                 '//span[contains(text(),"Archive")]')
            )
        ).click()
        self.teacher.sleep(2)
        archived = self.teacher.driver.find_elements(
            By.XPATH, '//li//a[@role="tab" and text()="' + period_name + '"]')
        assert(len(archived) == 0), ' not archived'
        # add the archived period back
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@class,"view-archived-periods")]//button')
            )
        ).click()
        periods = self.teacher.driver.find_elements(
            By.XPATH, '//div[@class="modal-content"]//tbody//tr'
        )
        for period in periods:
            try:
                period.find_element(
                    By.XPATH, ".//td[text()='" + period_name + "']")
                period.find_element(
                    By.XPATH,
                    ".//td//span[contains(@class,'restore-period')]//button"
                ).click()
                break
            except NoSuchElementException:
                if period == periods[-1]:
                    raise Exception
        self.teacher.sleep(2)
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + period_name + '"]')
            )
        )
        self.ps.test_updates['passed'] = True

    # Case C58354 - 009 - Teacher | Unarchive a section
    @pytest.mark.skipif(str(58354) not in TESTS, reason='Excluded')
    def test_teacher_unarchive_a_section_58354(self):
        """Unarchive a section.

        Steps:
        go to tutor-qa.openstax.org
        log in as a teacher
        click on a Concept Coach book
        click on the user menu
        select course roster
        Click "View Archived Section"
        Click "Unarchive" for the desired section

        Expected Result:
        section is unarchived
        """
        self.ps.test_updates['name'] = 'cc1.10.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.009',
            '58354'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        # name of period to archive (first tab)
        period_name = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab"]')
            )
        ).text
        # archive the section
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + period_name + '"]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(@class,"archive-period")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@role="tooltip"]//button' +
                 '//span[contains(text(),"Archive")]')
            )
        ).click()
        self.teacher.sleep(2)
        archived = self.teacher.driver.find_elements(
            By.XPATH, '//li//a[@role="tab" and text()="' + period_name + '"]')
        assert(len(archived) == 0), ' not archived'
        # add the archived period back
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@class,"view-archived-periods")]//button')
            )
        ).click()
        periods = self.teacher.driver.find_elements(
            By.XPATH, '//div[@class="modal-content"]//tbody//tr'
        )
        for period in periods:
            try:
                period.find_element(
                    By.XPATH, ".//td[text()='" + period_name + "']")
                period.find_element(
                    By.XPATH,
                    ".//td//span[contains(@class,'restore-period')]//button"
                ).click()
                break
            except NoSuchElementException:
                if period == periods[-1]:
                    raise Exception
        self.teacher.sleep(2)
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li//a[@role="tab" and text()="' + period_name + '"]')
            )
        )
        self.ps.test_updates['passed'] = True

    # Case C7723 - 010 - Teacher | Rename the course
    @pytest.mark.skipif(str(7723) not in TESTS, reason='Excluded')
    def test_teacher_rename_the_course_7723(self):
        """Rename the course.

        Steps:
        Go to Tutor
        Log in as a teacher
        Click on a Concept Coach book
        Click on the user menu
        Select course roster
        Click 'Rename Course'
        Enter a new Course name into the Course Name text box
        Click on the 'Rename' button

        Expected Result:
        Course is renamed.
        """
        self.ps.test_updates['name'] = 'cc1.10.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.010',
            '7723'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        # rename section
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[@class="-rename-course-link"]//button')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//input[@type="text"]')
            )
        ).send_keys("_EDIT")
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[@class="modal-content"]//button/span[text()="Rename"]'
        ).click()
        # check that the name was changed
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="course-settings-title"]' +
                 '//span[contains(text(),"_EDIT")]')
            )
        )
        # change it back
        self.teacher.sleep(1)
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[@class="-rename-course-link"]//button')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//input[@type="text"]')
            )
        ).send_keys(Keys.BACK_SPACE * 5)
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[@class="modal-content"]//button/span[text()="Rename"]'
        ).click()

        self.ps.test_updates['passed'] = True

    # Case C7724 - 011 - Teacher | Remove other teachers from the course
    @pytest.mark.skipif(str(7724) not in TESTS, reason='Excluded')
    def test_teacher_remove_other_teachers_from_the_course_7724(self):
        """Remove other teachers from the course.

        Steps:
        Go to Tutor
        Log in as a teacher
        Click on a Concept Coach book
        Click on the user menu
        Select course roster
        Click on 'Remove' on the same row as selected teacher
        Click on the 'Remove' button

        Expected Result:
        Instructor is removed from the course
        """
        self.ps.test_updates['name'] = 'cc1.10.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.011',
            '7724'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.admin.login()
        self.admin.driver.get(
            'https://tutor-qa.openstax.org/admin/courses/8/edit')
        self.admin.page.wait_for_page_load()
        teacher_name = 'Trent'
        self.admin.driver.find_element(
            By.XPATH, '//a[contains(text(),"Teachers")]').click()
        self.admin.driver.find_element(
            By.ID, 'course_teacher').send_keys(teacher_name)
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//li[contains(text(),"%s")]' % teacher_name)
            )
        ).click()
        self.admin.sleep(1)
        self.admin.driver.find_element(
            By.LINK_TEXT, 'Main Dashboard').click()
        self.admin.page.wait_for_page_load()
        self.admin.logout()
        # redo set-up, but make sure to go to course 8
        self.teacher.login()
        self.teacher.driver.get('https://tutor-qa.openstax.org/courses/8')
        self.teacher.open_user_menu()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Course Settings and Roster')
            )
        ).click()
        self.teacher.page.wait_for_page_load()
        # delete teacher
        teachers_list = self.teacher.driver.find_elements(
            By.XPATH, '//div[@class="teachers-table"]//tbody//tr')
        for x in teachers_list:
            temp_first = x.find_element(
                By.XPATH,
                './td[1]'
            ).text
            if temp_first == teacher_name:
                x.find_element(
                    By.XPATH,
                    './/td//span[contains(text(),"Remove")]'
                ).click()
                self.teacher.sleep(1)
                self.teacher.driver.find_element(
                    By.XPATH, '//div[@class="popover-content"]//button'
                ).click()
                break
            if x == teachers_list[-1]:
                print('added teacher was not found, and not deleted')
                raise Exception
        deleted_teacher = self.teacher.driver.find_elements(
            By.XPATH, '//td[contains(text(),"%s")]' % teacher_name)
        assert(len(deleted_teacher) == 0), 'teacher not deleted'

        self.ps.test_updates['passed'] = True

    # come back to this because adding teacher through admin first
    # Case C7725 - 012 - Teacher | Remove themself from the course
    @pytest.mark.skipif(str(7725) not in TESTS, reason='Excluded')
    def test_teacher_remove_themself_from_the_course_7725(self):
        """Remove themself from the course.

        Steps:
        Go to Tutor
        Log in as a teacher
        Click on a Concept Coach book
        Click on the user menu
        Select course roster
        Click on 'Remove' on the same row as themselves
        Click on the 'Remove' button

        Expected Result:
        Teacher is removed from course and taken back to dashboard
        """
        self.ps.test_updates['name'] = 'cc1.10.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.012',
            '7725'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.admin.login()
        self.admin.driver.get(
            'https://tutor-qa.openstax.org/admin/courses/8/edit')
        self.admin.page.wait_for_page_load()
        teacher_name = 'Trent'
        self.admin.driver.find_element(
            By.XPATH, '//a[contains(text(),"Teachers")]').click()
        self.admin.driver.find_element(
            By.ID, 'course_teacher').send_keys(teacher_name)
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//li[contains(text(),"%s")]' % teacher_name)
            )
        ).click()
        self.admin.sleep(1)
        self.admin.driver.find_element(
            By.LINK_TEXT, 'Main Dashboard').click()
        self.admin.page.wait_for_page_load()
        self.admin.logout()
        # redo set-up, but make sure to go to course 8
        # login as the teacher just added to the course
        teacher2 = Teacher(
            username='******',
            password=os.getenv('TEACHER_PASSWORD'),
            existing_driver=self.teacher.driver
        )
        teacher2.login()
        teacher2.driver.get('https://tutor-qa.openstax.org/courses/8')
        teacher2.open_user_menu()
        teacher2.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Course Settings and Roster')
            )
        ).click()
        teacher2.page.wait_for_page_load()
        # delete teacher
        teachers_list = teacher2.driver.find_elements(
            By.XPATH, '//div[@class="teachers-table"]//tbody//tr')
        for x in teachers_list:
            temp_first = x.find_element(
                By.XPATH,
                './td[1]'
            ).text
            if temp_first == teacher_name:
                x.find_element(
                    By.XPATH,
                    './/td//span[contains(text(),"Remove")]'
                ).click()
                teacher2.sleep(1)
                teacher2.driver.find_element(
                    By.XPATH, '//div[@class="popover-content"]//button'
                ).click()
                break
            if x == teachers_list[-1]:
                print('added teacher was not found, and not deleted')
                raise Exception
        # after removing self from course taken to dashboard
        # or course if only 1 other course
        assert('/courses/8' not in teacher2.current_url()), \
            'teacher not deleted'
        teacher2.delete()
        self.ps.test_updates['passed'] = True

    # Case C7726 - 013 - Teacher | Transfer a student to another period
    @pytest.mark.skipif(str(7726) not in TESTS, reason='Excluded')
    def test_teacher_transfer_a_student_to_another_period_7726(self):
        """Transfer a student to another period.

        Steps:
        Go to Tutor
        Log in as a teacher
        Click on a Concept Coach book
        Click on the user menu
        Select course roster
        Click on tab for section selected student is currently enrolled in
        Click on 'Change Section' on the row of the selected student
        Click on section to move student to

        Expected Result:
        Student is moved to chosen section
        """
        self.ps.test_updates['name'] = 'cc1.10.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.013',
            '7726'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        # move student
        first_student = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="period"]//tbody/tr[1]')
            )
        )
        student_name = first_student.find_element(
            By.XPATH, './/td[1]').text
        first_student.find_element(
            By.XPATH,
            './/td[@class="actions"]/a[@aria-describedby="change-period"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="popover-content"]//li[1]')
            )
        ).click()
        # check that student was moved
        self.teacher.sleep(2)
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//li[@tabindex="1"]//a[@role="tab"]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="period"]//tbody/tr' +
                 '//td[text()="' + student_name + '"]')
            )
        )
        self.ps.test_updates['passed'] = True

    # Case C7727 - 014 - Teacher | Remove a student from a course
    @pytest.mark.skipif(str(7727) not in TESTS, reason='Excluded')
    def test_teacher_remove_a_student_from_a_course_7727(self):
        """Remove a student from a course.

        Steps:
        Go to Tutor
        Log in as a teacher
        Click on a Concept Coach book
        Click on the user menu
        Select course roster
        Click on tab for section selected student is currently enrolled in
        Click on 'Drop' on the row of the selected student
        Click on the 'Drop' button

        Expected Result:
        Student is dropped from the course
        """
        self.ps.test_updates['name'] = 'cc1.10.014' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.014',
            '7727'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        # drop student
        first_student = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="period"]//tbody/tr[1]')
            )
        )
        student_name = first_student.find_element(
            By.XPATH, './/td[1]').text
        first_student.find_element(
            By.XPATH,
            './/td[@class="actions"]/a[@aria-describedby="drop-student"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@id="drop-student"]//button')
            )
        ).click()
        # check that student was removed
        self.teacher.sleep(2)
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@class,"dropped-students")]//tbody/tr' +
                 '//td[text()="' + student_name + '"]')
            )
        )
        self.ps.test_updates['passed'] = True

    # Case C7728 - 015 - Admin | Impersonate a teacher
    @pytest.mark.skipif(str(7728) not in TESTS, reason='Excluded')
    def test_admin_impersonate_a_teacher_7728(self):
        """Impersonate a teacher.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the admin user account in the username and password text boxes
        Click on the 'Sign in' button
        Click on the user's name in the top right corner to open drop down menu
        Click on the 'Admin' option of the drop down menu
        Click on 'Users' on the bar across the top
        [optional] Enter a teacher name into the search here text box
        Click on the 'Search' button
        Click on the 'Sign in as' button next to chosen teacher

        Expected Result:
        Signs in as chosen chosen teacher.
        Goes to chosen teacher's initial screen after login
        If multiple courses list of textbooks
        If one course straight to dashboard
        """
        self.ps.test_updates['name'] = 'cc1.10.015' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.015',
            '7728'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.admin.login()
        self.admin.open_user_menu()
        self.admin.driver.find_element(
            By.LINK_TEXT, 'Admin'
        ).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Users')
            )
        ).click()
        self.admin.page.wait_for_page_load()
        self.admin.driver.find_element(By.ID, 'query').send_keys('teacher01')
        self.admin.driver.find_element(
            By.XPATH, '//input[@value="Search"]').click()
        self.admin.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//a[contains(text(),"Sign in as")]')
            )
        ).click()
        self.admin.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//span[contains(text(),"Charles Morris")]')
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7729 - 016 - Admin | Change a course ecosystem
    @pytest.mark.skipif(str(7729) not in TESTS, reason='Excluded')
    def test_admin_change_a_course_ecosystem_7729(self):
        """Change a course ecosystem.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the admin user account in the username and password text boxes
        Click on the 'Sign in' button
        Click on the 'Admin' button from the user menu
        Open the drop down menu by clicking 'Course Organization'
        Click the 'Courses' option
        Click the 'Edit' link for the desired course
        Click on the 'Course content' tab
        Select a different option in the 'Ecosystem' drop down menu
        Click the 'Submit' button

        Expected Result:
        Course ecosystem change is put on a queue
        """
        self.ps.test_updates['name'] = 'cc1.10.016' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.016',
            '7729'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.admin.login()
        self.admin.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Admin'
        ).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Course Organization')
            )
        ).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Courses')
            )
        ).click()
        self.admin.page.wait_for_page_load()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Edit')
            )
        ).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Course content')
            )
        ).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.ID, 'ecosystem_id')
            )
        ).send_keys('1' + Keys.ENTER)
        # self.admin.wait.until(
        #     expect.visibility_of_element_located(
        #         (By.XPATH, '//select[@id="ecosystem_id"]//option[1]')
        #     )
        # ).click()
        self.admin.driver.find_element(
            By.XPATH, '//div[@id="content"]//input[@type="submit"]'
        ).click()
        self.admin.sleep(1)
        self.admin.driver.find_element(
            By.XPATH, '//div[contains(@class,"alert-info")]'
        )
        self.ps.test_updates['passed'] = True

    # Case C7730 - 017 - Admin | Change multiple course ecosystems in bulk
    @pytest.mark.skipif(str(7730) not in TESTS, reason='Excluded')
    def test_admin_change_multiple_course_ecosystems_in_bulk_7730(self):
        """Change multiple course ecosystems in bulk.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the admin user account in the username and password text boxes
        Click on the 'Sign in' button
        Click on the 'Admin' button from the user menu
        Open the drop down menu by clicking 'Course Organization'
        Click the 'Courses' option
        Check the checkboxes next to selected courses
        Select an option in the 'Select an ecosystem' drop down menu
        Click the 'Set Ecosystem' button

        Expected Result:
        Course ecosystem change is put on a queue
        """
        self.ps.test_updates['name'] = 'cc1.10.017' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.017',
            '7730'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.admin.login()
        self.admin.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT, 'Admin'
        ).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Course Organization')
            )
        ).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, 'Courses')
            )
        ).click()
        self.admin.page.wait_for_page_load()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.ID, 'courses_select_all')
            )
        ).click()
        # click the checkmarks for two courses
        courses = self.admin.driver.find_elements(
            By.XPATH, '//input[@class="course_id_select"]')
        course_1 = courses[0]
        self.admin.driver.execute_script(
            'return arguments[0].scrollIntoView();', course_1)
        self.admin.driver.execute_script('window.scrollBy(0, -120);')
        course_1.click()
        self.admin.sleep(0.5)
        course_2 = courses[1]
        self.admin.driver.execute_script(
            'return arguments[0].scrollIntoView();', course_2)
        self.admin.driver.execute_script('window.scrollBy(0, -120);')
        course_2.click()
        self.admin.sleep(0.5)
        # scroll to bottom and set bulk ecosystems
        self.admin.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.ID, 'ecosystem_id')
            )
        ).send_keys('1' + Keys.ENTER)
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[contains(@class,"alert-info")]')
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7731 - 018 - Teacher | Receive a notice when students register
    @pytest.mark.skipif(str(7731) not in TESTS, reason='Excluded')
    def test_teacher_receive_a_notice_when_students_register_7731(self):
        """Receive a notice when students register.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc1.10.018' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.018',
            '7731'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
class TestAccountEnhancements(unittest.TestCase):
    """T3.16 - Accounts Enhancements."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(use_env_vars=True,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
        else:
            self.teacher = Teacher(use_env_vars=True)

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    # Case C105592 - 001 - Student | Cannot use the same email for more than
    # one account
    @pytest.mark.skipif(str(105592) not in TESTS, reason='Excluded')
    def test_student_cannot_use_the_same_email_for_more_than_one_105592(self):
        """Cannot use the same email for more than one account.

        Steps:
        Create a student account with email and password
        Log out of new account.
        Try to Create another account with the same email

        Expected Result:
        "Email already in use. Are you trying to log in?" message displayed.
        Account cannot be created with the same email.
        """
        self.ps.test_updates['name'] = 't3.16.001' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.001', '105592']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C105593 - 002 - Teacher | Cannot use the same email for more than
    # one account
    @pytest.mark.skipif(str(105593) not in TESTS, reason='Excluded')
    def test_teacher_cannot_use_the_same_email_for_more_than_one_105593(self):
        """Cannot use the same email for more than one account.

        Steps:
        Create a teacher account with email and password
        Log out of new account.
        Try to Create another account with the same email

        Expected Result:
        "Email already in use. Are you trying to log in?" message displayed.
        Account cannot be created with the same email.
        """
        self.ps.test_updates['name'] = 't3.16.002' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.002', '105593']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C105594 - 003 - Student | Email must be verified
    @pytest.mark.skipif(str(105594) not in TESTS, reason='Excluded')
    def test_student_email_must_be_verified_105594(self):
        """Email must be verified.

        Steps:
        Go to https://accounts-qa.openstax.org/login
        Click the 'Sign up here' link
        Select 'Student' from the 'I am a' drop down menu
        Enter an email into the email text box
        Click 'Next'
        [an email with a pin is sent, log onto email and get pin]
        Enter Pin into text box
        Click 'Confirm'

        Expected Result:
        Email is verified by retrieving the pin.
        Cannot move on in account creation without pin
        """
        self.ps.test_updates['name'] = 't3.16.003' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.003', '105594']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C105595 - 004 - Teacher | Email must be verified
    @pytest.mark.skipif(str(105595) not in TESTS, reason='Excluded')
    def test_teacher_email_must_be_verified_105595(self):
        """Email must be verified.

        Steps:
        Go to https://accounts-qa.openstax.org/login
        Click the 'Sign up here' link
        Select 'Instructor' from the 'I am a' drop down menu
        Enter an email into the email text box
        Click 'Next'
        [an email with a pin is sent, log onto email and get pin]
        Enter Pin into text box
        Click 'Confirm'

        Expected Result:
        Email is verified by retrieving the pin.
        Cannot move on in account creation without pin
        """
        self.ps.test_updates['name'] = 't3.16.004' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.004', '105595']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C105596 - 005 - Student | Following login the student is shown
    # MyOpenstax
    @pytest.mark.skipif(str(105596) not in TESTS, reason='Excluded')
    def test_student_following_login_student_is_ahown_my_openstax_105596(self):
        """Following login the student is shown MyOpenStax.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.16.005' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.005', '105596']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C105597 - 006 - Teacher | Following login the teacher is shown
    # MyOpenstax
    @pytest.mark.skipif(str(105597) not in TESTS, reason='Excluded')
    def test_teacher_following_login_teacher_is_ahown_my_openstax_105597(self):
        """Following login the teacher is shown MyOpenStax.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.16.006' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.006', '105597']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C105598 - 007 - Teacher | Accounts stores faculty verification
    @pytest.mark.skipif(str(105598) not in TESTS, reason='Excluded')
    def test_teacher_accounts_stores_faculty_verification_105598(self):
        """Accounts stores faculty verification.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.16.007' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.007', '105598']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C105599 - 008 - Student | User must have at least one email
    @pytest.mark.skipif(str(105599) not in TESTS, reason='Excluded')
    def test_student_user_must_have_at_least_one_email_105599(self):
        """User must have at least one email.

        Steps:
        Go to https://accounts-qa.openstax.org/
        Login to an account with one email
        Click on the email

        Expected Result:
        No delete option is available.
        """
        self.ps.test_updates['name'] = 't3.16.008' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.008', '105599']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C105600 - 009 - Teacher | User must have at least one email
    @pytest.mark.skipif(str(105600) not in TESTS, reason='Excluded')
    def test_teacher_user_must_have_at_least_one_email_105600(self):
        """User must have at least one email.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.16.009' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.009', '105600']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    '''
    # Case C105601 - 010 - Student | Student is alerted during registration if
    # their school ID is already in use
    @pytest.mark.skipif(str(105601) not in TESTS, reason='Excluded')
    def test_student_is_alerted_during_registration_is_their_scho_105601(self):
        """Student is alerted during registration if their school ID is already
        in use.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.16.010' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.010', '105601']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    '''

    # Case C105602 - 011 - Teacher | Account information is sent to Salseforce
    @pytest.mark.skipif(str(105602) not in TESTS, reason='Excluded')
    def test_teacher_account_information_is_sent_to_salesforce_105602(self):
        """Account information is sent to Salseforce.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.16.011' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.011', '105602']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107581 - 012 - Teacher | Reason for requiring additional contact
    # information shown
    @pytest.mark.skipif(str(107581) not in TESTS, reason='Excluded')
    def test_teacher_reason_for_requiring_additional_contact_info_107581(self):
        """Reason for requiring additional contact information shown.

        Steps:
        Go to Accounts
        Start signup for an instructor account
        Proceed until the signup pin is confirmed

        Expected Result:
        Instructor verification is presented
        Current: "We need information to help verify you’re an instructor and
            give you access to materials like test banks and OpenStax Tutor
            course setup."
        """
        self.ps.test_updates['name'] = 't3.16.012' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.012', '107581']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107586 - 013 - Student | Register for an account without a username
    @pytest.mark.skipif(str(107586) not in TESTS, reason='Excluded')
    def test_student_register_for_an_Account_without_a_username_107586(self):
        """Register for an account without a username.

        Steps:
        Go to https://accounts-qa.openstax.org/login
        Click the 'Sign up here' link
        Select 'Student' from the 'I am a' drop down menu
        Enter an email into the email text box
        Click 'Next'
        [an email with a pin is sent, log onto email and get pin]
        Enter Pin into text box
        Click 'Confirm'
        Enter password [staxly16] into password text box
        Re-Enter password in confirm password text box
        Click Submit
        Enter first name into the 'First Name' text box
        Enter last name into the 'Last Name' text box
        Enter school into 'School' text box
        Click checkbox 'I Agree' for the Terms of Use and the Privacy Policy
        Click 'Create Account'
        Click the checkbox and click 'I Agree' for the Terms of Use
        Click the checkbox and click 'I Agree' for the Privacy Policy

        Expected Result:
        Account is created without username. Login only with email
        """
        self.ps.test_updates['name'] = 't3.16.013' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.013', '107586']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107587 - 014 - Admin | Login using a username
    @pytest.mark.skipif(str(107587) not in TESTS, reason='Excluded')
    def test_admin_login_using_a_username_107587(self):
        """Login using a username.

        Steps:
        Go to https://tutor-qa.openstax.org/
        Click on the 'Login' button
        Enter the admin username in the username text box
        Click 'Next'
        Enter the admin password in the password text box
        Click on the 'Login' button

        Expected Result:
        User logged in.
        """
        self.ps.test_updates['name'] = 't3.16.014' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.014', '107587']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107588 - 015 - Teacher | Login using a username
    @pytest.mark.skipif(str(107588) not in TESTS, reason='Excluded')
    def test_teacher_login_using_a_username_107588(self):
        """Login using a username.

        Steps:
        Go to https://tutor-qa.openstax.org/
        Click on the 'Login' button
        Enter the teacher username in the username text box
        Click 'Next'
        Enter the teacher password in the password text box
        Click on the 'Login' button

        Expected Result:
        User logged in.

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.16.015' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.015', '107588']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107589 - 016 - Student | Login using a username
    @pytest.mark.skipif(str(107589) not in TESTS, reason='Excluded')
    def test_student_login_using_a_username_107589(self):
        """Login using a username.

        Steps:
        Go to https://tutor-qa.openstax.org/
        Click on the 'Login' button
        Enter the student username in the username text box
        Click 'Next'
        Enter the student password in the password text box
        Click on the 'Login' button

        Expected Result:
        User logged in.
        """
        self.ps.test_updates['name'] = 't3.16.016' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.016', '107589']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107590 - 017 - Content Analyst | Login using a username
    @pytest.mark.skipif(str(107590) not in TESTS, reason='Excluded')
    def test_content_analyst_login_using_a_username_107590(self):
        """Login using a username.

        Steps:
        Go to https://tutor-qa.openstax.org/
        Click on the 'Login' button
        Enter the content username in the username text box
        Click 'Next'
        Enter the content password in the password text box
        Click on the 'Login' button

        Expected Result:
        User logged in.
        """
        self.ps.test_updates['name'] = 't3.16.017' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.017', '107590']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107591 - 018 - Admin | Login using an email address
    @pytest.mark.skipif(str(107591) not in TESTS, reason='Excluded')
    def test_admin_login_using_an_email_address_107591(self):
        """Login using an email address.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.16.018' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.018', '107591']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107592 - 019 - Teacher | Login using an email address
    @pytest.mark.skipif(str(107592) not in TESTS, reason='Excluded')
    def test_teacher_login_using_an_email_address_107592(self):
        """Login using an email address.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.16.019' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.019', '107592']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107593 - 020 - Student | Login using an email address
    @pytest.mark.skipif(str(107593) not in TESTS, reason='Excluded')
    def test_student_login_using_an_email_address_107593(self):
        """Login using an email address.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.16.020' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.020', '107593']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107594 - 021 - Content Analyst | Login using an email address
    @pytest.mark.skipif(str(107594) not in TESTS, reason='Excluded')
    def test_content_analyst_login_using_an_email_address_107594(self):
        """Login using an email address.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.16.021' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.16', 't3.16.021', '107594']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    def test_teacher_remove_themself_from_the_course_7725(self):
        """Remove themself from the course.

        Steps:
        Go to Tutor
        Log in as a teacher
        Click on a Concept Coach book
        Click on the user menu
        Select course roster
        Click on 'Remove' on the same row as themselves
        Click on the 'Remove' button

        Expected Result:
        Teacher is removed from course and taken back to dashboard
        """
        self.ps.test_updates['name'] = 'cc1.10.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.10',
            'cc1.10.012',
            '7725'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.admin.login()
        self.admin.driver.get(
            'https://tutor-qa.openstax.org/admin/courses/8/edit')
        self.admin.page.wait_for_page_load()
        teacher_name = 'Trent'
        self.admin.driver.find_element(
            By.XPATH, '//a[contains(text(),"Teachers")]').click()
        self.admin.driver.find_element(
            By.ID, 'course_teacher').send_keys(teacher_name)
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//li[contains(text(),"%s")]' % teacher_name)
            )
        ).click()
        self.admin.sleep(1)
        self.admin.driver.find_element(
            By.LINK_TEXT, 'Main Dashboard').click()
        self.admin.page.wait_for_page_load()
        self.admin.logout()
        # redo set-up, but make sure to go to course 8
        # login as the teacher just added to the course
        teacher2 = Teacher(
            username='******',
            password=os.getenv('TEACHER_PASSWORD'),
            existing_driver=self.teacher.driver
        )
        teacher2.login()
        teacher2.driver.get('https://tutor-qa.openstax.org/courses/8')
        teacher2.open_user_menu()
        teacher2.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Course Settings and Roster')
            )
        ).click()
        teacher2.page.wait_for_page_load()
        # delete teacher
        teachers_list = teacher2.driver.find_elements(
            By.XPATH, '//div[@class="teachers-table"]//tbody//tr')
        for x in teachers_list:
            temp_first = x.find_element(
                By.XPATH,
                './td[1]'
            ).text
            if temp_first == teacher_name:
                x.find_element(
                    By.XPATH,
                    './/td//span[contains(text(),"Remove")]'
                ).click()
                teacher2.sleep(1)
                teacher2.driver.find_element(
                    By.XPATH, '//div[@class="popover-content"]//button'
                ).click()
                break
            if x == teachers_list[-1]:
                print('added teacher was not found, and not deleted')
                raise Exception
        # after removing self from course taken to dashboard
        # or course if only 1 other course
        assert('/courses/8' not in teacher2.current_url()), \
            'teacher not deleted'
        teacher2.delete()
        self.ps.test_updates['passed'] = True
class TestTeacherViews(unittest.TestCase):
    """CC1.13 - Teacher Views."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(
                use_env_vars=True,
                pasta_user=self.ps,
                capabilities=self.desired_capabilities
            )
        else:
            self.teacher = Teacher(
                use_env_vars=True
            )
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH,
            '//p[contains(text(),"OpenStax Concept Coach")]'
        ).click()

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(
                job_id=str(self.teacher.driver.session_id),
                **self.ps.test_updates
            )
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7609 - 001 - Teacher | View the Concept Coach dashboard
    @pytest.mark.skipif(str(7609) not in TESTS, reason='Excluded')
    def test_teacher_view_the_concept_coach_dashboard_7609(self):
        """View the Concept Coach dashboard.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name

        Expected Result:
        The user is presented with the Concept Coach dashbaord
        """
        self.ps.test_updates['name'] = 'cc1.13.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.001', '7609']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.driver.find_element(
            By.XPATH, "//span[text()='Class Dashboard']"
        )

        self.ps.test_updates['passed'] = True

    # Case C7610 - 002 - Teacher | Switch between concurrently running courses
    @pytest.mark.skipif(str(7610) not in TESTS, reason='Excluded')
    def test_teacher_switch_between_concurrently_running_courses_7610(self):
        """Able to switch between concurrently running courses.

        Steps:
        Click on the OpenStax logo in the left corner of the header

        Expected Result:
        The user is presented with a list of Concept Coach courses
        Is able to switch to another course
        """
        self.ps.test_updates['name'] = 'cc1.13.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.002', '7610']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        url1 = self.teacher.current_url().split('course')[1]
        self.teacher.find(
            By.XPATH, '//a//i[@class="ui-brand-logo"]'
        ).click()
        try:
            self.teacher.find(
                By.XPATH,
                '//a[not(contains(@href,"' + url1 + '"))]' +
                '/p[contains(text(),"OpenStax Concept Coach")]'
            ).click()
        except NoSuchElementException:
            print('Only one CC course, cannot go to another')
            raise Exception
        # assert that user at cc dashboard
        self.teacher.driver.find_element(
            By.XPATH, "//span[text()='Class Dashboard']"
        )
        assert(url1 != self.teacher.current_url()), \
            'went to same course'

        self.ps.test_updates['passed'] = True

    # Case C7611 - 003 - Teacher | View links on dashboard to course materials
    @pytest.mark.skipif(str(7611) not in TESTS, reason='Excluded')
    def test_teacher_view_links_on_dashboard_to_course_materials_7611(self):
        """View links on dashboard to course materials.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name

        Expected Result:
        On header there is a link to 'Homework PDF', and 'Online Book'
        """
        self.ps.test_updates['name'] = 'cc1.13.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.003', '7611']
        self.ps.test_updates['passed'] = False

        # HW pdf
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Homework PDF")]'
        ).click()
        coursename = self.teacher.driver.find_element(
            By.XPATH, '//div[@class="cc-dashboard"]/div[@data-appearance]'
        ).get_attribute('data-appearance')
        coursename = coursename.split('_')
        home = os.getenv("HOME")
        files = os.listdir(home + '/Downloads')
        for i in range(len(files)):
            match = True
            for word in coursename:
                if not ((word in files[i]) and (files[i][-4:] == '.pdf')):
                    match = False
                    break
            if match:
                break
            else:
                if i == len(files)-1:
                    print("textbok pdf not downloaded")
                    raise Exception
        # online book
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Online Book")]'
        ).click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        assert('cnx' in self.teacher.current_url()), \
            'Not viewing the textbook PDF'
        self.teacher.driver.switch_to_window(
            self.teacher.driver.window_handles[0])
        # assignment links
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Assignment Links")]'
        ).click()
        assert('assignment-links' in self.teacher.current_url()), \
            'not viewing Assignment Links'

        self.ps.test_updates['passed'] = True

    # Case C7612 - 004 - Teacher | Able to copy a system-generated message
    # with a student code, links, and other information
    @pytest.mark.skipif(str(7612) not in TESTS, reason='Excluded')
    def test_able_to_copy_a_system_generated_message_with_a_student_7612(self):
        """Copy a system-generated message with a student code, links, etc.

        Steps:
        Click on the user menu in the right corner of the header
        Click "Course Roster"
        Click "Get Student Enrollment Code"
        Copy the system generated message

        Expected Result:
        The user is able to copy the system generated message
        """
        self.ps.test_updates['name'] = 'cc1.13.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.004', '7612']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.find(
            By.XPATH, '//a/div[contains(text(),"Course Settings and Roster")]'
        ).click()
        self.teacher.driver.find_element(
            By.XPATH, '//span[contains(text(),"enrollment")]'
        ).click()
        self.teacher.find(
            By.XPATH,
            '//span[contains(text(),"Send enrollment instructions")]'
        )

        self.ps.test_updates['passed'] = True

    # Case C7613 - 005 - Teacher | Periods are relabeled as sections for all
    # courses
    @pytest.mark.skipif(str(7613) not in TESTS, reason='Excluded')
    def test_teacher_periods_are_relabeled_as_sections_for_all_cour_7613(self):
        """Period is relabeled as section for college courses.

        Steps:
        Go to user menu
        Click on course roster
        Check that there is an '+ add section' button instead
            of an '+ add period' button

        Expected Result:
        There is an '+ add section' button instead of an '+ add period' button
        """
        self.ps.test_updates['name'] = 'cc1.13.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.005', '7613']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a/div[contains(text(),"Course Settings and Roster")]'
        ).click()
        self.teacher.find(
            By.XPATH,
            '//button[contains(@class,"add-period")]//span[text()="Section"]'
        )

        self.ps.test_updates['passed'] = True

    # Case C7614 - 006 - Teacher | View a score report
    @pytest.mark.skipif(str(7614) not in TESTS, reason='Excluded')
    def test_teacher_view_a_score_report_7614(self):
        """View a score report.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"

        Expected Result:
        The user is presented with a score report
        """
        self.ps.test_updates['name'] = 'cc1.13.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.006', '7614']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a/div[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7615 - 007 - Teacher | View a report showing an individual
    # student's work pages
    @pytest.mark.skipif(str(7615) not in TESTS, reason='Excluded')
    def test_teacher_view_a_report_showing_an_individual_students_7615(self):
        """View a report showing an individual student's work pages.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Click on the percentage in the "Score" column

        Expected Result:
        Individual student's work is shown
        """
        self.ps.test_updates['name'] = 'cc1.13.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.007', '7614']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a/div[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[contains(@class,"scores-cell")]' +
            '/div[@class="score"]'
        ).click()
        assert('step' in self.teacher.current_url()), \
            "Not taken to individual student's work for assignment"

        self.ps.test_updates['passed'] = True

    # Case C7616 - 008 - Teacher | View a summary report showing a class's work
    # pages
    @pytest.mark.skipif(str(7616) not in TESTS, reason='Excluded')
    def test_teacher_view_a_summary_report_showing_a_class_work_pag_7616(self):
        """View a summary report showing a class's work pages.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Click on the desired period tab

        Expected Result:
        The user is presented with a summary report
        """
        self.ps.test_updates['name'] = 'cc1.13.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.008', '7616']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a/div[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        periods = self.teacher.driver.find_elements(
            By.XPATH, '//span[contains(@class,"tab-item-period-name")]'
        )
        for period in periods:
            period.click()

        self.ps.test_updates['passed'] = True

    # Case C7617 - 009 - Teacher | View the aggregate student scores
    @pytest.mark.skipif(str(7617) not in TESTS, reason='Excluded')
    def test_teacher_view_the_aggregate_student_scores_7617(self):
        """View the aggregate student scores.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"

        Expected Result:
        The user is presented with Student scores
        """
        self.ps.test_updates['name'] = 'cc1.13.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.009', '7617']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a/div[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH, '//div[contains(@class,"course-scores-container")]')

        self.ps.test_updates['passed'] = True

    # Case C7618 - 010 - Teacher | View scores for an individual student's
    # scores
    @pytest.mark.skipif(str(7618) not in TESTS, reason='Excluded')
    def test_teacher_view_scores_for_an_individual_student_scores_7618(self):
        """View scores for an individual student's scores.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Scroll to the desired student

        Expected Result:
        The user is presented with scores for an individual student
        """
        self.ps.test_updates['name'] = 'cc1.13.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.010', '7618']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a/div[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[contains(@class,"name-cell")]'
        )

        self.ps.test_updates['passed'] = True

    # Case C7619 - 011 - Teacher | View an individual student's question set
    # for an assignment
    @pytest.mark.skipif(str(7619) not in TESTS, reason='Excluded')
    def test_teacher_view_an_individual_student_question_set_7619(self):
        """View an individual student's question set for an assignment.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Click on a student's score for the desired assignment

        Expected Result:
        The user is presented with a student's question set for the assignment
        """
        self.ps.test_updates['name'] = 'cc1.13.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.011', '7619']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a/div[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[contains(@class,"scores-cell")]' +
            '/div[@class="score"]'
        ).click()
        breadcrumbs = self.teacher.driver.find_elements(
            By.XPATH, '//span[contains(@class,"openstax-breadcrumbs-")]'
        )
        for i in range(len(breadcrumbs)-1):
            self.teacher.driver.find_element(
                By.XPATH,
                '//span[contains(@class,"openstax-breadcrumbs-")]' +
                '[' + str(i + 1) + ']'
            ).click()

        self.ps.test_updates['passed'] = True

    # Case C7620 - 012 - Teacher | View an assignment summary
    @pytest.mark.skipif(str(7620) not in TESTS, reason='Excluded')
    def test_teacher_view_an_assignment_summary_7620(self):
        """View an assignment summary.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Click on a student's score for the desired assignment
        Click "Summary"

        Expected Result:
        The user is presented with an assignmnent summary
        """
        self.ps.test_updates['name'] = 'cc1.13.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.012', '7620']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a/div[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[contains(@class,"scores-cell")]' +
            '/div[@class="score"]'
        ).click()
        self.teacher.driver.find_element(
            By.XPATH,
            '//span[contains(@class,"breadcrumb-end")]'
        ).click()
        self.teacher.sleep(0.5)
        breadcrumbs_answered = self.teacher.driver.find_elements(
            By.XPATH,
            '//span[contains(@class,"openstax-breadcrumbs-")' +
            'and contains(@class,"completed")]'
        )
        question_cards = self.teacher.driver.find_elements(
            By.XPATH, '//div[contains(@class,"openstax-exercise-card")]'
        )
        assert(len(question_cards) == len(breadcrumbs_answered)), \
            'all answered questions not in summary'

        self.ps.test_updates['passed'] = True

    # Case C7622 - 013 - Teacher | Download student scores
    @pytest.mark.skipif(str(7622) not in TESTS, reason='Excluded')
    def test_teacher_download_student_scores_7622(self):
        """Download student scores.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Click "Export"

        Expected Result:
        Student scores are downloaded in an excel spreadsheet
        """
        self.ps.test_updates['name'] = 'cc1.13.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.013', '7622']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a/div[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"export-button")]//button'
        ).click()
        # wait for it to export. It says generating when still not done
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@class,"export-button")]//button')
            )
        )
        # sleep to make sure the contents is downloaded
        self.teacher.sleep(5)

        # check that it was downloaded
        coursename = self.teacher.driver.find_element(
            By.XPATH, '//div[@class="course-name"]').text
        coursename = coursename.split(' ')[0].replace(' ', '')
        home = os.getenv("HOME")
        files = os.listdir(home + '/Downloads')
        for i in range(len(files)):
            if (coursename in files[i]) and ('Scores' in files[i]) \
                    and (files[i][-5:] == '.xlsx'):
                break
            else:
                if i == len(files)-1:
                    print(coursename)
                    raise Exception

        self.ps.test_updates['passed'] = True

    # Case C7624 - 014 - Teacher | Exercise IDs are shown for each assessment
    @pytest.mark.skipif(str(7624) not in TESTS, reason='Excluded')
    def test_teacher_exercise_ids_are_shown_for_each_assessment_7624(self):
        """Exercise IDs are shown for each assessment.

        Steps:
        Click the user menu in the right corner of the header
        Click "Question Library"
        Select a chapter
        Click "Show Questions"

        Expected Result:
        Exercise IDs are shown for each assessment in the bottom right hand
        corner of the box holding the question.
        """
        self.ps.test_updates['name'] = 'cc1.13.014' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.014', '7624']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a/div[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="score"]')
            )
        ).click()
        breadcrumbs = self.teacher.find_all(
            By.XPATH, '//span[contains(@class,"breadcrumb")]')
        for i in range(len(breadcrumbs)-1):
            self.teacher.driver.find_element(
                By.XPATH,
                '//span[contains(@class,"exercise-identifier-link")' +
                ' and contains(text(),"ID")]'
            )
            self.teacher.driver.find_element(
                By.XPATH,
                '//span[contains(@class,"openstax-breadcrumbs-")]' +
                '[' + str(i + 2) + ']'
            ).click()

        self.ps.test_updates['passed'] = True

    # Case C111251 - 015 - Teacher | Student score columns do not show a due
    # date
    @pytest.mark.skipif(str(111251) not in TESTS, reason='Excluded')
    def test_teacher_student_score_columns_so_not_show_a_due_date_111251(self):
        """Student score columns do not show a due date.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc1.13.015' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc1',
            'cc1.13',
            'cc1.13.015',
            '111251'
        ]
        self.ps.test_updates['passed'] = False

        self.teacher.open_user_menu()
        self.teacher.find(
            By.XPATH, '//a/div[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )

        assert(len(self.teacher.find_all(By.CSS_SELECTOR, 'div.Due')) == 0), \
            'Due date is present'

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a/div[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        date_cells = self.teacher.find_all(
            By.XPATH,
            '//div[@class="header-cell-wrapper"]//div[@class="header-row"]'
        )
        for i in range(len(date_cells)-1):
            assert(date_cells[i].text == ""), "date cell is not empty"

        self.ps.test_updates['passed'] = True
Ejemplo n.º 30
0
class TestViewClassPerformance(unittest.TestCase):
    """T1.22 - View Class Performance."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.teacher.login()
        self.teacher.select_course(appearance='biology')
        self.teacher.find(By.PARTIAL_LINK_TEXT, 'Performance Forecast').click()

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.teacher.delete()
        except:
            pass

    # Case C8148 - 001 - Teacher | View the period Performance Forecast
    @pytest.mark.skipif(str(8148) not in TESTS, reason='Excluded')
    def test_teacher_view_the_period_performance_forecast_8148(self):
        """View the period Performance Forecast.

        Steps:
        On the calendar dashboard, click on the "Performance Forecast" button
        on the upper right corner of the calendar OR
        click on the user drop down menu then click on the
        "Performance Forecast" button
        Click on the desired period

        Expected Result:
        The period Performance Forecast is presented to the user
        """
        self.ps.test_updates['name'] = 't1.22.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.22',
            't1.22.001',
            '8148'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assert('guide' in self.teacher.current_url()), \
            'Not viewing performance forecast'

        self.ps.test_updates['passed'] = True

    # Case C8149 - 002 - Teacher | Info icon shows an explanation of the data
    @pytest.mark.skipif(str(8149) not in TESTS, reason='Excluded')
    def test_teacher_info_icon_shows_an_explanation_of_the_data_8149(self):
        """Info icon shows an explanation of the data.

        Steps:
        On the calendar dashboard, click on the "Performance Forecast" button
            on the upper right corner of the calendar
            OR
        Click on the user drop down menu then click on the
        "Performance Forecast" button
        Hover the cursor over the info icon that is next to the
        "Performance Forecast" header

        Expected Result:
        Info icon shows an explanation of the data
        """
        self.ps.test_updates['name'] = 't1.22.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.22',
            't1.22.002',
            '8149'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assert('guide' in self.teacher.current_url()), \
            'Not viewing performance forecast'
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.CLASS_NAME, 'info-link')
            )
        ).click()

        self.ps.test_updates['passed'] = True

    # Case C8150 - 003 - Teacher | View the performance color key
    @pytest.mark.skipif(str(8150) not in TESTS, reason='Excluded')
    def test_teacher_view_the_performance_color_key_8150(self):
        """View the performance color key.

        Steps:
        On the calendar dashboard, click on the "Performance Forecast"
        button on the upper right corner of the calendar OR
        click on the user drop down menu
        click on the "Performance Forecast" button

        Expected Result:
        The performance color key is presented to the user
        (next to the 'Return to Dashboard' button)
        """
        self.ps.test_updates['name'] = 't1.22.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.22',
            't1.22.003',
            '8150'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assert('guide' in self.teacher.current_url()), \
            'Not viewing performance forecast'
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.CLASS_NAME, 'guide-key')
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C8151 - 004 - Teacher | Return to Dashboard button returns to
    # the calendar
    @pytest.mark.skipif(str(8151) not in TESTS, reason='Excluded')
    def test_teacher_return_to_dashboard_button_returns_to_the_cal_8151(self):
        """Return to Dashboard button returns to the calendar.

        Steps:
        On the calendar dashboard, click on the "Performance Forecast"
        button on the upper right corner of the calendar OR
        Click on the user drop down menu
        Click on the "Performance Forecast" button

        Expected Result:
        The calendar dashboard is presented to the user
        """
        self.ps.test_updates['name'] = 't1.22.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.22',
            't1.22.004',
            '8151'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions

        assert('guide' in self.teacher.current_url()), \
            'Not viewing performance forecast'
        self.teacher.open_user_menu()
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.LINK_TEXT, 'Dashboard')
            )
        ).click()

        assert('calendar' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.ps.test_updates['passed'] = True

    # Case C8152 - 005 - Teacher | Periods tabs are shown
    @pytest.mark.skipif(str(8152) not in TESTS, reason='Excluded')
    def test_teacher_period_tabs_are_shown_8152(self):
        """Period tabs are shown.

        Steps:
        On the calendar dashboard, click on the "Performance Forecast" button
        on the upper right corner of the calendar OR
        click on the user drop down menu
        click on the "Performance Forecast" button

        Expected Result:
        The period tabs are shown to the user
        (below the "Performance Forecast" header)
        """
        self.ps.test_updates['name'] = 't1.22.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.22',
            't1.22.005',
            '8152'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions

        assert('guide' in self.teacher.current_url()), \
            'Not viewing performance forecast'
        self.teacher.find(By.CLASS_NAME, 'active')

        self.ps.test_updates['passed'] = True

    # Case C8153 - 006 - Teacher | A period with zero answers does not
    # show section breakdowns
    @pytest.mark.skipif(str(8153) not in TESTS, reason='Excluded')
    def test_teacher_a_period_w_zero_answers_does_not_show_breaks_8153(self):
        """A period with zero answers does not show section breakdowns.

        Steps:
        On the calendar dashboard, click on the "Performance Forecast"
            button on the upper right corner of the calendar OR
        Click on the user drop down menu
        Click on the "Performance Forecast" button
        Click on the period with zero answers

        Expected Result:
        The user should see no section breakdowns as well as the words
        "There have been no questions worked for this period."
        """
        self.ps.test_updates['name'] = 't1.22.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.22',
            't1.22.006',
            '8153'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        # Create an empty period to use for the test
        period_name = "22_" + str(randint(100, 999))
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, 'Course Settings and Roster').click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, "//div[@class='control add-period']/button").click()
        self.teacher.find(
            By.XPATH,
            "//input[@class='form-control empty']").send_keys(period_name)
        self.teacher.find(
            By.XPATH,
            "//button[contains(@class,'-edit-period-confirm')]"
        ).click()
        popup = self.teacher.find(
            By.XPATH,
            '//div[@class="teacher-edit-period-modal fade in modal"]')
        self.teacher.wait.until(
            expect.staleness_of(
                (popup)
            )
        )
        # Check the new empty period in Performance Forecast
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, 'Performance Forecast').click()
        assert('guide' in self.teacher.current_url()), \
            'Not viewing performance forecast'
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.LINK_TEXT, period_name)
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.CLASS_NAME, 'no-data-message')
            )
        )
        # Archive the new period as clean up
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Course Settings and Roster'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located((
                By.LINK_TEXT, period_name)
            )
        ).click()
        self.teacher.find(
            By.XPATH, "//a[@class='control archive-period']").click()
        self.teacher.find(
            By.XPATH,
            "//button[@class='async-button archive-section btn btn-default']"
        ).click()

        self.ps.test_updates['passed'] = True

    # Case C8154 - 007 - Teacher | Weaker areas shows up to
    # four problematic sections
    @pytest.mark.skipif(str(8154) not in TESTS, reason='Excluded')
    def test_teacher_weaker_shows_up_to_four_problematic_sections_8154(self):
        """Weaker areas shows up to four problematic sections.

        Steps:
        On the calendar dashboard, click on the "Performance Forecast"
        button on the upper right corner of the calendar OR
        click on the user drop down menu
        click on the "Performance Forecast" button
        Click on the desired period

        Expected Result:
        Weaker Areas show up to four problematic sections
        """
        self.ps.test_updates['name'] = 't1.22.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.22',
            't1.22.007',
            '8154'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertion
        assert('guide' in self.teacher.current_url()), \
            'Not viewing performance forecast'
        weak = self.teacher.find_all(
            By.XPATH,
            "//div[@class='chapter-panel weaker']/div[@class='sections']/div")
        assert(len(weak) <= 4), \
            'Not viewing performance forecast'

        self.ps.test_updates['passed'] = True

    # Case C8155 - 008 - Teacher | Chapters are listed on the left with
    # their sections to the right
    @pytest.mark.skipif(str(8155) not in TESTS, reason='Excluded')
    def test_teacher_chapters_listed_on_left_w_sections_on_right_8155(self):
        """Chapter are listed on the left with their sections to the right.

        Steps:
        On the calendar dashboard, click on the "Performance Forecast"
            button on the upper right corner of the calendar
            OR
        Click on the user drop down menu
        Click on the "Performance Forecast" button
        Click on the desired period
        Scroll to the "Individual Chapters" section

        Expected Result:
        Chapters are listed on the left with their sections to the right
        """
        self.ps.test_updates['name'] = 't1.22.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.22',
            't1.22.008',
            '8155'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assert('guide' in self.teacher.current_url()), \
            'Not viewing performance forecast'
        self.teacher.page.wait_for_page_load()
        panels = self.teacher.find_all(By.CLASS_NAME, 'chapter-panel')
        for panel in panels:
            panel.find_elements_by_class_name('chapter')
            panel.find_elements_by_class_name('sections')

        self.ps.test_updates['passed'] = True
Ejemplo n.º 31
0
class TestImprovePracticeAndForecast(unittest.TestCase):
    """T2.14 - Improve Practice and Forecast."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(
                job_id=str(self.teacher.driver.session_id),
                **self.ps.test_updates
            )
        try:
            self.teacher.delete()
        except:
            pass

    '''
    # 14747 - 001 - Teacher | View how much students have practiced
    @pytest.mark.skipif(str(14747) not in TESTS, reason='Excluded')
    def test_teacher_view_how_much_students_have_practiced_14747(self):
        """View how much students have practiced.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.14.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.14',
            't2.14.001',
            '14747'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    '''

    # 14748 - 002 - Student | View changes in Performance Forecast at the end
    # of a retrieval practice in readings, hw, and previous practice
    @pytest.mark.skipif(str(14748) not in TESTS, reason='Excluded')
    def test_student_view_changes_in_performance_forecast_at_the_14748(self):
        """View changes in Performance Forecast at end of retrieval practice.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.14.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.14',
            't2.14.002',
            '14748'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    '''
class TestAnalyzeCollegeWorkflow(unittest.TestCase):
    """T2.05 - Analyze College Workflow."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(use_env_vars=True,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
            self.student = Student(use_env_vars=True,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities,
                                   existing_driver=self.teacher.driver)
        else:
            self.teacher = Teacher(use_env_vars=True)
            self.student = Student(use_env_vars=True,
                                   existing_driver=self.teacher.driver)

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        self.student = None
        try:
            self.teacher.delete()
        except:
            pass

    @pytest.mark.skipif(str(1) not in TESTS, reason='Excluded')
    def test_create_assignment_links_teacher(self):
        """
        Go to https://tutor-qa.openstax.org/
        Click on the 'Login' button
        Login to student account
        Click 'Next'
        Enter the teacher password [ password ] in the password text box
        Click on the 'Login' button
        If the user has more than one course, click on a Tutor course name
        Click on a published reading assignment on the calendar dashboard
        Click "Get Assignment Link"
        ***User is presented with links to assigned readings (t2.05.04)***

        Click on 'X' to get out of pop-up menu
        Click on a published homework assignment on the calendar dashboard
        ***Click "Get Assignment Link"
        User is presented with links to assigned homework (t2.05.05)***

        Expected Results:


        Corresponds to...
        t2.05.04 --> 05
        :return:
        """
        # t2.05.04 --> ser is presented with links to assigned readings (t2.05.04)
        self.teacher.login()

        self.teacher.select_course(appearance='biology')
        assignment_name = 'reading004_%d' % (randint(100, 999))
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=1)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=4)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(assignment='reading',
                                    args={
                                        'title': assignment_name,
                                        'description': 'description',
                                        'periods': {
                                            'all': (begin, end)
                                        },
                                        'reading_list': ['1.1'],
                                        'status': 'publish'
                                    })
        try:
            self.teacher.wait.until(
                expect.presence_of_element_located(
                    (By.XPATH, '//div[@class="month-wrapper"]')))
            self.teacher.find(
                By.XPATH, "//div/label[contains(text(), '" + assignment_name +
                "')]").click()
        except NoSuchElementException:
            self.teacher.find(
                By.XPATH,
                "//a[contains(@class, 'header-control next')]").click()
            self.teacher.wait.until(
                expect.presence_of_element_located(
                    (By.XPATH, '//div[@class="month-wrapper"]')))
            self.teacher.find(
                By.XPATH, "//div/label[contains(text(), '" + assignment_name +
                "')]").click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//a[@class="get-link"]'))).click()
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, '//div[@class="popover-content"]' +
                 '//input[contains(@value,"https://tutor")]')))

        # t2.05.05 --> Clicking "Get Assignment Link presents
        # user with links to assigned homework (t2.05.05)***

        ### FIND A WAY TO GET BACK TO MY CURRENT COURSES PAGE (maybe use teacher goto... method)

        self.teacher.select_course(appearance='biology')
        assignment_name = 'hw005_%d' % (randint(100, 999))
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=1)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=4)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(assignment='homework',
                                    args={
                                        'title': assignment_name,
                                        'description': 'description',
                                        'periods': {
                                            'all': (begin, end)
                                        },
                                        'problems': {
                                            '1.1': (2, 3),
                                        },
                                        'status': 'publish',
                                        'feedback': 'immediate'
                                    })
        try:
            self.teacher.wait.until(
                expect.presence_of_element_located(
                    (By.XPATH, '//div[@class="month-wrapper"]')))
            self.teacher.sleep(1)
            self.teacher.find(
                By.XPATH, "//div/label[contains(text(), '" + assignment_name +
                "')]").click()
        except NoSuchElementException:
            self.teacher.find(
                By.XPATH,
                "//a[contains(@class, 'header-control next')]").click()
            self.teacher.wait.until(
                expect.presence_of_element_located(
                    (By.XPATH, '//div[@class="month-wrapper"]')))
            self.teacher.find(
                By.XPATH, "//div/label[contains(text(), '" + assignment_name +
                "')]").click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//a[@class="get-link"]'))).click()
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, '//div[@class="popover-content"]' +
                 '//input[contains(@value,"https://tutor")]')))
class TestTeacherViews(unittest.TestCase):
    """CC1.13 - Teacher Views."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.teacher.login()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7609 - 001 - Teacher | View the Concept Coach dashboard
    @pytest.mark.skipif(str(7609) not in TESTS, reason='Excluded')
    def test_teacher_view_the_concept_coach_dashboard_7609(self):
        """View the Concept Coach dashboard.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name

        Expected Result:
        The user is presented with the Concept Coach dashbaord
        """
        self.ps.test_updates['name'] = 'cc1.13.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.001', '7609']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assert('cc-dashboard' in self.teacher.current_url()), \
            'not at Concept Coach Dashboard'

        self.ps.test_updates['passed'] = True

    # Case C7610 - 002 - Teacher | Switch between concurrently running courses
    @pytest.mark.skipif(str(7610) not in TESTS, reason='Excluded')
    def test_teacher_switch_between_concurrently_running_courses_7610(self):
        """Able to switch between concurrently running courses.

        Steps:
        Click on the OpenStax logo in the left corner of the header

        Expected Result:
        The user is presented with a list of Concept Coach courses
        Is able to switch to another course
        """
        self.ps.test_updates['name'] = 'cc1.13.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.002', '7610']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        url1 = self.teacher.current_url().split('courses')[1]
        self.teacher.driver.find_element(
            By.XPATH, '//a//i[@class="ui-brand-logo"]'
        ).click()
        try:
            self.teacher.driver.find_element(
                By.XPATH,
                '//a[contains(@href,"/cc-dashboard") ' +
                'and not(contains(@href,"'+str(url1)+'"))]'
            ).click()
        except NoSuchElementException:
            print('Only one CC course, cannot go to another')
            raise Exception
        assert('cc-dashboard' in self.teacher.current_url()), \
            'not at Concept Coach Dashboard'
        assert(url1 != self.teacher.current_url()), \
            'went to same course'

        self.ps.test_updates['passed'] = True

    # Case C7611 - 003 - Teacher | View links on dashboard to course materials
    @pytest.mark.skipif(str(7611) not in TESTS, reason='Excluded')
    def test_teacher_view_links_on_dashboard_to_course_materials_7611(self):
        """View links on dashboard to course materials.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name

        Expected Result:
        On header there is a link to 'Homework PDF', and 'Online Book'
        """
        self.ps.test_updates['name'] = 'cc1.13.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.003', '7611']
        self.ps.test_updates['passed'] = False

        # HW pdf
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Homework PDF")]'
        ).click()
        coursename = self.teacher.driver.find_element(
            By.XPATH, '//div[@class="cc-dashboard"]/div'
        ).get_attribute('data-appearance')
        coursename = coursename.replace('_', '-')
        home = os.getenv("HOME")
        files = os.listdir(home + '/Downloads')
        for i in range(len(files)):
            if (coursename in files[i]) and (files[i][-4:] == '.pdf'):
                break
            else:
                if i == len(files)-1:
                    raise Exception
        # online book
        self.teacher.driver.find_element(
            By.XPATH, '//a//span[contains(text(),"Online Book")]'
        ).click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        assert('cnx' in self.teacher.current_url()), \
            'Not viewing the textbook PDF'
        self.teacher.driver.switch_to_window(
            self.teacher.driver.window_handles[0])
        # assignment links
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Assignment Links")]'
        ).click()
        assert('assignment-links' in self.teacher.current_url()), \
            'not viewing Assignment Links'

        self.ps.test_updates['passed'] = True

    # Case C7612 - 004 - Teacher | Able to copy a system-generated message
    # with a student code, links, and other information
    @pytest.mark.skipif(str(7612) not in TESTS, reason='Excluded')
    def test_able_to_copy_a_system_generated_message_with_a_student_7612(self):
        """Copy a system-generated message with a student code, links, etc.

        Steps:
        Click on the user menu in the right corner of the header
        Click "Course Roster"
        Click "Get Student Enrollment Code"
        Copy the system generated message

        Expected Result:
        The user is able to copy the system generated message
        """
        self.ps.test_updates['name'] = 'cc1.13.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.004', '7612']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Course Settings and Roster")]'
        ).click()
        self.teacher.driver.find_element(
            By.XPATH, '//span[contains(text(),"student enrollment code")]'
        ).click()
        self.teacher.driver.find_element(
            By.XPATH,
            '//*[contains(text(),"Send the following enrollment instruction")]'
        )

        element = self.teacher.driver.find_element(
            By.XPATH,
            '//div[contains(@class,"enrollment-code-modal")]'
        )
        element.find_element(
            By.XPATH,
            './/*[contains(text(),"To register for Concept Coach:")]'
        )

        self.ps.test_updates['passed'] = True

    # Case C7613 - 005 - Teacher | Periods are relabeled as sections for all
    # courses
    @pytest.mark.skipif(str(7613) not in TESTS, reason='Excluded')
    def test_teacher_periods_are_relabeled_as_sections_for_all_cour_7613(self):
        """Period is relabeled as section for college courses.

        Steps:
        Go to user menu
        Click on course roster
        Check that there is an '+ add section' button instead
            of an '+ add period' button

        Expected Result:
        There is an '+ add section' button instead of an '+ add period' button
        """
        self.ps.test_updates['name'] = 'cc1.13.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.005', '7613']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Course Settings and Roster")]'
        ).click()
        self.teacher.driver.find_element(
            By.XPATH,
            '//li[contains(@class,"add-period")]//span[text()="Section"]'
        )

        self.ps.test_updates['passed'] = True

    # Case C7614 - 006 - Teacher | View a score report
    @pytest.mark.skipif(str(7614) not in TESTS, reason='Excluded')
    def test_teacher_view_a_score_report_7614(self):
        """View a score report.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"

        Expected Result:
        The user is presented with a score report
        """
        self.ps.test_updates['name'] = 'cc1.13.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.006', '7614']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7615 - 007 - Teacher | View a report showing an individual
    # student's work pages
    @pytest.mark.skipif(str(7615) not in TESTS, reason='Excluded')
    def test_teacher_view_a_report_showing_an_individual_students_7615(self):
        """View a report showing an individual student's work pages.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Click on the percentage in the "Score" column

        Expected Result:
        Individual student's work is shown
        """
        self.ps.test_updates['name'] = 'cc1.13.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.007', '7614']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[contains(@class,"scores-cell")]' +
            '/div[@class="score"]'
        ).click()
        assert('steps' in self.teacher.current_url()), \
            "Not taken to individual student's work for assignment"

        self.ps.test_updates['passed'] = True

    # Case C7616 - 008 - Teacher | View a summary report showing a class's work
    # pages
    @pytest.mark.skipif(str(7616) not in TESTS, reason='Excluded')
    def test_teacher_view_a_summary_report_showing_a_class_work_pag_7616(self):
        """View a summary report showing a class's work pages.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Click on the desired period tab

        Expected Result:
        The user is presented with a summary report
        """
        self.ps.test_updates['name'] = 'cc1.13.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.008', '7616']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        periods = self.teacher.driver.find_elements(
            By.XPATH, '//span[contains(@class,"tab-item-period-name")]'
        )
        for period in periods:
            period.click()

        self.ps.test_updates['passed'] = True

    # Case C7617 - 009 - Teacher | View the aggregate student scores
    @pytest.mark.skipif(str(7617) not in TESTS, reason='Excluded')
    def test_teacher_view_the_aggregate_student_scores_7617(self):
        """View the aggregate student scores.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"

        Expected Result:
        The user is presented with Student scores
        """
        self.ps.test_updates['name'] = 'cc1.13.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.009', '7617']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH, '//div[contains(@class,"course-scores-container")]')

        self.ps.test_updates['passed'] = True

    # Case C7618 - 010 - Teacher | View scores for an individual student's
    # scores
    @pytest.mark.skipif(str(7618) not in TESTS, reason='Excluded')
    def test_teacher_view_scores_for_an_individual_student_scores_7618(self):
        """View scores for an individual student's scores.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Scroll to the desired student

        Expected Result:
        The user is presented with scores for an individual student
        """
        self.ps.test_updates['name'] = 'cc1.13.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.010', '7618']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[contains(@class,"name-cell")]'
        )

        self.ps.test_updates['passed'] = True

    # Case C7619 - 011 - Teacher | View an individual student's question set
    # for an assignment
    @pytest.mark.skipif(str(7619) not in TESTS, reason='Excluded')
    def test_teacher_view_an_individual_student_question_set_7619(self):
        """View an individual student's question set for an assignment.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Click on a student's score for the desired assignment

        Expected Result:
        The user is presented with a student's question set for the assignment
        """
        self.ps.test_updates['name'] = 'cc1.13.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.011', '7619']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[contains(@class,"scores-cell")]' +
            '/div[@class="score"]'
        ).click()
        breadcrumbs = self.teacher.driver.find_elements(
            By.XPATH, '//span[contains(@class,"openstax-breadcrumbs-")]'
        )
        for i in range(len(breadcrumbs)-1):
            self.teacher.driver.find_element(
                By.XPATH,
                '//span[contains(@class,"openstax-breadcrumbs-")' +
                'and contains(@data-reactid,"step-' + str(i) + '")]'
            ).click()

        self.ps.test_updates['passed'] = True

    # Case C7620 - 012 - Teacher | View an assignment summary
    @pytest.mark.skipif(str(7620) not in TESTS, reason='Excluded')
    def test_teacher_view_an_assignment_summary_7620(self):
        """View an assignment summary.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Click on a student's score for the desired assignment
        Click "Summary"

        Expected Result:
        The user is presented with an assignmnent summary
        """
        self.ps.test_updates['name'] = 'cc1.13.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.012', '7620']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[contains(@class,"scores-cell")]' +
            '/div[@class="score"]'
        ).click()
        self.teacher.driver.find_element(
            By.XPATH,
            '//span[contains(@class,"openstax-breadcrumbs-")' +
            'and contains(@data-reactid,"-end-")]'
        ).click()
        self.teacher.sleep(0.5)
        breadcrumbs_answered = self.teacher.driver.find_elements(
            By.XPATH,
            '//span[contains(@class,"openstax-breadcrumbs-")' +
            'and contains(@class,"completed")]'
        )
        question_cards = self.teacher.driver.find_elements(
            By.XPATH, '//div[contains(@class,"openstax-exercise-card")]'
        )
        assert(len(question_cards) == len(breadcrumbs_answered)), \
            'all answered questions not in summary'

        self.ps.test_updates['passed'] = True

    # Case C7622 - 013 - Teacher | Download student scores
    @pytest.mark.skipif(str(7622) not in TESTS, reason='Excluded')
    def test_teacher_download_student_scores_7622(self):
        """Download student scores.

        Steps:
        Click the user menu in the right corner of the header
        Click "Student Scores"
        Click "Export"

        Expected Result:
        Student scores are downloaded in an excel spreadsheet
        """
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH, '//div[contains(@class,"export-button")]//button'
        ).click()
        # wait for it to export. It says generating when still not done
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@class,"export-button")]//button' +
                 '//span[text()="Export"]')
            )
        )
        # check that it was downloaded
        coursename = self.teacher.driver.find_element(
            By.XPATH, '//div[@class="course-name"]').text
        coursename = coursename.replace(' ', '_') + "_Scores"
        home = os.getenv("HOME")
        files = os.listdir(home + '/Downloads')
        for i in range(len(files)):
            if (coursename in files[i]) and (files[i][-5:] == '.xlsx'):
                break
            else:
                if i == len(files)-1:
                    raise Exception

        self.ps.test_updates['passed'] = True

    # Case C7624 - 014 - Teacher | Exercise IDs are shown for each assessment
    @pytest.mark.skipif(str(7624) not in TESTS, reason='Excluded')
    def test_teacher_exercise_ids_are_shown_for_each_assessment_7624(self):
        """Exercise IDs are shown for each assessment.

        Steps:
        Click the user menu in the right corner of the header
        Click "Question Library"
        Select a chapter
        Click "Show Questions"

        Expected Result:
        Exercise IDs are shown for each assessment in the bottom right hand
        corner of the box holding the question.
        """
        self.ps.test_updates['name'] = 'cc1.13.014' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.13', 'cc1.13.014', '7624']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.XPATH, '//a[contains(text(),"Student Scores")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Student Scores"]')
            )
        )
        self.teacher.driver.find_element(
            By.XPATH,
            '//div[contains(@class,"scores-cell")]' +
            '/div[@class="score"]'
        ).click()
        breadcrumbs = self.teacher.driver.find_elements(
            By.XPATH, '//span[contains(@class,"openstax-breadcrumbs-")]'
        )
        for i in range(len(breadcrumbs)-1):
            self.teacher.driver.find_element(
                By.XPATH,
                '//span[contains(@class,"exercise-identifier-link")]' +
                '//span[contains(text(),"ID")]'
            )
            self.teacher.driver.find_element(
                By.XPATH,
                '//span[contains(@class,"openstax-breadcrumbs-")' +
                'and contains(@data-reactid,"step-' + str(i) + '")]'
            ).click()

        self.ps.test_updates['passed'] = True
class TestViewTheCalendarDashboard(unittest.TestCase):
    """T1.13 - View the calendar."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.teacher.login()
        self.teacher.select_course(title='HS Physics')

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7978 - 001 - Teacher | View the calendar dashboard
    @pytest.mark.skipif(str(7978) not in TESTS, reason='Excluded')
    def test_teacher_view_the_calendar_dashboard_7978(self):
        """View the calendar dashboard.

        Steps:
        If the user has more than one course, click on a Tutor course name

        Expected Result:
        The teacher is presented their calendar dashboard.
        """
        self.ps.test_updates['name'] = 't1.13.001' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.001', '7978']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        assert('calendar' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.ps.test_updates['passed'] = True

    # Case C7979 - 002 - Teacher | View student scores using dashboard button
    @pytest.mark.skipif(str(7979) not in TESTS, reason='Excluded')
    def test_teacher_view_student_scores_using_the_dashboard_button_7979(self):
        """View student scores using the dashboard button.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the 'Student Scores' button

        Expected Result:
        The teacher is presented with the student scores
        """
        self.ps.test_updates['name'] = 't1.13.002' + \
            inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.002', '7979']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        self.teacher.find(By.LINK_TEXT, 'Student Scores').click()
        assert('scores' in self.teacher.current_url()), \
            'Not viewing student scores'

        self.ps.test_updates['passed'] = True

    # Case C7980 - 003 - Teacher | View student scores using the user menu link
    @pytest.mark.skipif(str(7980) not in TESTS, reason='Excluded')
    def test_teacher_view_student_scores_using_the_user_menu_link_7980(self):
        """View student scores using the user menu link.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the user menu
        Click on the 'Student Scores' link

        Expected Result:
        The teacher is presented with the student scores
        """
        self.ps.test_updates['name'] = 't1.13.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.003', '7980']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        self.teacher.open_user_menu()
        self.teacher.find(By.CLASS_NAME, 'viewScores'). \
            find_element_by_tag_name('a'). \
            click()
        assert('scores' in self.teacher.current_url()), \
            'Not viewing the student scores'

        self.ps.test_updates['passed'] = True

    # Case C7981 - 004 - Teacher | View performance forecast using the
    # dashboard button
    @pytest.mark.skipif(str(7981) not in TESTS, reason='Excluded')
    def test_teacher_view_performance_forecast_using_dash_button_7981(self):
        """View performance forecast using the dashboard button.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the 'Performance Forecast' button on the dashboard

        Expected Result:
        The teacher is presented with the performance forecast
        """
        self.ps.test_updates['name'] = 't1.13.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.004', '7981']
        self.ps.test_updates['passed'] = False

        self.teacher.find(By.LINK_TEXT, 'Performance Forecast').click()
        self.teacher.page.wait_for_page_load()
        assert('guide' in self.teacher.current_url()), \
            'Not viewing the performance forecast'

        self.ps.test_updates['passed'] = True

    # Case C7982 - 005 - Teacher | View performace forecast using
    # the user menu link
    @pytest.mark.skipif(str(7982) not in TESTS, reason='Excluded')
    def test_teacher_view_performance_forecast_using_user_menu_link_7982(self):
        """View performance forecast using the user menu link.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the user menu
        Click on the 'Performance Forecast' link

        Expected Result:
        The teacher is presented with the performance forecast
        """
        self.ps.test_updates['name'] = 't1.13.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.005', '7982']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        self.teacher.open_user_menu()
        self.teacher.find(By.CLASS_NAME, 'viewTeacherPerformanceForecast'). \
            find_element_by_tag_name('a'). \
            click()
        self.teacher.page.wait_for_page_load()
        assert('guide' in self.teacher.current_url()), \
            'Not viewing the performance forecast'

        self.ps.test_updates['passed'] = True

    # Case C7983 - 006 - Teacher | View a reading assignment summary
    @pytest.mark.skipif(str(7983) not in TESTS, reason='Excluded')
    def test_teacher_view_a_reading_assignment_summary_7983(self):
        """View a reading assignment summary.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Create a reading assignment
        Click on the reading assignment on the calendar

        Expected Result:
        The teacher is presented with the reading assignment summary
        """
        self.ps.test_updates['name'] = 't1.13.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.006', '7983']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(appearance='physics')
        # create an assignment
        assignment_name = 'reading-%s' % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=2)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=5)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(
            assignment='reading',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'reading_list': ['1.1'],
                'status': 'publish',
            }
        )
        # click on assignment
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, '//label[contains(text(), "%s")]' % assignment_name)
            )
        ).click()
        # check that it opened
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH,
                 '//*[@class="modal-title" and ' +
                 'contains(text(), "%s")]' % assignment_name)
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7984 - 007 - Teacher | View a homework assignment summary
    @pytest.mark.skipif(str(7984) not in TESTS, reason='Excluded')
    def test_teacher_view_a_homework_assignment_summary_7984(self):
        """View a homework assignment summary.

        Steps:
        create a homework assignment
        If the user has more than one course, click on a Tutor course name
        Click on a homework assignment on the calendar

        Expected Result:
        The teacher is presented with the homework assignment summary
        """
        self.ps.test_updates['name'] = 't1.13.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.007', '7984']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(appearance='physics')
        # create an assignment
        assignment_name = "homework-%s" % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=2)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=5)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(
            assignment='homework',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'problems': {'1.1': (2, 3), },
                'status': 'publish',
                'feedback': 'immediate'
            }
        )
        # click on assignment
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, '//label[contains(text(), "%s")]' % assignment_name)
            )
        ).click()
        # check that it opened
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH,
                 '//*[@class="modal-title" and ' +
                 'contains(text(), "%s")]' % assignment_name)
            )
        )
        self.ps.test_updates['passed'] = True

    # NOT DONE
    # Case C7985 - 008 - Teacher | View an external assignment summary
    @pytest.mark.skipif(str(7985) not in TESTS, reason='Excluded')
    def test_teacher_view_an_external_assignment_summary_7985(self):
        """View an external assignment summary.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on an external assignment on the calendar

        Expected Result:
        The teacher is presented with the external assignment summary
        """
        self.ps.test_updates['name'] = 't1.13.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.008', '7985']
        self.ps.test_updates['passed'] = False

        # create an assignment
        assignment_name = 'external-%s' % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=0)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=5)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(
            assignment='external',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'url': 'google.com',
                'status': 'publish'
            }
        )
        # click on assignment
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, '//label[contains(text(), "%s")]' % assignment_name)
            )
        ).click()
        # check that it opened
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH,
                 '//*[@class="modal-title" and ' +
                 'contains(text(), "%s")]' % assignment_name)
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7986 - 009 - Teacher | View an event summary
    @pytest.mark.skipif(str(7986) not in TESTS, reason='Excluded')
    def test_teacher_view_an_event_summary_7986(self):
        """View an event summary.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on an event on the calendar

        Expected Result:
        The teacher is presented with the event summary
        """
        self.ps.test_updates['name'] = 't1.13.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.009', '7986']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(appearance='physics')
        # create an assignment
        assignment_name = "homework-%s" % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=2)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=5)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'publish'
            }
        )
        # click on assignment
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH, '//label[contains(text(), "%s")]' % assignment_name)
            )
        ).click()
        # check that it opened
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH,
                 '//*[@class="modal-title" and ' +
                 'contains(text(), "%s")]' % assignment_name)
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C7987 - 010 - Teacher | Open the refrenece book using the dashboard
    # button
    @pytest.mark.skipif(str(7987) not in TESTS, reason='Excluded')
    def test_teacher_open_the_reference_book_using_dashboard_button_7987(self):
        """Open the refrenece book using the dashboard button.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the 'Browse The Book'button

        Expected Result:
        The teacher is preseneted with the book in a new tab
        """
        self.ps.test_updates['name'] = 't1.13.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.010', '7987']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        self.teacher.driver.find_element(
            By.LINK_TEXT,
            'Browse The Book'
        ).click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        assert('book' in self.teacher.current_url()), \
            'Not viewing the textbook PDF'

        self.ps.test_updates['passed'] = True

    # Case C7988 - 011 - Teacher | Open the refrenece book using user menu link
    @pytest.mark.skipif(str(7988) not in TESTS, reason='Excluded')
    def test_teacher_open_the_reference_book_using_user_menu_link_7988(self):
        """Open the refrenece book using the user menu link.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the user menu
        Click on the 'Browse the Book' link

        Expected Result:
        The teacher is presented with the book in a new tab
        """
        self.ps.test_updates['name'] = 't1.13.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.011', '7988']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(title='HS Physics')
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.LINK_TEXT,
            'Browse the Book'
        ).click()
        window_with_book = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_book)
        assert('book' in self.teacher.current_url()), \
            'Not viewing the textbook PDF'

        self.ps.test_updates['passed'] = True

    # Case C7989 - 012 - Teacher | Click on the course name to return to
    # the dashboard
    @pytest.mark.skipif(str(7989) not in TESTS, reason='Excluded')
    def test_teacher_click_course_name_to_return_to_the_dashboard_7989(self):
        """Click on the course name to return to the dashboard.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click on the 'Performance Forecast' button
        Click on the course name in the header

        Expected Result:
        The teacher is presented with their calendar dashboard
        """
        self.ps.test_updates['name'] = 't1.13.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.012', '7989']
        self.ps.test_updates['passed'] = False

        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.CLASS_NAME,
            'viewTeacherPerformanceForecast'
        ).click()
        self.teacher.driver.find_element(
            By.CLASS_NAME,
            'course-name'
        ).click()
        assert('calendar' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.ps.test_updates['passed'] = True

    # Case C7990 - 013 - Teacher | Cick on the OpenStax logo to return to
    # the course picker
    @pytest.mark.skipif(str(7990) not in TESTS, reason='Excluded')
    def test_teacher_click_openstax_logo_to_return_to_course_picker_7990(self):
        """Cick on the OpenStax logo to return to the course picker.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click in the OpenStax logo in the header

        Expected Result:
        The teacher is presented with the course picker
        """
        self.ps.test_updates['name'] = 't1.13.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.013', '7990']
        self.ps.test_updates['passed'] = False

        # self.teacher.select_course(appearance='physics')
        self.teacher.driver.find_element(
            By.CLASS_NAME,
            'ui-brand-logo'
        ).click()
        assert('dashboard' in self.teacher.current_url()), \
            'Not viewing the course picker'

        self.ps.test_updates['passed'] = True

    # Case C7991 - 014 - Teacher | CLick in the OpenStax logo to return to the
    # dashboard
    @pytest.mark.skipif(str(7991) not in TESTS, reason='Excluded')
    def test_teacher_clicks_openstax_logo_to_return_to_dashboard_7991(self):
        """CLick in the OpenStax logo to return to the dashboard.

        Steps:
        Click on the 'Performance Forecast' button
        Click on the OpenStax logo in the header

        Expected Result:
        The teacher is presented with their calendar dashboard
        """
        self.ps.test_updates['name'] = 't1.13.014' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.13', 't1.13.014', '7991']
        self.ps.test_updates['passed'] = False

        self.teacher.logout()
        teacher2 = Teacher(
            username=os.getenv('TEACHER_USER_ONE_COURSE'),
            password=os.getenv('TEACHER_PASSWORD'),
            site='https://tutor-qa.openstax.org',
            existing_driver=self.teacher.driver,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities,
        )
        print(teacher2.username)
        print(teacher2.password)
        teacher2.login()
        self.teacher.open_user_menu()
        self.teacher.driver.find_element(
            By.CLASS_NAME,
            'viewTeacherPerformanceForecast'
        ).click()
        self.teacher.driver.find_element(
            By.CLASS_NAME,
            'ui-brand-logo'
        ).click()
        assert('calendar' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.ps.test_updates['passed'] = True
Ejemplo n.º 35
0
class TestIImproveQuestionManagement(unittest.TestCase):
    """CC2.11 - Improve Question Management."""
    def setUp(self):
        """Pretest settings."""

        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(use_env_vars=True,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
            self.student = Student(use_env_vars=True,
                                   existing_driver=self.teacher.driver,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
        else:
            self.teacher = Teacher(use_env_vars=True)
            self.student = Student(
                use_env_vars=True,
                existing_driver=self.teacher.driver,
            )

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        self.student = None
        try:
            self.teacher.delete()
        except:
            pass

    # 14851 - 001 - Teacher | Review all questions
    @pytest.mark.skipif(str(14851) not in TESTS, reason='Excluded')
    def test_teacher_review_all_questions_14851(self):
        """Review all questions.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click "Question Library" from the user menu
        Select a section or chapter
        Click "Show Questions"

        Expected Result:
        The user is presented with all the questions for the section or chapter
        """
        self.ps.test_updates['name'] = 'cc2.11.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.001', '14851']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(By.XPATH,
                          '//a[contains(@href,"/cc-dashboard")]').click()
        self.teacher.open_user_menu()
        self.teacher.find(By.LINK_TEXT, 'Question Library').click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.1"]').click()
        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.find(By.XPATH,
                          '//button[text()="Show Questions"]').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="exercises"]')))
        self.ps.test_updates['passed'] = True

    # 14852 - 002 - Teacher | Exclude certain questions
    @pytest.mark.skipif(str(14852) not in TESTS, reason='Excluded')
    def test_teacher_exclude_certain_questions_14852(self):
        """Exclude certain quesitons.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Question Library" from the user menu
        Select a section or chapter
        Click "Show Questions"
        Hover over the desired question and click "Exclude question"

        Expected Result:
        Question is grayed out
        """
        self.ps.test_updates['name'] = 'cc2.11.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.002', '14852']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(By.XPATH,
                          '//a[contains(@href,"/cc-dashboard")]').click()
        self.teacher.open_user_menu()
        self.teacher.find(By.LINK_TEXT, 'Question Library').click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.2"]').click()
        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.find(By.XPATH,
                          '//button[text()="Show Questions"]').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="exercises"]')))
        self.teacher.sleep(1)
        i = 1
        question = None
        # loop finding a question that is not yet excleded
        # there are 9 question in the exact textbook and chpater this test
        # is searching. limiting loop at 7 incase questions are removed.
        while i < 8:
            question = self.teacher.find(
                By.XPATH, '//div[@class="exercises"]/div[' + str(i) + ']')
            if ('is-selected' not in question.get_attribute('class')):
                break
            i += 1
        Assignment.scroll_to(self.teacher.driver, question)
        self.teacher.sleep(1)
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(question)
        # way to stall because not sure how to add wait in action chain
        for _ in range(50):
            actions.move_by_offset(-1, 0)
        actions.click()
        actions.move_by_offset(-50, -300)
        actions.perform()
        self.teacher.sleep(0.5)
        question_excluded = self.teacher.find(
            By.XPATH, '//div[@class="exercises"]/div[' + str(i) +
            ']').get_attribute('class')
        assert ('is-selected' in question_excluded), 'question not excluded'
        self.ps.test_updates['passed'] = True

    '''
    # 14855 - 003 - Teacher | Pin tabs on top of screen when scrolled
    @pytest.mark.skipif(str(14855) not in TESTS, reason='Excluded')
    def test_teacher_pin_tabs_on_top_of_screen_when_scrolled_14855(self):
        """Pin tabs on top of screen when scrolled.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Question Library" from the user menu
        Select a section or chapter
        Click "Show Questions"
        Scroll down

        Expected Result:
        Tabs are pinned to top of the screen when scrolled
        """
        self.ps.test_updates['name'] = 'cc2.11.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.003', '14855']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Question Library'
        ).click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.2"]'
        ).click()
        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.find(
            By.XPATH, '//button[text()="Show Questions"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="exercises"]')
            )
        )
        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="pinned-header"]')
            )
        )
        self.ps.test_updates['passed'] = True
    '''

    # 14856 - 004 - Teacher | Make section links jumpable
    @pytest.mark.skipif(str(14856) not in TESTS, reason='Excluded')
    def test_teacher_make_section_links_jumpable_14856(self):
        """Make section links jumpable.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Question Library" from the user menu
        Select a section or chapter
        Click "Show Questions"
        Click on the section links at the top of the screen

        Expected Result:
        The screen scrolls to the selected questions
        """
        self.ps.test_updates['name'] = 'cc2.11.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.004', '14856']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(By.XPATH,
                          '//a[contains(@href,"/cc-dashboard")]').click()
        self.teacher.open_user_menu()
        self.teacher.find(By.LINK_TEXT, 'Question Library').click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.2"]').click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.1"]').click()

        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.find(By.XPATH,
                          '//button[text()="Show Questions"]').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="exercises"]')))
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="pinned-header"]'
                 '//div[@class="section" and text()="1.2"]'))).click()
        self.teacher.sleep(1)
        # click the heading as simple way to find that it is on screen
        # and not just visible but scrolled off screen
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="exercise-sections"]' +
                 '//span[@class="chapter-section" ' +
                 'and @data-chapter-section="1.2"]'))).click()
        self.ps.test_updates['passed'] = True

    # 14858 - 005 - Teacher | Report errata about assessments in Concept Coach
    @pytest.mark.skipif(str(14858) not in TESTS, reason='Excluded')
    def test_teacher_report_errata_about_assessments_in_cc_14858(self):
        """Report errata about assessments in Concept Coach.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Question Library" from the user menu
        Select a section or chapter
        Click "Show Questions"
        Hover over the desired question and click "Question details"
        Click "Report an error"

        Expected Result:
        A new tab with the assessment errata form appears, with the assessment
        ID already filled in
        """
        self.ps.test_updates['name'] = 'cc2.11.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.005', '14858']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(By.XPATH,
                          '//a[contains(@href,"/cc-dashboard")]').click()
        self.teacher.open_user_menu()
        self.teacher.find(By.LINK_TEXT, 'Question Library').click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.2"]').click()
        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.find(By.XPATH,
                          '//button[text()="Show Questions"]').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="exercises"]')))
        self.teacher.sleep(1)
        question = self.teacher.find(By.XPATH,
                                     '//div[@class="exercises"]/div[1]')
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(question)
        # way to stall because not sure how to add wait in action chain
        for _ in range(50):
            actions.move_by_offset(1, 0)
        actions.click()
        actions.perform()
        self.teacher.sleep(0.5)
        exercise_id = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//span[@class="exercise-tag" and contains(text(),"ID:")]'
                 ))).text
        question = self.teacher.find(
            By.XPATH, '//div[@class="action report-error"]').click()
        window_with_form = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_form)
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[text()="Report Content Errors"]')))
        self.teacher.find(By.XPATH,
                          '//input[@value="' + exercise_id[4:] + '"]')

        self.ps.test_updates['passed'] = True

    # 14859 - 006 - Student | Report errata about assessments in Concept Coach
    @pytest.mark.skipif(str(14859) not in TESTS, reason='Excluded')
    def test_student_report_errata_about_assessments_in_cc_14859(self):
        """Report errata about assessments in Concept Coach.

        Steps:
        Click on a CC course, if there are more than one
        Click on a non-introductory section
        Click "Jump to Concept Coach"
        Click "Launch Concept Coach"
        Click "Report an error" on an assessment

        Expected Result:
        A new tab with the assessment errata form appears, with the assessment
        ID already filled in
        """
        self.ps.test_updates['name'] = 'cc2.11.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.006', '14859']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.login()
        self.teacher.find(By.XPATH,
                          '//a[contains(@href,"cnx.org/contents/")]').click()
        # get to non-into section
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button//span[text()="Contents"]'))).click()
        self.student.sleep(0.5)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH,
                 '//span[@class="chapter-number" and text()="1.1"]'))).click()
        # open concept coach
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach'))).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]'))).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//span[contains(@class,"core breadcrumb-exercise")]'
                 ))).click()
        exercise_id = self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[@class="exercise-identifier-link"]' +
                 '/span[contains(text(),"@")]'))).text
        self.teacher.find(By.LINK_TEXT, 'Report an error').click()
        window_with_form = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_form)
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[text()="Report Content Errors"]')))
        self.teacher.find(By.XPATH, '//input[@value="' + exercise_id + '"]')
        self.ps.test_updates['passed'] = True

    # 100129 - 007 - Admin | View list of excluded assesments
    @pytest.mark.skipif(str(100129) not in TESTS, reason='Excluded')
    def test_admin_view_list_of_excluded_assesments_100129(self):
        """View list of excluded assesments.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc2.11.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc2', 'cc2.11', 'cc2.11.007', '100129'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 100130 - 008 - Admin | Export the list of excluded assesments to CSV
    @pytest.mark.skipif(str(100130) not in TESTS, reason='Excluded')
    def test_admin_export_the_list_of_excluded_assesments_to_csv_100130(self):
        """Export the list of excluded assesments to CSV.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc2.11.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            'cc2', 'cc2.11', 'cc2.11.008', '100130'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
class TestCreateAReading(unittest.TestCase):
    """T1.14 - Create a Reading."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(
                use_env_vars=True,
                pasta_user=self.ps,
                capabilities=self.desired_capabilities
            )
        else:
            self.teacher = Teacher(
                use_env_vars=True
            )
        self.teacher.login()
        self.teacher.select_course(appearance='college_physics')

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(
                job_id=str(self.teacher.driver.session_id),
                **self.ps.test_updates
            )
        try:
            self.teacher.delete()
        except:
            pass

    # Case C162172 001 Teacher | Add a new open event for all periods
    @pytest.mark.skipif(str(162172) not in TESTS, reason="Excluded")
    def test_teacher_add_a_new_open_event_all_periods_162172(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162172']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name = 'event_001_%d' % (randint(100, 999))
        assignment = Assignment()

        # Open Add Reading page
        self.teacher.assign.open_assignment_menu(self.teacher.driver)
        self.teacher.find(By.LINK_TEXT, 'Add Event').click()
        assert ('event/new' in self.teacher.current_url()), \
            'not at add event screen'

        # Find and fill in title
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'reading-title')
            )
        ).send_keys(assignment_name)

        # Fill in description
        self.teacher.find(
            By.XPATH, '//textarea[contains(@class, "form-control")]'
        ).send_keys('description')

        # Set date
        today = datetime.date.today()
        end = randint(1, 5)
        opens_on = today.strftime(
            '%m/%d/%Y')  # make the start date today so it will be open
        closes_on = (today + datetime.timedelta(days=end)) \
            .strftime('%m/%d/%Y')
        assignment.assign_periods(
            self.teacher.driver, {'all': (opens_on, closes_on)})

        # publish
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//button[contains(@class,"-publish")]')
            )
        ).click()
        try:
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(assignment_name)
            )
        except NoSuchElementException:
            self.teacher.find(
                By.XPATH,
                '//a[contains(@class,"header-control next")]'
            ).click()
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(assignment_name)
            )

        self.ps.test_updates['passed'] = True


    # Case C162173 002 Teacher | Save a draft for individual periods
    @pytest.mark.skipif(str(162173) not in TESTS, reason="Excluded")
    def test_teacher_save_a_draft_event_for_individual_periods_162173(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162173']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name = 'event_002_%d' % (randint(100, 999))
        assignment = Assignment()

        # Open Add Reading page
        self.teacher.assign.open_assignment_menu(self.teacher.driver)
        self.teacher.find(By.LINK_TEXT, 'Add Event').click()
        assert ('event/new' in self.teacher.current_url()), \
            'not at add readings screen'

        # Find and fill in title
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'reading-title')
            )
        ).send_keys(assignment_name)

        # Set date
        today = datetime.date.today()
        start = randint(0, 6)
        end = start + randint(1, 5)
        opens_on = (today + datetime.timedelta(days=start)) \
            .strftime('%m/%d/%Y')
        closes_on = (today + datetime.timedelta(days=end)) \
            .strftime('%m/%d/%Y')

        # Find all individual periods
        self.teacher.find(By.ID, 'show-periods-radio').click()
        period_boxes = self.teacher.driver.find_elements(
            By.XPATH, '//input[contains(@id, "period-toggle-period")]'
        )
        period_assignment = {}
        for period in period_boxes:
            period_assignment[
                self.teacher.driver.find_element(
                    By.XPATH,
                    '//label[contains(@for, "%s")]' % period.get_attribute(
                        'id')).text
            ] = (opens_on, closes_on)

        assignment.assign_periods(self.teacher.driver, period_assignment)

        # Save as draft
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'builder-draft-button')
            )
        ).click()

        # Check if the draft is on the dashboard
        try:
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(assignment_name)
            )
        except NoSuchElementException:
            self.teacher.find(
                By.XPATH,
                '//a[contains(@class,"header-control next")]'
            ).click()
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(assignment_name)
            )

        self.ps.test_updates['passed'] = True


    # Case C162174 003 Teacher | Create and publish a new unopened assignment from calendar
    @pytest.mark.skipif(str(162174) not in TESTS, reason="Excluded")
    def test_teacher_create_and_publish_new_unopened_event_from_calendar_162174(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162174']
        self.ps.test_updates['passed'] = False
        # Test steps and verification assertions
        calendar_date = self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//div[contains(@class,"Day--upcoming")]')
            )
        )
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();',
            calendar_date
        )
        self.teacher.sleep(1)
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(calendar_date)
        actions.move_by_offset(0, -35)
        actions.click()
        actions.move_by_offset(30, 105)
        actions.click()
        actions.perform()

        assert ('event/new' in self.teacher.current_url()), \
            'not at Add Event page'

        assignment_name = 'event_003_%d' % (randint(100, 999))
        assignment = Assignment()

        # Find and fill in title
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'reading-title')
            )
        ).send_keys(assignment_name)

        # Fill in description
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"assignment-description")]' +
            '//textarea[contains(@class,"form-control")]'
        ).send_keys('description')
        # or change it to span .assignment-description > .form-control

        # Set date
        today = datetime.date.today()
        start = randint(1, 5)
        end = start + randint(1, 5)

        # the open date should be in the future for the assignment to be unopened
        opens_on = (today + datetime.timedelta(days=start)) \
            .strftime('%m/%d/%Y')
        closes_on = (today + datetime.timedelta(days=end)) \
            .strftime('%m/%d/%Y')
        assignment.assign_periods(
            self.teacher.driver, {'all': (opens_on, closes_on)})

        # Publish
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//button[contains(@class, "-publish")]')
            )
        ).click()
        try:
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(assignment_name)
            )
        except NoSuchElementException:
            self.teacher.find(
                By.XPATH,
                '//a[contains(@class,"header-control next")]'
            ).click()
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(assignment_name))

        self.ps.test_updates['passed'] = True


    # Case C162175 004 Teacher | Publish a draft event
    @pytest.mark.skipif(str(162175) not in TESTS, reason="Excluded")
    def test_teacher_publish_a_draft_event_162175(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162175']

        self.ps.test_updates['passed'] = False
        # Test steps and verification assertions
        assignment_name = 'event_004_%s' % randint(100, 999)
        today = datetime.date.today()
        start = randint(0, 6)
        finish = start + randint(1, 5)
        begin = (today + datetime.timedelta(days=start)) \
            .strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=finish)) \
            .strftime('%m/%d/%Y')
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'draft',
            }
        )

        # Find the draft event on the calendar
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH, '//label[contains(text(),"{0}")]'.format(assignment_name)
        ).click()

        # Publish the draft assignment
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//button[contains(@class,"-publish")]')
            )
        ).click()

        try:
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(assignment_name)
            )
        except NoSuchElementException:
            self.teacher.find(
                By.XPATH,
                '//a[contains(@class,"header-control next")]'
            ).click()
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(assignment_name)
            )

        self.ps.test_updates['passed'] = True


    # Case C162176 005 Teacher | Cancel a new event before making changes
    @pytest.mark.skipif(str(162176) not in TESTS, reason="Excluded")
    def test_teacher_cancel_a_new_event_before_changes_162176(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162176']
        self.ps.test_updates['passed'] = False

        # Open "Add Event" page
        self.teacher.assign.open_assignment_menu(self.teacher.driver)
        self.teacher.find(By.LINK_TEXT, 'Add Event').click()
        assert ('event/new' in self.teacher.current_url()), \
            'not at add event screen'

        # Cancel a reading with "Cancel" button
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'builder-cancel-button')
            )
        ).click()
        assert ('month' in self.teacher.current_url()), \
            'not back at calendar after cancelling event'

        # Open "Add Event" page
        self.teacher.assign.open_assignment_menu(self.teacher.driver)
        self.teacher.find(By.LINK_TEXT, 'Add Event').click()
        assert ('event/new' in self.teacher.current_url()), \
            'not at add event screen'

        # Cancel an event with "X" button
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button[contains(@class,"openstax-close-x")]')
            )
        ).click()
        assert ('month' in self.teacher.current_url()), \
            'not back at calendar after cancelling event'

        self.ps.test_updates['passed'] = True


    # Case C162177 006 Teacher | Cancel a new event after making changes
    @pytest.mark.skipif(str(162177) not in TESTS, reason="Excluded")
    def test_teacher_cancel_a_new_event_after_changes_162177(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162177']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name = 'event_006_%d' % (randint(100, 999))

        # Open "Add Event" page
        self.teacher.assign.open_assignment_menu(self.teacher.driver)
        self.teacher.find(By.LINK_TEXT, 'Add Event').click()
        assert ('event/new' in self.teacher.current_url()), \
            'not at add Event screen'

        # Add title
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'reading-title')
            )
        ).send_keys(assignment_name)
        sleep(1)

        # Cancel with "Cancel" button
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'builder-cancel-button')
            )
        ).click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button[contains(@class,"ok")]')
            )
        ).click()

        # Check if back at user dashboard
        assert ('month' in self.teacher.current_url()), \
            'not back at calendar after cancelling Event'

        # Open "Add Event" page
        self.teacher.assign.open_assignment_menu(self.teacher.driver)
        self.teacher.find(By.LINK_TEXT, 'Add Event').click()
        assert ('event/new' in self.teacher.current_url()), \
            'not at add Event screen'

        # Add title
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'reading-title')
            )
        ).send_keys(assignment_name)

        # Cancel with "X" button
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button[contains(@class,"openstax-close-x")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//button[contains(@class,"ok")]')
            )
        ).click()
        assert ('month' in self.teacher.current_url()), \
            'not back at calendar after cancelling Event'

        self.ps.test_updates['passed'] = True


    # Case C162178 007 Teacher | Cancel a draft event before making changes
    @pytest.mark.skipif(str(162178) not in TESTS, reason="Excluded")
    def test_teacher_cancel_a_draft_event_before_changes_162178(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162178']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name_1 = 'event_007_%s' % randint(100, 500)
        assignment_name_2 = 'event_007_%s' % randint(500, 999)

        today = datetime.date.today()
        finish = randint(1, 5)
        begin = today.strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=finish)) \
            .strftime('%m/%d/%Y')

        # Create a draft assignment
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name_1,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'draft',
            }
        )

        # Find the draft Event on the calendar
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//label[contains(text(),"{0}")]'.format(assignment_name_1)
        ).click()
        sleep(1)

        # Cancel with "Cancel" button
        cancel_button = self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'builder-cancel-button')
            )
        )
        self.teacher.scroll_to(cancel_button)
        cancel_button.click()

        # Check if teacher is taken to user dashboard
        self.teacher.page.wait_for_page_load()
        assert ('month' in self.teacher.current_url()), \
            'not back at calendar after cancelling Event'

        # Add a draft Event
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name_2,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'draft',
            }
        )

        # Find the draft Event on the calendar
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//label[contains(text(),"{0}")]'.format(assignment_name_2)
        ).click()
        sleep(1)

        # Cancel with "X" button
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button[contains(@class,"openstax-close-x")]')
            )
        ).click()

        # Check if the teacher is back to user dashboard
        assert ('month' in self.teacher.current_url()), \
            'not back at calendar after cancelling Event'

        self.ps.test_updates['passed'] = True


    # Case C162179 008 Teacher | Cancel a draft event after making changes
    @pytest.mark.skipif(str(162179) not in TESTS, reason="Excluded")
    def test_teacher_cancel_a_draft_event_after_changes_162179(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162179']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name_1 = 'event_008_%s' % randint(100, 500)
        assignment_name_2 = 'event_008_%s' % randint(500, 999)

        today = datetime.date.today()
        finish = randint(1, 5)
        begin = today.strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=finish)) \
            .strftime('%m/%d/%Y')

        # Create a draft assignment
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name_1,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'draft',
            }
        )

        # Find the draft Event on the calendar
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//label[contains(text(),"{0}")]'.format(assignment_name_1)
        ).click()
        sleep(1)

        # Edit the assignment
        self.teacher.find(
            By.ID, "reading-title"
        ).send_keys('changed')

        # Cancel with "Cancel" button
        cancel_button = self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'builder-cancel-button')
            )
        )
        self.teacher.scroll_to(cancel_button)
        cancel_button.click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button[contains(@class,"ok")]')
            )
        ).click()

        # Check if teacher is taken to user dashboard
        self.teacher.page.wait_for_page_load()
        assert ('month' in self.teacher.current_url()), \
            'not back at calendar after cancelling Event'

        # Create a draft assignment
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name_2,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'draft',
            }
        )

        # Find the draft Event on the calendar
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//label[contains(text(),"{0}")]'.format(assignment_name_2)
        ).click()
        sleep(1)

        # Edit the assignment
        self.teacher.find(
            By.ID, "reading-title"
        ).send_keys('changed')

        # Cancel with "X" button
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button[contains(@class,"openstax-close-x")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button[contains(@class,"ok")]')
            )
        ).click()

        # Check if the teacher is back to user dashboard
        assert ('month' in self.teacher.current_url()), \
            'not back at calendar after cancelling Event'

        self.ps.test_updates['passed'] = True


    # Case C162180 009 Teacher | Attempt to save or publish an event with blank required fields
    @pytest.mark.skipif(str(162180) not in TESTS, reason="Excluded")
    def test_teacher_attempt_to_save_or_publish_events_with_blank_required_fields_162180(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162180']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.assign.open_assignment_menu(self.teacher.driver)
        self.teacher.find(By.LINK_TEXT, 'Add Event').click()
        assert ('event/new' in self.teacher.current_url()), \
            'not at add Event screen'

        # Publish without filling in any fields
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button[contains(@class,"-publish")]')
            )
        ).click()

        # Required field reminder
        self.teacher.find(
            By.XPATH, '//div[contains(text(),"Required field")]')
        assert ('event' in self.teacher.current_url()), \
            'went back to calendar even though required fields were left blank'

        # Refresh the page
        self.teacher.driver.refresh()
        sleep(3)

        # Save without filling in any fields
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button[contains(@class, "save")]')
            )
        ).click()

        # Required field reminder
        self.teacher.find(
            By.XPATH, '//div[contains(text(),"Required field")]')
        assert ('event' in self.teacher.current_url()), \
            'went back to calendar even though required fields were left blank'

        self.ps.test_updates['passed'] = True


    # Case C162181 010 Teacher | Delete a draft event
    @pytest.mark.skipif(str(162181) not in TESTS, reason="Excluded")
    def test_teacher_delete_a_draft_event_162181(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162181']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name = 'event_010_%s' % randint(100, 500)

        today = datetime.date.today()
        finish = randint(1, 5)
        begin = today.strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=finish)) \
            .strftime('%m/%d/%Y')

        # Create a draft assignment
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'draft',
            }
        )

        # Find the draft Event on the calendar
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//label[contains(text(),"{0}")]'.format(assignment_name)
        ).click()
        sleep(1)

        # Delete the draft assignment
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//button[contains(@class,"delete-link")]')
            )
        ).click()
        self.teacher.find(
            By.XPATH, '//button[contains(text(),"Yes")]'
        ).click()
        sleep(3)

        assert ('month' in self.teacher.current_url()), \
            'not returned to calendar after deleting an assignment'

        # have to refresh to remove the assignment tab from calendar
        self.teacher.driver.refresh()
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        deleted_event = self.teacher.find_all(
            By.XPATH, '//label[@data-title="{0}"]'.format(assignment_name)
        )
        assert (len(deleted_event) == 0), 'Event not deleted'

        self.ps.test_updates['passed'] = True


    # Case C162182 011 Teacher | Delete an unopened event
    @pytest.mark.skipif(str(162182) not in TESTS, reason="Excluded")
    def test_teacher_delete_an_unopened_event_162182(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162182']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name = 'event_011_%s' % randint(100, 500)

        today = datetime.date.today()
        start = randint(2, 3)
        finish = start + randint(1, 5)
        begin = (today + datetime.timedelta(days=start)) \
            .strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=finish)) \
            .strftime('%m/%d/%Y')

        # Create an unopened assignment
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'publish',
            }
        )

        # Find the unopened Event on the calendar
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//label[contains(text(),"{0}")]'.format(assignment_name)
        ).click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'edit-assignment-button')
            )
        ).click()

        # Delete the assignment
        delete_button = self.teacher.find(
            By.XPATH, '//button[contains(@class,"delete-link")]'
        )
        self.teacher.scroll_to(delete_button)
        delete_button.click()
        sleep(3)
        confirm_button = self.teacher.find(
            By.XPATH, '//button[contains(text(),"Yes")]'
        )
        self.teacher.scroll_to(confirm_button)
        confirm_button.click()
        sleep(3)

        assert ('month' in self.teacher.current_url()), \
            'not returned to calendar after deleting an assignment'

        # Have to refresh the browser to remove assignment tab from calendar
        self.teacher.driver.refresh()
        deleted_unopened = self.teacher.find_all(
            By.XPATH, '//label[@data-title="{0}"]'.format(assignment_name)
        )
        assert len(deleted_unopened) == 0, 'unopened reading not deleted'

        self.ps.test_updates['passed'] = True


    # Case C162183 012 Teacher | Delete an open event
    @pytest.mark.skipif(str(162183) not in TESTS, reason="Excluded")
    def test_teacher_delete_an_open_event_162183(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162183']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name = 'event_012_%s' % randint(100, 500)

        today = datetime.date.today()
        finish = randint(1, 5)
        begin = today.strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=finish)) \
            .strftime('%m/%d/%Y')

        # Create an unopened assignment
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'publish',
            }
        )

        # Find the open Event on the calendar
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//label[contains(text(),"{0}")]'.format(assignment_name)
        ).click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'edit-assignment-button')
            )
        ).click()

        # Delete the assignment
        delete_button = self.teacher.find(
            By.XPATH, '//button[contains(@class,"delete-link")]'
        )
        self.teacher.scroll_to(delete_button)
        delete_button.click()
        sleep(3)
        confirm_button = self.teacher.find(
            By.XPATH, '//button[contains(text(),"Yes")]'
        )
        self.teacher.scroll_to(confirm_button)
        confirm_button.click()
        sleep(3)

        assert ('month' in self.teacher.current_url()), \
            'not returned to calendar after deleting an assignment'

        # Have to refresh the browser to remove assignment tab from calendar
        self.teacher.driver.refresh()
        deleted_unopened = self.teacher.find_all(
            By.XPATH, '//label[@data-title="{0}"]'.format(assignment_name)
        )
        assert len(
            deleted_unopened) == 0, 'open Event not deleted'

        self.ps.test_updates['passed'] = True


    # Case C162184 013 Teacher | Change a draft event
    @pytest.mark.skipif(str(162184) not in TESTS, reason="Excluded")
    def test_teacher_change_a_draft_event_162184(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162184']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name = 'event_013_%s' % randint(100, 500)
        assignment = Assignment()
        today = datetime.date.today()
        finish = randint(1, 5)
        begin = today.strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=finish)) \
            .strftime('%m/%d/%Y')

        # Create a draft assignment
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'draft',
            }
        )

        # Find the draft Event on the calendar
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//label[contains(text(),"{0}")]'.format(assignment_name)
        ).click()
        sleep(1)

        # Change the title
        self.teacher.find(
            By.ID, "reading-title"
        ).send_keys("changed")

        # Change the description
        self.teacher.find(
            By.CSS_SELECTOR, ".assignment-description>.form-control"
        ).send_keys("changed")

        # Set new due dates
        today = datetime.date.today()
        start = randint(1, 6)
        end = start + randint(1, 5)
        opens_on = (today + datetime.timedelta(days=start)) \
            .strftime('%m/%d/%Y')
        closes_on = (today + datetime.timedelta(days=end)) \
            .strftime('%m/%d/%Y')
        assignment.assign_periods(
            self.teacher.driver,
            {'all': (opens_on, closes_on)}
        )

        # Save as draft
        self.teacher.find(
            By.XPATH, '//button[contains(@class,"-save")]'
        ).click()
        sleep(1)

        # Find the new title on the calendar
        try:
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(
                    assignment_name + 'changed')
            )
        except NoSuchElementException:
            self.teacher.find(
                By.XPATH,
                '//a[contains(@class,"header-control next")]'
            ).click()
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(
                    assignment_name + 'changed')
            )

        self.ps.test_updates['passed'] = True


    # Case C162185 014 Teacher | Change an unopened event
    @pytest.mark.skipif(str(162185) not in TESTS, reason="Excluded")
    def test_teacher_change_an_unopened_event_162185(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162185']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name = 'event_014_%s' % randint(100, 500)
        assignment = Assignment()

        today = datetime.date.today()
        start = randint(2, 3)
        finish = start + randint(1, 5)
        begin = (today + datetime.timedelta(days=start)) \
            .strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=finish)) \
            .strftime('%m/%d/%Y')

        # Create an unopened assignment
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'publish',
            }
        )

        # Find the unopened Event on the calendar
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//label[contains(text(),"{0}")]'.format(assignment_name)
        ).click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'edit-assignment-button')
            )
        ).click()

        # Change the title
        self.teacher.find(
            By.ID, "reading-title"
        ).send_keys("changed")

        # Change the description
        self.teacher.find(
            By.CSS_SELECTOR, ".assignment-description>.form-control"
        ).send_keys("changed")

        # Set new due dates
        today = datetime.date.today()
        start = randint(1, 6)
        end = start + randint(1, 5)
        opens_on = (today + datetime.timedelta(days=start)) \
            .strftime('%m/%d/%Y')
        closes_on = (today + datetime.timedelta(days=end)) \
            .strftime('%m/%d/%Y')
        assignment.assign_periods(
            self.teacher.driver,
            {'all': (opens_on, closes_on)}
        )

        # Publish
        self.teacher.find(
            By.XPATH, '//button[contains(@class,"-publish")]'
        ).click()
        sleep(1)

        # Find the new title on the calendar
        try:
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(
                    assignment_name + 'changed')
            )
        except NoSuchElementException:
            self.teacher.find(
                By.XPATH,
                '//a[contains(@class,"header-control next")]'
            ).click()
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(
                    assignment_name + 'changed')
            )

        self.ps.test_updates['passed'] = True


    # Case C162186 015 Teacher | Change an open event
    @pytest.mark.skipif(str(162186) not in TESTS, reason="Excluded")
    def test_teacher_change_an_open_event_162186(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162186']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name = 'event_015_%s' % randint(100, 500)
        assignment = Assignment()

        today = datetime.date.today()
        finish = randint(1, 5)
        begin = today.strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=finish)) \
            .strftime('%m/%d/%Y')

        # Create an open assignment
        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'status': 'publish',
            }
        )

        # Find the open Event on the calendar
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH,
            '//label[contains(text(),"{0}")]'.format(assignment_name)
        ).click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'edit-assignment-button')
            )
        ).click()

        # Change the title
        self.teacher.find(
            By.ID, "reading-title"
        ).send_keys("changed")

        # Change the description
        self.teacher.find(
            By.CSS_SELECTOR, ".assignment-description>.form-control"
        ).send_keys("changed")

        # Set new due dates
        end = randint(1, 5)
        closes_on = (today + datetime.timedelta(days=end)) \
            .strftime('%m/%d/%Y')
        assignment.assign_date(
            driver=self.teacher.driver, date=closes_on, is_all=True,
            target='due'
        )

        # Publish
        self.teacher.find(
            By.XPATH, '//button[contains(@class,"-publish")]'
        ).click()
        sleep(1)

        # Find the new title on the calendar
        try:
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(
                    assignment_name + 'changed')
            )
        except NoSuchElementException:
            self.teacher.find(
                By.XPATH,
                '//a[contains(@class,"header-control next")]'
            ).click()
            self.teacher.find(
                By.XPATH,
                '//label[contains(text(),"{0}")]'.format(
                    assignment_name + 'changed')
            )

        self.ps.test_updates['passed'] = True


    # Case C162187 016 Teacher | Add an event by dragging and dropping
    @pytest.mark.skipif(str(162187) not in TESTS, reason="Excluded")
    def test_teacher_add_an_event_by_drag_and_drop_162187(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162187']
        self.ps.test_updates['passed'] = False

        # Test verification
        self.teacher.assign.open_assignment_menu(self.teacher.driver)
        event_tab = self.teacher.find(
            By.LINK_TEXT, 'Add Event'
        )

        due_date = self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//div[contains(@class,"Day--upcoming")]')
            )
        )
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(event_tab)

        actions.drag_and_drop(event_tab, due_date).perform()
        sleep(3)

        assert ('event/new' in self.teacher.current_url()), \
            'not at Add Event page'

        self.ps.test_updates['passed'] = True


    # Case C162188 017 Teacher| Get assignment link test info icons
    @pytest.mark.skipif(str(162188) not in TESTS, reason="Excluded")
    def test_teacher_get_assignment_link_and_view_info_icons_162188(self):
        self.ps.test_updates['name'] = 'tutor_event_teacher' \
                                       + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['tutor', 'event', 'teacher',
                                        '162188']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        assignment_name = 'event_017_%d' % (randint(100, 999))
        assignment = Assignment()
        today = datetime.date.today()
        start = randint(2, 6)
        finish = start + randint(1, 5)
        begin_today = today.strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=finish)).strftime('%m/%d/%Y')

        # Open Add Event page
        assignment.open_assignment_menu(self.teacher.driver)
        self.teacher.find(By.LINK_TEXT, 'Add Event').click()
        assert ('event/new' in self.teacher.current_url()), \
            'not at add event screen'

        # Test info icon
        self.teacher.find(
            By.XPATH, '//button[contains(@class, "footer-instructions")]'
        ).click()
        self.teacher.find(By.ID, 'plan-footer-popover')

        self.ps.test_updates['passed'] = True

        # Back to dashboard
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'builder-cancel-button')
            )
        ).click()
        assert ('month' in self.teacher.current_url()), \
            'not back at calendar after cancelling event'

        self.teacher.add_assignment(
            assignment='event',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin_today, end)},
                'url': 'www.openstax.org',
                'status': 'publish'
            }
        )

        # View assignment summary
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.CLASS_NAME, 'month-wrapper')
            )
        )
        self.teacher.find(
            By.XPATH, '//label[contains(text(),"{0}")]'.format(assignment_name)
        ).click()

        # Get assignment link
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.ID, 'lms-info-link')
            )
        ).click()
        sleep(3)
        self.teacher.find(
            By.XPATH, '//div[contains(@id, "sharable-link-popover")]'
        )

        self.ps.test_updates['passed'] = True
class TestEditCourseSettingsAndRoster(unittest.TestCase):
    """T1.42 - Edit Course Settings and Roster."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.teacher.login()
        self.teacher.select_course(appearance='physics')
        self.teacher.open_user_menu()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Course Settings and Roster')
            )
        ).click()
        self.teacher.page.wait_for_page_load()

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.teacher.delete()
        except:
            pass

    # Case C8258 - 001 - Teacher | Edit the course name
    @pytest.mark.skipif(str(8258) not in TESTS, reason='Excluded')
    def test_teacher_edit_the_course_name_8258(self):
        """Edit the course name.

        Steps:
        Click the "Rename Course" button that is next to the course name
        Enter a new course name
        Click the "Rename" button
        Click the X that is on the upper right corner of the dialogue box

        Expected Result:
        The course name is edited.
        (then put it back at the end)
        """
        self.ps.test_updates['name'] = 't1.42.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.001', '8258']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        course_name = self.teacher.driver.find_element(
            By.XPATH,
            '//div[@class="course-settings-title"]/span'
        ).text
        self.teacher.find(
            By.XPATH, '//button[contains(@class,"edit-course")]' +
            '//span[contains(text(),"Rename Course")]'
        ).click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//input[contains(@class,"form-control")]')
            )
        ).send_keys('_EDIT')
        self.teacher.find(
            By.XPATH,
            '//button[contains(@class,"edit-course-confirm")]'
        ).click()
        # check that it was edited
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="course-settings-title"]' +
                 '/span[contains(text(),"%s_EDIT")]' % course_name)
            )
        )
        # set it back
        self.teacher.sleep(1)
        self.teacher.driver.find_element(
            By.XPATH,
            '//button[contains(@class,"edit-course")]' +
            '//span[contains(text(),"Rename Course")]'
        ).click()
        for _ in range(len('_EDIT')):
            self.teacher.wait.until(
                expect.element_to_be_clickable(
                    (By.XPATH, '//input[contains(@class,"form-control")]')
                )
            ).send_keys(Keys.BACK_SPACE)
        self.teacher.find(
            By.XPATH,
            '//button[contains(@class,"edit-course-confirm")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="course-settings-title"]' +
                 '/span[text()="%s"]' % course_name)
            )
        )

        self.ps.test_updates['passed'] = True

    # Case C8259 - 002 - Teacher | Remove an instructor from the course
    @pytest.mark.skipif(str(8259) not in TESTS, reason='Excluded')
    def test_teacher_remove_an_instructor_from_a_course_8259(self):
        """Remove an instructor from the course.

        Steps:
        Click "Remove" for an instructor under the Instructors section
        Click "Remove" on the box that pops up

        Expected Result:
        The instructor is removed from the Instructors list.
        """
        self.ps.test_updates['name'] = 't1.42.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.002', '8259']
        self.ps.test_updates['passed'] = False

        self.teacher.logout()
        # add extra instructor through admin first
        admin = Admin(
            use_env_vars=True,
            existing_driver=self.teacher.driver,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        admin.login()
        admin.get('https://tutor-qa.openstax.org/admin/courses/1/edit')
        admin.page.wait_for_page_load()
        teacher_name = 'Trent'
        admin.find(
            By.XPATH, '//a[contains(text(),"Teachers")]').click()
        admin.find(
            By.ID, 'course_teacher').send_keys(teacher_name)
        admin.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//li[contains(text(),"%s")]' % teacher_name)
            )
        ).click()
        admin.sleep(1)
        admin.find(
            By.LINK_TEXT, 'Main Dashboard').click()
        admin.page.wait_for_page_load()
        admin.logout()
        # redo set-up, but make sure to go to course 1
        self.teacher.login()
        self.teacher.get('https://tutor-qa.openstax.org/courses/1')
        self.teacher.open_user_menu()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Course Settings and Roster')
            )
        ).click()
        self.teacher.page.wait_for_page_load()
        # delete teacher
        teachers_list = self.teacher.find_all(
            By.XPATH, '//div[@class="teachers-table"]//tbody//tr')
        for x in range(len(teachers_list)):
            temp_first = self.teacher.find(
                By.XPATH,
                '//div[@class="teachers-table"]//tbody//tr[' +
                str(x + 1) + ']/td'
            ).text
            if temp_first == teacher_name:
                self.teacher.find(
                    By.XPATH,
                    '//div[@class="teachers-table"]//tbody//tr[' +
                    str(x + 1) + ']//td//span[contains(text(),"Remove")]'
                ).click()
                self.teacher.sleep(1)
                self.teacher.find(
                    By.XPATH, '//div[@class="popover-content"]//button'
                ).click()
                break
            if x == len(teachers_list) - 1:
                print('added teacher was not found, and not deleted')
                raise Exception
        deleted_teacher = self.teacher.driver.find_elements(
            By.XPATH, '//td[contains(text(),"%s")]' % teacher_name)
        assert(len(deleted_teacher) == 0), 'teacher not deleted'

        self.ps.test_updates['passed'] = True

    # Case C8260 - 003 - Teacher | Remove the last instructor from the course
    @pytest.mark.skipif(str(8260) not in TESTS, reason='Excluded')
    def test_teacher_remove_the_last_instructor_from_the_course_8260(self):
        """Remove the last instructor from the course.

        Steps:
        Click on the user menu in the upper right corner of the page
        Click "Course Roster"
        Click "Remove" for an instructor under the Instructors section
        Click "Remove" on the box that pops up

        Expected Result:
        The instructor is removed from the Instructors list.
        """
        self.ps.test_updates['name'] = 't1.42.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.003', '8260']
        self.ps.test_updates['passed'] = False

        raise NotImplementedError(inspect.currentframe().f_code.co_name)
        self.teacher.logout()
        # add extra instructor through admin first
        admin = Admin(
            use_env_vars=True,
            existing_driver=self.teacher.driver,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        admin.login()
        admin.get('https://tutor-qa.openstax.org/admin/courses/1/edit')
        admin.page.wait_for_page_load()
        teacher_name = 'Trent'
        admin.find(
            By.XPATH, '//a[contains(text(),"Teachers")]').click()
        admin.find(
            By.ID, 'course_teacher').send_keys(teacher_name)
        admin.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//li[contains(text(),"%s")]' % teacher_name)
            )
        ).click()
        admin.sleep(1)
        admin.find(
            By.LINK_TEXT, 'Main Dashboard').click()
        admin.page.wait_for_page_load()
        admin.logout()
        # redo set-up, but make sure to go to course 1
        self.teacher.login()
        self.teacher.get('https://tutor-qa.openstax.org/courses/1')
        self.teacher.open_user_menu()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Course Settings and Roster')
            )
        ).click()
        self.teacher.page.wait_for_page_load()
        # delete teacher
        teachers_list = self.teacher.find_all(
            By.XPATH, '//div[@class="teachers-table"]//tbody//tr')
        for x in range(len(teachers_list)):
            temp_first = self.teacher.find(
                By.XPATH,
                '//div[@class="teachers-table"]//tbody//tr[' +
                str(x + 1) + ']/td'
            ).text
            if temp_first == teacher_name:
                self.teacher.find(
                    By.XPATH,
                    '//div[@class="teachers-table"]//tbody//tr[' +
                    str(x + 1) + ']//td//span[contains(text(),"Remove")]'
                ).click()
                self.teacher.sleep(1)
                self.teacher.find(
                    By.XPATH, '//div[@class="popover-content"]//button'
                ).click()
                break
            if x == len(teachers_list) - 1:
                print('added teacher was not found, and not deleted')
                raise Exception
        deleted_teacher = self.teacher.driver.find_elements(
            By.XPATH, '//td[contains(text(),"%s")]' % teacher_name)
        assert(len(deleted_teacher) == 0), 'teacher not deleted'

        self.ps.test_updates['passed'] = True

    # Case C8261 - 004 - Teacher | Add a period
    @pytest.mark.skipif(str(8261) not in TESTS, reason='Excluded')
    def test_teacher_add_a_period_8261(self):
        """Add a period.

        Steps:
        Click "+ Add Period"
        Enter a period name into the Period Name text box
        Click "Add"

        Expected Result:
        A new period is added.
        """
        self.ps.test_updates['name'] = 't1.42.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.004', '8261']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        period_name = 'automated_' + str(randint(0, 999))
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"add-period")]//button').click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//input[contains(@class,"form-control")]')
            )
        ).send_keys(period_name)
        self.teacher.find(
            By.XPATH,
            '//button[contains(@class,"edit-period-confirm")]'
        ).click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH, '//a[contains(text(),"'+period_name+'")]')

        self.ps.test_updates['passed'] = True

    # Case C8262 - 005 - Teacher | Rename a period
    @pytest.mark.skipif(str(8262) not in TESTS, reason='Excluded')
    def test_teacher_rename_a_period_8262(self):
        """Rename a period.

        Steps:
        Click "Rename Period"
        Enter a new period name into the Period Name text box
        Click "Rename"

        Expected Result:
        A period is renamed.
        """
        self.ps.test_updates['name'] = 't1.42.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.005', '8262']
        self.ps.test_updates['passed'] = False

        # create a period
        period_name = 'automated_' + str(randint(0, 999))
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"add-period")]//button').click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//input[contains(@class,"form-control")]')
            )
        ).send_keys(period_name)
        self.teacher.find(
            By.XPATH,
            '//button[contains(@class,"edit-period-confirm")]'
        ).click()
        self.teacher.sleep(1)
        # edit the period
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//a[contains(text(),"'+period_name+'")]')
            )
        ).click()
        self.teacher.find(
            By.XPATH, '//span[contains(@class,"rename-period")]/button'
        ).click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//input[contains(@class,"form-control")]')
            )
        ).send_keys('_EDIT')
        self.teacher.find(
            By.XPATH,
            '//button[contains(@class,"edit-period-confirm")]'
        ).click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH, '//a[contains(text(),"'+period_name+'_EDIT")]')

        self.ps.test_updates['passed'] = True

    # Case C8263 - 006 - Teacher | Archive an empty period
    @pytest.mark.skipif(str(8263) not in TESTS, reason='Excluded')
    def test_teacher_archive_an_empt_period_8263(self):
        """Archive an empty period.

        Steps:
        Click on an empty period
        Click "Archive Period"
        Click "Archive" on the dialogue box

        Expected Result:
        An empty period is archived.
        """
        self.ps.test_updates['name'] = 't1.42.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.006', '8263']
        self.ps.test_updates['passed'] = False

        # create a period
        period_name = 'automated_' + str(randint(0, 999))
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"add-period")]//button').click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//input[contains(@class,"form-control")]')
            )
        ).send_keys(period_name)
        self.teacher.find(
            By.XPATH,
            '//button[contains(@class,"edit-period-confirm")]'
        ).click()
        self.teacher.sleep(1)
        # edit the period
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//a[contains(text(),"'+period_name+'")]')
            )
        ).click()
        self.teacher.find(
            By.XPATH, '//a[contains(@class,"archive-period")]').click()
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"popover-content")]' +
            '//button[contains(@class,"archive")]').click()
        self.teacher.sleep(2)
        archived_period = self.teacher.find_all(
            By.XPATH, '//a[contains(text(),"'+period_name+'")]')
        assert(len(archived_period) == 0), 'period not archived'

        self.ps.test_updates['passed'] = True

    # Case C8264 - 007 - Teacher | Archive a non-empty period
    @pytest.mark.skipif(str(8264) not in TESTS, reason='Excluded')
    def test_teacher_archive_a_non_empty_period_8264(self):
        """Archive a non-empty period.

        Steps:
        Click on a non-empty period
        Click "Archive Period"
        Click Archive

        Expected Result:
        Period is archived
        """
        self.ps.test_updates['name'] = 't1.42.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.007', '8264']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        period_name = self.teacher.find(
            By.XPATH, '//ul[@role="tablist"]//a[@role="tab"]').text
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//a[contains(text(),"'+period_name+'")]')
            )
        ).click()
        self.teacher.find(
            By.XPATH, '//a[contains(@class,"archive-period")]').click()
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"popover-content")]' +
            '//button[contains(@class,"archive")]').click()
        self.teacher.find(
            By.XPATH, '//span[contains(text(),"View Archived")]').click()
        self.teacher.find(
            By.XPATH, '//div[@class="modal-body"]//td[contains(text(),"' +
            period_name + '")]')
        # add the section back
        periods = self.teacher.find_all(
            By.XPATH, '//div[@class="modal-body"]//table//tbody//tr')
        for x in range(len(periods)):
            temp_period = self.teacher.find(
                By.XPATH, '//div[@class="modal-body"]//table//tbody' +
                '//tr['+str(x+1)+']/td').text
            if temp_period == period_name:
                self.teacher.find(
                    By.XPATH,
                    '//div[@class="modal-body"]//table//tbody//tr[' +
                    str(x+1) + ']//button//span[contains(text(),"Unarchive")]'
                ).click()
                break

        self.ps.test_updates['passed'] = True

    # Case C8265 - 008 - Teacher | Move a student to another period
    @pytest.mark.skipif(str(8265) not in TESTS, reason='Excluded')
    def test_teacher_mover_a_student_to_another_period_8265(self):
        """Move a student to another period.

        Steps:
        Click on the user menu in the upper right corner of the page
        Click "Course Roster"
        Click "Change Period" for a student under the Roster section
        Click the desired period to move a student

        Expected Result:
        A student is moved to another period
        """
        self.ps.test_updates['name'] = 't1.42.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.008', '8265']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.find(
            By.XPATH, '//a[@aria-describedby="change-period"]').click()
        student_name = self.teacher.find(
            By.XPATH, '//div[@class="roster"]//td').text
        element = self.teacher.find(
            By.XPATH, '//div[@class="popover-content"]//a')
        period_name = element.text
        element.click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH, '//li/a[contains(text(),"'+period_name+'")]').click()
        self.teacher.driver.find_element(
            By.XPATH, '//td[contains(text(),"%s")]' % student_name)

        self.ps.test_updates['passed'] = True

    # Case C8266 - 009 - Teacher | Drop a student
    @pytest.mark.skipif(str(8266) not in TESTS, reason='Excluded')
    def test_teacher_drop_a_student_8266(self):
        """Drop a student.

        Steps:
        Click on the user menu in the upper right corner of the page
        Click "Course Roster"
        Click "Drop" for a student under the Roster section
        Click "Drop" in the box that pops up

        Expected Result:
        A student is dropped from the course and
        is put under the Dropped Students section
        """
        self.ps.test_updates['name'] = 't1.42.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.009', '8266']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        student_name = self.teacher.find(
            By.XPATH, '//div[@class="roster"]//td').text
        self.teacher.find(
            By.XPATH, '//a[@aria-describedby="drop-student"]').click()
        self.teacher.find(
            By.XPATH, '//div[@class="popover-content"]//button').click()
        self.teacher.sleep(1)
        # check that student was droped
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"dropped-students")]' +
            '//td[contains(text(),"%s")]' % student_name
        )

        self.ps.test_updates['passed'] = True

    # Case C8267 - 010 - Teacher | Readd a dropped student
    @pytest.mark.skipif(str(8267) not in TESTS, reason='Excluded')
    def test_teacher_readd_a_dropped_student_8267(self):
        """Readd a dropped student.

        Steps:
        Click "Add Back to Active Roster" for a student under
            the Dropped Students section
        Click "Add" on the box that pops up

        Expected Result:
        A student is added back to the course
        """
        self.ps.test_updates['name'] = 't1.42.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.010', '8267']
        self.ps.test_updates['passed'] = False

        # drop a student (to make sure there is someone to add back)
        student_name = self.teacher.find(
            By.XPATH, '//div[@class="roster"]//td').text
        self.teacher.find(
            By.XPATH, '//a[@aria-describedby="drop-student"]').click()
        self.teacher.find(
            By.XPATH, '//div[@class="popover-content"]//button').click()
        self.teacher.sleep(1)
        # add a student back (not necessarily the same student)
        element = self.teacher.find(
            By.XPATH, '//div[contains(@class,"dropped-students")]' +
            '//span[contains(text(),"Add Back to Active Roster")]')
        self.teacher.driver.execute_script(
            'return arguments[0].scrollIntoView();', element)
        self.teacher.driver.execute_script('window.scrollBy(0, -80);')
        element.click()
        self.teacher.find(
            By.XPATH, '//div[@class="popover-content"]//button').click()
        # check that student was added back
        self.teacher.find(
            By.XPATH,
            '//div[@class="roster"]//td[contains(text(),"%s")]' % student_name)

        self.ps.test_updates['passed'] = True

    # Case C58356 - 011 - Teacher | Unarchive an empty period
    @pytest.mark.skipif(str(58356) not in TESTS, reason='Excluded')
    def test_teacher_unarchive_an_empty_period_58356(self):
        """Unarchive an empty period.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account [ teacher001 ] and password in the boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a Tutor course name
        Click on the user menu in the upper right corner of the page
        Click "Course Settings and Roster"
        Click "View Archived Period(s)"
        Click Unarchived period next to selected course

        Expected Result:
        Period is made active.
        """
        self.ps.test_updates['name'] = 't1.42.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.011', '58356']
        self.ps.test_updates['passed'] = False

        # create a period
        period_name = 'automated_011_' + str(randint(0, 999))
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"add-period")]//button').click()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//input[contains(@class,"form-control")]')
            )
        ).send_keys(period_name)
        self.teacher.find(
            By.XPATH,
            '//button[contains(@class,"edit-period-confirm")]'
        ).click()
        self.teacher.sleep(1)
        # archive the period
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//a[contains(text(),"'+period_name+'")]')
            )
        ).click()
        self.teacher.find(
            By.XPATH, '//a[contains(@class,"archive-period")]').click()
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"popover-content")]' +
            '//button[contains(@class,"archive")]').click()
        self.teacher.sleep(2)
        archived_period = self.teacher.find_all(
            By.XPATH, '//a[contains(text(),"'+period_name+'")]')
        assert(len(archived_period) == 0), 'period not archived'
        # unarchive the period
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"view-archived-periods")]//button'
        ).click()
        self.teacher.sleep(1)
        rows = self.teacher.find_all(
            By.XPATH, '//div[@class="modal-content"]//tbody/tr')
        for row in rows:
            temp_name = row.find_element(By.XPATH, "./td[1]").text
            if temp_name == period_name:
                row.find_element(
                    By.XPATH,
                    "./td[3]//button[contains(@class,'unarchive-section')]"
                ).click()
                self.teacher.find(
                    By.XPATH,
                    '//div[@class="modal-content"]//button[@class="close"]'
                ).click()
                break
        # check that period is no longer archived
        self.teacher.find(
            By.XPATH, '//a[contains(text(),"'+period_name+'")]')

        self.ps.test_updates['passed'] = True
Ejemplo n.º 38
0
class TestStaxingTutorTeacher(unittest.TestCase):
    """Staxing case tests for Teacher."""

    book_sections = None
    class_start_end_dates = None

    def setUp(self):
        """Pretest settings."""
        self.teacher = Teacher(use_env_vars=True, driver_type=DRIVER)
        self.teacher.username = os.getenv('TEACHER_USER_MULTI',
                                          self.teacher.username)
        self.teacher.set_window_size(height=700, width=1200)
        self.teacher.login()
        courses = self.teacher.get_course_list()
        if len(courses) < 1:
            raise ValueError('No course available for selection')
        course = courses[randint(0, len(courses) - 1)]

        self.teacher.select_course(title=course.get_attribute('data-title'))

        if not self.__class__.book_sections:
            self.__class__.book_sections = self.teacher.get_book_sections()
        if not self.__class__.class_start_end_dates:
            self.__class__.class_start_end_dates = \
                self.teacher.get_course_begin_end()

        self.book_sections = self.__class__.book_sections
        self.start_end = self.__class__.class_start_end_dates

    def tearDown(self):
        """Test destructor."""
        try:
            self.teacher.delete()
        except Exception:
            pass

    @pytest.mark.skipif(str(301) not in TESTS, reason='Excluded')
    def test_add_reading_assignment_individual_publish_301(self):
        """Build reading assignments.

        Type:     reading
        Sections: individualized
        Action:   publish
        """
        assignment_title = 'Reading-%s' % Assignment.rword(5)

        left_delta = randint(0, 20)
        left = datetime.date.today() + datetime.timedelta(left_delta)
        start_date_1 = self.teacher.date_string(day_delta=left_delta)
        start_date_2 = self.teacher.date_string(day_delta=left_delta + 1)
        start_date_3 = self.teacher.date_string(day_delta=left_delta + 2)
        start_date_4 = self.teacher.date_string(day_delta=left_delta + 3)
        if not self.teacher.date_is_valid(left):
            start_date_1 = (self.class_start_end_dates[0]) \
                .strftime('%m/%d/%Y')
            start_date_2 = \
                (self.class_start_end_dates[0] + datetime.timedelta(1)) \
                .strftime('%m/%d/%Y')
            start_date_3 = \
                (self.class_start_end_dates[0] + datetime.timedelta(2)) \
                .strftime('%m/%d/%Y')
            start_date_4 = \
                (self.class_start_end_dates[0] + datetime.timedelta(3)) \
                .strftime('%m/%d/%Y')
        right_delta = left_delta + randint(1, 10)
        right = datetime.date.today() + datetime.timedelta(right_delta)
        end_date_1 = self.teacher.date_string(day_delta=right_delta)
        end_date_2 = self.teacher.date_string(day_delta=right_delta + 1)
        end_date_3 = self.teacher.date_string(day_delta=right_delta + 2)
        end_date_4 = self.teacher.date_string(day_delta=right_delta + 3)
        if not self.teacher.date_is_valid(right):
            end_date_1 = \
                (self.class_start_end_dates[1] - datetime.timedelta(3)) \
                .strftime('%m/%d/%Y')
            end_date_2 = \
                (self.class_start_end_dates[1] - datetime.timedelta(2)) \
                .strftime('%m/%d/%Y')
            end_date_3 = \
                (self.class_start_end_dates[1] - datetime.timedelta(1)) \
                .strftime('%m/%d/%Y')
            end_date_4 = \
                (self.class_start_end_dates[1]) \
                .strftime('%m/%d/%Y')
        print('Left: %s  Right: %s' % (left, right))
        start_time_2 = '6:30 am'
        end_time_2 = '11:59 pm'
        reading_start = randint(0, (len(self.book_sections) - 1))
        reading_end = reading_start + randint(1, 5)
        reading_list = self.book_sections[reading_start:reading_end]
        sections = self.teacher.get_course_sections()
        assign_sections = {}
        if len(sections) >= 1 and sections[0]:
            assign_sections[sections[0]] = (start_date_1, end_date_1)
        if len(sections) >= 2 and sections[1]:
            assign_sections[sections[1]] = ((start_date_2, start_time_2),
                                            (end_date_2, end_time_2))
        if len(sections) >= 3 and sections[2]:
            assign_sections[sections[2]] = (start_date_3, end_date_3)
        if len(sections) >= 4 and sections[3]:
            assign_sections[sections[3]] = (start_date_4, end_date_4)
        for number, section in enumerate(sections):
            assign_sections[section] = ((start_date_1, start_time_2),
                                        (end_date_1, end_time_2))
        self.teacher.add_assignment(
            assignment='reading',
            args={
                'title': assignment_title,
                'description':
                'Staxing test reading - individual periods - ' + 'publish',
                'periods': assign_sections,
                'reading_list': reading_list,
                'status': 'publish',
                'break_point': None,
            })
        assert('course' in self.teacher.current_url()), \
            'Not at dashboard'
        print(self.teacher.current_url())
        self.teacher.rotate_calendar(end_date_1)
        reading = self.teacher.find(By.XPATH,
                                    '//label[text()="%s"]' % assignment_title)
        time.sleep(5.0)
        assert (reading), '%s not publishing on %s' % (assignment_title,
                                                       end_date_1)

    @pytest.mark.skipif(str(302) not in TESTS, reason='Excluded')
    def test_add_reading_assignment_all_publish_302(self):
        """Build reading assignments."""
        # Reading, all periods, publish
        assignment_title = 'Reading-%s' % Assignment.rword(5)

        left_delta = randint(0, 20)
        left = datetime.date.today() + datetime.timedelta(left_delta)
        # start_date_1 = self.teacher.date_string(day_delta=left_delta)
        start_date_2 = self.teacher.date_string(day_delta=left_delta + 1)
        if not self.teacher.date_is_valid(left):
            # start_date_1 = \
            #     (self.class_start_end_dates[0]) \
            #     .strftime('%m/%d/%Y')
            start_date_2 = \
                (self.class_start_end_dates[0] + datetime.timedelta(1)) \
                .strftime('%m/%d/%Y')
        right_delta = left_delta + randint(1, 10)
        right = datetime.date.today() + datetime.timedelta(right_delta)
        end_date_1 = self.teacher.date_string(day_delta=right_delta)
        end_date_2 = self.teacher.date_string(day_delta=right_delta + 1)
        if not self.teacher.date_is_valid(right):
            end_date_1 = \
                (self.class_start_end_dates[1] - datetime.timedelta(2)) \
                .strftime('%m/%d/%Y')
            end_date_2 = \
                (self.class_start_end_dates[1] - datetime.timedelta(1)) \
                .strftime('%m/%d/%Y')
        print('Left: %s  Right: %s' % (left, right))
        # self.book_sections = self.teacher.get_book_sections()
        reading_start = randint(0, (len(self.book_sections) - 1))
        reading_end = reading_start + randint(1, 5)
        reading_list = self.book_sections[reading_start:reading_end]
        self.teacher.add_assignment(
            assignment='reading',
            args={
                'title': assignment_title,
                'description': 'Staxing test reading - all periods - publish',
                'periods': {
                    # '1st': (start_date_1, end_date_1),
                    'all': (start_date_2, end_date_2),
                },
                'reading_list': reading_list,
                'status': 'publish',
                'break_point': None,
            })
        assert('course' in self.teacher.current_url()), \
            'Not at dashboard'
        time.sleep(2.0)
        self.teacher.rotate_calendar(end_date_1)
        reading = self.teacher.find(By.XPATH,
                                    '//label[text()="%s"]' % assignment_title)
        time.sleep(5.0)
        assert (reading), '%s not publishing on %s' % (assignment_title,
                                                       end_date_2)

    @pytest.mark.skipif(str(303) not in TESTS, reason='Excluded')
    def test_add_reading_assignment_individual_draft_303(self):
        """Build reading assignments."""
        # Reading, individual periods, draft
        assignment_title = 'Reading-%s' % Assignment.rword(5)
        left_delta = randint(0, 20)
        left = datetime.date.today() + datetime.timedelta(left_delta)
        '''start_date_1 = self.teacher.date_string(day_delta=left_delta)
        start_date_2 = self.teacher.date_string(day_delta=left_delta + 1)
        start_date_3 = self.teacher.date_string(day_delta=left_delta + 2)
        if not self.teacher.date_is_valid(left):
            start_date_1 = \
                (self.class_start_end_dates[0]).strftime('%m/%d/%Y')
            start_date_2 = \
                (self.class_start_end_dates[0] + datetime.timedelta(1)) \
                .strftime('%m/%d/%Y')
            start_date_3 = \
                (self.class_start_end_dates[0] + datetime.timedelta(2)) \
                .strftime('%m/%d/%Y')'''
        right_delta = left_delta + randint(1, 10)
        right = datetime.date.today() + datetime.timedelta(right_delta)
        end_date_1 = self.teacher.date_string(day_delta=right_delta)
        # end_date_2 = self.teacher.date_string(day_delta=right_delta + 1)
        end_date_3 = self.teacher.date_string(day_delta=right_delta + 2)
        if not self.teacher.date_is_valid(right):
            end_date_1 = \
                (self.class_start_end_dates[1] - datetime.timedelta(2)) \
                .strftime('%m/%d/%Y')
            # end_date_2 = \
            #     (self.class_start_end_dates[1] - datetime.timedelta(1)) \
            #     .strftime('%m/%d/%Y')
            end_date_3 = \
                (self.class_start_end_dates[1]) \
                .strftime('%m/%d/%Y')
        print('Left: %s  Right: %s' % (left, right))
        # self.book_sections = self.teacher.get_book_sections()
        reading_start = randint(0, (len(self.book_sections) - 1))
        reading_end = reading_start + randint(1, 5)
        reading_list = self.book_sections[reading_start:reading_end]
        sections = self.teacher.get_course_sections()
        periods = {}
        for index, section in enumerate(sections):
            periods[section] = \
                (self.teacher.date_string(day_delta=left_delta + index),
                 self.teacher.date_string(day_delta=right_delta + index))
        self.teacher.add_assignment(
            assignment='reading',
            args={
                'title': assignment_title,
                'description':
                'Staxing test reading - individual periods ' + '- draft',
                'periods': periods,
                'reading_list': reading_list,
                'status': 'draft',
                'break_point': None,
            })
        assert('course' in self.teacher.current_url()), \
            'Not at dashboard'
        self.teacher.rotate_calendar(end_date_1)
        reading = self.teacher.find(By.XPATH,
                                    '//label[text()="%s"]' % assignment_title)
        time.sleep(5.0)
        assert (reading), '%s not publishing on %s' % (assignment_title,
                                                       end_date_3)

    @pytest.mark.skipif(str(304) not in TESTS, reason='Excluded')
    def test_add_reading_assignment_all_draft_304(self):
        """Build reading assignments."""
        # Reading, all periods, draft
        assignment_title = 'Reading-%s' % Assignment.rword(5)
        left_delta = randint(0, 20)
        left = datetime.date.today() + datetime.timedelta(left_delta)
        start_date_1 = self.teacher.date_string(day_delta=left_delta)
        if not self.teacher.date_is_valid(left):
            start_date_1 = \
                (self.class_start_end_dates[0]) \
                .strftime('%m/%d/%Y')

        right_delta = left_delta + randint(1, 10)
        right = datetime.date.today() + datetime.timedelta(right_delta)
        end_date_1 = self.teacher.date_string(day_delta=right_delta)
        if not self.teacher.date_is_valid(right):
            end_date_1 = \
                (self.class_start_end_dates[1] - datetime.timedelta(2)) \
                .strftime('%m/%d/%Y')
        print('Left: %s  Right: %s' % (left, right))
        # self.book_sections = self.teacher.get_book_sections()
        reading_start = randint(0, (len(self.book_sections) - 1))
        reading_end = reading_start + randint(1, 5)
        reading_list = self.book_sections[reading_start:reading_end]
        self.teacher.add_assignment(
            assignment='reading',
            args={
                'title': assignment_title,
                'description': 'Staxing test reading - all periods - draft',
                'periods': {
                    'all': (start_date_1, end_date_1),
                },
                'reading_list': reading_list,
                'status': 'draft',
                'break_point': None,
            })
        assert('course' in self.teacher.current_url()), \
            'Not at dashboard'
        self.teacher.rotate_calendar(end_date_1)
        reading = self.teacher.find(By.XPATH,
                                    '//label[text()="%s"]' % assignment_title)
        time.sleep(5.0)
        assert (reading), '%s not publishing on %s' % (assignment_title,
                                                       end_date_1)

    @pytest.mark.skipif(str(305) not in TESTS, reason='Excluded')
    def test_add_reading_assignment_one_cancel_305(self):
        """Build reading assignments."""
        # Reading, one period, cancel
        assignment_title = 'Reading-%s' % Assignment.rword(5)
        left_delta = randint(0, 20)
        left = datetime.date.today() + datetime.timedelta(left_delta)
        start_date_1 = self.teacher.date_string(day_delta=left_delta)
        if not self.teacher.date_is_valid(left):
            start_date_1 = \
                (self.class_start_end_dates[0]) \
                .strftime('%m/%d/%Y')
        right_delta = left_delta + randint(1, 10)
        right = datetime.date.today() + datetime.timedelta(right_delta)
        end_date_1 = self.teacher.date_string(day_delta=right_delta)
        if not self.teacher.date_is_valid(right):
            end_date_1 = \
                (self.class_start_end_dates[1] - datetime.timedelta(2)) \
                .strftime('%m/%d/%Y')
        print('Left: %s  Right: %s' % (left, right))
        # self.book_sections = self.teacher.get_book_sections()
        reading_start = randint(0, (len(self.book_sections) - 1))
        reading_end = reading_start + randint(1, 5)
        reading_list = self.book_sections[reading_start:reading_end]
        sections = self.teacher.get_course_sections()
        if not isinstance(sections, list):
            sections = [sections]
        self.teacher.add_assignment(assignment='reading',
                                    args={
                                        'title': assignment_title,
                                        'description':
                                        'Staxing test reading - cancel',
                                        'periods': {
                                            sections[0]:
                                            (start_date_1, end_date_1),
                                        },
                                        'reading_list': reading_list,
                                        'status': 'cancel',
                                        'break_point': None,
                                    })
        assert('course' in self.teacher.current_url()), \
            'Not at dashboard'
        self.teacher.rotate_calendar(end_date_1)
        time.sleep(5.0)
        with pytest.raises(NoSuchElementException):
            self.teacher.find(By.XPATH,
                              '//label[text()="%s"]' % assignment_title)

    @pytest.mark.skipif(str(306) not in TESTS, reason='Excluded')
    def test_change_assignment_306(self):
        """No test placeholder."""
        pass

    @pytest.mark.skipif(str(307) not in TESTS, reason='Excluded')
    def test_delete_assignment_307(self):
        """No test placeholder."""
        assignment_title = 'Reading-%s' % Assignment.rword(5)
        left_delta = randint(0, 20)
        left = datetime.date.today() + datetime.timedelta(left_delta)
        start_date = self.teacher.date_string(day_delta=left_delta)
        if not self.teacher.date_is_valid(left):
            start_date = \
                (self.class_start_end_dates[0]) \
                .strftime('%m/%d/%Y')
        right_delta = left_delta + randint(1, 10)
        right = datetime.date.today() + datetime.timedelta(right_delta)
        end_date = self.teacher.date_string(day_delta=right_delta)
        if not self.teacher.date_is_valid(right):
            end_date = \
                (self.class_start_end_dates[1] - datetime.timedelta(2)) \
                .strftime('%m/%d/%Y')
        self.teacher.add_assignment(assignment='reading',
                                    args={
                                        'title': assignment_title,
                                        'periods': {
                                            'all': (start_date, end_date),
                                        },
                                        'reading_list': ['1', '1.1'],
                                        'status': 'publish',
                                        'break_point': None,
                                    })
        assert('course' in self.teacher.current_url()), \
            'Not at dashboard'
        self.teacher.rotate_calendar(end_date)
        reading = self.teacher.find(By.XPATH,
                                    '//label[text()="%s"]' % assignment_title)
        print('Waiting for publish')

        time.sleep(5.0)
        assert(reading), \
            '%s not publishing on %s' % (assignment_title, end_date)
        self.teacher.delete_assignment(assignment='reading',
                                       args={
                                           'title': assignment_title,
                                           'periods': {
                                               'all': (start_date, end_date),
                                           },
                                       })
        self.teacher.rotate_calendar(end_date)
        time.sleep(5.0)
        try:
            self.teacher.find(By.XPATH,
                              '//label[text()="%s"]' % assignment_title)
            assert (False), '%s still exists' % assignment_title
        except Exception:
            pass

    @pytest.mark.skipif(str(308) not in TESTS, reason='Excluded')
    def test_goto_menu_item_308(self):
        """No test placeholder."""
        pass

    @pytest.mark.skipif(str(309) not in TESTS, reason='Excluded')
    def test_goto_calendar_309(self):
        """No test placeholder."""
        pass

    @pytest.mark.skipif(str(310) not in TESTS, reason='Excluded')
    def test_goto_performance_forecast_310(self):
        """No test placeholder."""
        self.teacher.goto_performance_forecast()

    @pytest.mark.skipif(str(311) not in TESTS, reason='Excluded')
    def test_goto_student_scores_311(self):
        """No test placeholder."""
        self.teacher.goto_student_scores()

    @pytest.mark.skipif(str(312) not in TESTS, reason='Excluded')
    def test_goto_course_roster_312(self):
        """No test placeholder."""
        self.teacher.goto_course_roster()

    @pytest.mark.skipif(str(313) not in TESTS, reason='Excluded')
    def test_goto_course_settings_313(self):
        """No test placeholder."""
        self.teacher.goto_course_settings()

    @pytest.mark.skipif(str(314) not in TESTS, reason='Excluded')
    def test_add_course_section_314(self):
        """Add a course section to a class."""
        section_name = 'New Section'
        self.teacher.add_course_section(section_name)
        classes = self.teacher.find_all(By.CSS_SELECTOR, 'a[role*="tab"]')
        section_names = []
        for section in classes:
            section_names.append(section.get_attribute('innerHTML'))
        assert(section_name in section_names), \
            '%s not in %s' % (section_name, section_names)
        self.teacher.goto_course_settings()
        self.teacher.find

    @pytest.mark.skipif(str(315) not in TESTS, reason='Excluded')
    def test_get_enrollment_code_315(self):
        """No test placeholder."""
        code = self.teacher.get_enrollment_code()
        assert('enroll' in code and re.search('\d{6}', code) is not None), \
            '%s is not the correct enrollment URL' % code

    @pytest.mark.skipif(str(316) not in TESTS, reason='Excluded')
    def test_teacher_handle_modals_316(self):
        self.teacher.enable_debug_mode()
        self.teacher.close_beta_windows()
        time.sleep(3)
        assert ("modal closed")
Ejemplo n.º 39
0
class TestEditCourseSettingsAndRoster(unittest.TestCase):
    """T1.42 - Edit Course Settings and Roster."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(use_env_vars=True,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
        else:
            self.teacher = Teacher(use_env_vars=True)
        self.teacher.login()

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    # Case 162189 - 002 - Teacher | Move, Drop, and Readd a Student
    @pytest.mark.skipif(str(162189) not in TESTS, reason='Excluded')
    def test_teacher_mover_a_student_to_another_period_162189(self):
        """

        #STEPS
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher username [ ] in the username text box
        Click 'Next'
        Enter the teacher password [ ] in the password text box
        Click on the 'Login' button
        Click on a Tutor course name
        ***The user selects a course and is presented with the calendar dashboard.***

        Click on the user menu in the upper right corner of the page
        Click "Course Settings and Roster"
        Click "Change Section" for a student under the student section
        Click the desired section to move a student
        Click the section the student was moved to
        ***A student is moved to another section***

        Click "Drop" for a student under the student section
        Click "Drop" in the box that pops up
        ***A student is dropped from the course and is put under the Dropped Students section***

        Click "Add Back to Active Roster" for a student under the Dropped Students section
        Click "Add" on the box that pops up

        # EXPECTED RESULT 
        ***A student is added back to the course***

        """
        # Test steps and verification assertions
        self.ps.test_updates['name'] = 't1.42.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.42', 't1.42.008', '162189']
        self.ps.test_updates['passed'] = False

        # Select a course and see the calendar dashboard
        self.teacher.select_course(appearance='intro_sociology')
        self.teacher.open_user_menu()
        self.teacher.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Course Settings and Roster'))).click()
        self.teacher.page.wait_for_page_load()

        # Move Students
        self.teacher.find(By.XPATH,
                          '//a[@aria-describedby="change-period"]').click()
        student_name = self.teacher.find(By.XPATH,
                                         '//div[@class="roster"]//td').text
        element = self.teacher.find(By.XPATH,
                                    '//div[@class="popover-content"]//a')
        period_name = element.text
        element.click()
        self.teacher.sleep(1)
        self.teacher.find(By.XPATH, '//a/h2[contains(text(),"' + period_name +
                          '")]').click()
        self.teacher.driver.find_element(
            By.XPATH, '//td[contains(text(),"%s")]' % student_name)

        # Drop Student
        student_name = self.teacher.find(By.XPATH,
                                         '//div[@class="roster"]//td').text
        self.teacher.find(By.XPATH,
                          '//a[@aria-describedby="drop-student"]').click()
        self.teacher.find(By.XPATH,
                          '//div[@class="popover-content"]//button').click()
        self.teacher.sleep(1)
        # check that student was dropped
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"dropped-students")]' +
            '//td[contains(text(),"%s")]' % student_name)

        # Readd Student
        # add a student back (not necessarily the same student)
        self.teacher.find(
            By.XPATH,
            '//a[@aria-describedby="drop-student-popover-1216"]').click()
        self.teacher.find(By.XPATH,
                          '//div[@class="popover-content"]//button').click()
        self.teacher.sleep(1)
        # check that student was added back
        self.teacher.find(
            By.XPATH,
            '//div[@class="roster"]//td[contains(text(),"%s")]' % student_name)

        self.ps.test_updates['passed'] = True
class TestImproveCourseManagement(unittest.TestCase):
    """T2.07 - Improve Course Management."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(use_env_vars=True,
                               pasta_user=self.ps,
                               capabilities=self.desired_capabilities)
        self.admin = Admin(use_env_vars=True,
                           pasta_user=self.ps,
                           capabilities=self.desired_capabilities,
                           existing_driver=self.teacher.driver)

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        self.admin = None
        try:
            self.teacher.delete()
        except:
            pass

    # 14651 - 001 - Admin | View Student Use Statistics for Concept Coach
    # college assessments
    @pytest.mark.skipif(str(14651) not in TESTS, reason='Excluded')
    def test_admin_view_student_use_statistics_for_cc_college_asse_14651(self):
        """View Student Use Statistics for Concept Coach college assessments.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the admin account in the username and password text boxes
        Click on the 'Sign in' button
        Click "Admin" in the user menu
        Click "Stats"
        Click "Concept Coach"

        Expected Result:
        The user is presented with Concept Coach statistics
        """
        self.ps.test_updates['name'] = 't2.07.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.07', 't2.07.001', '14651']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.admin.login()
        self.admin.goto_admin_control()
        self.admin.sleep(5)
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Stats'))).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Concept Coach'))).click()

        assert('/stats/concept_coach' in self.admin.current_url()), \
            'Not viewing Concept Coach stats'

        self.ps.test_updates['passed'] = True

    '''
    # 14652 - 002 - Teacher | Delegate teaching tasks to supporting instructors
    @pytest.mark.skipif(str(14652) not in TESTS, reason='Excluded')
    def test_teacher_delegate_teaching_tasks_to_supporting_instruc_14652(self):
        """Delegate teaching tasks to supporting instructors.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.07.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.002',
            '14652'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    '''
    '''
    # 14653 - 003 - Teacher | Move a student and their data to a new section
    @pytest.mark.skipif(str(14653) not in TESTS, reason='Excluded')
    def test_teacher_move_a_student_and_their_data_to_new_section_14653(self):
        """Move a student and their data to a new section.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Course Settings and Roster" from the user menu
        Click "Change Period" for the desired student and select a period

        Expected Result:
        Student is moved to new section with their data
        """
        self.ps.test_updates['name'] = 't2.07.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.003',
            '14653'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.select_course(appearance='physics')
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Course Settings and Roster").click()
        self.teacher.sleep(5)

        # Move the student to another period
        first = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[1]"
        ).text
        last = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[2]"
        ).text

        self.teacher.find(By.PARTIAL_LINK_TEXT, "Change Period").click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH, "//ul[@class='nav nav-pills nav-stacked']/li/a").click()

        self.teacher.sleep(5)

        # Verify the move, then move the student back to the original period
        self.teacher.find(
            By.XPATH,
            "//div[@class='roster']/div[@class='settings-section periods']" +
            "/ul[@class='nav nav-tabs']/li[2]/a").click()
        roster = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr")
        index = 0
        for student in roster:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                self.teacher.driver.find_elements_by_partial_link_text(
                    "Change Period")[index].click()
                self.teacher.sleep(1)
                self.teacher.find(
                    By.XPATH,
                    "//ul[@class='nav nav-pills nav-stacked']/li/a").click()
                break
            index += 1

        self.teacher.sleep(2)
        self.teacher.find(
            By.XPATH,
            "//div[@class='roster']/div[@class='settings-section periods']" +
            "/ul[@class='nav nav-tabs']/li[1]/a").click()
        roster = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr")

        assert(first in roster[0].text and last in roster[0].text), \
            'error'

        self.ps.test_updates['passed'] = True

    # 14655 - 004 - Teacher | Drop a student from a section and hide their data
    @pytest.mark.skipif(str(14655) not in TESTS, reason='Excluded')
    def test_teacher_drop_student_from_section_and_hide_their_data_14655(self):
        """Drop a student from a section and hide their data.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Course Settings and Roster" from the user menu
        Click "Drop" for the desired student

        Expected Result:
        The student appears under the "Dropped Students" section
        """
        self.ps.test_updates['name'] = 't2.07.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.004',
            '14655'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.select_course(appearance='physics')
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Course Settings and Roster").click()
        self.teacher.sleep(5)

        # Drop the student
        first = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[1]"
        ).text
        last = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[2]"
        ).text
        self.teacher.find(By.PARTIAL_LINK_TEXT, "Drop").click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH,
            "//button[@class='-drop-student btn btn-danger']").click()

        self.teacher.sleep(5)

        # Verify the student was dropped and add back to active roster
        dropped = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='settings-section dropped-students']/table[@class" +
            "='roster table table-striped table-bordered table-condensed " +
            "table-hover']/tbody/tr")
        index = 0
        for student in dropped:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                self.teacher.driver.find_elements_by_partial_link_text(
                    "Add Back to Active Roster")[index].click()
                self.teacher.sleep(1)
                self.teacher.find(
                    By.XPATH,
                    "//button[@class='-undrop-student btn btn-success']"
                ).click()
                self.teacher.sleep(20)
                break
            index += 1

        self.ps.test_updates['passed'] = True

    # 14656 - 005 - Teacher | Drop a student from a section and don't hide
    # their data
    @pytest.mark.skipif(str(14656) not in TESTS, reason='Excluded')
    def test_teacher_drop_a_student_from_section_and_dont_hide_dat_14656(self):
        """Drop a student from a section and don't hide their data.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.07.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.005',
            '14656'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    '''

    # 14657 - 006 - Teacher | In Student Scores dropped students are not
    # displayed
    @pytest.mark.skipif(str(14657) not in TESTS, reason='Excluded')
    def test_teacher_in_student_scores_dropped_students_are_not_14657(self):
        """In Student Scores dropped students are not displayed.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Course Settings and Roster" from the calendar dashboard
        Click "Drop" for the desired student
        Click "Student Scores" from the user menu
        Click on the period from which you have dropped the student

        Expected Result:
        Dropped student should not be displayed in Student Scores
        """
        self.ps.test_updates['name'] = 't2.07.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.07', 't2.07.006', '14657']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.select_course(appearance='physics')
        self.teacher.open_user_menu()
        self.teacher.find(By.PARTIAL_LINK_TEXT,
                          "Course Settings and Roster").click()
        self.teacher.sleep(5)

        # Drop the student
        first = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[1]"
        ).text
        last = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[2]"
        ).text

        self.teacher.find(By.PARTIAL_LINK_TEXT, "Drop").click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH,
            "//button[@class='-drop-student btn btn-danger']").click()

        self.teacher.sleep(5)

        # Go to student scores, verify the student is not seen
        self.teacher.open_user_menu()
        self.teacher.find(By.PARTIAL_LINK_TEXT, "Student Scores").click()
        self.teacher.sleep(10)

        odd_scores = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='fixedDataTableRowLayout_main public_fixedData" +
            "TableRow_main public_fixedDataTableRow_even public_fixedDataTa" +
            "ble_bodyRow']/div[@class='fixedDataTableRowLayout_body']/div" +
            "[@class='fixedDataTableCellGroupLayout_cellGroupWrapper'][1]/d" +
            "iv[@class='fixedDataTableCellGroupLayout_cellGroup']/div[@clas" +
            "s='fixedDataTableCellLayout_main public_fixedDataTableCell_" +
            "main'][1]/div[@class='fixedDataTableCellLayout_wrap1 public_fi" +
            "xedDataTableCell_wrap1']/div[@class='fixedDataTableCellLayout_w" +
            "rap2 public_fixedDataTableCell_wrap2']/div[@class='fixedDataTab" +
            "leCellLayout_wrap3 public_fixedDataTableCell_wrap3']/div[@class" +
            "='name-cell']/a[@class='student-name public_fixedDataTableCell" +
            "_cellContent']")
        even_scores = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='fixedDataTableRowLayout_main public_fixedDataTab" +
            "leRow_main public_fixedDataTableRow_highlighted public_fixedDa" +
            "taTableRow_odd public_fixedDataTable_bodyRow']/div[@class='fix" +
            "edDataTableRowLayout_body']/div[@class='fixedDataTableCellGrou" +
            "pLayout_cellGroupWrapper'][1]/div[@class='fixedDataTableCellGr" +
            "oupLayout_cellGroup']/div[@class='fixedDataTableCellLayout_mai" +
            "n public_fixedDataTableCell_main'][1]/div[@class='fixedDataTab" +
            "leCellLayout_wrap1 public_fixedDataTableCell_wrap1']/div[@clas" +
            "s='fixedDataTableCellLayout_wrap2 public_fixedDataTableCell_wr" +
            "ap2']/div[@class='fixedDataTableCellLayout_wrap3 public_fixedD" +
            "ataTableCell_wrap3']/div[@class='name-cell']/a[@class='student" +
            "-name public_fixedDataTableCell_cellContent']")

        found = False
        for student in odd_scores:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                found = True
                break

        if not found:
            for stud in even_scores:
                if stud.text.find(first) >= 0 and stud.text.find(last) >= 0:
                    found = True
                    break

        # Add back to active roster
        self.teacher.open_user_menu()
        self.teacher.find(By.PARTIAL_LINK_TEXT,
                          "Course Settings and Roster").click()
        dropped = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='settings-section dropped-students']/table[@class" +
            "='roster table table-striped table-bordered table-condensed ta" +
            "ble-hover']/tbody/tr")
        index = 0
        for student in dropped:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                self.teacher.driver.find_elements_by_partial_link_text(
                    "Add Back to Active Roster")[index].click()
                self.teacher.sleep(1)
                self.teacher.find(
                    By.XPATH,
                    "//button[@class='-undrop-student btn btn-success']"
                ).click()
                self.teacher.sleep(20)
                break
            index += 1

        if not found:
            self.ps.test_updates['passed'] = True

    # 14850 - 007 - Teacher | In Student Scores view moved students
    @pytest.mark.skipif(str(14850) not in TESTS, reason='Excluded')
    def test_teacher_in_student_scores_view_moved_students_14850(self):
        """In Student Scores view moved students.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Course Settings and Roster" from the calendar dashboard
        Click "Change Period" for the desired student
        Click on the desired period
        Click "Student Scores" from the user menu
        Click on the period to which the student was moved

        Expected Result:
        The user is presented with the moved student under their new period
        """
        self.ps.test_updates['name'] = 't2.07.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.07', 't2.07.007', '14850']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.select_course(appearance='physics')
        self.teacher.open_user_menu()
        self.teacher.find(By.PARTIAL_LINK_TEXT,
                          "Course Settings and Roster").click()
        self.teacher.sleep(5)

        # Move the student to another period
        first = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[1]"
        ).text
        last = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[2]"
        ).text

        self.teacher.find(By.PARTIAL_LINK_TEXT, "Change Period").click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH, "//ul[@class='nav nav-pills nav-stacked']/li/a").click()

        self.teacher.sleep(5)

        # Go to student scores, verify the student is seen
        self.teacher.open_user_menu()
        self.teacher.find(By.PARTIAL_LINK_TEXT, "Student Scores").click()
        self.teacher.sleep(10)
        self.teacher.find(
            By.XPATH,
            "//nav[@class='collapse in']/ul[@class='nav nav-tabs']/li[2]/a"
        ).click()

        odd_scores = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='fixedDataTableRowLayout_main public_fixedData" +
            "TableRow_main public_fixedDataTableRow_even public_fixedDataTa" +
            "ble_bodyRow']/div[@class='fixedDataTableRowLayout_body']/div" +
            "[@class='fixedDataTableCellGroupLayout_cellGroupWrapper'][1]/d" +
            "iv[@class='fixedDataTableCellGroupLayout_cellGroup']/div[@clas" +
            "s='fixedDataTableCellLayout_main public_fixedDataTableCell_" +
            "main'][1]/div[@class='fixedDataTableCellLayout_wrap1 public_fi" +
            "xedDataTableCell_wrap1']/div[@class='fixedDataTableCellLayout_w" +
            "rap2 public_fixedDataTableCell_wrap2']/div[@class='fixedDataTab" +
            "leCellLayout_wrap3 public_fixedDataTableCell_wrap3']/div[@class" +
            "='name-cell']/a[@class='student-name public_fixedDataTableCell" +
            "_cellContent']")
        even_scores = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='fixedDataTableRowLayout_main public_fixedDataTab" +
            "leRow_main public_fixedDataTableRow_highlighted public_fixedDa" +
            "taTableRow_odd public_fixedDataTable_bodyRow']/div[@class='fix" +
            "edDataTableRowLayout_body']/div[@class='fixedDataTableCellGrou" +
            "pLayout_cellGroupWrapper'][1]/div[@class='fixedDataTableCellGr" +
            "oupLayout_cellGroup']/div[@class='fixedDataTableCellLayout_mai" +
            "n public_fixedDataTableCell_main'][1]/div[@class='fixedDataTab" +
            "leCellLayout_wrap1 public_fixedDataTableCell_wrap1']/div[@clas" +
            "s='fixedDataTableCellLayout_wrap2 public_fixedDataTableCell_wr" +
            "ap2']/div[@class='fixedDataTableCellLayout_wrap3 public_fixedD" +
            "ataTableCell_wrap3']/div[@class='name-cell']/a[@class='student" +
            "-name public_fixedDataTableCell_cellContent']")

        found = False
        for student in odd_scores:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                found = True
                break

        if found:
            for stud in even_scores:
                if stud.text.find(first) >= 0 and stud.text.find(last) >= 0:
                    found = True
                    break

        # Add student back to original period
        self.teacher.open_user_menu()
        self.teacher.find(By.PARTIAL_LINK_TEXT,
                          "Course Settings and Roster").click()
        self.teacher.sleep(10)
        self.teacher.find(
            By.XPATH,
            "//div[@class='roster']/div[@class='settings-section periods']" +
            "/ul[@class='nav nav-tabs']/li[2]/a").click()
        roster = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr")
        index = 0
        for student in roster:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                self.teacher.driver.find_elements_by_partial_link_text(
                    "Change Period")[index].click()
                self.teacher.sleep(1)
                self.teacher.find(
                    By.XPATH,
                    "//ul[@class='nav nav-pills nav-stacked']/li/a").click()
                break
            index += 1

        if found:
            self.ps.test_updates['passed'] = True

    # 14658 - 008 - Teacher | Require emails for all students for roster import
    @pytest.mark.skipif(str(14658) not in TESTS, reason='Excluded')
    def test_teacher_require_emails_for_all_students_for_roster_14658(self):
        """Require emails for all students for roster imports.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.07.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.07', 't2.07.008', '14658']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14660 - 009 - Teacher | Set time zone for a course
    @pytest.mark.skipif(str(14660) not in TESTS, reason='Excluded')
    def test_teacher_set_time_zone_for_a_course_14660(self):
        """Set time zone for a course.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Course Settings and Roster"
        Click "Change Course Timezone"
        Select the desired timezone
        Click Save

        Expected Result:
        The time zone is set
        """
        self.ps.test_updates['name'] = 't2.07.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.07', 't2.07.009', '14660']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.select_course(appearance='physics')
        self.teacher.open_user_menu()
        self.teacher.find(By.PARTIAL_LINK_TEXT,
                          "Course Settings and Roster").click()
        self.teacher.sleep(5)

        # Change the timezone
        self.teacher.driver.find_elements_by_xpath(
            "//button[@class='edit-course btn btn-link']")[1].click()
        self.teacher.sleep(2)
        self.teacher.find(By.XPATH,
                          "//div[@class='tutor-radio']/label").click()
        self.teacher.find(
            By.XPATH, "//button[@class='async-button -edit-course-" +
            "confirm btn btn-default']").click()
        self.teacher.sleep(5)

        # Verify the change and change the time back to Central
        self.teacher.driver.find_elements_by_xpath(
            "//button[@class='edit-course btn btn-link']")[1].click()

        assert('Central Time' not in self.teacher.find(
            By.XPATH, "//div[@class='tutor-radio active']/label").text), \
            'Not viewing Concept Coach stats'

        self.teacher.sleep(2)
        options = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='tutor-radio']/label")

        for timezone in options:
            if timezone.text.find('Central Time') >= 0:
                timezone.click()
                break

        self.teacher.find(
            By.XPATH, "//button[@class='async-button -edit-course-" +
            "confirm btn btn-default']").click()

        self.ps.test_updates['passed'] = True

    # 14661 - 010 - System | Distinguish between high school and college
    # courses
    @pytest.mark.skipif(str(14661) not in TESTS, reason='Excluded')
    def test_system_distinguish_between_hs_and_college_courses_14661(self):
        """Distinguish between high school and college courses.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.07.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.07', 't2.07.010', '14661']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 116648 - 011 - Admin | View the start and end dates from the
    # admin console course list
    @pytest.mark.skipif(str(116648) not in TESTS, reason='Excluded')
    def test_admin_view_start_end_dates_from_course_list_116648(self):
        """View the start and end dates from the admin console course list.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.07.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.07', 't2.07.011', '116648']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.admin.login()
        self.admin.goto_admin_control()
        self.admin.sleep(5)
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Course Organization'))).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Courses'))).click()
        self.admin.sleep(3)
        self.admin.find(By.XPATH, "//div[@class='course-duration']")

        self.ps.test_updates['passed'] = True
class TestImproveScoresReporting(unittest.TestCase):
    """T2.08 - Improve Scores Reporting."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(use_env_vars=True,
                               pasta_user=self.ps,
                               capabilities=self.desired_capabilities)

        self.teacher.login()

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    # 14671 - 001 - Teacher | View a Scores Export for my students' work
    @pytest.mark.skipif(str(14671) not in TESTS, reason='Excluded')
    def test_teacher_view_a_scores_export_for_my_students_work_14671(self):
        """View a Scores Export for my students' work.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a Tutor course name
        Click "Student Scores" from calendar dashboard
        Click "Export"

        Expected Result:
        The user is presented with a scores export
        """
        self.ps.test_updates['name'] = 't2.08.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.08', 't2.08.001', '14671']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    '''
    # 14672 - 002 - Teacher | Import Tutor high school Student Scores export
    # into a gradebook
    @pytest.mark.skipif(str(14672) not in TESTS, reason='Excluded')
    def test_teacher_import_tutor_hs_student_scores_export_14672(self):
        """Import Tutor high school Student Scores export into a gradebook.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.08.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.08',
            't2.08.002',
            '14672'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    '''
    '''
    # 14674 - 003 - Teacher | Import Tutor college Student Scores export into
    # an LMS
    @pytest.mark.skipif(str(14674) not in TESTS, reason='Excluded')
    def test_teacher_import_tutor_college_student_scores_14674(self):
        """Import Tutor college Student Scores export into an LMS.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.08.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.08',
            't2.08.003',
            '14674'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    '''
    '''
    # 14826 - 004 - Teacher | Import Tutor college Student Scores into an LMS
    @pytest.mark.skipif(str(14826) not in TESTS, reason='Excluded')
    def test_teacher_import_tutor_college_student_scores_into_lms_14826(self):
        """Import Tutor college Student Scores into an LMS.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.08.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.08',
            't2.08.004',
            '14826'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    '''

    # 14827 - 005 - Teacher | View the overall score column
    @pytest.mark.skipif(str(14827) not in TESTS, reason='Excluded')
    def test_teacher_view_the_overall_score_column_14827(self):
        """View the overall score column.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Student Scores" from calendar dashboard

        Expected Result:
        The user is presented with the overall score column
        """
        self.ps.test_updates['name'] = 't2.08.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.08', 't2.08.005', '14827']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='college_physics')

        assert('course' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.teacher.find(By.PARTIAL_LINK_TEXT, 'Student Scores').click()

        assert('scores' in self.teacher.current_url()), \
            'Not viewing Student Scores'

        self.teacher.sleep(5)

        self.teacher.find(By.XPATH, "//div[@class='overall-header-cell']")

        self.teacher.sleep(5)

        self.ps.test_updates['passed'] = True

    # 14828 - 006 - Teacher | Overall score percentage does not change format
    # when selecting Number in the Percentage/Number toggle
    @pytest.mark.skipif(str(14828) not in TESTS, reason='Excluded')
    def test_teacher_overall_score_percentage_does_not_change_form_14828(self):
        """Overall score percentage does not change format.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Student Scores" from calendar dashboard
        Click "Number"

        Expected Result:
        Overall score percentage does not change format when selecting Number
        in the Percentage/Number toggle
        """
        self.ps.test_updates['name'] = 't2.08.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.08', 't2.08.006', '14828']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='college_physics')

        assert('course' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.teacher.find(By.PARTIAL_LINK_TEXT, 'Student Scores').click()

        assert('scores' in self.teacher.current_url()), \
            'Not viewing Student Scores'

        self.teacher.sleep(5)

        average1 = self.teacher.find(By.XPATH, "//div[@class='average']").text
        self.teacher.find(By.XPATH,
                          "//button[@class='btn btn-sm btn-default']").click()
        self.teacher.sleep(3)
        average2 = self.teacher.find(By.XPATH, "//div[@class='average']").text

        assert(average1 == average2), \
            'Overall average is not the same between percentage and number'

        self.ps.test_updates['passed'] = True

    # 14829 - 007 - Teacher | No score is displayed for readings
    @pytest.mark.skipif(str(14829) not in TESTS, reason='Excluded')
    def test_teacher_no_score_is_displayed_for_reading_14829(self):
        """No score is displayed for readings.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Student Scores" from calendar dashboard
        Look for a reading assignment

        Expected Result:
        The user is presented with progress icon but no score
        """
        self.ps.test_updates['name'] = 't2.08.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.08', 't2.08.007', '14829']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14830 - 008 - Teacher | The class average info icon displays a definition
    # of how class and overall scores are calculated
    @pytest.mark.skipif(str(14830) not in TESTS, reason='Excluded')
    def test_teacher_the_class_average_info_icon_displayed_a_defin_14830(self):
        """The class average info icon displays a definition.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Student Scores" from calendar dashboard
        Click on the info icon next to "Class Average"

        Expected Result:
        The class average info icon displays a definition of how class and
        overall scores are calculated
        """
        self.ps.test_updates['name'] = 't2.08.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.08', 't2.08.008', '14830']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='college_physics')

        assert('course' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.teacher.find(By.PARTIAL_LINK_TEXT, 'Student Scores').click()

        assert('scores' in self.teacher.current_url()), \
            'Not viewing Student Scores'

        self.teacher.sleep(5)
        self.teacher.find(
            By.XPATH,
            "//i[@class='tutor-icon fa fa-info-circle clickable']").click()
        self.teacher.sleep(2)
        self.teacher.find(By.XPATH, "//div[@class='popover-content']")

        self.ps.test_updates['passed'] = True

    # 14831 - 009 - Teacher | Accept late work
    @pytest.mark.skipif(str(14831) not in TESTS, reason='Excluded')
    def test_teacher_accept_late_work_14831(self):
        """Accept late work.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Student Scores" from calendar dashboard
        Click on the orange triangle in the upper right corner of a progress
            cell
        Click "Accept late score"

        Expected Result:
        The late score replaces the score at due date
        """
        self.ps.test_updates['name'] = 't2.08.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.08', 't2.08.009', '14831']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='college_physics')

        assert('course' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.teacher.find(By.PARTIAL_LINK_TEXT, 'Student Scores').click()

        assert('scores' in self.teacher.current_url()), \
            'Not viewing Student Scores'

        self.teacher.sleep(10)

        found = False

        scrollbar = self.teacher.find(
            By.XPATH, "//div[@class='ScrollbarLayout_main " +
            "ScrollbarLayout_mainHorizontal public_Scrollbar_main " +
            "public_Scrollbar_mainOpaque']")
        scrollbar.click()

        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(scrollbar)
        actions.click(scrollbar)
        actions.perform()

        newbar = self.teacher.find(
            By.XPATH, "//div[@class='ScrollbarLayout_main " +
            "ScrollbarLayout_mainHorizontal public_Scrollbar_main " +
            "public_Scrollbar_mainOpaque public_Scrollbar_mainActive']")
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(newbar)
        actions.click(newbar)
        actions.perform()
        scrolls = 0
        # Four arrow rights bring a new assignment into view, try to bring
        # Bring three new assignments into view at a time
        for num in range(100):
            for num1 in range(12):
                newbar.send_keys(Keys.ARROW_RIGHT)
            if len(
                    self.teacher.driver.find_elements_by_xpath(
                        "//div[@class='late-caret']")) > 0:
                for num2 in range(5):
                    newbar.send_keys(Keys.ARROW_RIGHT)
                while not found:
                    try:
                        caret = self.teacher.find(
                            By.XPATH, "//div[@class='late-caret']")

                        self.teacher.sleep(3)
                        caret.click()

                        self.teacher.find(
                            By.XPATH,
                            "//button[@class='late-button btn btn-default']"
                        ).click()
                        """
                        self.teacher.find_elements_by_xpath(
                            By.XPATH, "//div[@class='late-caret accepted']"
                        )[index].click()

                        self.teacher.find(
                            By.XPATH,
                            "//button[@class='late-button btn btn-default']"
                        ).click()
                        """
                        found = True
                        break

                    except:

                        if scrolls == 20:
                            break
                        try:
                            scrollbar = self.teacher.find(
                                By.XPATH,
                                "//div[@class='ScrollbarLayout_main " +
                                "ScrollbarLayout_mainVertical " +
                                "public_Scrollbar_main']")

                            scrollbar.click()

                        except:
                            pass

                        newbar = self.teacher.find(
                            By.XPATH, "//div[@class='ScrollbarLayout_main " +
                            "ScrollbarLayout_mainVertical " +
                            "public_Scrollbar_main " +
                            "public_Scrollbar_mainActive']")

                        actions = ActionChains(self.teacher.driver)
                        actions.move_to_element(newbar)
                        actions.click(newbar)
                        actions.perform()
                        for i in range(3):
                            scrolls += 1
                            newbar.send_keys(Keys.ARROW_DOWN)

                break

        lates = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='late-caret accepted']")

        revert = False
        if found:
            for item in lates:
                try:
                    item.click()
                    self.teacher.find(
                        By.XPATH,
                        "//button[@class='late-button btn btn-default']"
                    ).click()
                    revert = True
                    break

                except:
                    pass

        self.teacher.sleep(5)
        assert(found), \
            'Not found'

        assert(revert), \
            'Didnt revert'

        self.ps.test_updates['passed'] = True

    # 14832 - 010 - Teacher | Un-accept late work
    @pytest.mark.skipif(str(14832) not in TESTS, reason='Excluded')
    def test_teacher_unaccept_late_work_14832(self):
        """Un-accept late work.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Student Scores" from calendar dashboard
        Click on the gray triangle in the upper right corner of a progress cell
        Click "Use this score"

        Expected Result:
        The score is converted back to the score at due date
        """
        self.ps.test_updates['name'] = 't2.08.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.08', 't2.08.010', '14832']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='college_physics')

        assert('course' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.teacher.find(By.PARTIAL_LINK_TEXT, 'Student Scores').click()

        assert('scores' in self.teacher.current_url()), \
            'Not viewing Student Scores'

        self.teacher.sleep(10)

        found = False

        scrollbar = self.teacher.find(
            By.XPATH, "//div[@class='ScrollbarLayout_main " +
            "ScrollbarLayout_mainHorizontal public_Scrollbar_main " +
            "public_Scrollbar_mainOpaque']")
        scrollbar.click()

        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(scrollbar)
        actions.click(scrollbar)
        actions.perform()

        newbar = self.teacher.find(
            By.XPATH, "//div[@class='ScrollbarLayout_main " +
            "ScrollbarLayout_mainHorizontal public_Scrollbar_main " +
            "public_Scrollbar_mainOpaque public_Scrollbar_mainActive']")
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(newbar)
        actions.click(newbar)
        actions.perform()
        scrolls = 0
        # Four arrow rights bring a new assignment into view, try to bring
        # Bring three new assignments into view at a time
        for num in range(100):
            for num1 in range(12):
                newbar.send_keys(Keys.ARROW_RIGHT)
            if len(
                    self.teacher.driver.find_elements_by_xpath(
                        "//div[@class='late-caret accepted']")) > 0:
                for num2 in range(3):
                    newbar.send_keys(Keys.ARROW_RIGHT)
                while not found:
                    try:

                        caret = self.teacher.find(
                            By.XPATH, "//div[@class='late-caret accepted']")
                        self.teacher.sleep(2)
                        caret.click()
                        self.teacher.sleep(5)

                        self.teacher.find(
                            By.XPATH,
                            "//button[@class='late-button btn btn-default']"
                        ).click()
                        self.teacher.sleep(5)
                        """
                        self.teacher.find_elements_by_xpath(
                            By.XPATH, "//div[@class='late-caret accepted']"
                        )[index].click()

                        self.teacher.find(
                            By.XPATH,
                            "//button[@class='late-button btn btn-default']"
                        ).click()
                        """
                        found = True
                        break

                    except:

                        if scrolls == 20:
                            break
                        try:
                            scrollbar = self.teacher.find(
                                By.XPATH,
                                "//div[@class='ScrollbarLayout_main " +
                                "ScrollbarLayout_mainVertical " +
                                "public_Scrollbar_main']")

                            scrollbar.click()

                        except:
                            pass

                        newbar = self.teacher.find(
                            By.XPATH, "//div[@class='ScrollbarLayout_main " +
                            "ScrollbarLayout_mainVertical " +
                            "public_Scrollbar_main " +
                            "public_Scrollbar_mainActive']")

                        actions = ActionChains(self.teacher.driver)
                        actions.move_to_element(newbar)
                        actions.click(newbar)
                        actions.perform()
                        for i in range(1):
                            scrolls += 1
                            newbar.send_keys(Keys.ARROW_DOWN)

                break

        lates = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='late-caret']")

        revert = False
        if found:
            for item in lates:
                try:
                    item.click()
                    self.teacher.find(
                        By.XPATH,
                        "//button[@class='late-button btn btn-default']"
                    ).click()
                    revert = True
                    break

                except:
                    pass

        self.teacher.sleep(5)
        assert(found), \
            'Not found'

        assert(revert), \
            'Didnt revert'

        self.ps.test_updates['passed'] = True

    # 14833 - 011 - Teacher | When accepting late work, the progress icon
    # changes to reflect the last worked progress
    @pytest.mark.skipif(str(14833) not in TESTS, reason='Excluded')
    def test_teacher_when_accepting_late_work_the_progress_icon_ch_14833(self):
        """The progress icon changes to reflect the last worked progress.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Student Scores" from calendar dashboard
        Click on the orange triangle in the upper right corner of a
            progress cell
        Click "Accept late score"

        Expected Result:
        The progress icon changes to reflect the last worked progress
        """
        self.ps.test_updates['name'] = 't2.08.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.08', 't2.08.011', '14833']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.select_course(appearance='college_physics')

        assert('course' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.teacher.find(By.PARTIAL_LINK_TEXT, 'Student Scores').click()

        assert('scores' in self.teacher.current_url()), \
            'Not viewing Student Scores'

        self.teacher.sleep(10)

        found = False

        # Setup scrollbar for scrolling
        scrollbar = self.teacher.find(
            By.XPATH, "//div[@class='ScrollbarLayout_main " +
            "ScrollbarLayout_mainHorizontal public_Scrollbar_main " +
            "public_Scrollbar_mainOpaque']")
        scrollbar.click()

        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(scrollbar)
        actions.click(scrollbar)
        actions.perform()

        newbar = self.teacher.find(
            By.XPATH, "//div[@class='ScrollbarLayout_main " +
            "ScrollbarLayout_mainHorizontal public_Scrollbar_main " +
            "public_Scrollbar_mainOpaque public_Scrollbar_mainActive']")
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(newbar)
        actions.click(newbar)
        actions.perform()
        scrolls = 0

        p = False
        for i in range(6):
            newbar.send_keys(Keys.PAGE_UP)
        self.teacher.sleep(3)
        # Four arrow rights bring a new assignment into view, try to bring
        # Bring three new assignments into view at a time
        for num in range(100):
            for num1 in range(12):
                newbar.send_keys(Keys.ARROW_RIGHT)
            if len(
                    self.teacher.driver.find_elements_by_xpath(
                        "//div[@class='late-caret']")) > 0:
                for num2 in range(3):
                    newbar.send_keys(Keys.ARROW_RIGHT)

                while not found:
                    try:
                        caret = self.teacher.find(
                            By.XPATH, "//div[@class='late-caret']")

                        try:
                            parent = caret.find_element_by_xpath(
                                "..").find_element_by_xpath("..")
                        except:
                            pass
                        try:
                            worked = parent.find_element_by_class_name(
                                "worked")
                        except:
                            pass
                        try:
                            not_started = worked.find_elements_by_class_name(
                                "not-started")
                        except:
                            pass

                        try:
                            if len(worked.find_elements_by_tag_name(
                                    'path')) > 0:
                                p = True

                        except:
                            pass

                        caret1 = caret.find_element_by_xpath("..")

                        caret1.click()
                        self.teacher.find(
                            By.XPATH,
                            "//button[@class='late-button btn btn-default']"
                        ).click()
                        found = True
                        break

                    # Scroll down if the late assignment is not immediately
                    # visible, continue to scroll until found
                    except:

                        if scrolls == 20:
                            break
                        try:
                            scrollbar = self.teacher.find(
                                By.XPATH,
                                "//div[@class='ScrollbarLayout_main " +
                                "ScrollbarLayout_mainVertical " +
                                "public_Scrollbar_main']")

                            scrollbar.click()

                        except:
                            pass

                        newbar = self.teacher.find(
                            By.XPATH, "//div[@class='ScrollbarLayout_main " +
                            "ScrollbarLayout_mainVertical " +
                            "public_Scrollbar_main " +
                            "public_Scrollbar_mainActive']")

                        actions = ActionChains(self.teacher.driver)
                        actions.move_to_element(newbar)
                        actions.click(newbar)
                        actions.perform()
                        for i in range(1):
                            scrolls += 1
                            newbar.send_keys(Keys.ARROW_DOWN)

                break

        revert = False
        diff = False

        # Case if assignment was not started at all before due date
        if len(not_started) > 0:
            slice_late = worked.find_elements_by_tag_name('circle')
            assert(slice_late[0].get_attribute('class') == 'slice late'), \
                'No change'

            diff = True

        # Case if assignment was partially complete before due date
        else:
            assert (p)
            assert(len(worked.find_elements_by_tag_name('path')) == 0), \
                'No change'

            diff = True

        assert(diff), \
            'No change'

        item = worked.find_element_by_xpath(
            "//div[@class='late-caret accepted']")

        item.click()
        self.teacher.find(
            By.XPATH,
            "//button[@class='late-button btn btn-default']").click()
        revert = True

        self.teacher.sleep(5)
        assert(found), \
            'Not found'

        assert(revert), \
            'Didnt revert'

        self.ps.test_updates['passed'] = True

    # 14834 - 012 - Teacher | Assignments that are not due yet are not
    # displayed
    @pytest.mark.skipif(str(14834) not in TESTS, reason='Excluded')
    def test_teacher_assignments_that_are_not_due_yet_are_not_disp_14834(self):
        """Assignment that is not due yet is not displayed.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.08.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.08', 't2.08.012', '14834']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14835 - 013 - Teacher | Supress columns in Score Report
    @pytest.mark.skipif(str(14835) not in TESTS, reason='Excluded')
    def test_teacher_suppress_columns_in_score_report_14835(self):
        """Supress columns in Score Report.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.08.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.08', 't2.08.013', '14835']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14836 - 014 - Teacher | External assignments are not included in the
    # scores export
    @pytest.mark.skipif(str(14836) not in TESTS, reason='Excluded')
    def test_teacher_external_assignments_are_not_included_in_the_14836(self):
        """External assignments are not included in the scores export.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Student Scores" from calendar dashboard
        Click "Export"

        Expected Result:
        External assignments are not included in the scores export
        """
        self.ps.test_updates['name'] = 't2.08.014' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.08', 't2.08.014', '14836']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
class TestIImproveQuestionManagement(unittest.TestCase):
    """CC2.11 - Improve Question Management."""

    def setUp(self):
        """Pretest settings."""

        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.student = Student(
            use_env_vars=True,
            existing_driver=self.teacher.driver,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        self.student = None
        try:
            self.teacher.delete()
        except:
            pass

    # 14851 - 001 - Teacher | Review all questions
    @pytest.mark.skipif(str(14851) not in TESTS, reason='Excluded')
    def test_teacher_review_all_questions_14851(self):
        """Review all questions.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click "Question Library" from the user menu
        Select a section or chapter
        Click "Show Questions"

        Expected Result:
        The user is presented with all the questions for the section or chapter
        """
        self.ps.test_updates['name'] = 'cc2.11.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.001', '14851']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Question Library'
        ).click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.1"]'
        ).click()
        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.find(
            By.XPATH, '//button[text()="Show Questions"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="exercises"]')
            )
        )
        self.ps.test_updates['passed'] = True

    # 14852 - 002 - Teacher | Exclude certain questions
    @pytest.mark.skipif(str(14852) not in TESTS, reason='Excluded')
    def test_teacher_exclude_certain_questions_14852(self):
        """Exclude certain quesitons.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Question Library" from the user menu
        Select a section or chapter
        Click "Show Questions"
        Hover over the desired question and click "Exclude question"

        Expected Result:
        Question is grayed out
        """
        self.ps.test_updates['name'] = 'cc2.11.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.002', '14852']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Question Library'
        ).click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.2"]'
        ).click()
        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.find(
            By.XPATH, '//button[text()="Show Questions"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="exercises"]')
            )
        )
        self.teacher.sleep(1)
        i = 1
        question = None
        # loop finding a question that is not yet excleded
        # there are 9 question in the exact textbook and chpater this test
        # is searching. limiting loop at 7 incase questions are removed.
        while i < 8:
            question = self.teacher.find(
                By.XPATH,
                '//div[@class="exercises"]/div[' + str(i) + ']'
            )
            if ('is-selected' not in question.get_attribute('class')):
                break
            i += 1
        Assignment.scroll_to(self.teacher.driver, question)
        self.teacher.sleep(1)
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(question)
        # way to stall because not sure how to add wait in action chain
        for _ in range(50):
            actions.move_by_offset(-1, 0)
        actions.click()
        actions.move_by_offset(-50, -300)
        actions.perform()
        self.teacher.sleep(0.5)
        question_excluded = self.teacher.find(
            By.XPATH, '//div[@class="exercises"]/div[' + str(i) + ']'
        ).get_attribute('class')
        assert('is-selected' in question_excluded), 'question not excluded'
        self.ps.test_updates['passed'] = True

    # 14855 - 003 - Teacher | Pin tabs on top of screen when scrolled
    @pytest.mark.skipif(str(14855) not in TESTS, reason='Excluded')
    def test_teacher_pin_tabs_on_top_of_screen_when_scrolled_14855(self):
        """Pin tabs on top of screen when scrolled.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Question Library" from the user menu
        Select a section or chapter
        Click "Show Questions"
        Scroll down

        Expected Result:
        Tabs are pinned to top of the screen when scrolled
        """
        self.ps.test_updates['name'] = 'cc2.11.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.003', '14855']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Question Library'
        ).click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.2"]'
        ).click()
        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.find(
            By.XPATH, '//button[text()="Show Questions"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="exercises"]')
            )
        )
        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="pinned-header"]')
            )
        )
        self.ps.test_updates['passed'] = True

    # 14856 - 004 - Teacher | Make section links jumpable
    @pytest.mark.skipif(str(14856) not in TESTS, reason='Excluded')
    def test_teacher_make_section_links_jumpable_14856(self):
        """Make section links jumpable.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Question Library" from the user menu
        Select a section or chapter
        Click "Show Questions"
        Click on the section links at the top of the screen

        Expected Result:
        The screen scrolls to the selected questions
        """
        self.ps.test_updates['name'] = 'cc2.11.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.004', '14856']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Question Library'
        ).click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.2"]'
        ).click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.1"]'
        ).click()

        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.find(
            By.XPATH, '//button[text()="Show Questions"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="exercises"]')
            )
        )
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="pinned-header"]'
                 '//div[@class="section" and text()="1.2"]')
            )
        ).click()
        self.teacher.sleep(1)
        # click the heading as simple way to find that it is on screen
        # and not just visible but scrolled off screen
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="exercise-sections"]' +
                 '//span[@class="chapter-section" ' +
                 'and @data-chapter-section="1.2"]')
            )
        ).click()
        self.ps.test_updates['passed'] = True

    # 14858 - 005 - Teacher | Report errata about assessments in Concept Coach
    @pytest.mark.skipif(str(14858) not in TESTS, reason='Excluded')
    def test_teacher_report_errata_about_assessments_in_cc_14858(self):
        """Report errata about assessments in Concept Coach.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Question Library" from the user menu
        Select a section or chapter
        Click "Show Questions"
        Hover over the desired question and click "Question details"
        Click "Report an error"

        Expected Result:
        A new tab with the assessment errata form appears, with the assessment
        ID already filled in
        """
        self.ps.test_updates['name'] = 'cc2.11.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.005', '14858']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"/cc-dashboard")]'
        ).click()
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Question Library'
        ).click()
        self.teacher.find(
            By.XPATH,
            '//div[@class="section"]//span[@class="chapter-section" ' +
            'and @data-chapter-section="1.2"]'
        ).click()
        self.teacher.driver.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        self.teacher.find(
            By.XPATH, '//button[text()="Show Questions"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="exercises"]')
            )
        )
        self.teacher.sleep(1)
        question = self.teacher.find(
            By.XPATH, '//div[@class="exercises"]/div[1]'
        )
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(question)
        # way to stall because not sure how to add wait in action chain
        for _ in range(50):
            actions.move_by_offset(1, 0)
        actions.click()
        actions.perform()
        self.teacher.sleep(0.5)
        exercise_id = self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//span[@class="exercise-tag" and contains(text(),"ID:")]')
            )
        ).text
        question = self.teacher.find(
            By.XPATH, '//div[@class="action report-error"]'
        ).click()
        window_with_form = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_form)
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[text()="Report Content Errors"]')
            )
        )
        self.teacher.find(
            By.XPATH, '//input[@value="' + exercise_id[4:] + '"]')

        self.ps.test_updates['passed'] = True

    # 14859 - 006 - Student | Report errata about assessments in Concept Coach
    @pytest.mark.skipif(str(14859) not in TESTS, reason='Excluded')
    def test_student_report_errata_about_assessments_in_cc_14859(self):
        """Report errata about assessments in Concept Coach.

        Steps:
        Click on a CC course, if there are more than one
        Click on a non-introductory section
        Click "Jump to Concept Coach"
        Click "Launch Concept Coach"
        Click "Report an error" on an assessment

        Expected Result:
        A new tab with the assessment errata form appears, with the assessment
        ID already filled in
        """
        self.ps.test_updates['name'] = 'cc2.11.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.11', 'cc2.11.006', '14859']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        # raise NotImplementedError(inspect.currentframe().f_code.co_name)
        self.student.login()
        self.teacher.find(
            By.XPATH, '//a[contains(@href,"cnx.org/contents/")]'
        ).click()
        # get to non-into section
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//button//span[text()="Contents"]')
            )
        ).click()
        self.student.sleep(0.5)
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, '//span[@class="chapter-number" and text()="1.1"]')
            )
        ).click()
        # open concept coach
        self.student.wait.until(
            expect.element_to_be_clickable(
                (By.LINK_TEXT, 'Jump to Concept Coach')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[text()="Launch Concept Coach"]')
            )
        ).click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//span[contains(@class,"core breadcrumb-exercise")]')
            )
        ).click()
        exercise_id = self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//span[@class="exercise-identifier-link"]' +
                 '/span[contains(text(),"@")]')
            )
        ).text
        self.teacher.find(By.LINK_TEXT, 'Report an error').click()
        window_with_form = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_form)
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[text()="Report Content Errors"]')
            )
        )
        self.teacher.find(
            By.XPATH, '//input[@value="' + exercise_id + '"]')
        self.ps.test_updates['passed'] = True
class TestAnalyzeCollegeWorkflow(unittest.TestCase):
    """T2.05 - Analyze College Workflow."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.student = Student(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities,
            existing_driver=self.teacher.driver
        )

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.student = None
            self.teacher.delete()
        except:
            pass

    # 14645 - 001 - Student | All work is visible for college students
    # not just "This Week"
    @pytest.mark.skipif(str(14645) not in TESTS, reason='Excluded')
    def test_student_all_work_is_visible_for_college_students_14645(self):
        """All work is visible for college students, not just 'This Week'.

        Steps:
        Log into tutor-qa as student
        Click on a college course

        Expected Result:
        Can view assignments due later than this week
        """
        self.ps.test_updates['name'] = 't2.05.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.05',
            't2.05.001',
            '14645'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.login()
        self.student.select_course(appearance='physics')
        assert('list/' in self.student.current_url()), \
            'Not viewing the calendar dashboard'

        self.student.sleep(5)

        page = self.student.driver.page_source
        assert('Coming Up' in page or 'No upcoming events' in page), \
            'No Coming Up/No upcoming events text is visible/present'

        self.ps.test_updates['passed'] = True

    # 14646 - 002 - Teacher | Create a link to the OpenStax Dashboard
    @pytest.mark.skipif(str(14646) not in TESTS, reason='Excluded')
    def test_teacher_create_a_link_to_the_openstax_dashboard_14646(self):
        """Create a link to the OpenStax Dashboard.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.05.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.05',
            't2.05.002',
            '14646'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14647 - 003 - Teacher | Create a link to the OpenStax Dashboard
    @pytest.mark.skipif(str(14647) not in TESTS, reason='Excluded')
    def test_teacher_create_a_link_to_the_openstax_dashboard_14647(self):
        """Create a link to the OpenStax Dashboard.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.05.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.05',
            't2.05.003',
            '14647'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14648 - 004 - Teacher | Create links to assigned readings in their LMS
    @pytest.mark.skipif(str(14648) not in TESTS, reason='Excluded')
    def test_teacher_create_links_to_assigned_readings_in_lms_14648(self):
        """Create links to assigned readings in their LMS.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click on a published reading assignment on the calendar dashboard
        Click "Get Assignment Link"

        Expected Result:
        The user is presented with links to assigned readings
        """
        self.ps.test_updates['name'] = 't2.05.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.05',
            't2.05.004',
            '14648'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()

        self.teacher.select_course(appearance='physics')
        assert('calendar' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.ID, 'add-assignment')
            )
        ).click()
        self.teacher.find(By.PARTIAL_LINK_TEXT, 'Add Reading').click()
        assert('readings' in self.teacher.current_url()), \
            'Not on the add a homework page'

        self.teacher.find(
            By.XPATH, "//input[@id = 'reading-title']").send_keys('Epic 5-4')
        self.teacher.find(
            By.XPATH, "//input[@id = 'hide-periods-radio']").click()

        # Choose the second date calendar[1], first is calendar[0]
        self.teacher.driver.find_elements_by_xpath(
            "//div[@class = 'datepicker__input-container']")[1].click()
        while(self.teacher.find(
            By.XPATH,
            "//span[@class = 'datepicker__current-month']"
        ).text != 'December 2016'):
            self.teacher.find(
                By.XPATH, "//a[@class = 'datepicker__navigation datepicker__" +
                "navigation--next']").click()

        # Choose the due date of December 31, 2016
        weekends = self.teacher.driver.find_elements_by_xpath(
            "//div[@class = 'datepicker__day datepicker__day--weekend']")
        for day in weekends:
            if day.text == '31':
                due = day
                due.click()
                break

        self.teacher.sleep(3)

        # Choose reading sections
        self.teacher.find(
            By.XPATH, "//button[@id='reading-select']").click()
        self.teacher.find(
            By.XPATH, "//span[@class = 'chapter-checkbox']").click()
        self.teacher.find(
            By.XPATH,
            "//button[@class='-show-problems btn btn-primary']").click()
        self.teacher.sleep(10)

        # Publish the assignment
        self.teacher.driver.execute_script('window.scrollBy(0, -200);')
        self.teacher.find(
            By.XPATH,
            "//button[@class='async-button -publish btn btn-primary']").click()

        # Give the assignment time to publish
        self.teacher.sleep(60)

        assert('calendar' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        spans = self.teacher.driver.find_elements_by_tag_name('span')
        for element in spans:
            if element.text.endswith('2016'):
                month = element

        # Change the calendar date if necessary
        while (month.text != 'December 2016'):
            self.teacher.find(
                By.XPATH,
                "//a[@class = 'calendar-header-control next']").click()

        # Select the newly created assignment, get the LMS link, and delete it
        assignments = self.teacher.driver.find_elements_by_tag_name('label')
        for assignment in assignments:
            if assignment.text == 'Epic 5-4':
                assignment.click()
                self.teacher.find(
                    By.PARTIAL_LINK_TEXT, "Get assignment link").click()
                self.teacher.find(
                    By.XPATH,
                    "//div[@class = 'fade in lms-sharable-link popover top']")
                self.teacher.sleep(5)
                self.teacher.find(
                    By.XPATH,
                    "//a[@class='btn btn-default -edit-assignment']").click()
                self.teacher.sleep(5)
                self.teacher.find(
                    By.XPATH,
                    "//button[@class='async-button delete-link pull-" +
                    "right btn btn-default']").click()
                self.teacher.find(
                    By.XPATH, "//button[@class='btn btn-primary']").click()
                self.teacher.sleep(5)
                break

        self.teacher.driver.refresh()
        deleted = True

        # Verfiy the assignment was deleted
        spans = self.teacher.driver.find_elements_by_tag_name('span')
        for element in spans:
            if element.text.endswith('2016'):
                month = element

        while (month.text != 'December 2016'):
            self.teacher.find(
                By.XPATH,
                "//a[@class = 'calendar-header-control next']").click()

        assignments = self.teacher.driver.find_elements_by_tag_name('label')
        for assignment in assignments:
            if assignment.text == 'Epic 5-4':
                deleted = False
                break

        if deleted:
            self.ps.test_updates['passed'] = True

    # 14649 - 005 - Teacher | Create links to assigned homework in their LMS
    @pytest.mark.skipif(str(14649) not in TESTS, reason='Excluded')
    def test_teacher_create_links_to_assigned_homework_in_lms_14649(self):
        """Create links to assigned homework in their LMS.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click on a published homework assignment on the calendar dashboard
        Click "Get Assignment Link"

        Expected Result:
        The user is presented with links to assigned homework
        """
        self.ps.test_updates['name'] = 't2.05.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.05',
            't2.05.005',
            '14649'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()

        self.teacher.select_course(appearance='physics')
        assert('calendar' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.ID, 'add-assignment')
            )
        ).click()
        self.teacher.find(By.PARTIAL_LINK_TEXT, 'Add Homework').click()
        assert('homeworks' in self.teacher.current_url()), \
            'Not on the add a homework page'

        self.teacher.find(
            By.XPATH, "//input[@id = 'reading-title']").send_keys('Epic 5-5')
        self.teacher.find(
            By.XPATH, "//input[@id = 'hide-periods-radio']").click()

        # Choose the second date calendar[1], first is calendar[0]
        self.teacher.driver.find_elements_by_xpath(
            "//div[@class = 'datepicker__input-container']")[1].click()
        while(self.teacher.find(
            By.XPATH,
            "//span[@class = 'datepicker__current-month']"
        ).text != 'December 2016'):
            self.teacher.find(
                By.XPATH, "//a[@class = 'datepicker__navigation datepicker__" +
                "navigation--next']").click()

        # Choose the due date of December 31, 2016
        weekends = self.teacher.driver.find_elements_by_xpath(
            "//div[@class = 'datepicker__day datepicker__day--weekend']")
        for day in weekends:
            if day.text == '31':
                due = day
                due.click()
                break

        self.teacher.sleep(3)

        # Open the select problem cards
        self.teacher.find(
            By.XPATH, "//button[@id = 'problems-select']").click()
        self.teacher.find(
            By.XPATH, "//span[@class = 'chapter-checkbox']").click()
        self.teacher.find(
            By.XPATH,
            "//button[@class='-show-problems btn btn-primary']").click()
        self.teacher.sleep(10)

        # Choose a problem for the assignment
        element = self.teacher.find(
            By.XPATH, "//div[@class = 'controls-overlay'][1]")
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(element)
        actions.perform()
        self.teacher.find(By.XPATH, "//div[@class = 'action include']").click()
        self.teacher.find(
            By.XPATH,
            "//button[@class='-review-exercises btn btn-primary']").click()
        self.teacher.sleep(2)

        # Publish the assignment
        self.teacher.driver.execute_script('window.scrollBy(0, -200);')
        self.teacher.find(
            By.XPATH,
            "//button[@class='async-button -publish btn btn-primary']").click()

        # Give the assignment time to publish
        self.teacher.sleep(60)

        assert('calendar' in self.teacher.current_url()), \
            'Not viewing the calendar dashboard'

        spans = self.teacher.driver.find_elements_by_tag_name('span')
        for element in spans:
            if element.text.endswith('2016'):
                month = element

        # Change the calendar date if necessary
        while (month.text != 'December 2016'):
            self.teacher.find(
                By.XPATH,
                "//a[@class = 'calendar-header-control next']").click()

        # Select the newly created assignment, get the LMS link, and delete it
        assignments = self.teacher.driver.find_elements_by_tag_name('label')
        for assignment in assignments:
            if assignment.text == 'Epic 5-5':
                assignment.click()
                self.teacher.find(
                    By.PARTIAL_LINK_TEXT, "Get assignment link").click()
                self.teacher.find(
                    By.XPATH,
                    "//div[@class = 'fade in lms-sharable-link popover top']")
                self.teacher.sleep(5)
                self.teacher.find(
                    By.XPATH,
                    "//a[@class='btn btn-default -edit-assignment']").click()
                self.teacher.sleep(5)
                self.teacher.find(
                    By.XPATH,
                    "//button[@class='async-button delete-link pull-" +
                    "right btn btn-default']").click()
                self.teacher.find(
                    By.XPATH, "//button[@class='btn btn-primary']").click()
                self.teacher.sleep(5)
                break

        self.teacher.driver.refresh()
        deleted = True

        # Verfiy the assignment was deleted
        spans = self.teacher.driver.find_elements_by_tag_name('span')
        for element in spans:
            if element.text.endswith('2016'):
                month = element

        while (month.text != 'December 2016'):
            self.teacher.find(
                By.XPATH,
                "//a[@class = 'calendar-header-control next']").click()

        assignments = self.teacher.driver.find_elements_by_tag_name('label')
        for assignment in assignments:
            if assignment.text == 'Epic 5-5':
                deleted = False
                break

        if deleted:
            self.ps.test_updates['passed'] = True

    # 14650 - 006 - Teacher | View instructions on how to export summary grade
    # for my student's OpenStax practice to my LMS
    @pytest.mark.skipif(str(14650) not in TESTS, reason='Excluded')
    def test_teacher_view_instructions_on_how_to_export_summary_14650(self):
        """View instructions on how to export summary grade into LMS.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.05.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.05',
            't2.05.006',
            '14650'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
class TestCreateNewQuestionAndAssignmentTypes(unittest.TestCase):
    """T2.12 - Create New Question and Assignment Types."""

    def setUp(self):
        """Pretest settings."""

        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.student = Student(
            use_env_vars=True,
            existing_driver=self.teacher.driver,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        self.student = None
        try:
            self.teacher.delete()
        except:
            pass

    # 14739 - 001 - Teacher | Vocabulary question is a question type
    @pytest.mark.skipif(str(14739) not in TESTS, reason='Excluded')
    def test_teacher_vocabulary_question_is_a_question_type_14739(self):
        """Vocabulary question is a question type.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher account in the username and password text boxes
        Click on the 'Sign in' button
        Click "Write a new exercise"
        Click "New Vocabulary Term"

        Expected Result:
        The user is presented with a page where a new vocabulary question can
        be created
        """
        self.ps.test_updates['name'] = 't2.12.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.12', 't2.12.001', '14739']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get("https://exercises-qa.openstax.org/")
        # login
        self.teacher.find(
            By.XPATH, '//div[@id="account-bar-content"]//a[text()="Sign in"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'auth_key'
        ).send_keys(self.teacher.username)
        self.teacher.find(
            By.ID, 'password'
        ).send_keys(self.teacher.password)
        self.teacher.find(
            By.XPATH, '//button[text()="Sign in"]'
        ).click()
        # create new vocab
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//a[@href="/exercises/new"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[text()="New Vocabulary Term"]')
            )
        ).click()
        assert('/vocabulary/new' in self.teacher.current_url()), \
            'not at new vocab page'

        self.ps.test_updates['passed'] = True

    # 14741 - 002 - Teacher | True/False is a question type
    @pytest.mark.skipif(str(14741) not in TESTS, reason='Excluded')
    def test_teacher_truefalse_is_a_question_type_14741(self):
        """True/False is a question type.

        Steps:
        Click "Write a new exercise"
        Click on the "True/False" radio button

        Expected Result:
        The user is presented with a page where a True/False question can be
        created
        """
        self.ps.test_updates['name'] = 't2.12.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.12', 't2.12.002', '14741']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get("https://exercises-qa.openstax.org/")
        # login
        self.teacher.find(
            By.XPATH, '//div[@id="account-bar-content"]//a[text()="Sign in"]'
        ).click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.ID, 'auth_key'
        ).send_keys(self.teacher.username)
        self.teacher.find(
            By.ID, 'password'
        ).send_keys(self.teacher.password)
        self.teacher.find(
            By.XPATH, '//button[text()="Sign in"]'
        ).click()
        # create new vocab
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH, '//a[@href="/exercises/new"]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//input[@label="True/False"]')
            )
        ).click()
        self.teacher.find(
            By.XPATH, '//span[text()="True/False"]'
        )
        self.ps.test_updates['passed'] = True

    # possibly changed implementation on site
    # no info icon found
    # 14742 - 003 - System | Display embedded videos with attribution and link
    # back to author
    @pytest.mark.skipif(str(14742) not in TESTS, reason='Excluded')
    def test_system_display_embedded_videos_with_attribution_14742(self):
        """Display embedded videos with attribution and a link back to author.

        Steps:
        Go to Tutor
        Click Login
        Sign in as student01
        Click "HS AP Physics LG"
        Click on a homework assignment
        Click through it until you get to a video
        Click on the info icon on the video

        Expected Result:
        Attribution and links are displayed
        """
        self.ps.test_updates['name'] = 't2.12.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.12', 't2.12.003', '14742']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # NOT DONE
    # create hw helper still not working
    # but works for manually created assignemnt, add assignemnt commented out
    # 14743 - 004 - Teacher | Each part of a multi-part question counts as a
    # seperate problem when scored
    @pytest.mark.skipif(str(14743) not in TESTS, reason='Excluded')
    def test_teacher_each_part_of_a_multipart_question_counts_as_14743(self):
        """Multi-part questions count as seperate problems when scored.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Log in as teacher03
        Click "College Introduction to Sociology"
        Go to "Student Scores"
        Pick a homework that has multipart question
        Click "Review"

        Expected Result:
        There is a breadcrumb for each part of a multipart question
        """
        self.ps.test_updates['name'] = 't2.12.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.12', 't2.12.004', '14743']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        # create a hw with a multi part question, and gice it a randomized name
        # ID: 12061@6 is multi part
        self.teacher.login()
        self.teacher.find(
            By.XPATH,
            '//div[@data-appearance="intro_sociology"]' +
            '//a[not(contains(@href,"/cc-dashboard"))]'
        ).click()
        assignment_name = "homework-%s" % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=0)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=100)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(
            assignment='homework',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'problems': {'1.1': ['12024@10'], },
                'status': 'publish',
            }
        )
        self.teacher.open_user_menu()
        self.teacher.find(
            By.LINK_TEXT, 'Student Scores'
        ).click()
        self.teacher.page.wait_for_page_load()
        # can just click the first review because assignemnt just created
        # and should be the most recent one
        self.teacher.find(
            By.LINK_TEXT, 'Review'
        ).click()
        cards = self.teacher.find_all(
            By.XPATH, '//div[contains(@class,"card-body")]')
        questions = self.teacher.find_all(
            By.XPATH, '//div[contains(@class,"openstax-question")]')
        breadcrumbs = self.teacher.find_all(
            By.XPATH, '//span[contains(@class,"openstax-breadcrumb")]')
        assert(len(questions) == len(breadcrumbs)), \
            'breadcrumbs and questions not equal'
        assert(len(cards) < len(breadcrumbs)), \
            'multipart question card has multiple questions,' + \
            'not matching up with  breadcrumbs'

        self.ps.test_updates['passed'] = True

    # NOT DONE
    # same issue as above w/ add_homework helper
    # but works for manually created assignemnt
    # (add assignemnt gets commented out, manual assignemnt name added)
    # 14744 - 005 - Student | Each part of a multi-part question counts as a
    # seperate problem when scored
    @pytest.mark.skipif(str(14744) not in TESTS, reason='Excluded')
    def test_student_each_part_of_a_multipart_question_counts_as_14744(self):
        """Multi-part questions count as seperate problems when scored.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Log in as abarnes
        Click "College Introduction to Sociology"
        Click on a homework assignment
        Go through the questions

        Expected Result:
        There is a breadcrumb for each part in the multipart question and the
        progress/score is out of the total number of questions, rather than
        counting the multipart question as one question
        """
        self.ps.test_updates['name'] = 't2.12.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t2', 't2.12', 't2.12.005', '14744']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        # create a hw with a multi part question, and give it a randomized name
        # ID: 12252@5 is multi part
        self.teacher.login()
        self.teacher.find(
            By.XPATH,
            '//div[@data-appearance="intro_sociology"]' +
            '//a[not(contains(@href,"/cc-dashboard"))]'
        ).click()
        assignment_name = "homework-%s" % randint(100, 999)
        today = datetime.date.today()
        begin = (today + datetime.timedelta(days=0)).strftime('%m/%d/%Y')
        end = (today + datetime.timedelta(days=100)).strftime('%m/%d/%Y')
        self.teacher.add_assignment(
            assignment='homework',
            args={
                'title': assignment_name,
                'description': 'description',
                'periods': {'all': (begin, end)},
                'problems': {'1.1': ['12024@10'], },
                'status': 'publish',
            }
        )
        self.teacher.logout()
        # assignemnt name put here for manual testing
        # assignment_name = 'hw w/ video and multi part question'
        # login as student and go to same class
        self.student.login()
        self.teacher.find(
            By.XPATH,
            '//div[@data-appearance="intro_sociology"]' +
            '//a[not(contains(@href,"/cc-dashboard"))]'
        ).click()
        self.student.page.wait_for_page_load()
        # go to assignment (find my assignemnt_name)
        self.student.find(
            By.XPATH,
            '//a[contains(@class,"homework workable")]' +
            '//span[text()="' + assignment_name + '"]'
        ).click()
        # go through all questions
        breadcrumbs = self.teacher.find_all(
            By.XPATH,
            '//span[contains(@class,"openstax-breadcrumb")' +
            ' and not(contains(@class,"intro"))' +
            ' and not(contains(@class,"personalized"))'
            ' and not(contains(@class,"end"))]')
        total_questions = 0
        found_multipart = False
        i = 0
        while i < len(breadcrumbs):
            breadcrumbs[i].click()
            try:
                self.student.find(
                    By.XPATH, '//span[text()="Multi-part question"]')
                found_multipart = True
                questions = self.teacher.find_all(
                    By.XPATH, '//div[contains(@class,"openstax-question")]')
                total_questions += len(questions)
                i += len(questions)
            except NoSuchElementException:
                i += 1
                questions = self.teacher.find_all(
                    By.XPATH, '//div[contains(@class,"openstax-question")]')
                total_questions += len(questions)
        # check that everything worked out
        assert(found_multipart), 'no multipart question found'
        assert(total_questions == len(breadcrumbs)), \
            'breadcrumbs and questions not equal'

        self.ps.test_updates['passed'] = True
class TestGuideMonitorSupportAndTrainUsers(unittest.TestCase):
    """T2.18 - Guide, Monitor, Support, and Train Users."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities["name"] = self.id()
        self.teacher = Teacher(use_env_vars=True, pasta_user=self.ps, capabilities=self.desired_capabilities)

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(job_id=str(self.teacher.driver.session_id), **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    # 14752 - 001 - User | In-app Notification of downtime
    @pytest.mark.skipif(str(14752) not in TESTS, reason="Excluded")
    def test_user_inapp_notification_of_downtime_14752(self):
        """In-app Notification of downtime.

        Steps:

        Go to Tutor
        Log in as admin
        Click "Admin" from the user menu
        Click "System Setting"
        Click "Notifications"
        Enter a new notification into the text box
        Click "Add"
        Log out of admin
        Log in as teacher01

        Expected Result:
        An orange header with the notification pops up when you sign in
        """
        self.ps.test_updates["name"] = "t2.18.001" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.001", "14752"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 14751 - 002 - Teacher | Directed to a "No Courses" page when not in any
    # courses yet
    @pytest.mark.skipif(str(14751) not in TESTS, reason="Excluded")
    def test_teacher_directed_to_a_no_courses_page_when_not_in_any_14751(self):
        """Directed to a "No Courses" page when not in any courses yet.

        Steps:
        Go to tutor-qa.openstax.org
        Sign in as demo_teacher; password

        Expected Result:
        The message "We cannot find an OpenStax course associated with your
        account" displays with help links below
        """
        self.ps.test_updates["name"] = "t2.18.002" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.002", "14751"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58279 - 003 - Teacher | View "Getting Started with Tutor" Guide
    @pytest.mark.skipif(str(58279) not in TESTS, reason="Excluded")
    def test_teacher_view_getting_started_with_tutor_guide_58279(self):
        """View "Getting Started with Tutor" Guide.

        Steps:
        Click "Tutor Instructors. Get help"

        Expected Result:
        Tutor Help Center opens in another tab with the Getting Started guide
        """
        self.ps.test_updates["name"] = "t2.18.003" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.003", "58279"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58280 - 004 - Teacher | Access Tutor Help Center after registering for
    # a course
    @pytest.mark.skipif(str(58280) not in TESTS, reason="Excluded")
    def test_teacher_access_tutor_help_center_after_registering_58280(self):
        """Access Tutor Help Center after registering for a course.

        Steps:
        Go to Tutor
        Sign in as teacher01
        Click on a Tutor course if the user is in more than one
        Click "Get Help" from the user menu in the upper right corner of the
            screen

        Expected Result:
        The user is presented with the Tutor Help Center
        """
        self.ps.test_updates["name"] = "t2.18.004" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.004", "58280"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58284 - 005 - Teacher | Submit a question
    @pytest.mark.skipif(str(58284) not in TESTS, reason="Excluded")
    def test_teacher_submit_a_question_58284(self):
        """Submit a question.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter

        Expected Result:
        The user is presented with search results
        """
        self.ps.test_updates["name"] = "t2.18.005" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.005", "58284"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58352 - 006 - Teacher | View "Contact Us" button after submitting a
    # question
    @pytest.mark.skipif(str(58352) not in TESTS, reason="Excluded")
    def test_teacher_view_contact_us_button_after_submitting_quest_58352(self):
        """View "Contact Us" button after submitting a question.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Scroll to the bottom of the screen

        Expected Result:
        "Contact Us" button exists
        """
        self.ps.test_updates["name"] = "t2.18.006" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.006", "58352"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58288 - 007 - Teacher | View an article after submitting a question
    @pytest.mark.skipif(str(58288) not in TESTS, reason="Excluded")
    def test_teacher_view_an_article_after_submitting_a_question_58288(self):
        """View an article after submitting a question.

        Steps:

        Click "Get Help" from the user menu in the upper right corner of the
        screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result

        Expected Result:
        The user is presented with an article containing answer to the question
        """
        self.ps.test_updates["name"] = "t2.18.007" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.007", "58288"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58313 - 008 - Teacher | Indicate that the article was helpful
    @pytest.mark.skipif(str(58313) not in TESTS, reason="Excluded")
    def test_teacher_indicate_that_the_article_was_helpful_58313(self):
        """Indicate that the article was helpful.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "Yes"

        Expected Result:
        A message that says "Thanks for your feedback!" is displayed
        """
        self.ps.test_updates["name"] = "t2.18.008" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.008", "58313"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58314 - 009 - Teacher | Negative feedback renders a feedback popup box
    @pytest.mark.skipif(str(58314) not in TESTS, reason="Excluded")
    def test_teacher_negative_feedback_renders_feedback_popup_box_58314(self):
        """Negative feedback renders a feedback popup box.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"

        Expected Result:
        The user is presented with a popup box that allows them to input
        feedback
        """
        self.ps.test_updates["name"] = "t2.18.009" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.009", "58314"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58315 - 010 - Teacher | Submit feedback for an article
    @pytest.mark.skipif(str(58315) not in TESTS, reason="Excluded")
    def test_teacher_submit_feedback_for_an_article_58315(self):
        """Submit feedback for an article.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        Enter feedback into the box that pops up
        Click "Submit"

        Expected Result:
        A message that says "Thanks for your feedback!" is displayed in the box
        """
        self.ps.test_updates["name"] = "t2.18.010" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.010", "58315"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58322 - 011 - Teacher | Close window after submitting feedback for an
    # article
    @pytest.mark.skipif(str(58322) not in TESTS, reason="Excluded")
    def test_teacher_close_window_after_submitting_feedback_for_58322(self):
        """Close window after submitting feedback for an article.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        Enter feedback into the box that pops up
        Click "Submit"
        Click "Close window"

        Expected Result:
        The popup box closes and the message "Thanks for your feedback"
        displays beneath "Feedback"
        """
        self.ps.test_updates["name"] = "t2.18.011" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.011", "58322"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58316 - 012 - Teacher | Cancel feedback
    @pytest.mark.skipif(str(58316) not in TESTS, reason="Excluded")
    def test_teacher_cancel_feedback_before_making_changes_58316(self):
        """Cancel feedback.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        [optional] Enter feedback into the text box
        Click "Cancel"

        Expected Result:
        The popup box closes
        """
        self.ps.test_updates["name"] = "t2.18.012" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.012", "58316"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58318 - 013 - Teacher | View related articles
    @pytest.mark.skipif(str(58318) not in TESTS, reason="Excluded")
    def test_teacher_view_related_articles_58318(self):
        """View related articles.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Related Articles"
        Click on one of the articles (if any)

        Expected Result:
        The user is presented with the related article
        """
        self.ps.test_updates["name"] = "t2.18.013" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.013", "58318"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58319 - 014 - Teacher | Submit a question to Customer Support
    @pytest.mark.skipif(str(58319) not in TESTS, reason="Excluded")
    def test_teacher_submit_a_question_to_customer_support_58319(self):
        """Submit a question to Customer Support.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        CLick "Search" or press enter
        Click on a search result
        Scroll to the bottom of the page
        CLick "Contact Us"
        Fill out the required fields
        Enter "Submit"

        Expected Result:
        The message "Thank you for your message! We'll be back to you within
        one business day" is displayed
        """
        self.ps.test_updates["name"] = "t2.18.014" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.014", "58319"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 14755 - 015 - Teacher | View guided tutorials of Tutor
    @pytest.mark.skipif(str(14755) not in TESTS, reason="Excluded")
    def test_teacher_view_guided_tutorials_of_concept_coach_14755(self):
        """View guided tutorials of Tutor.

        Steps:


        Expected Result:

        """
        self.ps.test_updates["name"] = "t2.18.015" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.015", "14755"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 14750 - 016 - Student | Directed to a "No Courses" page when not in any
    # courses yet
    @pytest.mark.skipif(str(14750) not in TESTS, reason="Excluded")
    def test_student_directed_to_a_no_courses_page_when_not_in_any_14750(self):
        """Directed to a "No Courses" page when not in any courses yet.

        Steps:
        Go to Tutor
        Log in as qa_student_37003

        Expected Result:
        The message "We cannot find an OpenStax course associated with your
        account" displays with help links
        """
        self.ps.test_updates["name"] = "t2.18.016" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.016", "14750"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58336 - 017 - Student | View "Getting Started with Tutor" Guide
    @pytest.mark.skipif(str(58336) not in TESTS, reason="Excluded")
    def test_student_view_getting_started_with_tutor_guide_58336(self):
        """View "Getting Started with Tutor" Guide.

        Steps:
        Click "Tutor Students. Get help"

        Expected Result:
        Tutor Help Center opens in another tab with the Getting Started guide
        """
        self.ps.test_updates["name"] = "t2.18.017" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.017", "58336"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58337 - 018 - Student | Access Tutor Help Center after registering for a
    # course
    @pytest.mark.skipif(str(58337) not in TESTS, reason="Excluded")
    def test_student_access_tutor_help_center_after_registering_58337(self):
        """Access Tutor Help Center after registering for a course.

        Steps:
        Go to Tutor
        Sign in as student01
        Click on a Tutor course if the user is in more than one
        Click "Get Help" from the user menu in the upper right corner of the
            screen

        Expected Result:
        The user is presented with the Tutor Help Center
        """
        self.ps.test_updates["name"] = "t2.18.018" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.018", "58337"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58338 - 019 - Student | Submit a question
    @pytest.mark.skipif(str(58338) not in TESTS, reason="Excluded")
    def test_student_submit_a_question_58338(self):
        """Submit a question.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter

        Expected Result:
        The user is presented with search results
        """
        self.ps.test_updates["name"] = "t2.18.019" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.019", "58338"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58353 - 020 - Student | View "Contact Us" button after submitting a
    # question
    @pytest.mark.skipif(str(58353) not in TESTS, reason="Excluded")
    def test_student_view_contact_us_button_after_submitting_quest_58353(self):
        """View "Contact Us" button after submitting a question.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Scroll to the bottom of the page

        Expected Result:
        "Contact Us" button exists
        """
        self.ps.test_updates["name"] = "t2.18.020" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.020", "58353"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58339 - 021 - Student | View an article after submitting a question
    @pytest.mark.skipif(str(58339) not in TESTS, reason="Excluded")
    def test_student_view_an_article_after_submitting_a_question_58339(self):
        """View an article after submitting a question.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result

        Expected Result:
        The user is presented with an article containing answer to the question
        """
        self.ps.test_updates["name"] = "t2.18.021" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.021", "58339"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58340 - 022 - Student | Indicate that the article was helpful
    @pytest.mark.skipif(str(58340) not in TESTS, reason="Excluded")
    def test_student_indicate_that_the_article_was_helpful_58340(self):
        """Indicate that the article was helpful.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "Yes"

        Expected Result:
        A message that says "Thanks for your feedback!" is displayed
        """
        self.ps.test_updates["name"] = "t2.18.022" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.022", "58340"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58341 - 023 - Student | Negative feedback renders a feedback popup box
    @pytest.mark.skipif(str(58341) not in TESTS, reason="Excluded")
    def test_student_negative_feedback_renders_feedback_popup_box_58341(self):
        """Negative feedback renders a feedback popup box.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"

        Expected Result:
        The user is presented with a popup box that allows them to input
        feedback
        """
        self.ps.test_updates["name"] = "t2.18.023" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.023", "58341"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58342 - 024 - Student | Submit feedback for an article
    @pytest.mark.skipif(str(58342) not in TESTS, reason="Excluded")
    def test_student_submit_feedback_for_an_article_58342(self):
        """Submit feedback for an article.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        Enter feedback into the box that pops up
        Click "Submit"

        Expected Result:
        A message that says "Thanks for your feedback!" is displayed in the box
        """
        self.ps.test_updates["name"] = "t2.18.024" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.024", "58342"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58343 - 025 - Student | Close window after submitting feedback for an
    # article
    @pytest.mark.skipif(str(58343) not in TESTS, reason="Excluded")
    def test_student_close_window_after_submitting_feedback_for_58343(self):
        """Close window after submitting feedback for an article.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        Enter feedback into the box that pops up
        Click "Submit"
        Click "Close window"

        Expected Result:
        The popup box closes and the message "Thanks for your feedback"
        displays beneath "Feedback"
        """
        self.ps.test_updates["name"] = "t2.18.025" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.025", "58343"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58344 - 026 - Student | Cancel feedback
    @pytest.mark.skipif(str(58344) not in TESTS, reason="Excluded")
    def test_student_cancel_feedback_58344(self):
        """Cancel feedback.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Feedback"
        Click "No"
        [optional] Enter feedback into text box
        Click "Cancel"

        Expected Result:
        The popup box closes
        """
        self.ps.test_updates["name"] = "t2.18.026" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.026", "58344"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58346 - 027 - Student | View related articles
    @pytest.mark.skipif(str(58346) not in TESTS, reason="Excluded")
    def test_student_view_related_articles_58346(self):
        """View related articles.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to "Related Articles"
        Click on one of the articles (if any)

        Expected Result:
        The user is presented with the related article
        """
        self.ps.test_updates["name"] = "t2.18.027" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.027", "58346"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58347 - 028 - Student | Submit a question to Customer Support
    @pytest.mark.skipif(str(58347) not in TESTS, reason="Excluded")
    def test_student_submit_a_question_to_customer_support_58347(self):
        """Submit a question to Customer Support.

        Steps:
        Click "Get Help" from the user menu in the upper right corner of the
            screen
        Enter a question or search words into the search engine
        Click "Search" or press enter
        Click on a search result
        Scroll to the bottom of the page
        Click "Contact Us"
        Fill out the required fields
        Enter "Submit"

        Expected Result:
        The message "Thank you for your message! We'll be back to you within
        one business day" is displayed
        """
        self.ps.test_updates["name"] = "t2.18.028" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.028", "58347"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True

    # 58348 - 029 - Student | View guided tutorials of Tutor
    @pytest.mark.skipif(str(58348) not in TESTS, reason="Excluded")
    def test_student_view_guided_tutorials_of_concept_coach_58348(self):
        """View guided tutorial of Tutor.

        Steps:


        Expected Result:

        """
        self.ps.test_updates["name"] = "t2.18.029" + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates["tags"] = ["t2", "t2.18", "t2.18.029", "58348"]
        self.ps.test_updates["passed"] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates["passed"] = True
class TestCourseAdoptionAndReadoption(unittest.TestCase):
    """T3.09 - Course Adoption and Readoption."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(use_env_vars=True,
                               pasta_user=self.ps,
                               capabilities=self.desired_capabilities)

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                           **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    # Case C106450 - 001 - Teacher | Add a course via MyOpenstax
    @pytest.mark.skipif(str(106450) not in TESTS, reason='Excluded')
    def test_teacher_add_a_course_via_my_openstax_106450(self):
        """Add a course via my openstax.

        Steps:
        Log in to openstax.org
        Go to “My openstax” page
        Click “+ add courses” under “Courses”
        Choose semester/quarter and year and click continue
        Choose “New or copy”.
        “Cancel” button can bring user back to the main page at any time.

        Expected Result:
        User is directed to Tutor Dashboard'
        """
        self.ps.test_updates['name'] = 't3.09.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.001', '106450']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106451 - 002 - Teacher | Add a course via the course picker page
    @pytest.mark.skipif(str(106451) not in TESTS, reason='Excluded')
    def test_teacher_add_a_course_via_the_course_picker_page_106451(self):
        """Add a course via the course picker page.

        Steps:
        Log in to tutor.openstax.org
        If there is no current course, a message “no current course” will be
            shown, and below it there is an “add a course” gray box.
        If there is a current course, the current course box followed by an
            “add a course” box appears.
        Click “Add a Course”
        Select a tutor or a concept coach course
        Select year, enter name and section number for the course.
        “Cancel” button can bring user back to the main page at any time.

        Expected Result:
        User is directed to Tutor Dashboard
        """
        self.ps.test_updates['name'] = 't3.09.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.002', '106451']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106452 - 003 - Teacher | Add a course via the Tutor dashboard
    @pytest.mark.skipif(str(106452) not in TESTS, reason='Excluded')
    def test_teacher_add_a_course_via_the_tutor_dashboard_106452(self):
        """Add a course via the Tutor dashboard.

        Steps:
        Log in to tutor.openstax.org
        Go to dashboard.
        In the upper panel, there is a message asking whether user wishes to
            teach again. Select “Yes”.
        Select whether to copy question library, and select semester.
        “Cancel” directs users back to the Course Picker Page in any step
        “Continue” directs to the next step
        The color of the selected option is grey
        “Back” directs users to last page

        Expected Result:
        User is taken to a new course dashboard, with old course data copied
        """
        self.ps.test_updates['name'] = 't3.09.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.003', '106452']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106453 - 004 - Teacher | A past course is available for cloning
    @pytest.mark.skipif(str(106453) not in TESTS, reason='Excluded')
    def test_teacher_apast_course_is_available_for_cloning_106453(self):
        """A past course is available for cloning.

        Steps:
        Login to tutor
        Select “Copy a past course” from the user menu
        Select Tutor or Concept Coach
        Select a course
        Select a semester
        Select "Copy a past Course"


        Expected Result:
        Past courses appears in the following section
        """
        self.ps.test_updates['name'] = 't3.09.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.004', '106453']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106454 - 005 - Teacher | Able to copy the question library during
    # cloning
    @pytest.mark.skipif(str(106454) not in TESTS, reason='Excluded')
    def test_teacher_able_to_copy_the_question_library_during_clo_106454(self):
        """Able to copy the question library during cloning.

        Steps:
        Log in to tutor.openstax.org
        Click “Add a Course”
        Select a tutor or a concept coach course
        Select “Copy a past course”
        Select a past course from the next page.

        Expected Result:
        Message “Choose whether to copy the question library” appears
        """
        self.ps.test_updates['name'] = 't3.09.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.005', '106454']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106455 - 006 - Teacher | Able to select the name for a new course
    @pytest.mark.skipif(str(106455) not in TESTS, reason='Excluded')
    def test_teacher_able_to_select_the_name_for_a_new_course_106455(self):
        """Able to select the name for a new course.

        Steps:
        Log in to tutor.openstax.org
        Click “Add a Course”
        Select a tutor or a concept coach course
        Select “Copy a past course”
        Select a past course.
        Select “Copy question library”.
        Enter a name for the tutor course

        Expected Result:
        Text could be entered into the text box.
        """
        self.ps.test_updates['name'] = 't3.09.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.006', '106455']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106456 - 007 - Teacher | Specify the number of sections for a new
    # course
    @pytest.mark.skipif(str(106456) not in TESTS, reason='Excluded')
    def test_teacher_specify_the_number_of_sections_for_a_new_cou_106456(self):
        """Specify the number of sections for a new course.

        Steps:
        Log in to tutor.openstax.org
        Click “Add a Course”
        Select a tutor or a concept coach course
        Select “Copy a past course”
        Select a past course.
        Select “Copy question library”.
        Enter a number into the tutor course sections panel

        Expected Result:
        Number could be entered. The page won’t proceed if anything else is
        entered into the number panel
        """
        self.ps.test_updates['name'] = 't3.09.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.007', '106456']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106457 - 008 - Teacher | A course's setting match those selected
    # during the cloning process
    @pytest.mark.skipif(str(106457) not in TESTS, reason='Excluded')
    def test_teacher_a_courses_settings_match_those_selected_duri_106457(self):
        """A course's setting match those selected during the cloning process.

        Steps:
        Log in to tutor.openstax.org
        Click “Add a Course”
        Select a tutor or a concept coach course
        Select “Copy a past course”
        Select a past course.
        Select “Copy question library”.
        Enter a name for the tutor course
        Enter a number into the tutor course sections

        Expected Result:
        Course dashboard appears with the name and section number user entered
        """
        self.ps.test_updates['name'] = 't3.09.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.008', '106457']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106458 - 009 - Teacher | Add a new course
    @pytest.mark.skipif(str(106458) not in TESTS, reason='Excluded')
    def test_teacher_add_a_new_course_106458(self):
        """Add a new course.

        Steps:
        Log in to tutor.openstax.org
        Click “Add a Course”
        Select a tutor or a concept coach course
        Select “Create a new course”.
        Enter the name and number of sections for the new course.
        Click “create course”.

        Expected Result:
        User is taken to a dashboard with a blank calendar, with the
        corresponding course name and section number
        """
        self.ps.test_updates['name'] = 't3.09.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.009', '106458']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106459 - 010 - Teacher | Copy a homework
    @pytest.mark.skipif(str(106459) not in TESTS, reason='Excluded')
    def test_teacher_copy_a_homework_106459(self):
        """Copy a homework.

        Steps:
        Log in to tutor.openstax.org
        Click “Add a Course”
        Select a tutor or a concept coach course
        Select “Copy an old course”
        Select the course user wishes to copy.
        Select “Copy” when system asks “Do you want to copy past questions?”
        Enter course name and number of sections in the new pop-up.
        User is taken to dashboard, with past assignments appearing on the left

        Expected Result:
        When user clicks on a past assignment on the left panel, An auto-filled
        assignment creation form appeared
        """
        self.ps.test_updates['name'] = 't3.09.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.010', '106459']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106460 - 011 - Teacher | Copy an event
    @pytest.mark.skipif(str(106460) not in TESTS, reason='Excluded')
    def test_teacher_copy_an_event_106460(self):
        """Copy an event.

        Steps:
        Log in to tutor.openstax.org
        Click “Add a Course”
        Select a tutor or a concept coach course
        Select “Copy an old course”
        Select the course user wishes to copy.
        Select “Copy” when system prompts “Do you want to copy past questions?”
        Enter course name and number of sections in the new pop-up.
        User is taken to dashboard, with past assignments appearing on the left

        Expected Result:
        When user clicks on a past Event on the left panel, An auto-filled
        event creation form appeared
        """
        self.ps.test_updates['name'] = 't3.09.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.011', '106460']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106461 - 012 - Teacher | Copy a reading
    @pytest.mark.skipif(str(106461) not in TESTS, reason='Excluded')
    def test_teacher_copy_a_reading_106461(self):
        """Copy a reading.

        Steps:
        Log in to tutor.openstax.org
        Click “Add a Course”
        Select a tutor or a concept coach course
        Select “Copy an old course”
        Select the course user wishes to copy.
        Select “Copy” when system asks “Do you want to copy past questions?”
        Enter course name and number of sections in the new pop-up.
        User is taken to dashboard, with past assignments appearing on the left

        Expected Result:
        When user clicks on a past reading on the left panel, An auto-filled
        reading creation form appeared
        """
        self.ps.test_updates['name'] = 't3.09.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.012', '106461']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C106462 - 013 - Teacher | Copy an external assignment
    @pytest.mark.skipif(str(106462) not in TESTS, reason='Excluded')
    def test_teacher_copy_an_external_assignment_106462(self):
        """Copy an external assignment.

        Steps:
        Log in to tutor.openstax.org
        Click “Add a Course”
        Select a tutor or a concept coach course
        Select “Copy an old course”
        Select the course user wishes to copy.
        Select “Copy” when system asks “Do you want to copy past questions?”
        Enter course name and number of sections in the new pop-up.
        User is taken to dashboard, with past assignments appearing on the left

        Expected Result:
        When user clicks on a past assignment on the left panel, An auto-filled
        external assignment creation form appeared
        """
        self.ps.test_updates['name'] = 't3.09.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.013', '106462']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107576 - 014 - Admin | Change the course term
    @pytest.mark.skipif(str(107576) not in TESTS, reason='Excluded')
    def test_admin_change_the_course_term_107576(self):
        """Change the course term.

        Steps:
        Log in as an Admin
        Go to the course management page
        Edit a course
        Change the term
        Click Save

        Expected Result:
        Start and end dates should reflect the new term's timeframe
        """
        self.ps.test_updates['name'] = 't3.09.014' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.014', '107576']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107577 - 015 - Admin | Change the course year
    @pytest.mark.skipif(str(107577) not in TESTS, reason='Excluded')
    def test_admin_change_the_course_year_107576(self):
        """Change the course year.

        Steps:
        Log in as an Admin
        Go to the course management page
        Edit a course
        Change the year
        Click Save

        Expected Result:
        Start and end dates should reflect the new year's timeframe
        """
        self.ps.test_updates['name'] = 't3.09.015' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.015', '107577']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107578 - 016 - Admin | Change the course start date
    @pytest.mark.skipif(str(107578) not in TESTS, reason='Excluded')
    def test_admin_change_the_course_start_date_107578(self):
        """Change the course start date.

        Steps:
        Log in as an Admin
        Go to the course management page
        Edit a course
        Change the Starts at date
        Click Save

        Expected Result:
        Start date is changed
        """
        self.ps.test_updates['name'] = 't3.09.016' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.016', '107578']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107579 - 017 - Admin | Change the course end date
    @pytest.mark.skipif(str(107579) not in TESTS, reason='Excluded')
    def test_admin_change_the_course_end_date_107579(self):
        """Change the course end_date.

        Steps:
        Log in as an Admin
        Go to the course management page
        Edit a course
        Change the Ends at date
        Click Save

        Expected Result:
        End date is changed
        """
        self.ps.test_updates['name'] = 't3.09.017' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.017', '107579']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107580 - 018 - Teacher | Provide a registration link to co-teachers
    @pytest.mark.skipif(str(107580) not in TESTS, reason='Excluded')
    def test_teacher_provide_a_registration_link_to_co_teachers_107580(self):
        """Provide a registration link to co-teachers.

        Steps:
        Log in as a teacher
        Go to a course dashboard
        Go to the course roster
        Click Add an instructor
        Copy the link provided
        Log out
        Log in as a different teacher
        Go to the link

        Expected Result:
        New teacher is at the course dashboard
        """
        self.ps.test_updates['name'] = 't3.09.018' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.018', '107580']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107582 - 019 - Teacher | Add a section to a course
    @pytest.mark.skipif(str(107582) not in TESTS, reason='Excluded')
    def test_teacher_add_a_section_to_a_course_107582(self):
        """Add a section to a course.

        Steps:
        Log in as a teacher
        Click on a tutor course
        Click on Course Settings and roster in the user menu
        Click "+ Add Section"
        Enter a new section name into into the "Section Name" text field
        Click Add

        Expected Result:
        A new section is created and its tab is displayed
        """
        self.ps.test_updates['name'] = 't3.09.019' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.019', '107582']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107583 - 020 - Teacher | Delete a section to a course
    @pytest.mark.skipif(str(107583) not in TESTS, reason='Excluded')
    def test_teacher_delete_a_section_to_a_course_107583(self):
        """Delete a section to a course.

        Steps:
        Log in as a teacher
        Click on a tutor course
        Click on "Course Settings and Roster" in the user menu
        Click on period tab for period to delete
        Click "Delete Section"
        Click "Delete" in the pop up box

        Expected Result:
        The period is deleted and its tab is removed
        """
        self.ps.test_updates['name'] = 't3.09.020' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.020', '107583']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C107584 - 021 - Teacher | A course with zero sections displays a
    # message to add at leat one section to the class
    @pytest.mark.skipif(str(107584) not in TESTS, reason='Excluded')
    def test_teacher_a_course_with_zero_sections_displays_a_messa_107584(self):
        """A course with zero sections displays a message to add at leat one
        section to the clas.

        Steps:
        Log in as a teacher
        Click on tutor course with zero sections, or create one
        Click on "Course Settings and Roster" in the user menu

        Expected Result:
        A message to add at least one section to the course is displayed with a
        button to do so
        """
        self.ps.test_updates['name'] = 't3.09.021' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.021', '107584']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    '''
    # Case C107595 - 022 - Teacher | Unable to create an assignment prior to
    # the start of term
    @pytest.mark.skipif(str(107595) not in TESTS, reason='Excluded')
    def test_teacher_unable_to_create_an_assignment_prior_to_star_107595(self):
        """Unable to create an assignment prior to the start of term.

        Steps:
        Login as a teacher
        Click on a course with a start date after the current date, or create
            one
        Click on the add assignment menu
        Click on the add event option
        Click on the open date text field
        Click on the due date text field

        Expected Result:
        A due date or open date cannot be set to before the start of term. The
        calendars cannot be rotated to view months prior to the start of course
        """
        self.ps.test_updates['name'] = 't3.09.022' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.022', '107595']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    '''

    # Case C107596 - 023 - Teacher | Unable to create an assignment after the
    # end of term
    @pytest.mark.skipif(str(107596) not in TESTS, reason='Excluded')
    def test_teacher_unable_to_create_an_assignment_after_the_end_107596(self):
        """Unable to create an assignment after the end of term.

        Steps:
        Login as a teacher
        Click on a current tutor course
        Click on the Add Assignment menu
        Click on Add Event
        Click on the Open Date text field
        Click the forward arrow to rotate the calendar to the course end date
        Click on the Due Date text field
        Click the forward arrow to rotate the calendar to the course end date

        Expected Result:
        A due date or open date cannot be set to after the end of term. The
        calendars cannot be rotated to view months after to the end of course.
        """
        self.ps.test_updates['name'] = 't3.09.023' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.023', '107596']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C111265 - 024 - Teacher | Able to select Not Listed from the subject
    # list
    @pytest.mark.skipif(str(111265) not in TESTS, reason='Excluded')
    def test_teacher_able_to_select_not_listed_from_the_subject_l_111265(self):
        """Able to select Not Listed from the subject list

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 't3.09.024' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t3', 't3.09', 't3.09.024', '111265']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
class TestImprovesScoresReporting(unittest.TestCase):
    """CC2.08 - Improves Scores Reporting."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.teacher = Teacher(use_env_vars=True,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
        else:
            self.teacher = Teacher(use_env_vars=True)
        self.teacher.login()
        self.teacher.find(By.XPATH,
                          '//a[contains(@href,"/cc-dashboard")]').click()

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                               **self.ps.test_updates)
        try:
            self.teacher.delete()
        except:
            pass

    # 14806 - 001 - Teacher | View student scores as percent complete
    @pytest.mark.skipif(str(14806) not in TESTS, reason='Excluded')
    def test_teacher_view_student_scores_as_percent_complete_14806(self):
        """View student scores as percent complete.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click on the icon in the progress column

        Expected Result:
        Student Scores are presented as percent complete
        """
        self.ps.test_updates['name'] = 'cc2.08.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.001', '14806']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(text(),"View Detailed Scores")]'))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')))
        self.teacher.find(By.XPATH,
                          '//button[contains(text(),"percentage")]').click()
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"score")]//a[contains(text(),"%")]')
        self.ps.test_updates['passed'] = True

    # 14807 - 002 - Teacher | View student scores as number of total
    @pytest.mark.skipif(str(14807) not in TESTS, reason='Excluded')
    def test_teacher_view_student_scores_as_number_of_total_14807(self):
        """View student scores as number of total.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click "Number"

        Expected Result:
        Student Scores are presented as "Number of Total"
        """
        self.ps.test_updates['name'] = 'cc2.08.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.002', '14807']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(text(),"View Detailed Scores")]'))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')))
        self.teacher.find(By.XPATH,
                          '//button[contains(text(),"number")]').click()
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"score")]//a[contains(text()," of ")]')

        self.ps.test_updates['passed'] = True

    # 14808 - 003 - Teacher | View tooltips on hover
    @pytest.mark.skipif(str(14808) not in TESTS, reason='Excluded')
    def test_teacher_view_tooltips_on_hover_14808(self):
        """View tooltips on hover.

        Steps:
        If the user has more than one course, click on a CC course name
        Hover over the info icons

        Expected Result:
        The user is presented with tooltips
        """
        self.ps.test_updates['name'] = 'cc2.08.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.003', '14808']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(text(),"View Detailed Scores")]'))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')))
        self.teacher.find(By.XPATH, '//i[@type="info-circle"]').click()
        self.teacher.find(
            By.XPATH, '//h3[@class="popover-title" and ' +
            'contains(text(), "Class and Overall Averages")]')
        self.ps.test_updates['passed'] = True

    # 14810 - 004 - Teacher | Sort student scores based on score
    @pytest.mark.skipif(str(14810) not in TESTS, reason='Excluded')
    def test_teacher_sort_student_scores_based_on_score_14810(self):
        """Sort student scores based on score.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click "Score" for the desired assignment

        Expected Result:
        Students are sorted based on score
        """
        self.ps.test_updates['name'] = 'cc2.08.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.004', '14810']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(text(),"View Detailed Scores")]'))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')))
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"sortable")]//div[text()="Score"]').click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"is-descending")]//div[text()="Score"]'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"is-ascending")]//div[text()="Score"]')
        self.ps.test_updates['passed'] = True

    # 14811 - 005 - Teacher | Sort student scores based on number complete
    @pytest.mark.skipif(str(14811) not in TESTS, reason='Excluded')
    def test_teacher_sort_student_scores_based_on_number_completed_14811(self):
        """Sort student scores based on number complete.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click "Progress" for the desired assignment

        Expected Result:
        Students are sorted based on number completed
        """
        self.ps.test_updates['name'] = 'cc2.08.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.005', '14811']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(text(),"View Detailed Scores")]'))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')))
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"sortable")]//div[text()="Progress"]'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"is-descending")]//div[text()="Progress"]'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[contains(@class,"is-ascending")]//div[text()="Progress"]')
        self.ps.test_updates['passed'] = True

    # 14668 - 006 - Teacher | All popups in the roster have an X button
    @pytest.mark.skipif(str(14668) not in TESTS, reason='Excluded')
    def test_teacher_all_popups_in_the_roster_have_an_x_button_14668(self):
        """All popups in the roster have an X button.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Course Settings and Roster" from the user menu
        Click "Rename Course," "Change Course Timezone,"
        "View Archived Period," "Add Period," "Rename," and "Get Student
            Enrollment Code"

        Expected Result:
        All pop ups have an X button
        """
        self.ps.test_updates['name'] = 'cc2.08.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.006', '14668']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.find(By.XPATH,
                          '//a[text()="Course Settings and Roster"]').click()
        self.teacher.sleep(1)
        # rename couse
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"Rename Course")]').click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]').click()
        self.teacher.sleep(0.75)
        # course timezone
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"Change Course Timezone")]').click(
            )
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]').click()
        self.teacher.sleep(0.75)
        # add period/section
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"add-period")]//button').click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]').click()
        self.teacher.sleep(0.75)
        # rename period
        self.teacher.find(
            By.XPATH,
            '//span[contains(@class,"rename-period")]//button').click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]').click()
        self.teacher.sleep(0.75)
        # student enrollemnt code
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"Your student enrollment code")]'
        ).click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]').click()
        self.teacher.sleep(0.75)
        # View Archived periods
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"View Archived ")]').click()
        self.teacher.sleep(0.75)
        self.teacher.find(
            By.XPATH,
            '//div[@class="modal-content"]//button[@class="close"]').click()
        self.ps.test_updates['passed'] = True

    # 14670 - 007 - Teacher | Close popup with X button
    @pytest.mark.skipif(str(14670) not in TESTS, reason='Excluded')
    def test_teacher_close_popup_with_x_button_14670(self):
        """Close popup with X button.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "Course Settings and Roster" from the user menu
        Click ONE of the following:
        * Rename Course
        * Change Course Timezone
        * View Archived Period
        * Add Period
        * Rename
        * Get Student Enrollment Code
        Click the X on the pop up

        Expected Result:
        Popup is closed
        """
        self.ps.test_updates['name'] = 'cc2.08.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.007', '14670']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.open_user_menu()
        self.teacher.find(By.XPATH,
                          '//a[text()="Course Settings and Roster"]').click()
        self.teacher.sleep(1)
        # rename couse
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//button//span[contains(text(),"Rename Course")]'))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]'
                 ))).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(By.XPATH, '//div[@class="modal-content"]')
        # course timezone
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"Change Course Timezone")]').click(
            )
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]'
                 ))).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(By.XPATH, '//div[@class="modal-content"]')
        # add period/section
        self.teacher.find(
            By.XPATH, '//div[contains(@class,"add-period")]//button').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]'
                 ))).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(By.XPATH, '//div[@class="modal-content"]')
        # rename period
        self.teacher.find(
            By.XPATH,
            '//span[contains(@class,"rename-period")]//button').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]'
                 ))).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(By.XPATH, '//div[@class="modal-content"]')
        # student enrollemnt code
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"Your student enrollment code")]'
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]'
                 ))).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(By.XPATH, '//div[@class="modal-content"]')
        # View Archived Periods
        self.teacher.find(
            By.XPATH,
            '//button//span[contains(text(),"View Archived")]').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[@class="modal-content"]//button[@class="close"]'
                 ))).click()
        self.teacher.sleep(1)
        with self.assertRaises(NoSuchElementException):
            self.teacher.find(By.XPATH, '//div[@class="modal-content"]')

        self.ps.test_updates['passed'] = True

    # 14669 - 008 - Teacher | The icon in the progress column shows info on
    # percentage complete, attempted out of total possible questions, and
    # the date last worked
    @pytest.mark.skipif(str(14669) not in TESTS, reason='Excluded')
    def test_teacher_the_icon_in_the_progress_column_shows_info_14669(self):
        """The icon in the progress column shows info.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click on the icon in the progress column for a completed assignment

        Expected Result:
        Shows information on percentage complete, attempted out of total
        possible questions as well as the date last worked
        """
        self.ps.test_updates['name'] = 'cc2.08.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.008', '14669']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(text(),"View Detailed Scores")]'))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')))
        icon = self.teacher.find(
            By.XPATH,
            '//span[contains(@aria-describedby,"scores-cell-info-popover")]')
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(icon)
        actions.perform()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//div[contains(@id,"scores-cell-info-popover")]'))).click()
        # more on each individial thing
        self.ps.test_updates['passed'] = True

    '''
    # 14812 - 009 - Teacher | Import CC Student Scores export into an LMS
    @pytest.mark.skipif(str(14812) not in TESTS, reason='Excluded')
    def test_teacher_import_cc_student_scores_export_into_an_lms_14812(self):
        """Import CC student scores export into an LMS.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc2.08.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.009', '14812']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    '''

    # 14813 - 010 - Teacher | View zeros in exported scores instead of blank
    # cells for incomplete assignments
    @pytest.mark.skipif(str(14813) not in TESTS, reason='Excluded')
    def test_teacher_view_zeros_in_exported_scores_instead_of_blan_14813(self):
        """View zeros in exported scores for incomplete assignments.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores"
        Click "Export"
        Open the excel file

        Expected Result:
        For incomplete assignments or assignments that are not started,
        there are zeros instead of blank cells
        """
        self.ps.test_updates['name'] = 'cc2.08.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.010', '14813']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(text(),"View Detailed Scores")]'))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')))
        self.teacher.find(By.XPATH,
                          '//div[@class="export-button"]//button').click()
        # wait until button return and no longer is loading
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="export-button"]//button' +
                 '/span[text()="Export"]')))
        self.teacher.sleep(2)
        coursename = self.teacher.find(By.XPATH,
                                       '//div[@class="course-name"]').text
        coursename = coursename.replace(' ', '_') + "_Scores"
        home = os.getenv("HOME")
        files = os.listdir(home + '/Downloads')
        file_name = ''
        for i in range(len(files)):
            if (coursename in files[i]) and (files[i][-5:] == '.xlsx'):
                file_name = files[i]
                break
            else:
                if i == len(files) - 1:
                    raise Exception
        period = self.teacher.find(
            By.XPATH, '//span[contains(@class,"tab-item-period-name")]').text
        wb = load_workbook(str(home + '/Downloads/' + file_name))
        sheet = wb[period + ' - %']
        rows = sheet.rows
        start_row = float("inf")
        for i in range(len(sheet.rows)):
            if rows[i][0].value == 'First Name':
                start_row = i
            if i >= start_row:
                if rows[i][4].value == 0:
                    # found that 0% is being used istead of blanks
                    break
                elif rows[i + 1][4].value is None:
                    print('empty cell instead of 0%')
                    raise Exception
        self.ps.test_updates['passed'] = True

    # 14814 - 011 - Teacher | Green check icon is displayed for completed
    # assignments
    @pytest.mark.skipif(str(14814) not in TESTS, reason='Excluded')
    def test_teacher_green_check_icon_is_displayed_for_completed_14814(self):
        """Green check icon is displayed for completed assignments.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores

        Expected Result:
        Green check icon is displayed for completed assignments
        """
        self.ps.test_updates['name'] = 'cc2.08.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.011', '14814']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(text(),"View Detailed Scores")]'))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')))
        # scroll to find a green checkmark
        assignments = self.teacher.find_all(
            By.XPATH,
            "//span[contains(@aria-describedby,'header-cell-title')]")

        for i in range(len(assignments) // 4):
            try:
                self.teacher.find(
                    By.XPATH, '//span[contains(@class,"trig")]' +
                    '//*[contains(@class,"finished")]')
                break
            except (NoSuchElementException, ElementNotVisibleException):
                if i >= (len(assignments) // 4) - 1:
                    print("completed assignments for this period")
                    raise Exception
                # try to drag scroll bar instead of scrolling
                scroll_bar = self.teacher.find(
                    By.XPATH,
                    '//div[contains(@class,"ScrollbarLayout_faceHorizontal")]')
                actions = ActionChains(self.teacher.driver)
                actions.move_to_element(scroll_bar)
                actions.click_and_hold()
                actions.move_by_offset(50, 0)
                actions.release()
                actions.perform()

        self.ps.test_updates['passed'] = True

    '''
    # 14815 - 012 - Teacher | The class average info icon displays a definition
    # about scores from completed assignments
    @pytest.mark.skipif(str(14815) not in TESTS, reason='Excluded')
    def test_teacher_class_average_info_icon_displays_definition_14815(self):
        """The class average info icon displays a definition.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores
        Click on the info icon next to "Class Average"

        Expected Result:
        The class average info icon displays a definition about scores from
        completed assignments
        """
        self.ps.test_updates['name'] = 'cc2.08.012' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.012', '14815']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//a[contains(text(),"View Detailed Scores")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')
            )
        )
        self.teacher.find(
            By.XPATH, '//i[@type="info-circle"]').click()
        self.teacher.find(
            By.XPATH,
            '//h3[@class="popover-title" and ' +
            'contains(text(), "Class and Overall Averages")]')

        self.ps.test_updates['passed'] = True
    '''

    # 14816 - 013 - Teacher | View the overall score column
    @pytest.mark.skipif(str(14816) not in TESTS, reason='Excluded')
    def test_teacher_view_the_overall_score_column_14816(self):
        """View the overall score column.

        Steps:
        If the user has more than one course, click on a CC course name
        Click "View Detailed Scores

        Expected Result:
        User is presented with the overall score column next to student names
        """
        self.ps.test_updates['name'] = 'cc2.08.013' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc2', 'cc2.08', 'cc2.08.013', '14816']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(text(),"View Detailed Scores")]'))).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(text(),"Student Scores")]')))
        self.teacher.find(By.XPATH,
                          '//div[contains(@class,"overall-header-cell")]')

        self.ps.test_updates['passed'] = True
class TestImproveCourseManagement(unittest.TestCase):
    """T2.07 - Improve Course Management."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.admin = Admin(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities,
            existing_driver=self.teacher.driver
        )

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(
            job_id=str(self.teacher.driver.session_id),
            **self.ps.test_updates
        )
        try:
            self.admin = None
            self.teacher.delete()
        except:
            pass

    # 14651 - 001 - Admin | View Student Use Statistics for Concept Coach
    # college assessments
    @pytest.mark.skipif(str(14651) not in TESTS, reason='Excluded')
    def test_admin_view_student_use_statistics_for_cc_college_asse_14651(self):
        """View Student Use Statistics for Concept Coach college assessments.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the admin account in the username and password text boxes
        Click on the 'Sign in' button
        Click "Admin" in the user menu
        Click "Stats"
        Click "Concept Coach"

        Expected Result:
        The user is presented with Concept Coach statistics
        """
        self.ps.test_updates['name'] = 't2.07.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.001',
            '14651'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.admin.login()
        self.admin.goto_admin_control()
        self.admin.sleep(5)
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Stats')
            )
        ).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Concept Coach')
            )
        ).click()

        assert('/stats/concept_coach' in self.admin.current_url()), \
            'Not viewing Concept Coach stats'

        self.ps.test_updates['passed'] = True

    # 14652 - 002 - Teacher | Delegate teaching tasks to supporting instructors
    @pytest.mark.skipif(str(14652) not in TESTS, reason='Excluded')
    def test_teacher_delegate_teaching_tasks_to_supporting_instruc_14652(self):
        """Delegate teaching tasks to supporting instructors.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.07.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.002',
            '14652'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14653 - 003 - Teacher | Move a student and their data to a new section
    @pytest.mark.skipif(str(14653) not in TESTS, reason='Excluded')
    def test_teacher_move_a_student_and_their_data_to_new_section_14653(self):
        """Move a student and their data to a new section.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Course Settings and Roster" from the user menu
        Click "Change Period" for the desired student and select a period

        Expected Result:
        Student is moved to new section with their data
        """
        self.ps.test_updates['name'] = 't2.07.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.003',
            '14653'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.select_course(appearance='physics')
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Course Settings and Roster").click()
        self.teacher.sleep(5)

        # Move the student to another period
        first = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[1]"
        ).text
        last = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[2]"
        ).text

        self.teacher.find(By.PARTIAL_LINK_TEXT, "Change Period").click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH, "//ul[@class='nav nav-pills nav-stacked']/li/a").click()

        self.teacher.sleep(5)

        # Verify the move, then move the student back to the original period
        self.teacher.find(
            By.XPATH,
            "//div[@class='roster']/div[@class='settings-section periods']" +
            "/ul[@class='nav nav-tabs']/li[2]/a").click()
        roster = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr")
        index = 0
        for student in roster:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                self.teacher.driver.find_elements_by_partial_link_text(
                    "Change Period")[index].click()
                self.teacher.sleep(1)
                self.teacher.find(
                    By.XPATH,
                    "//ul[@class='nav nav-pills nav-stacked']/li/a").click()
                break
            index += 1

        self.teacher.sleep(2)
        self.teacher.find(
            By.XPATH,
            "//div[@class='roster']/div[@class='settings-section periods']" +
            "/ul[@class='nav nav-tabs']/li[1]/a").click()
        roster = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr")

        assert(first in roster[0].text and last in roster[0].text), \
            'error'

        self.ps.test_updates['passed'] = True

    # 14655 - 004 - Teacher | Drop a student from a section and hide their data
    @pytest.mark.skipif(str(14655) not in TESTS, reason='Excluded')
    def test_teacher_drop_student_from_section_and_hide_their_data_14655(self):
        """Drop a student from a section and hide their data.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Course Settings and Roster" from the user menu
        Click "Drop" for the desired student

        Expected Result:
        The student appears under the "Dropped Students" section
        """
        self.ps.test_updates['name'] = 't2.07.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.004',
            '14655'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.select_course(appearance='physics')
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Course Settings and Roster").click()
        self.teacher.sleep(5)

        # Drop the student
        first = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[1]"
        ).text
        last = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[2]"
        ).text
        self.teacher.find(By.PARTIAL_LINK_TEXT, "Drop").click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH,
            "//button[@class='-drop-student btn btn-danger']").click()

        self.teacher.sleep(5)

        # Verify the student was dropped and add back to active roster
        dropped = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='settings-section dropped-students']/table[@class" +
            "='roster table table-striped table-bordered table-condensed " +
            "table-hover']/tbody/tr")
        index = 0
        for student in dropped:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                self.teacher.driver.find_elements_by_partial_link_text(
                    "Add Back to Active Roster")[index].click()
                self.teacher.sleep(1)
                self.teacher.find(
                    By.XPATH,
                    "//button[@class='-undrop-student btn btn-success']"
                ).click()
                self.teacher.sleep(20)
                break
            index += 1

        self.ps.test_updates['passed'] = True

    # 14656 - 005 - Teacher | Drop a student from a section and don't hide
    # their data
    @pytest.mark.skipif(str(14656) not in TESTS, reason='Excluded')
    def test_teacher_drop_a_student_from_section_and_dont_hide_dat_14656(self):
        """Drop a student from a section and don't hide their data.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.07.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.005',
            '14656'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14657 - 006 - Teacher | In Student Scores dropped students are not
    # displayed
    @pytest.mark.skipif(str(14657) not in TESTS, reason='Excluded')
    def test_teacher_in_student_scores_dropped_students_are_not_14657(self):
        """In Student Scores dropped students are not displayed.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Course Settings and Roster" from the calendar dashboard
        Click "Drop" for the desired student
        Click "Student Scores" from the user menu
        Click on the period from which you have dropped the student

        Expected Result:
        Dropped student should not be displayed in Student Scores
        """
        self.ps.test_updates['name'] = 't2.07.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.006',
            '14657'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.select_course(appearance='physics')
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Course Settings and Roster").click()
        self.teacher.sleep(5)

        # Drop the student
        first = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[1]"
        ).text
        last = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[2]"
        ).text

        self.teacher.find(By.PARTIAL_LINK_TEXT, "Drop").click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH,
            "//button[@class='-drop-student btn btn-danger']").click()

        self.teacher.sleep(5)

        # Go to student scores, verify the student is not seen
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Student Scores").click()
        self.teacher.sleep(10)

        odd_scores = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='fixedDataTableRowLayout_main public_fixedData" +
            "TableRow_main public_fixedDataTableRow_even public_fixedDataTa" +
            "ble_bodyRow']/div[@class='fixedDataTableRowLayout_body']/div" +
            "[@class='fixedDataTableCellGroupLayout_cellGroupWrapper'][1]/d" +
            "iv[@class='fixedDataTableCellGroupLayout_cellGroup']/div[@clas" +
            "s='fixedDataTableCellLayout_main public_fixedDataTableCell_" +
            "main'][1]/div[@class='fixedDataTableCellLayout_wrap1 public_fi" +
            "xedDataTableCell_wrap1']/div[@class='fixedDataTableCellLayout_w" +
            "rap2 public_fixedDataTableCell_wrap2']/div[@class='fixedDataTab" +
            "leCellLayout_wrap3 public_fixedDataTableCell_wrap3']/div[@class" +
            "='name-cell']/a[@class='student-name public_fixedDataTableCell" +
            "_cellContent']")
        even_scores = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='fixedDataTableRowLayout_main public_fixedDataTab" +
            "leRow_main public_fixedDataTableRow_highlighted public_fixedDa" +
            "taTableRow_odd public_fixedDataTable_bodyRow']/div[@class='fix" +
            "edDataTableRowLayout_body']/div[@class='fixedDataTableCellGrou" +
            "pLayout_cellGroupWrapper'][1]/div[@class='fixedDataTableCellGr" +
            "oupLayout_cellGroup']/div[@class='fixedDataTableCellLayout_mai" +
            "n public_fixedDataTableCell_main'][1]/div[@class='fixedDataTab" +
            "leCellLayout_wrap1 public_fixedDataTableCell_wrap1']/div[@clas" +
            "s='fixedDataTableCellLayout_wrap2 public_fixedDataTableCell_wr" +
            "ap2']/div[@class='fixedDataTableCellLayout_wrap3 public_fixedD" +
            "ataTableCell_wrap3']/div[@class='name-cell']/a[@class='student" +
            "-name public_fixedDataTableCell_cellContent']")

        found = False
        for student in odd_scores:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                found = True
                break

        if not found:
            for stud in even_scores:
                if stud.text.find(first) >= 0 and stud.text.find(last) >= 0:
                    found = True
                    break

        # Add back to active roster
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Course Settings and Roster").click()
        dropped = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='settings-section dropped-students']/table[@class" +
            "='roster table table-striped table-bordered table-condensed ta" +
            "ble-hover']/tbody/tr")
        index = 0
        for student in dropped:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                self.teacher.driver.find_elements_by_partial_link_text(
                    "Add Back to Active Roster")[index].click()
                self.teacher.sleep(1)
                self.teacher.find(
                    By.XPATH,
                    "//button[@class='-undrop-student btn btn-success']"
                ).click()
                self.teacher.sleep(20)
                break
            index += 1

        if not found:
            self.ps.test_updates['passed'] = True

    # 14850 - 007 - Teacher | In Student Scores view moved students
    @pytest.mark.skipif(str(14850) not in TESTS, reason='Excluded')
    def test_teacher_in_student_scores_view_moved_students_14850(self):
        """In Student Scores view moved students.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Course Settings and Roster" from the calendar dashboard
        Click "Change Period" for the desired student
        Click on the desired period
        Click "Student Scores" from the user menu
        Click on the period to which the student was moved

        Expected Result:
        The user is presented with the moved student under their new period
        """
        self.ps.test_updates['name'] = 't2.07.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.007',
            '14850'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.select_course(appearance='physics')
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Course Settings and Roster").click()
        self.teacher.sleep(5)

        # Move the student to another period
        first = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[1]"
        ).text
        last = self.teacher.find(
            By.XPATH,
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr[1]/td[2]"
        ).text

        self.teacher.find(By.PARTIAL_LINK_TEXT, "Change Period").click()
        self.teacher.sleep(1)
        self.teacher.find(
            By.XPATH, "//ul[@class='nav nav-pills nav-stacked']/li/a").click()

        self.teacher.sleep(5)

        # Go to student scores, verify the student is seen
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Student Scores").click()
        self.teacher.sleep(10)
        self.teacher.find(
            By.XPATH,
            "//nav[@class='collapse in']/ul[@class='nav nav-tabs']/li[2]/a"
        ).click()

        odd_scores = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='fixedDataTableRowLayout_main public_fixedData" +
            "TableRow_main public_fixedDataTableRow_even public_fixedDataTa" +
            "ble_bodyRow']/div[@class='fixedDataTableRowLayout_body']/div" +
            "[@class='fixedDataTableCellGroupLayout_cellGroupWrapper'][1]/d" +
            "iv[@class='fixedDataTableCellGroupLayout_cellGroup']/div[@clas" +
            "s='fixedDataTableCellLayout_main public_fixedDataTableCell_" +
            "main'][1]/div[@class='fixedDataTableCellLayout_wrap1 public_fi" +
            "xedDataTableCell_wrap1']/div[@class='fixedDataTableCellLayout_w" +
            "rap2 public_fixedDataTableCell_wrap2']/div[@class='fixedDataTab" +
            "leCellLayout_wrap3 public_fixedDataTableCell_wrap3']/div[@class" +
            "='name-cell']/a[@class='student-name public_fixedDataTableCell" +
            "_cellContent']")
        even_scores = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='fixedDataTableRowLayout_main public_fixedDataTab" +
            "leRow_main public_fixedDataTableRow_highlighted public_fixedDa" +
            "taTableRow_odd public_fixedDataTable_bodyRow']/div[@class='fix" +
            "edDataTableRowLayout_body']/div[@class='fixedDataTableCellGrou" +
            "pLayout_cellGroupWrapper'][1]/div[@class='fixedDataTableCellGr" +
            "oupLayout_cellGroup']/div[@class='fixedDataTableCellLayout_mai" +
            "n public_fixedDataTableCell_main'][1]/div[@class='fixedDataTab" +
            "leCellLayout_wrap1 public_fixedDataTableCell_wrap1']/div[@clas" +
            "s='fixedDataTableCellLayout_wrap2 public_fixedDataTableCell_wr" +
            "ap2']/div[@class='fixedDataTableCellLayout_wrap3 public_fixedD" +
            "ataTableCell_wrap3']/div[@class='name-cell']/a[@class='student" +
            "-name public_fixedDataTableCell_cellContent']")

        found = False
        for student in odd_scores:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                found = True
                break

        if found:
            for stud in even_scores:
                if stud.text.find(first) >= 0 and stud.text.find(last) >= 0:
                    found = True
                    break

        # Add student back to original period
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Course Settings and Roster").click()
        self.teacher.sleep(10)
        self.teacher.find(
            By.XPATH,
            "//div[@class='roster']/div[@class='settings-section periods']" +
            "/ul[@class='nav nav-tabs']/li[2]/a").click()
        roster = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='period']/table[@class='roster table table-striped" +
            " table-bordered table-condensed table-hover']/tbody/tr")
        index = 0
        for student in roster:
            if student.text.find(first) >= 0 and student.text.find(last) >= 0:
                self.teacher.driver.find_elements_by_partial_link_text(
                    "Change Period")[index].click()
                self.teacher.sleep(1)
                self.teacher.find(
                    By.XPATH,
                    "//ul[@class='nav nav-pills nav-stacked']/li/a").click()
                break
            index += 1

        if found:
            self.ps.test_updates['passed'] = True

    # 14658 - 008 - Teacher | Require emails for all students for roster import
    @pytest.mark.skipif(str(14658) not in TESTS, reason='Excluded')
    def test_teacher_require_emails_for_all_students_for_roster_14658(self):
        """Require emails for all students for roster imports.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.07.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.008',
            '14658'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # 14660 - 009 - Teacher | Set time zone for a course
    @pytest.mark.skipif(str(14660) not in TESTS, reason='Excluded')
    def test_teacher_set_time_zone_for_a_course_14660(self):
        """Set time zone for a course.

        Steps:
        If the user has more than one course, click on a Tutor course name
        Click "Course Settings and Roster"
        Click "Change Course Timezone"
        Select the desired timezone
        Click Save

        Expected Result:
        The time zone is set
        """
        self.ps.test_updates['name'] = 't2.07.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.009',
            '14660'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.select_course(appearance='physics')
        self.teacher.open_user_menu()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, "Course Settings and Roster").click()
        self.teacher.sleep(5)

        # Change the timezone
        self.teacher.driver.find_elements_by_xpath(
            "//button[@class='edit-course btn btn-link']")[1].click()
        self.teacher.sleep(2)
        self.teacher.find(
            By.XPATH, "//div[@class='tutor-radio']/label").click()
        self.teacher.find(
            By.XPATH,
            "//button[@class='async-button -edit-course-" +
            "confirm btn btn-default']").click()
        self.teacher.sleep(5)

        # Verify the change and change the time back to Central
        self.teacher.driver.find_elements_by_xpath(
            "//button[@class='edit-course btn btn-link']")[1].click()

        assert('Central Time' not in self.teacher.find(
            By.XPATH, "//div[@class='tutor-radio active']/label").text), \
            'Not viewing Concept Coach stats'

        self.teacher.sleep(2)
        options = self.teacher.driver.find_elements_by_xpath(
            "//div[@class='tutor-radio']/label")

        for timezone in options:
            if timezone.text.find('Central Time') >= 0:
                timezone.click()
                break

        self.teacher.find(
            By.XPATH,
            "//button[@class='async-button -edit-course-" +
            "confirm btn btn-default']").click()

        self.ps.test_updates['passed'] = True

    # 14661 - 010 - System | Distinguish between high school and college
    # courses
    @pytest.mark.skipif(str(14661) not in TESTS, reason='Excluded')
    def test_system_distinguish_between_hs_and_college_courses_14661(self):
        """Distinguish between high school and college courses.

        Steps:


        Expected Result:

        """
        self.ps.test_updates['name'] = 't2.07.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't2',
            't2.07',
            't2.07.010',
            '14661'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True
    def test_teacher_view_instructor_notification_112523(self):
        """View an active instructor-only system notification.

        Steps:

        Expected Result:

        """
        self.ps.test_updates['name'] = 't1.57.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['t1', 't1.57', 't1.57.010', '112523']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'System Setting'))).click()
        self.admin.wait.until(
            expect.visibility_of_element_located(
                (By.PARTIAL_LINK_TEXT, 'Notifications'))).click()
        self.admin.sleep(5)

        self.admin.find(
            By.XPATH,
            "//div[3]//input[@id='message']").send_keys('automated test')

        self.admin.driver.find_elements_by_xpath(
            "//input[@class='btn btn-default']")[1].click()

        self.admin.sleep(5)

        # View notification as student
        teacher = Teacher(use_env_vars=True)
        teacher.login()
        teacher.select_course(appearance='physics')
        teacher.sleep(10)
        notifs = teacher.driver.find_elements_by_xpath(
            "//div[@class='notification system']/span")

        found = False

        for notif in notifs:
            if notif.text.find("automated test") >= 0:
                found = True

        teacher.delete()

        # Delete notification
        notif = self.admin.driver.find_elements_by_xpath(
            "//div[@class='col-xs-12']")

        for index, n in enumerate(notif):
            if n.text.find('automated test') >= 0:
                self.admin.driver.find_elements_by_xpath(
                    "//a[@class='btn btn-warning']")[index].click()
                self.admin.driver.switch_to_alert().accept()
                self.ps.test_updates['passed'] = True
                break

        self.admin.sleep(5)

        notif = self.admin.driver.find_elements_by_xpath(
            "//div[@class='col-xs-12']")

        assert (found), 'notification not seen'

        self.ps.test_updates['passed'] = True
Ejemplo n.º 50
0
class TestTrainingAndSupportingTeachersAndStudents(unittest.TestCase):
    """CC1.14 - Training and Supporting Teachers and Students."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.teacher = Teacher(use_env_vars=True,
                               pasta_user=self.ps,
                               capabilities=self.desired_capabilities)
        self.student = Student(use_env_vars=True,
                               existing_driver=self.teacher.driver,
                               pasta_user=self.ps,
                               capabilities=self.desired_capabilities)

    def tearDown(self):
        """Test destructor."""
        self.ps.update_job(job_id=str(self.teacher.driver.session_id),
                           **self.ps.test_updates)
        self.student = None
        try:
            self.teacher.delete()
        except:
            pass

    # Case C7704 - 001 - System | Concept Coach Zendesk is web-accessible
    @pytest.mark.skipif(str(7704) not in TESTS, reason='Excluded')
    def test_system_concept_coach_zendesk_is_web_accessible_7704(self):
        """Concept Coach Zendesk is web-accesible.

        Steps:
        Log in to Tutor as teacher
        If more then one course, click on a concept coach course
        In user menu in top right of header, click 'Get Help'

        Expected Result:
        In a new window or tab, zendesk help is opened
        """
        self.ps.test_updates['name'] = 'cc1.14.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.14', 'cc1.14.001', '7704']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(By.XPATH,
                          '//a[contains(@href,"/cc-dashboard/")]').click()
        self.teacher.open_user_menu()
        self.teacher.find(By.LINK_TEXT, 'Get Help').click()
        # change to window with help center
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]')
        assert ('support' in self.teacher.current_url()), 'not at help center'

        self.ps.test_updates['passed'] = True

    # Case C7705 - 002 - Teacher | Can access user support
    @pytest.mark.skipif(str(7705) not in TESTS, reason='Excluded')
    def test_teacher_can_access_user_support_7705(self):
        """Can access user support.

        Steps:
        Click on the user menu
        Click on the Get Help option

        Expected Result:
        In a new tab or window Zendesk is opened
        """
        self.ps.test_updates['name'] = 'cc1.14.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.14', 'cc1.14.002', '7705']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(By.XPATH,
                          '//a[contains(@href,"/cc-dashboard/")]').click()
        self.teacher.open_user_menu()
        self.teacher.find(By.LINK_TEXT, 'Get Help').click()
        # change to window with help center
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]')
        assert ('support' in self.teacher.current_url()), 'not at help center'

        self.ps.test_updates['passed'] = True

    # Case C7706 - 003 - Student | Can access user support
    @pytest.mark.skipif(str(7706) not in TESTS, reason='Excluded')
    def test_student_can_access_user_support_7706(self):
        """Can access user support.

        Steps:
        Click on the user menu
        Click on the Get Help option

        Expected Result:
        In a new tab or window zendesk is opened
        """
        self.ps.test_updates['name'] = 'cc1.14.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.14', 'cc1.14.003', '7706']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.login()
        self.student.open_user_menu()
        self.student.find(By.LINK_TEXT, 'Get Help').click()
        # change to window with help center
        window_with_help = self.student.driver.window_handles[1]
        self.student.driver.switch_to_window(window_with_help)
        self.student.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]')
        assert ('support' in self.student.current_url()), 'not at help center'
        self.ps.test_updates['passed'] = True

    # Case C7707 - 004 - Non-user | Submit support questions
    @pytest.mark.skipif(str(7707) not in TESTS, reason='Excluded')
    def test_nonuser_submit_support_questions_7707(self):
        """Submit support questions.

        Steps:
        Go to the Concept Coach landing page
        click support in the header
        enter text into the search box
        click contact us
        fillout form
        click Submit

        Expected Result:
        'Message sent' displayed in help box
        """
        self.ps.test_updates['name'] = 'cc1.14.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.14', 'cc1.14.004', '7707']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.get('http://cc.openstax.org/')
        self.teacher.sleep(1)
        # number hardcoded because condenses at different size than tutor
        if self.teacher.driver.get_window_size()['width'] < 1105:
            element = self.teacher.wait.until(
                expect.visibility_of_element_located(
                    (By.XPATH, '//label[@for="mobileNavToggle"]')))
            actions = ActionChains(self.teacher.driver)
            # use action chain because it is clicking to the wrong elemnt
            actions.move_to_element(element)
            actions.click()
            actions.perform()
        support = self.teacher.find(By.LINK_TEXT, 'support')
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(support)
        actions.click()
        actions.perform()
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.page.wait_for_page_load()
        self.teacher.find(By.ID, 'searchAskInput').send_keys('fake_question')
        self.teacher.find(By.ID, 'searchAskButton').click()
        self.teacher.find(By.LINK_TEXT, 'Contact Us').click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH,
            '//input[contains(@id,"contactUsForm:firstName")]').send_keys('qa')
        self.teacher.find(
            By.XPATH,
            '//input[contains(@id,"contactUsForm:lastName")]').send_keys(
                'test')
        self.teacher.find(
            By.XPATH,
            '//input[contains(@id,"contactUsForm:email")]').send_keys(
                '*****@*****.**')
        self.teacher.find(By.XPATH,
                          '//div[@class="submit-container"]//input').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//p[contains(text(),"Thank you")]')))
        self.ps.test_updates['passed'] = True

    # Case C7708 - 005 - Teacher | Submit support questions
    @pytest.mark.skipif(str(7708) not in TESTS, reason='Excluded')
    def test_teacher_submit_support_questions_7708(self):
        """Submit support questions.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If user has more than one course, click on a Concept Coach course
        Click the user menu in the right corner of the header
        Click "Get Help"
        Click "Submit a request"
        Fill out all the necessary text fields
        Click "Submit"

        Expected Result:
        The user submits support questions
        """
        self.ps.test_updates['name'] = 'cc1.14.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.14', 'cc1.14.005', '7708']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(By.XPATH,
                          '//a[contains(@href,"/cc-dashboard/")]').click()
        self.teacher.open_user_menu()
        self.teacher.find(By.LINK_TEXT, 'Get Help').click()
        # change to window with help center
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]')
        assert ('support' in self.teacher.current_url()), 'not at help center'
        self.teacher.page.wait_for_page_load()
        self.teacher.find(By.ID, 'searchAskInput').send_keys('fake_question')
        self.teacher.find(By.ID, 'searchAskButton').click()
        self.teacher.find(By.LINK_TEXT, 'Contact Us').click()
        self.teacher.page.wait_for_page_load()
        self.teacher.find(
            By.XPATH,
            '//input[contains(@id,"contactUsForm:firstName")]').send_keys('qa')
        self.teacher.find(
            By.XPATH,
            '//input[contains(@id,"contactUsForm:lastName")]').send_keys(
                'test')
        self.teacher.find(
            By.XPATH,
            '//input[contains(@id,"contactUsForm:email")]').send_keys(
                '*****@*****.**')
        self.teacher.find(By.XPATH,
                          '//div[@class="submit-container"]//input').click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//p[contains(text(),"Thank you")]')))
        self.ps.test_updates['passed'] = True

    # Case C7709 - 006 - Student | Submit support questions
    @pytest.mark.skipif(str(7709) not in TESTS, reason='Excluded')
    def test_student_submit_support_questions_7709(self):
        """Submit support questions.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account in the username and password text boxes
        Click on the 'Sign in' button
        Click the user menu in the right corner of the header
        Click "Get Help"
        Click "Submit a request"
        Fill out all the necessary text fields
        Click "Submit"

        Expected Result:
        The user submits support questions
        """
        self.ps.test_updates['name'] = 'cc1.14.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.14', 'cc1.14.006', '7709']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.login()
        self.student.open_user_menu()
        self.student.find(By.LINK_TEXT, 'Get Help').click()
        # change to window with help center
        window_with_help = self.student.driver.window_handles[1]
        self.student.driver.switch_to_window(window_with_help)
        self.student.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]')
        assert ('support' in self.student.current_url()), 'not at help center'
        self.student.page.wait_for_page_load()
        self.student.find(By.ID, 'searchAskInput').send_keys('fake_question')
        self.student.find(By.ID, 'searchAskButton').click()
        self.student.find(By.LINK_TEXT, 'Contact Us').click()
        self.student.page.wait_for_page_load()
        self.student.find(
            By.XPATH,
            '//input[contains(@id,"contactUsForm:firstName")]').send_keys('qa')
        self.student.find(
            By.XPATH,
            '//input[contains(@id,"contactUsForm:lastName")]').send_keys(
                'test')
        self.student.find(
            By.XPATH,
            '//input[contains(@id,"contactUsForm:email")]').send_keys(
                '*****@*****.**')
        self.student.find(By.XPATH,
                          '//div[@class="submit-container"]//input').click()
        self.student.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//p[contains(text(),"Thank you")]')))

        self.ps.test_updates['passed'] = True

    # Case C7710 - 007 - Teacher | View instructions on how to use CC
    @pytest.mark.skipif(str(7710) not in TESTS, reason='Excluded')
    def test_teacher_view_instructions_on_how_to_use_cc_7710(self):
        """View instructions on how to use Concept Coach.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If user has more than one course, click on a Concept Coach course
        Click the user menu in the right corner of the header
        Click "Get Help"
        Click "Getting Started Guide"
        * Click on the pdf link
            OR
        * Click "Getting Started" from the user menu

        Expected Result:
        The user is presented with a guide to use CC
        """
        self.ps.test_updates['name'] = 'cc1.14.007' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.14', 'cc1.14.007', '7710']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(By.XPATH,
                          '//a[contains(@href,"/cc-dashboard/")]').click()
        self.teacher.open_user_menu()
        self.teacher.find(By.LINK_TEXT, 'Getting Started').click()
        self.teacher.find(By.XPATH,
                          '//h3[contains(text(),"Getting Started")]').click()
        assert ('help' in self.teacher.current_url()), 'not at help center'

        self.ps.test_updates['passed'] = True

    # Case C7711 - 008 - Student | View instructions on how to use CC
    @pytest.mark.skipif(str(7711) not in TESTS, reason='Excluded')
    def test_student_view_instructions_on_how_to_use_cc_7711(self):
        """View instructions on how to use Concept Coach.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account in the username and password text boxes
        Click on the 'Sign in' button
        Click the user menu in the right corner of the header
        Click "Get Help"
        Scroll down to the questions under "Students"

        Expected Result:
        The user is presented with instructions on how to use CC
        """
        self.ps.test_updates['name'] = 'cc1.14.008' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.14', 'cc1.14.008', '7711']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.login()
        self.student.open_user_menu()
        self.student.find(By.LINK_TEXT, 'Get Help').click()
        # change to window with help center
        window_with_help = self.student.driver.window_handles[1]
        self.student.driver.switch_to_window(window_with_help)
        self.student.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]')
        assert ('support' in self.student.current_url()), 'not at help center'
        self.ps.test_updates['passed'] = True

    # Case C7712 - 009 - Teacher | View instructions on how to assign CC
    @pytest.mark.skipif(str(7712) not in TESTS, reason='Excluded')
    def test_teacher_view_instructions_on_how_to_assign_cc_7712(self):
        """View instructions on how to use Concept Coach.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account in the username and password text boxes
        Click on the 'Sign in' button
        If user has more than one course, click on a Concept Coach course
        Click the user menu in the right corner of the header
        Click "Get Help"

        Expected Result:
        Taken to Zendesk in a new window or tab
        Assorted help is displayed
        """
        self.ps.test_updates['name'] = 'cc1.14.009' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.14', 'cc1.14.009', '7712']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.teacher.login()
        self.teacher.find(By.XPATH,
                          '//a[contains(@href,"/cc-dashboard/")]').click()
        self.teacher.open_user_menu()
        self.teacher.find(By.LINK_TEXT, 'Get Help').click()
        # change to window with help center
        window_with_help = self.teacher.driver.window_handles[1]
        self.teacher.driver.switch_to_window(window_with_help)
        self.teacher.find(
            By.XPATH, '//center[contains(text(),"Concept Coach Help Center")]')
        assert ('support' in self.teacher.current_url()), 'not at help center'

        self.ps.test_updates['passed'] = True

    # Case C7713 - 010 - Student | Get help during account registration
    @pytest.mark.skipif(str(7713) not in TESTS, reason='Excluded')
    def test_student_get_help_during_account_registration_7713(self):
        """View instructions on how to use Concept Coach.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc1.14.010' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.14', 'cc1.14.010', '7713']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True

    # Case C7714 - 011 - Teacher | View instructions for Legacy users
    # transitioning to Concept Coach
    @pytest.mark.skipif(str(7714) not in TESTS, reason='Excluded')
    def test_teacher_view_instructions_for_legacy_users_transition_7714(self):
        """View instructions for Legacy users transitioning to Concept Coach.

        Steps:

        Expected Result:
        """
        self.ps.test_updates['name'] = 'cc1.14.011' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = ['cc1', 'cc1.14', 'cc1.14.011', '7714']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        raise NotImplementedError(inspect.currentframe().f_code.co_name)

        self.ps.test_updates['passed'] = True