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
Пример #2
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")]')
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 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 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
Пример #6
0
class TestChooseCourse(unittest.TestCase):
    """T1.38 - Choose Course."""

    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        self.user = None

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

    # Case C8254 - 001 - Student | Select a course
    @pytest.mark.skipif(str(8254) not in TESTS, reason='Excluded')
    def test_student_select_a_course_8254(self):
        """Select a course.

        Steps:
        Click on a Tutor course name

        Expected Result:
        The user selects a course and is presented with the dashboard.
        """
        self.ps.test_updates['name'] = 't1.38.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.38',
            't1.38.001',
            '8254'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.user = Student(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.user.login()
        self.user.select_course(appearance='physics')

        assert('list' in self.user.current_url()), \
            'Not in a course'

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

    # Case C8255 - 002 - Student | Bypass the course picker
    @pytest.mark.skipif(str(8255) not in TESTS, reason='Excluded')
    def test_student_bypass_the_course_picker_8255(self):
        """Bypass the course picker.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the student user account qas_01
        Click on the 'Sign in' button

        Expected Result:
        The user bypasses the course picker and is presented with the
        dashboard (because qas_01 is only enrolled in one course)
        """
        self.ps.test_updates['name'] = 't1.38.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.38',
            't1.38.002',
            '8255'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.user = Student(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.user.login(username="******")
        assert('list' in self.user.current_url()), \
            'Not in a course'

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

    # Case C8256 - 003 - Teacher | Select a course
    @pytest.mark.skipif(str(8256) not in TESTS, reason='Excluded')
    def test_teacher_select_a_course_8256(self):
        """Select a course.

        Steps:
        Click on a Tutor course name

        Expected Result:
        The user selects a course and is presented with the calendar dashboard
        """
        self.ps.test_updates['name'] = 't1.38.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.38',
            't1.38.003',
            '8256'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.user = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.user.login()
        self.user.select_course(appearance='physics')
        assert('calendar' in self.user.current_url()), \
            'Not in a course'

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

    # Case C8257 - 004 - Teacher | Bypass the course picker
    @pytest.mark.skipif(str(8257) not in TESTS, reason='Excluded')
    def test_teacher_bypass_the_course_picker_8257(self):
        """Bypass the course picker.

        Steps:
        Go to Tutor
        Click on the 'Login' button
        Enter the teacher user account [ qateacher | password ] in the
            username and password text boxes
        Click on the 'Sign in' button

        Expected Result:
        The user bypasses the course picker and is presented with the
        calendar dashboard (because qateacher only has one course)
        """
        self.ps.test_updates['name'] = 't1.38.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.38',
            't1.38.004',
            '8257'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.user = Teacher(
            use_env_vars=True,
            pasta_user=self.ps,
            capabilities=self.desired_capabilities
        )
        self.user.login(username="******")
        assert('calendar' in self.user.current_url()), \
            'Not in a course'

        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 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
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.teacher.login()
        # go to student scores
        self.teacher.select_course(appearance='college_physics')
        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

    def TestReadingAssignments(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 "Review" button under the selected reading assignment.
        ***Displays students progress on chosen assignment for selected period,
        actual questions, and question results. (t1.23.12)***
        ***Complete, In Progress, and Not Started counts for selected period
        are displayed (t1.23.19)***
        ***Current Topics Performance and Spaced Practice Performance
         section numbers match the section breadcrumbs (t1.23.20)***

        Click on a breadcrumb of selected section of reading.
        ***Screen is moved down to selected section of reading. (t1.23.16)***

        Click on "View Student Text Responses" button for selected question
        ***List of student text responses for selected question is displayed.
        (t1.23.22)***

        Click on user menu for drop down
        Click on "Student Scores"
        Hover over cell for chosen student and reading assignment
        Click review in the popup
        ***Teacher view of student work shown. Teacher can go through different
        sections with side arrows or breadcrumbs. Only sections student has
        gone through are shown. (t1.23.24)***

        Expected Results:

        ***Corresponds to***
        t1.23. 12,16, 19, 20, 22, 24
        '''
        # t1.23.12 --> Displays students progress on chosen assignment for
        # selected period, actual questions, and question results.
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//span[contains(@class, "tab-item-period-name")]')
            )
        ).click()

        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:
                self.teacher.driver.find_element(
                    By.XPATH,
                    '//span[contains(@class,"review-link wide")]' +
                    '//a[contains(text(),"Review")]'
                ).click()
                assert ('metrics' in self.teacher.current_url()), \
                    'Not viewing reading assignment summary'
                break
            except (NoSuchElementException,
                    ElementNotVisibleException,
                    WebDriverException):
                bar += scroll_width
                if scroll_total_size <= bar:
                    print("No readings 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.19 --> Complete, In Progress, and Not Started counts for
        # selected period are displayed
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//ul[contains(@role,"tablist")]' +
                 '//span[contains(@class,"tab-item-period-name")]')
            )
        )

        self.teacher.driver.find_element(
            By.XPATH, '//div[contains(@class,"stat complete")]' +
                      '//label[contains(text(),"Complete")]')
        self.teacher.driver.find_element(
            By.XPATH, '//div[contains(@class,"stat in-progress")]' +
                      '//label[contains(text(),"In Progress")]')
        self.teacher.driver.find_element(
            By.XPATH, '//div[contains(@class,"stat not-started")]' +
                      '//label[contains(text(),"Not Started")]')

        # T1.23.16 --> Screen is moved down to selected section of reading
        # MAYBE ADD T1.23.16 HERE??
        # I'M NOT SURE IF WOULD WORK --> ON LINE 766
        # SELECTING ON SECTIONS[-1] MIGHT MEAN IT WON'T WORK

        # t1.23.20 --> Current Topics Performance and
        # Spaced Practice Performance section numbers match the section
        # breadcrumbs

        sections = self.teacher.driver.find_elements(
            By.XPATH,
            '//label[contains(text(),"Current Topics")]/..' +
            '//div[contains(@class,"reading-progress")]' +
            '//span[contains(@class,"text-success")]')
        section_breadcrumbs = self.teacher.driver.find_elements(
            By.XPATH, '//span[contains(@class,"breadcrumbs")]')
        section_nums = []
        for x in section_breadcrumbs:
            section_nums.append(x.get_attribute("data-chapter"))
        for x in sections:
            assert (x.text in section_nums), \
                ("section and breadcrumb don't match: " + x.text)

        # ALMOST SURE THAT 23 IS A SUBCASE OF 19 -- VERIFY

        # only check against current topics because spaced Practice
        # will not be displayed in breadcrubms if no students have worked
        # problems from a section yet

        # t1.23.16 -->Screen is moved down to selected section of reading.

        sections = self.teacher.driver.find_elements(
            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'

        # t1.23.22 -->List of student text responses for selected question is
        # displayed

        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH,
                 '//a[contains(text(),"View student text responses")]')
            )
        ).click()
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.XPATH, '//div[@class="free-response"]')
            )
        ).click()

        # t1.23.24 -->
        # LOOKING BACK AT THIS CODE, I'M NOT SURE WHAT THIS ELEMNET IS SUPPOSED
        # TO BE
        '''element.click()
        actions = ActionChains(self.teacher.driver)
        actions.move_to_element(element)
        for _ in range(90):
            actions.move_by_offset(-1, 0)
        for _ in range(15):
            actions.move_by_offset(0, 1)
        actions.click()
        actions.perform()'''

        assert ('step' in self.teacher.current_url()), 'not at student work'
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.teacher.login()
        # go to student scores
        self.teacher.select_course(appearance='college_physics')
        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

    def TestExternalFromStudentScores(self):
        '''
        Go to https://tutor-qa.openstax.org/
        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 on the "Student Scores" button
        ***For external assignments the percentage of students who have clicked on the assignment is displayed.***
        (T1.23.15)


        Click on the tab for the chosen period
        Click on cell for chosen student and external assignment assignment
        ***Teacher view of student work shown. (Shows link to external assignment as a student would see it) (t1.23.26)***

        Corresponds to
        t1.23 15, 26
        '''
        # t1.23.15 --> For external assignments the percentage of students
        # who have clicked on the assignment is displayed

        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:
                self.teacher.driver.find_element(
                    By.XPATH, '//span[@class="click-rate"]')
                break
            except (NoSuchElementException, ElementNotVisibleException,
                    WebDriverException):
                bar += scroll_width
                if scroll_total_size <= bar:
                    print("No readings 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.26 -->  Teacher view of student work shown.
        # (Shows link to external assignment as a student would see it)

        external_assignment = self.teacher.find(
            By.XPATH, "//div[contains(@class,"
            "'external-cell')]//span[contains(text(),'---')]")
        Assignment.scroll_to(self.teacher.driver, external_assignment)
        external_assignment.click()

        self.student.find(By.XPATH, "//div[contains(@class,'external-step')]")
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
Пример #12
0
class TestWorkAReading(unittest.TestCase):
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.student = Student(use_env_vars=True,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
            self.teacher = Teacher(use_env_vars=True,
                                   pasta_user=self.ps,
                                   existing_driver=self.student.driver,
                                   capabilities=self.desired_capabilities)
        else:
            self.student = Student(use_env_vars=True, )
            self.teacher = Teacher(existing_driver=self.student.driver,
                                   use_env_vars=True)
        self.wait = WebDriverWait(self.student.driver, Assignment.WAIT_TIME)

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.student.driver.session_id),
                               **self.ps.test_updates)
        try:
            # Delete the assignment
            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 and delete it
            assignments = self.teacher.driver.find_elements_by_tag_name(
                'label')
            for assignment in assignments:
                if assignment.text == 'Epic 28':
                    assignment.click()
                    self.teacher.find(
                        By.XPATH,
                        "//a[@class='btn btn-default -edit-assignment']"
                    ).click()
                    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
        except:
            pass
        try:
            self.teacher.driver.refresh()
            self.teacher.sleep(5)

            self.teacher = None
            self.student.delete()
        except:
            pass

### NOT CERTAIN IF FINISH_READING_ASSIGNMENT WORKS

    def finish_reading_assignment(self, assignment_identifier):
        """
        HELPER FUNCTION
        Arguments:
        -assignment_identifier : a string that will identify the assignment
        (can either be the whole name or portion the name)

        Will complete the assignment, so that we get to the completion report

        :param assignment_identifier: (string) name or identifier that we
        can use to find the assignment of interest on the student course dashboard
        """
        while (True):

            # this is for progressing through the actual reading itself
            while ('arrow right' in self.student.driver.page_source):
                self.student.find(
                    By.XPATH, "//a[contains(@class,'arrow') " +
                    "and contains(@class,'right')]").click()

            # come here if multiple choice question
            if ('exercise-multiple-choice' in self.student.driver.page_source):

                answers = self.student.find(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.wait.until(
                    expect.element_to_be_clickable(
                        (By.XPATH, '//button[contains(@class,"async-button")' +
                         ' and contains(@class,"continue")]'))).click()
                self.student.sleep(5)
                page = self.student.driver.page_source
                assert ('question-feedback bottom' in page), \
                    'Did not submit MC'

            # come here if free response question
            elif ('textarea' in self.student.driver.page_source):
                self.student.find(
                    By.TAG_NAME,
                    'textarea').send_keys('An answer for this textarea')
                self.student.sleep(1)
                self.student.wait.until(
                    expect.element_to_be_clickable(
                        (By.XPATH, '//button[contains(@class,"async-button")' +
                         ' and contains(@class,"continue")]')))

    @pytest.mark.skipif(str(1) not in TESTS, reason='Excluded')
    def test_make_reading_teacher(self):
        """This is to make a reading assignment for the student to work"""
        self.teacher.login()

        # Create a reading for the student to work
        self.teacher.select_course(appearance='physics')
        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/new' in self.teacher.current_url()), \
            'Not on the add a reading page'

        self.teacher.find(
            By.XPATH, "//input[@id = 'reading-title']").send_keys('Epic 28')
        self.teacher.find(By.XPATH,
                          "//textarea[@class='form-control empty']").send_keys(
                              "instructions go here")
        self.teacher.find(By.XPATH,
                          "//input[@id = 'hide-periods-radio']").click()

        # Choose the first date calendar[0], second is calendar[1]
        # and set the open date to today
        self.teacher.driver.find_elements_by_xpath(
            "//div[@class = 'datepicker__input-container']")[0].click()
        self.teacher.driver.find_element_by_xpath(
            "//div[@class = 'datepicker__day datepicker__day--today']").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.find(By.XPATH, "//button[@id='reading-select']").click()
        self.teacher.driver.find_elements_by_xpath(
            "//span[@class='chapter-checkbox']")[5].click()
        self.teacher.find(
            By.XPATH,
            "//button[@class='-show-problems btn btn-primary']").click()
        self.teacher.sleep(10)

        # Publish the assignment
        self.teacher.find(
            By.XPATH,
            "//button[@class='async-button -publish btn btn-primary']").click(
            )
        # wait for it to publish
        self.teacher.sleep(20)

### IN THE CASE THAT WE NEED TO MAKE A READING ASSIGNMENT THAT WE WANT TO WORK (AND THAT
# WE WON'T ALREADY HAVE ONE, WE MUST USE THE TEACHER MAKE READING SCRIPT ABOVE )

    @pytest.mark.skipif(str(2) not in TESTS, reason='Excluded')
    def test_complete_reading_assignment_student(self):
        """
        Go to https://tutor-qa.openstax.org/
        Click on the 'Login' button
        Login with student account that has an unopened reading assignment
        Click 'Next'
        Enter the student 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 reading assignment under the tab "This Week" on the dashboard
        ***the user is presented with the first page of the reading assignment(t1.28.01)***

        Hover over the calendar in the header
        ***The user is presented with the due date/time in a popup box (t1.28.02)***

        Click on the arrow on the right
        ***The user is presented with the next reading section (t1.28.03)***

        Click the "Continue" button
        On a card with a free response assessment, enter a free response into the free response assessment text box
        ***The "Answer" button is activated (t1.28.04)***

        Click the "Answer" button
        ***A free response answer is submitted and the multiple choice is presented to the user (t1.28.05)***

        Select a multiple choice answer
        ***The "Submit" button is activated (t1.28.06)***

        Click the "Submit" button in the left corner of the footer
        ***A multiple choice answer is submitted and feedback is presented (t1.28.07)***
        ***Answer feedback is presented to the user (t1.28.08)***
        ***Correctness for a completed assessment is displayed in the milestones (t1.28.09)***

        Keep navigating thru cards until you've found
        On a card with a video, click the play button
        ***The video should play (t1.28.14)***

        Continue to the end of the reading assignment
        ***The user may be presented with a Review assessment at the end of the reading assignment (t1.28.16)***
        ***A user may be presented with a personalized assessment at the end of the reading assignment (t1.28.17)***
        ***Once finished with the reading, the user is presented with the completion report that shows "You are done" (t1.28.19)***

        After you have completed reading the sections you get to the spaced practice problem
        ***The reading review card should appear before the first spaced practice question (t2.13.03)***

        At the end of the reading, click the "Back to Dashboard" button
        ***The user views the completion report and return to the dashboard (t1.28.18)***
        ***The reading is marked "Complete" in the dashboard progress column (t1.28.20)***

        Corresponds to...
        t1.28 01 —> 09, 14, 16 —> 20
        T2.13 003
        :return:
        """
        self.student.login()

        # t1.28.01 --> the user is presented with the first page of the reading assignment
        # Test steps and verification assertions

        # self.student.select_course(appearance='physics') ### MAYBE USE THIS
        course_number = str(394)

        self.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, "//div[contains(@data-course-id,%s)]" %
                 course_number))).click()

        assignment_identifier = 'aaa'  ### COME BACK TO EDIT THIS!
        # ^ should be some string designating the reading that you should be working on

        reading = self.wait.until(
            expect.presence_of_element_located((
                By.XPATH,
                "//a[contains(@aria-labelledby,'%s') and contains(@class,'reading')]"
                % assignment_identifier)))
        assert (course_number in self.student.current_url()), \
            'Not viewing the calendar dashboard'
        reading.click()

        name = self.student.find(By.CLASS_NAME, 'center-control-assignment')

        assert (assignment_identifier in name.text), \
            'Not viewing the reading'
        assert ('steps/1' in self.student.current_url()), \
            'Not on the first page of the reading'

        # t1.28.02 --> The user is presented with the due date/time in a popup box
        reading_calendar = self.student.find(
            By.XPATH, "//button[contains(@class,'fa-calendar-o')]")
        ActionChains(
            self.student.driver).move_to_element(reading_calendar).perform()

        due_date_tooltip = self.student.driver.find_element(
            By.XPATH, "//*[contains(@id,'tooltip')]")
        due_text = due_date_tooltip.text

        assert('Due' in due_text),"Due date tooltip not " \
                                  "showing when hovering over calendar"

        past_url = self.student.driver.current_url
        # for comparison's sake later

        # t1.28.03 --> The user is presented with the next reading section
        ActionChains(self.student.driver).send_keys(Keys.ARROW_RIGHT)
        new_url = self.student.driver.current_url

        assert (past_url != new_url), "Right arrow didn't navigate to new page"
        assert ('steps/2' in self.student.current_url()), \
            'Not on the second page of the reading'
        ### NOT SURE WHETHER TO ASSUME THAT WE BEGIN ON THE FIRST PAGE

        while (True):
            try:
                question = self.student.find(
                    By.XPATH,
                    "//textarea[contains(@aria-labelledby,'text box')]")
                for i in answer_text:
                    question.send_keys(i)
                answer_btn = self.wait.until(
                    expect.element_to_be_clickable(
                        (By.XPATH, '//button[contains(@class,"continue")]')))

            except:
                # section_title = self.student.find(
                #     By.XPATH, "//textarea[contains(@class,'title')]")

                ActionChains(self.student.driver).send_keys(Keys.ARROW_RIGHT)
                # Navigate through the reading if you don't find a question

        # t1.28.04 -->  The "Answer" button is activated
        answer_btn.click()

        # t1.28.05 --> A free response answer is
        # submitted and the multiple choice is presented to the user
        mc_choice = self.student.find(By.XPATH,
                                      '//div[@class="answer-letter"]')
        self.student.driver.execute_script(
            'return arguments[0].scrollIntoView();', mc_choice)

        # t1.28.06 --> The "Submit" button is activated
        mc_choice.click()
        submit_btn = self.wait.until(
            expect.element_to_be_clickable(
                (By.XPATH, "//button[contains(@class,'continue')]")))
        # make sure that submit button can be clicked

        # t1.28.07 -->  multiple choice answer is
        # submitted and feedback is presented
        submit_btn.click()

        try:
            # this is looking for question feedback -- though not all questions might have
            self.student.find(
                By.XPATH,
                '//div[contains(@class,"question-feedback-content")]')

        except:
            correct_answer = self.student.find(
                By.XPATH, "//div[contains(@class,'disabled answer-correct')]")

        # t1.28.08 -->  Answer feedback is presented to the user
        ### HOW IS THIS DIFFERENT FROM THE PREVIOUS TEST? (T1.28.07)

        # t1.28.09 --> Correctness for a completed
        # assessment is displayed in the milestones
        milestone_toggle = self.student.find(
            By.XPATH, "//a[contains(@class,'milestones')]")
        milestone_toggle.click()

        self.student.find(
            By.XPATH, "//span[contains(@class,'openstax-breadcrumbs')"
            "and contains(@class,'correct')]")
        milestone_toggle.click()

        # # t1.28.14 --> an embedded video should play when clicked
        # ### BEST WAY TO DEAL WITH THIS? SHOULD I JUST ALWAYS LOOK FOR AN EMBEDDED VIDEO WHEN
        # ### COMPLETING THE OTHER TEST CASES? OR SHOULD I JUST DO THIS SEPARATELY?
        #
        # # After readings are completed, will navigate through the reading with the arrow keys
        # # will keep going until a video is found
        # while(True):
        #     try:
        #         video_play_btn = self.student.find(
        #             By.XPATH, "//button[contains(@class,'play-button')]")
        #         video_play_btn.click()
        #
        #     except:
        #         # section_title = self.student.find(
        #         #     By.XPATH, "//textarea[contains(@class,'title')]")
        #
        #         ActionChains(self.student.driver).send_keys(Keys.ARROW_RIGHT)
        #         # Navigate through the reading if you don't find a question
        #
        # self.wait.until(expect.presence_of_element_located(
        #         (By.XPATH,"//div[contains(@id,'playing-mode')]"
        #         )
        #     )
        # )
        # # if failed, then video didn't play upon clicking the play button

        # t1.28.16 -->The user may be presented with
        # a Review assessment at the end of the reading assignment
        ### BY THIS DOES IT MEAN "SPACED PRACTICE"?

        # t1.28.17 -->A user may be presented with a personalized
        # assessment at the end of the reading assignment
        ### HOW DO I DEAL WITH TEST CASES THAT MIGHT NOT TURN OUT TRUE?

        # t2.13.03 --> the reading review card should
        # appear before the first spaced practice question
        ### WHAT'S READING REVIEW?

        # t1.28.19 --> Once finished with the reading, the
        # user is presented with the completion report
        # that shows "You are done"
        completed_message = self.student.find(
            By.XPATH, "//div[contains(@class,'completed-message')]")
        completed_message.find_element(By.XPATH, "//h1")
        assert ('You are done' in completed_message.text
                ), "Completion report doesn't say 'You are done'"

        # t1.28.18 --> The user views the completion
        # report and return to the dashboard
        dashboard_button = self.student.find(
            By.XPATH, "//a[contains(@class,'btn-primary')]")
        dashboard_button.click()

        # t1.28.20 --> The reading is marked "Complete" in the dashboard
        # progress column
        self.wait.until(expect.presence_of_element_located((By.XPATH, "//")))
        reading = self.wait.until(
            expect.presence_of_element_located((
                By.XPATH,
                "//a[contains(@aria-labelledby,'%s') and contains(@class,'reading')]"
                % assignment_identifier)))
        reading.find_element(By.XPATH, "//span[contains(text(),'Complete')]")
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.teacher.driver.execute_script("window.resizeTo(1920,1080)")
        self.teacher.select_course(appearance='ap_biology')
        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'],
                                        '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.select_course(appearance='ap_biology')
        self.student.wait.until(
            expect.visibility_of_element_located((By.LINK_TEXT, 'This Week')))
        reading = self.student.driver.find_element(
            By.XPATH, '//div[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()
        self.student.driver.set_window_size(width=1300, height=1200)

    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

    # 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.paging-control.next').click()
        self.student.sleep(1)
        self.student.find(By.CSS_SELECTOR, 'a.paging-control.next').click()
        self.student.sleep(1)
        self.student.find(By.CSS_SELECTOR, 'a.paging-control.next').click()
        self.student.sleep(5)
        self.student.driver.execute_script("window.scrollTo(0, 0);")
        element = self.student.find(By.XPATH,
                                    "//a[@class='milestones-toggle']")
        actions = ActionChains(self.student.driver)
        actions.move_to_element(element)
        actions.click()
        actions.perform()
        self.student.sleep(1)
        self.student.driver.execute_script("window.scrollTo(0, 0);")
        cards = self.student.find_all(
            By.XPATH, "//div[@class='milestone milestone-reading']")
        # preview = ''
        if not isinstance(cards, list):
            # preview = cards.find_element(
            #    By.XPATH,
            #    "//div[@class='milestone milestone-reading']"
            # ).text
            cards.click()
        else:
            card = randint(0, len(cards))
            # preview = cards[card].find_element(
            #    By.XPATH,
            #    "//div[@class='milestone milestone-reading']"
            # ).text
            cards[card].click()

        string = "step/" + str(card + 1)

        assert(self.student.driver.current_url.find(string) >= 0), \
            'Something'

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

    # C85291 - 003 - Student | Reading Review card appears before the first
    # spaced practice question
    @pytest.mark.skipif(str(85291) not in TESTS, reason='Excluded')
    def test_student_reading_review_card_appears_before_first_spac_85291(self):
        """Reading Review card appears before first spaced practice question.

        Steps:
        Login as student
        Work the reading assignment
        After completing reading the sections you get a spaced practice problem

        Expected Result:
        The reading review card should appear before the first spaced practice
            question
        """
        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', '85291']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        while (1):
            while ('paging-control next' in self.student.driver.page_source
                   and 'Concept Coach' not in self.student.driver.page_source
                   and 'exercise-multiple-choice'
                   not in self.student.driver.page_source
                   and 'textarea' not in self.student.driver.page_source):
                self.student.find(By.XPATH,
                                  "//a[@class='paging-control next']").click()

            # multiple choice case
            if ('exercise-multiple-choice' in self.student.driver.page_source):

                answers = self.student.driver.find_elements(
                    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.wait.until(
                    expect.element_to_be_clickable(
                        (By.XPATH, '//button[contains(@class,"async-button")' +
                         ' and contains(@class,"continue")]'))).click()
                self.student.sleep(5)
                page = self.student.driver.page_source
                assert('question-feedback bottom' in page), \
                    'Did not submit MC'

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

            # free response case
            elif ('textarea' in self.student.driver.page_source):
                self.student.find(
                    By.TAG_NAME,
                    'textarea').send_keys('An answer for this textarea')
                self.student.sleep(2)
                self.student.wait.until(
                    expect.element_to_be_clickable(
                        (By.XPATH, '//button[contains(@class,"async-button")' +
                         ' and contains(@class,"continue")]'))).click()

                self.student.wait.until(
                    expect.visibility_of_element_located(
                        (By.CLASS_NAME, 'exercise-multiple-choice')))

                self.student.sleep(2)

            # Reached Concept Coach card
            if ('Spaced Practice' in self.student.driver.page_source
                    and 'spaced-practice-intro'
                    in self.student.driver.page_source):
                self.student.sleep(5)
                break

            self.student.sleep(2)

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

    # C100126 - 004 - Student | Section number is seen at the beginning of each
    # new section in a reading assignment
    @pytest.mark.skipif(str(100126) not in TESTS, reason='Excluded')
    def test_student_section_number_is_seen_st_the_beginning_of_e_100126(self):
        """Section number seen at beginning of each new section in a reading.

        Steps:
        Login as a student
        Click on a tutor course
        Click on a reading assignment
        Continue to work through reading assignment

        Expected Result:
        At the start of each new section, the section number is displayed
        """
        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', '100126']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.find(By.XPATH, "//span[@class='section']")
        self.student.sleep(3)

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

    # C100127 - 005 - Teacher | Section numbers are listed at the top of each
    # section in reference view
    @pytest.mark.skipif(str(100127) not in TESTS, reason='Excluded')
    def test_student_section_numbers_listed_at_the_top_of_each_se_100127(self):
        """Section numbers listed at the top of each section in reference view.

        Steps:
        Login as teacher
        Click on a tutor course
        Click "Browse the Book" or select "Browse the Book" from the user menu
        Select a section from the contents

        Expected Result:
        Section number listed in header
        """
        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', '100127']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.logout()
        self.teacher.login()
        self.teacher.select_course(appearance='ap_biology')
        self.teacher.open_user_menu()
        self.teacher.find(By.LINK_TEXT, "Browse the Book").click()
        self.teacher.sleep(5)
        self.teacher.driver.switch_to_window(
            self.student.driver.window_handles[-1])
        self.teacher.find(By.XPATH,
                          "//li[3]/ul[@class='section']/li/a").click()
        self.teacher.find(By.XPATH, "//span[@class='section']")
        self.teacher.sleep(3)

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

    # C100128 - 006 - Student | Section numbers are listed at the top of each
    # section in reference view
    @pytest.mark.skipif(str(100128) not in TESTS, reason='Excluded')
    def test_student_section_numbers_listed_at_the_top_of_each_se_100128(self):
        """Section numbers listed at the top of each section in reference view.

        Steps:
        Login as student
        Click on a tutor course
        Click "Browse the Book" or select "Browse the Book" from the user menu
        Select a section from the contents

        Expected Result:
        Section number listed in header
        """
        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', '100128']
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.open_user_menu()
        self.student.find(By.LINK_TEXT, "Browse the Book").click()
        self.student.sleep(5)
        self.student.driver.switch_to_window(
            self.student.driver.window_handles[-1])
        self.student.find(By.XPATH,
                          "//li[3]/ul[@class='section']/li/a").click()
        self.student.find(By.XPATH, "//span[@class='section']")
        self.student.sleep(3)

        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()
        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 TestWorkAReading(unittest.TestCase):
    """T1.28 - Work a reading."""
    def setUp(self):
        """Pretest settings."""
        self.ps = PastaSauce()
        self.desired_capabilities['name'] = self.id()
        if not LOCAL_RUN:
            self.student = Student(use_env_vars=True,
                                   pasta_user=self.ps,
                                   capabilities=self.desired_capabilities)
            self.teacher = Teacher(use_env_vars=True,
                                   pasta_user=self.ps,
                                   existing_driver=self.student.driver,
                                   capabilities=self.desired_capabilities)
        else:
            self.student = Student(use_env_vars=True, )
            self.teacher = Teacher(use_env_vars=True)
        self.teacher.login()

        # Create a reading for the student to work
        self.teacher.select_course(appearance='physics')
        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/new' in self.teacher.current_url()), \
            'Not on the add a reading page'

        self.teacher.find(
            By.XPATH, "//input[@id = 'reading-title']").send_keys('Epic 28')
        self.teacher.find(By.XPATH,
                          "//textarea[@class='form-control empty']").send_keys(
                              "instructions go here")
        self.teacher.find(By.XPATH,
                          "//input[@id = 'hide-periods-radio']").click()

        # Choose the first date calendar[0], second is calendar[1]
        # and set the open date to today
        self.teacher.driver.find_elements_by_xpath(
            "//div[@class = 'datepicker__input-container']")[0].click()
        self.teacher.driver.find_element_by_xpath(
            "//div[@class = 'datepicker__day datepicker__day--today']").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

        # Choose reading sections, pick physics chapter 6 since it has a video
        self.teacher.find(By.XPATH, "//button[@id='reading-select']").click()
        self.teacher.driver.find_elements_by_xpath(
            "//span[@class='chapter-checkbox']")[5].click()
        self.teacher.find(
            By.XPATH,
            "//button[@class='-show-problems btn btn-primary']").click()
        self.teacher.sleep(10)

        # Publish the assignment
        self.teacher.find(
            By.XPATH,
            "//button[@class='async-button -publish btn btn-primary']").click(
            )
        self.teacher.sleep(60)

        self.student.login()

    def tearDown(self):
        """Test destructor."""
        if not LOCAL_RUN:
            self.ps.update_job(job_id=str(self.student.driver.session_id),
                               **self.ps.test_updates)
        try:
            # Delete the assignment
            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 and delete it
            assignments = self.teacher.driver.find_elements_by_tag_name(
                'label')
            for assignment in assignments:
                if assignment.text == 'Epic 28':
                    assignment.click()
                    self.teacher.find(
                        By.XPATH,
                        "//a[@class='btn btn-default -edit-assignment']"
                    ).click()
                    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
        except:
            pass
        try:
            self.teacher.driver.refresh()
            self.teacher.sleep(5)

            self.teacher = None
            self.student.delete()
        except:
            pass

    @pytest.mark.skipif(str(1) not in TESTS, reason='Excluded')
    def test_start_reading_assignment_student(self):
        """
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
Пример #17
0
from staxing.helper import Teacher

basic_test_env = json.dumps([{
    'platform': 'OS X 10.11',
    'browserName': 'chrome',
    'version': 'latest',
    'screenResolution': "1024x768",
}])

BROWSERS = json.loads(os.getenv('BROWSERS', basic_test_env))
COURSE = "college_physics"

# Log in to tutor
teacher = Teacher(use_env_vars=True)
teacher.login()
teacher.select_course(appearance=COURSE)


def delete_assignment(target_element, is_published):
    """
    target_element: the web element of assignment to be deleted
    """
    target_element.click()
    sleep(1)
    if is_published:
        teacher.find(By.ID, "edit-assignment-button").click()
        sleep(1)
    delete_button = teacher.wait.until(
        expect.element_to_be_clickable(
            (By.XPATH, '//button[contains(@class,"delete-link")]')))
    teacher.scroll_to(delete_button)
Пример #18
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
Пример #19
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
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
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")]')))
Пример #22
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 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
class TestWorkAnExternalAssignment(unittest.TestCase):
    """T1.48 - Work an external assignment."""

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

        # Create an external assignment for the student to work
        self.teacher.select_course(appearance='physics')
        self.teacher.wait.until(
            expect.visibility_of_element_located(
                (By.ID, 'add-assignment')
            )
        ).click()
        self.teacher.find(
            By.PARTIAL_LINK_TEXT, 'Add External Assignment').click()
        assert('externals/new' in self.teacher.current_url()), \
            'Not on the add an external assignment page'

        self.teacher.find(
            By.XPATH, "//input[@id = 'reading-title']").send_keys('Epic 48')
        self.teacher.find(
            By.XPATH, "//textarea[@class='form-control empty']").send_keys(
            "instructions go here")
        self.teacher.find(
            By.XPATH, "//input[@id = 'hide-periods-radio']").click()

        # Choose the first date calendar[0], second is calendar[1]
        # and set the open date to today
        self.teacher.driver.find_elements_by_xpath(
            "//div[@class = 'datepicker__input-container']")[0].click()
        self.teacher.driver.find_element_by_xpath(
            "//div[@class = 'datepicker__day datepicker__day--today']").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.find(By.XPATH, "//input[@id='external-url']").send_keys(
            "google.com")
        self.teacher.sleep(5)

        # Publish the assignment
        self.teacher.find(
            By.XPATH,
            "//button[@class='async-button -publish btn btn-primary']").click()
        self.teacher.sleep(60)
        self.student.login()

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

            # Delete the assignment
            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 and delete it
            assignments = self.teacher.driver.find_elements_by_tag_name(
                'label')
            for assignment in assignments:
                if assignment.text == 'Epic 48':
                    assignment.click()
                    self.teacher.find(
                        By.XPATH,
                        "//a[@class='btn btn-default -edit-assignment']"
                    ).click()
                    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
        except:
            pass
        try:
            self.teacher.driver.refresh()
            self.teacher.sleep(5)

            self.teacher = None
            self.student.delete()
        except:
            pass

    # Case C8281 - 001 - Student | Click on an external assignment
    @pytest.mark.skipif(str(8281) not in TESTS, reason='Excluded')
    def test_student_click_on_a_external_assignment_8281(self):
        """Click on an external assignment.

        Steps:
        Click on an external assignment under the tab "This Week"
        on the dashboard

        Expected Result:
        The user is presented with the assignment link and instructions
        """
        self.ps.test_updates['name'] = 't1.48.001' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.48',
            't1.48.001',
            '8281'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.select_course(appearance='physics')
        assert('list' in self.student.current_url()), \
            'Not viewing the calendar dashboard'

        assignments = self.student.driver.find_elements_by_xpath(
            "//div[@class='task row external workable']")
        for assignment in assignments:
            if (assignment.text.find('Epic 48') >= 0):
                assignment.click()
                break

        assert('tasks' in self.student.current_url()), \
            'Not viewing assignment page'

        assert('steps' in self.student.current_url()), \
            'Not viewing assignment page'

        self.student.sleep(5)

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

    # Case C8282 - 002 - Student | Read the directions below the assignment
    # link or hover over the info icon in the footer
    @pytest.mark.skipif(str(8282) not in TESTS, reason='Excluded')
    def test_student_read_directions_below_or_hover_over_info_icon_8282(self):
        """Read directions below assignment link or hover over the info icon.

        Steps:
        Click on an external assignment under the tab "This Week"
            on the dashboard
        Hover the cursor over the info icon in the footer

        Expected Result:
        The user is presented with the directions for the assignment
        """
        self.ps.test_updates['name'] = 't1.48.002' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.48',
            't1.48.002',
            '8282'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.select_course(appearance='physics')
        assert('list' in self.student.current_url()), \
            'Not viewing the calendar dashboard'

        assignments = self.student.driver.find_elements_by_xpath(
            "//div[@class='task row external workable']")
        for assignment in assignments:
            if (assignment.text.find('Epic 48') >= 0):
                assignment.click()
                break

        assert('tasks' in self.student.current_url()), \
            'Not viewing assignment page'

        assert('steps' in self.student.current_url()), \
            'Not viewing assignment page'

        instructions = self.student.driver.find_elements_by_tag_name("p")
        flag = False
        for instruction in instructions:
            if (instruction.text == 'instructions go here'):
                flag = True
                break

        assert(flag), \
            'Did not read instructions'

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

    # Case C8283 - 003 - Student | Click the assignment link
    @pytest.mark.skipif(str(8283) not in TESTS, reason='Excluded')
    def test_student_click_the_assignment_link_8283(self):
        """Click the assignment link.

        Steps:
        Click on an external assignment under the tab "This Week"
            on the dashboard
        Click on the link to the external assignment

        Expected Result:
        The user is presented with the external assignment
        """
        self.ps.test_updates['name'] = 't1.48.003' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.48',
            't1.48.003',
            '8283'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.select_course(appearance='physics')
        assert('list' in self.student.current_url()), \
            'Not viewing the calendar dashboard'

        assignments = self.student.driver.find_elements_by_xpath(
            "//div[@class='task row external workable']")
        for assignment in assignments:
            if (assignment.text.find('Epic 48') >= 0):
                assignment.click()
                break

        assert('tasks' in self.student.current_url()), \
            'Not viewing assignment page'

        assert('steps' in self.student.current_url()), \
            'Not viewing assignment page'

        link = self.student.driver.find_element_by_link_text(
            'Epic 48')
        original = self.student.current_url()
        self.student.driver.get(link.get_attribute("href"))

        assert('google' in self.student.current_url()), \
            'Not viewing assignment link'

        self.student.sleep(5)
        self.student.driver.get(original)

        assert('tasks' in self.student.current_url()), \
            'Not viewing assignment page'

        assert('steps' in self.student.current_url()), \
            'Not viewing assignment page'

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

    # Case C8284 - 004 - Student | Close the assignment tab or window
    @pytest.mark.skipif(str(8284) not in TESTS, reason='Excluded')
    def test_student_close_the_assignment_8284(self):
        """Close the assignment tab or window.

        Steps:
        Click on an external assignment under the tab "This Week"
            on the dashboard
        Click on the link to the external assignment
        Close the assignment tab

        Expected Result:
        The assignment tab is closed and the user is presented with the
        external assignment link and instructions on Tutor
        """
        self.ps.test_updates['name'] = 't1.48.004' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.48',
            't1.48.004',
            '8284'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.select_course(appearance='physics')
        assert('list' in self.student.current_url()), \
            'Not viewing the calendar dashboard'

        assignments = self.student.driver.find_elements_by_xpath(
            "//div[@class='task row external workable']")
        for assignment in assignments:
            if (assignment.text.find('Epic 48') >= 0):
                assignment.click()
                break

        assert('tasks' in self.student.current_url()), \
            'Not viewing assignment page'

        assert('steps' in self.student.current_url()), \
            'Not viewing assignment page'

        link = self.student.driver.find_element_by_link_text(
            'Epic 48')
        original = self.student.current_url()
        self.student.driver.get(link.get_attribute("href"))

        assert('google' in self.student.current_url()), \
            'Not viewing assignment link'

        self.student.sleep(5)
        self.student.driver.get(original)

        assert('tasks' in self.student.current_url()), \
            'Not viewing assignment page'

        assert('steps' in self.student.current_url()), \
            'Not viewing assignment page'

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

    # Case C8285 - 005 - Student | Click the Back To Dashboard button to
    # finish the assignment
    @pytest.mark.skipif(str(8285) not in TESTS, reason='Excluded')
    def test_student_click_back_to_dashboard_button_8285(self):
        """Click the Back To Dashboard button to finish the assignment.

        Steps:
        Click on an external assignment under the tab "This Week"
            on the dashboard
        Click on the link to the external assignment
        Close the assignment tab
        Click "Back To Dashboard"

        Expected Result:
        The user is presented with the dashboard
        """
        self.ps.test_updates['name'] = 't1.48.005' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.48',
            't1.48.005',
            '8285'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.select_course(appearance='physics')
        assert('list' in self.student.current_url()), \
            'Not viewing the calendar dashboard'

        assignments = self.student.driver.find_elements_by_xpath(
            "//div[@class='task row external workable']")
        for assignment in assignments:
            if (assignment.text.find('Epic 48') >= 0):
                assignment.click()
                break

        assert('tasks' in self.student.current_url()), \
            'Not viewing assignment page'

        assert('steps' in self.student.current_url()), \
            'Not viewing assignment page'

        link = self.student.driver.find_element_by_link_text(
            'Epic 48')
        original = self.student.current_url()
        self.student.driver.get(link.get_attribute("href"))

        assert('google' in self.student.current_url()), \
            'Not viewing assignment link'

        self.student.sleep(5)
        self.student.driver.get(original)

        assert('tasks' in self.student.current_url()), \
            'Not viewing assignment page'

        assert('steps' in self.student.current_url()), \
            'Not viewing assignment page'

        self.student.find(By.LINK_TEXT, 'Back To Dashboard').click()

        assert('list' in self.student.current_url()), \
            'Not viewing the calendar dashboard'

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

    # Case C8286 - 006 - Student | Verify the assignment status as Clicked
    @pytest.mark.skipif(str(8286) not in TESTS, reason='Excluded')
    def test_student_verify_assignment_status_as_clicked_8286(self):
        """Verify the assignment status as Clicked.

        Steps:
        Click on an external assignment under the tab "This Week"
            on the dashboard
        Click on the link to the external assignment
        Close the assignment tab
        Click "Back To Dashboard"

        Expected Result:
        The external assignment is marked as "Clicked" in the Progress column
        on the dashboard
        """
        self.ps.test_updates['name'] = 't1.48.006' \
            + inspect.currentframe().f_code.co_name[4:]
        self.ps.test_updates['tags'] = [
            't1',
            't1.48',
            't1.48.006',
            '8286'
        ]
        self.ps.test_updates['passed'] = False

        # Test steps and verification assertions
        self.student.select_course(appearance='physics')
        assert('list' in self.student.current_url()), \
            'Not viewing the calendar dashboard'

        assignments = self.student.driver.find_elements_by_xpath(
            "//div[@class='task row external workable']")
        for assignment in assignments:
            if (assignment.text.find('Epic 48') >= 0):
                assignment.click()
                break

        assert('tasks' in self.student.current_url()), \
            'Not viewing assignment page'

        assert('steps' in self.student.current_url()), \
            'Not viewing assignment page'

        link = self.student.driver.find_element_by_link_text(
            'Epic 48')
        original = self.student.current_url()
        self.student.driver.get(link.get_attribute("href"))

        assert('google' in self.student.current_url()), \
            'Not viewing assignment link'

        self.student.sleep(5)
        self.student.driver.get(original)

        assert('tasks' in self.student.current_url()), \
            'Not viewing assignment page'

        assert('steps' in self.student.current_url()), \
            'Not viewing assignment page'

        self.student.find(By.LINK_TEXT, 'Back To Dashboard').click()

        assert('list' in self.student.current_url()), \
            'Not viewing the calendar dashboard'

        externals = self.student.driver.find_elements_by_xpath(
            "//div[@class = 'task row external workable']")

        for assignment in externals:
            if assignment.text.find("Clicked") >= 0 \
                    and assignment.text.find("Epic 48") >= 0:
                self.ps.test_updates['passed'] = True
                break
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
Пример #26
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

    '''
Пример #27
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")
Пример #28
0
class TestStaxingTutorTeacher(unittest.TestCase):
    """Staxing case tests."""

    def setUp(self):
        """Pretest settings."""
        self.teacher = Teacher(use_env_vars=True)
        self.teacher.username = os.getenv('TEACHER_USER_MULTI',
                                          self.teacher.username)
        self.teacher.set_window_size(height=700, width=1200)
        self.teacher.login()
        self.teacher.select_course(title='High School Physics')

    def tearDown(self):
        """Test destructor."""
        try:
            self.teacher.driver.quit()
        except:
            pass

    @pytest.mark.skipif(str(301) not in TESTS, reason='Excluded')
    def test_add_reading_assignment_individual_publish(self):
        """Build reading assignments."""
        # Reading, individual periods, publish
        assignment_title = 'Reading-%s' % Assignment.rword(5)
        left = randint(5, 20)
        right = left + randint(1, 10)
        start_date_1 = self.teacher.date_string(day_delta=left)
        end_date_1 = self.teacher.date_string(day_delta=left + right)
        start_date_2 = self.teacher.date_string(day_delta=left + 1)
        end_date_2 = self.teacher.date_string(day_delta=left + right + 1)
        start_time_2 = '6:30 am'
        end_time_2 = '11:59 pm'
        start_date_3 = self.teacher.date_string(day_delta=left + 2)
        end_date_3 = self.teacher.date_string(day_delta=left + right + 2)
        reading_options = self.teacher.get_book_sections()
        reading_start = randint(0, (len(reading_options) - 1))
        reading_end = reading_start + randint(1, 5)
        reading_list = reading_options[reading_start:reading_end]
        self.teacher.add_assignment(
            assignment='reading',
            args={
                'title': assignment_title,
                'description': 'Staxing test reading - individual periods - ' +
                               'publish',
                'periods': {
                    'First': (start_date_1, end_date_1),
                    'Second': ((start_date_2, start_time_2),
                               (end_date_2, end_time_2)),
                    'Third': (start_date_3, end_date_3),
                },
                'reading_list': reading_list,
                'status': 'publish',
                'break_point': None,
            }
        )
        assert('courses' 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(302) not in TESTS, reason='Excluded')
    def test_add_reading_assignment_all_publish(self):
        """Build reading assignments."""
        # Reading, all periods, publish
        assignment_title = 'Reading-%s' % Assignment.rword(5)
        left = randint(5, 20)
        right = left + randint(1, 10)
        start_date_1 = self.teacher.date_string(day_delta=left)
        end_date_1 = self.teacher.date_string(day_delta=left + right)
        start_date_2 = self.teacher.date_string(day_delta=left + 1)
        end_date_2 = self.teacher.date_string(day_delta=left + right + 1)
        reading_options = self.teacher.get_book_sections()
        reading_start = randint(0, (len(reading_options) - 1))
        reading_end = reading_start + randint(1, 5)
        reading_list = reading_options[reading_start:reading_end]
        self.teacher.add_assignment(
            assignment='reading',
            args={
                'title': assignment_title,
                'description': 'Staxing test reading - all periods - publish',
                'periods': {
                    'First': (start_date_1, end_date_1),
                    'all': (start_date_2, end_date_2),
                },
                'reading_list': reading_list,
                'status': 'publish',
                'break_point': None,
            }
        )
        assert('courses' 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_2)

    @pytest.mark.skipif(str(303) not in TESTS, reason='Excluded')
    def test_add_reading_assignment_individual_draft(self):
        """Build reading assignments."""
        # Reading, individual periods, draft
        assignment_title = 'Reading-%s' % Assignment.rword(5)
        left = randint(5, 20)
        right = left + randint(1, 10)
        start_date_1 = self.teacher.date_string(day_delta=left)
        end_date_1 = self.teacher.date_string(day_delta=left + right)
        start_date_2 = self.teacher.date_string(day_delta=left + 1)
        end_date_2 = self.teacher.date_string(day_delta=left + right + 1)
        start_date_3 = self.teacher.date_string(day_delta=left + 2)
        end_date_3 = self.teacher.date_string(day_delta=left + right + 2)
        reading_options = self.teacher.get_book_sections()
        reading_start = randint(0, (len(reading_options) - 1))
        reading_end = reading_start + randint(1, 5)
        reading_list = reading_options[reading_start:reading_end]
        self.teacher.add_assignment(
            assignment='reading',
            args={
                'title': assignment_title,
                'description': 'Staxing test reading - individual periods ' +
                               '- draft',
                'periods': {
                    'First': (start_date_1, end_date_1),
                    'Second': (start_date_2, end_date_2),
                    'Third': (start_date_3, end_date_3),
                },
                'reading_list': reading_list,
                'status': 'draft',
                'break_point': None,
            }
        )
        assert('courses' 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(self):
        """Build reading assignments."""
        # Reading, all periods, draft
        assignment_title = 'Reading-%s' % Assignment.rword(5)
        left = randint(5, 20)
        right = left + randint(1, 10)
        start_date_1 = self.teacher.date_string(day_delta=left)
        end_date_1 = self.teacher.date_string(day_delta=left + right)
        reading_options = self.teacher.get_book_sections()
        reading_start = randint(0, (len(reading_options) - 1))
        reading_end = reading_start + randint(1, 5)
        reading_list = reading_options[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('courses' 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(self):
        """Build reading assignments."""
        # Reading, one period, cancel
        assignment_title = 'Reading-%s' % Assignment.rword(5)
        left = randint(5, 20)
        right = left + randint(1, 10)
        start_date_1 = self.teacher.date_string(day_delta=left)
        end_date_1 = self.teacher.date_string(day_delta=left + right)
        reading_options = self.teacher.get_book_sections()
        reading_start = randint(0, (len(reading_options) - 1))
        reading_end = reading_start + randint(1, 5)
        reading_list = reading_options[reading_start:reading_end]
        self.teacher.add_assignment(
            assignment='reading',
            args={
                'title': assignment_title,
                'description': 'Staxing test reading - cancel',
                'periods': {
                    'First': (start_date_1, end_date_1),
                },
                'reading_list': reading_list,
                'status': 'cancel',
                'break_point': None,
            }
        )
        assert('courses' 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(self):
        """No test placeholder."""
        pass

    @pytest.mark.skipif(str(307) not in TESTS, reason='Excluded')
    def test_delete_assignment(self):
        """No test placeholder."""
        assignment_title = 'Reading-%s' % Assignment.rword(5)
        start_date = self.teacher.date_string(day_delta=1)
        end_date = self.teacher.date_string(day_delta=3)
        self.teacher.add_assignment(
            assignment='reading',
            args={
                'title': assignment_title,
                'periods': {
                    'all': (start_date, end_date),
                },
                'reading_list': ['1', '1.1'],
                'status': 'draft',
                'break_point': None,
            }
        )
        assert('courses' 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
        )
        time.sleep(5.0)
        assert(reading), \
            '%s not publishing on %s' % (assignment_title, end_date)
        new_date = start_date.split('/')
        new_date = '%s/%s' % (int(new_date[0]), int(new_date[1]))
        self.teacher.wait.until(
            expect.presence_of_element_located(
                (By.XPATH,
                 '//label[@data-title="%s" and @data-opens-at="%s"]' %
                 (assignment_title, new_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)
        with pytest.raises(NoSuchElementException):
            self.teacher.find(
                By.XPATH,
                '//label[text()="%s"]' % assignment_title
            )

    @pytest.mark.skipif(str(308) not in TESTS, reason='Excluded')
    def test_goto_menu_item(self):
        """No test placeholder."""
        pass

    @pytest.mark.skipif(str(309) not in TESTS, reason='Excluded')
    def test_goto_calendar(self):
        """No test placeholder."""
        pass

    @pytest.mark.skipif(str(310) not in TESTS, reason='Excluded')
    def test_goto_performance_forecast(self):
        """No test placeholder."""
        pass

    @pytest.mark.skipif(str(311) not in TESTS, reason='Excluded')
    def test_goto_student_scores(self):
        """No test placeholder."""
        pass

    @pytest.mark.skipif(str(312) not in TESTS, reason='Excluded')
    def test_goto_course_roster(self):
        """No test placeholder."""
        pass

    @pytest.mark.skipif(str(313) not in TESTS, reason='Excluded')
    def test_goto_course_settings(self):
        """No test placeholder."""
        pass

    @pytest.mark.skipif(str(314) not in TESTS, reason='Excluded')
    def test_add_course_section(self):
        """No test placeholder."""
        pass

    @pytest.mark.skipif(str(315) not in TESTS, reason='Excluded')
    def test_get_enrollment_code(self):
        """No test placeholder."""
        pass
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
    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
Пример #31
0
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

    # 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(title='College Physics with Courseware')

        # find either upcoming events, or a message stating there are none.
        try:
            self.teacher.wait.until(
                expect.visibility_of_element_located(
                    (By.XPATH, '//span[contains(text(),"%s")]' % "Coming Up")))
        except TimeoutException:
            self.teacher.wait.until(
                expect.visibility_of_element_located(
                    (By.XPATH,
                     '//div[contains(text(),"%s")]' % "No upcoming events")))
        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:
        Login as a teacher
        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"

        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='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")]')))
        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='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")]')))
        self.ps.test_updates['passed'] = True

    '''