class CoursewareMultipleVerticalsTest(UniqueCourseTest, EventsTestMixin):
    """
    Test courseware with multiple verticals
    """
    USERNAME = "******"
    EMAIL = "*****@*****.**"

    def setUp(self):
        super(CoursewareMultipleVerticalsTest, self).setUp()

        self.courseware_page = CoursewarePage(self.browser, self.course_id)

        self.course_outline = CourseOutlinePage(self.browser,
                                                self.course_info['org'],
                                                self.course_info['number'],
                                                self.course_info['run'])

        # Install a course with sections/problems, tabs, updates, and handouts
        course_fix = CourseFixture(self.course_info['org'],
                                   self.course_info['number'],
                                   self.course_info['run'],
                                   self.course_info['display_name'])

        course_fix.add_children(
            XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
                XBlockFixtureDesc(
                    'sequential', 'Test Subsection 1,1').add_children(
                        XBlockFixtureDesc(
                            'problem',
                            'Test Problem 1',
                            data='<problem>problem 1 dummy body</problem>'),
                        XBlockFixtureDesc(
                            'html',
                            'html 1',
                            data="<html>html 1 dummy body</html>"),
                        XBlockFixtureDesc(
                            'problem',
                            'Test Problem 2',
                            data="<problem>problem 2 dummy body</problem>"),
                        XBlockFixtureDesc(
                            'html',
                            'html 2',
                            data="<html>html 2 dummy body</html>"),
                    ),
                XBlockFixtureDesc(
                    'sequential', 'Test Subsection 1,2').add_children(
                        XBlockFixtureDesc(
                            'problem',
                            'Test Problem 3',
                            data='<problem>problem 3 dummy body</problem>'), ),
                XBlockFixtureDesc(
                    'sequential',
                    'Test HIDDEN Subsection',
                    metadata={
                        'visible_to_staff_only': True
                    }).add_children(
                        XBlockFixtureDesc(
                            'problem',
                            'Test HIDDEN Problem',
                            data='<problem>hidden problem</problem>'), ),
            ),
            XBlockFixtureDesc('chapter', 'Test Section 2').add_children(
                XBlockFixtureDesc(
                    'sequential', 'Test Subsection 2,1').add_children(
                        XBlockFixtureDesc(
                            'problem',
                            'Test Problem 4',
                            data='<problem>problem 4 dummy body</problem>'), ),
            ),
            XBlockFixtureDesc(
                'chapter',
                'Test HIDDEN Section',
                metadata={
                    'visible_to_staff_only': True
                }).add_children(
                    XBlockFixtureDesc('sequential',
                                      'Test HIDDEN Subsection'), ),
        ).install()

        # Auto-auth register for the course.
        AutoAuthPage(self.browser,
                     username=self.USERNAME,
                     email=self.EMAIL,
                     course_id=self.course_id,
                     staff=False).visit()
        self.courseware_page.visit()
        self.course_nav = CourseNavPage(self.browser)

    def test_navigation_buttons(self):
        # start in first section
        self.assert_navigation_state('Test Section 1',
                                     'Test Subsection 1,1',
                                     0,
                                     next_enabled=True,
                                     prev_enabled=False)

        # next takes us to next tab in sequential
        self.courseware_page.click_next_button_on_top()
        self.assert_navigation_state('Test Section 1',
                                     'Test Subsection 1,1',
                                     1,
                                     next_enabled=True,
                                     prev_enabled=True)

        # go to last sequential position
        self.courseware_page.go_to_sequential_position(4)
        self.assert_navigation_state('Test Section 1',
                                     'Test Subsection 1,1',
                                     3,
                                     next_enabled=True,
                                     prev_enabled=True)

        # next takes us to next sequential
        self.courseware_page.click_next_button_on_bottom()
        self.assert_navigation_state('Test Section 1',
                                     'Test Subsection 1,2',
                                     0,
                                     next_enabled=True,
                                     prev_enabled=True)

        # next takes us to next chapter
        self.courseware_page.click_next_button_on_top()
        self.assert_navigation_state('Test Section 2',
                                     'Test Subsection 2,1',
                                     0,
                                     next_enabled=False,
                                     prev_enabled=True)

        # previous takes us to previous chapter
        self.courseware_page.click_previous_button_on_top()
        self.assert_navigation_state('Test Section 1',
                                     'Test Subsection 1,2',
                                     0,
                                     next_enabled=True,
                                     prev_enabled=True)

        # previous takes us to last tab in previous sequential
        self.courseware_page.click_previous_button_on_bottom()
        self.assert_navigation_state('Test Section 1',
                                     'Test Subsection 1,1',
                                     3,
                                     next_enabled=True,
                                     prev_enabled=True)

        # previous takes us to previous tab in sequential
        self.courseware_page.click_previous_button_on_bottom()
        self.assert_navigation_state('Test Section 1',
                                     'Test Subsection 1,1',
                                     2,
                                     next_enabled=True,
                                     prev_enabled=True)

        # test UI events emitted by navigation
        filter_sequence_ui_event = lambda event: event.get(
            'name', '').startswith('edx.ui.lms.sequence.')

        sequence_ui_events = self.wait_for_events(
            event_filter=filter_sequence_ui_event, timeout=2)
        legacy_events = [
            ev for ev in sequence_ui_events
            if ev['event_type'] in {'seq_next', 'seq_prev', 'seq_goto'}
        ]
        nonlegacy_events = [
            ev for ev in sequence_ui_events if ev not in legacy_events
        ]

        self.assertTrue(
            all('old' in json.loads(ev['event']) for ev in legacy_events))
        self.assertTrue(
            all('new' in json.loads(ev['event']) for ev in legacy_events))
        self.assertFalse(
            any('old' in json.loads(ev['event']) for ev in nonlegacy_events))
        self.assertFalse(
            any('new' in json.loads(ev['event']) for ev in nonlegacy_events))

        self.assert_events_match([
            {
                'event_type': 'seq_next',
                'event': {
                    'old': 1,
                    'new': 2,
                    'current_tab': 1,
                    'tab_count': 4,
                    'widget_placement': 'top',
                }
            },
            {
                'event_type': 'seq_goto',
                'event': {
                    'old': 2,
                    'new': 4,
                    'current_tab': 2,
                    'target_tab': 4,
                    'tab_count': 4,
                    'widget_placement': 'top',
                }
            },
            {
                'event_type': 'edx.ui.lms.sequence.next_selected',
                'event': {
                    'current_tab': 4,
                    'tab_count': 4,
                    'widget_placement': 'bottom',
                }
            },
            {
                'event_type': 'edx.ui.lms.sequence.next_selected',
                'event': {
                    'current_tab': 1,
                    'tab_count': 1,
                    'widget_placement': 'top',
                }
            },
            {
                'event_type': 'edx.ui.lms.sequence.previous_selected',
                'event': {
                    'current_tab': 1,
                    'tab_count': 1,
                    'widget_placement': 'top',
                }
            },
            {
                'event_type': 'edx.ui.lms.sequence.previous_selected',
                'event': {
                    'current_tab': 1,
                    'tab_count': 1,
                    'widget_placement': 'bottom',
                }
            },
            {
                'event_type': 'seq_prev',
                'event': {
                    'old': 4,
                    'new': 3,
                    'current_tab': 4,
                    'tab_count': 4,
                    'widget_placement': 'bottom',
                }
            },
        ], sequence_ui_events)

    def test_outline_selected_events(self):
        self.course_nav.go_to_section('Test Section 1', 'Test Subsection 1,2')

        self.course_nav.go_to_section('Test Section 2', 'Test Subsection 2,1')

        # test UI events emitted by navigating via the course outline
        filter_selected_events = lambda event: event.get(
            'name', '') == 'edx.ui.lms.outline.selected'
        selected_events = self.wait_for_events(
            event_filter=filter_selected_events, timeout=2)

        # note: target_url is tested in unit tests, as the url changes here with every test (it includes GUIDs).
        self.assert_events_match([
            {
                'event_type': 'edx.ui.lms.outline.selected',
                'name': 'edx.ui.lms.outline.selected',
                'event': {
                    'target_name': 'Test Subsection 1,2 ',
                    'widget_placement': 'accordion',
                }
            },
            {
                'event_type': 'edx.ui.lms.outline.selected',
                'name': 'edx.ui.lms.outline.selected',
                'event': {
                    'target_name': 'Test Subsection 2,1 ',
                    'widget_placement': 'accordion',
                }
            },
        ], selected_events)

    def test_link_clicked_events(self):
        """
        Given that I am a user in the courseware
        When I navigate via the left-hand nav
        Then a link clicked event is logged
        """
        self.course_nav.go_to_section('Test Section 1', 'Test Subsection 1,2')
        self.course_nav.go_to_section('Test Section 2', 'Test Subsection 2,1')

        filter_link_clicked = lambda event: event.get(
            'name', '') == 'edx.ui.lms.link_clicked'
        link_clicked_events = self.wait_for_events(
            event_filter=filter_link_clicked, timeout=2)
        self.assertEqual(len(link_clicked_events), 2)

    def assert_navigation_state(self, section_title, subsection_title,
                                subsection_position, next_enabled,
                                prev_enabled):
        """
        Verifies that the navigation state is as expected.
        """
        self.assertTrue(
            self.course_nav.is_on_section(section_title, subsection_title))
        self.assertEquals(self.courseware_page.sequential_position,
                          subsection_position)
        self.assertEquals(self.courseware_page.is_next_button_enabled,
                          next_enabled)
        self.assertEquals(self.courseware_page.is_previous_button_enabled,
                          prev_enabled)

    def test_tab_position(self):
        # test that using the position in the url direct to correct tab in courseware
        self.course_nav.go_to_section('Test Section 1', 'Test Subsection 1,1')
        subsection_url = self.course_nav.active_subsection_url
        url_part_list = subsection_url.split('/')
        self.assertEqual(len(url_part_list), 9)

        course_id = url_part_list[4]
        chapter_id = url_part_list[-3]
        subsection_id = url_part_list[-2]
        problem1_page = CoursewareSequentialTabPage(self.browser,
                                                    course_id=course_id,
                                                    chapter=chapter_id,
                                                    subsection=subsection_id,
                                                    position=1).visit()
        self.assertIn('problem 1 dummy body',
                      problem1_page.get_selected_tab_content())

        html1_page = CoursewareSequentialTabPage(self.browser,
                                                 course_id=course_id,
                                                 chapter=chapter_id,
                                                 subsection=subsection_id,
                                                 position=2).visit()
        self.assertIn('html 1 dummy body',
                      html1_page.get_selected_tab_content())

        problem2_page = CoursewareSequentialTabPage(self.browser,
                                                    course_id=course_id,
                                                    chapter=chapter_id,
                                                    subsection=subsection_id,
                                                    position=3).visit()
        self.assertIn('problem 2 dummy body',
                      problem2_page.get_selected_tab_content())

        html2_page = CoursewareSequentialTabPage(self.browser,
                                                 course_id=course_id,
                                                 chapter=chapter_id,
                                                 subsection=subsection_id,
                                                 position=4).visit()
        self.assertIn('html 2 dummy body',
                      html2_page.get_selected_tab_content())

    @attr('a11y')
    def test_courseware_a11y(self):
        """
        Run accessibility audit for the problem type.
        """
        self.course_nav.go_to_section('Test Section 1', 'Test Subsection 1,1')
        # Set the scope to the sequence navigation
        self.courseware_page.a11y_audit.config.set_scope(
            include=['div.sequence-nav'])
        self.courseware_page.a11y_audit.check_for_accessibility_errors()
class CoursewareMultipleVerticalsTest(UniqueCourseTest, EventsTestMixin):
    """
    Test courseware with multiple verticals
    """
    USERNAME = "******"
    EMAIL = "*****@*****.**"

    def setUp(self):
        super(CoursewareMultipleVerticalsTest, self).setUp()

        self.courseware_page = CoursewarePage(self.browser, self.course_id)

        self.course_outline = CourseOutlinePage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )

        # Install a course with sections/problems, tabs, updates, and handouts
        course_fix = CourseFixture(
            self.course_info['org'], self.course_info['number'],
            self.course_info['run'], self.course_info['display_name']
        )

        course_fix.add_children(
            XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection 1,1').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 1', data='<problem>problem 1 dummy body</problem>'),
                    XBlockFixtureDesc('html', 'html 1', data="<html>html 1 dummy body</html>"),
                    XBlockFixtureDesc('problem', 'Test Problem 2', data="<problem>problem 2 dummy body</problem>"),
                    XBlockFixtureDesc('html', 'html 2', data="<html>html 2 dummy body</html>"),
                ),
                XBlockFixtureDesc('sequential', 'Test Subsection 1,2').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 3', data='<problem>problem 3 dummy body</problem>'),
                ),
                XBlockFixtureDesc(
                    'sequential', 'Test HIDDEN Subsection', metadata={'visible_to_staff_only': True}
                ).add_children(
                    XBlockFixtureDesc('problem', 'Test HIDDEN Problem', data='<problem>hidden problem</problem>'),
                ),
            ),
            XBlockFixtureDesc('chapter', 'Test Section 2').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection 2,1').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 4', data='<problem>problem 4 dummy body</problem>'),
                ),
            ),
            XBlockFixtureDesc('chapter', 'Test HIDDEN Section', metadata={'visible_to_staff_only': True}).add_children(
                XBlockFixtureDesc('sequential', 'Test HIDDEN Subsection'),
            ),
        ).install()

        # Auto-auth register for the course.
        AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL,
                     course_id=self.course_id, staff=False).visit()
        self.courseware_page.visit()
        self.course_nav = CourseNavPage(self.browser)

    def test_navigation_buttons(self):
        # start in first section
        self.assert_navigation_state('Test Section 1', 'Test Subsection 1,1', 0, next_enabled=True, prev_enabled=False)

        # next takes us to next tab in sequential
        self.courseware_page.click_next_button_on_top()
        self.assert_navigation_state('Test Section 1', 'Test Subsection 1,1', 1, next_enabled=True, prev_enabled=True)

        # go to last sequential position
        self.courseware_page.go_to_sequential_position(4)
        self.assert_navigation_state('Test Section 1', 'Test Subsection 1,1', 3, next_enabled=True, prev_enabled=True)

        # next takes us to next sequential
        self.courseware_page.click_next_button_on_bottom()
        self.assert_navigation_state('Test Section 1', 'Test Subsection 1,2', 0, next_enabled=True, prev_enabled=True)

        # next takes us to next chapter
        self.courseware_page.click_next_button_on_top()
        self.assert_navigation_state('Test Section 2', 'Test Subsection 2,1', 0, next_enabled=False, prev_enabled=True)

        # previous takes us to previous chapter
        self.courseware_page.click_previous_button_on_top()
        self.assert_navigation_state('Test Section 1', 'Test Subsection 1,2', 0, next_enabled=True, prev_enabled=True)

        # previous takes us to last tab in previous sequential
        self.courseware_page.click_previous_button_on_bottom()
        self.assert_navigation_state('Test Section 1', 'Test Subsection 1,1', 3, next_enabled=True, prev_enabled=True)

        # previous takes us to previous tab in sequential
        self.courseware_page.click_previous_button_on_bottom()
        self.assert_navigation_state('Test Section 1', 'Test Subsection 1,1', 2, next_enabled=True, prev_enabled=True)

        # test UI events emitted by navigation
        filter_sequence_ui_event = lambda event: event.get('name', '').startswith('edx.ui.lms.sequence.')

        sequence_ui_events = self.wait_for_events(event_filter=filter_sequence_ui_event, timeout=2)
        legacy_events = [ev for ev in sequence_ui_events if ev['event_type'] in {'seq_next', 'seq_prev', 'seq_goto'}]
        nonlegacy_events = [ev for ev in sequence_ui_events if ev not in legacy_events]

        self.assertTrue(all('old' in json.loads(ev['event']) for ev in legacy_events))
        self.assertTrue(all('new' in json.loads(ev['event']) for ev in legacy_events))
        self.assertFalse(any('old' in json.loads(ev['event']) for ev in nonlegacy_events))
        self.assertFalse(any('new' in json.loads(ev['event']) for ev in nonlegacy_events))

        self.assert_events_match(
            [
                {
                    'event_type': 'seq_next',
                    'event': {
                        'old': 1,
                        'new': 2,
                        'current_tab': 1,
                        'tab_count': 4,
                        'widget_placement': 'top',
                    }
                },
                {
                    'event_type': 'seq_goto',
                    'event': {
                        'old': 2,
                        'new': 4,
                        'current_tab': 2,
                        'target_tab': 4,
                        'tab_count': 4,
                        'widget_placement': 'top',
                    }
                },
                {
                    'event_type': 'edx.ui.lms.sequence.next_selected',
                    'event': {
                        'current_tab': 4,
                        'tab_count': 4,
                        'widget_placement': 'bottom',
                    }
                },
                {
                    'event_type': 'edx.ui.lms.sequence.next_selected',
                    'event': {
                        'current_tab': 1,
                        'tab_count': 1,
                        'widget_placement': 'top',
                    }
                },
                {
                    'event_type': 'edx.ui.lms.sequence.previous_selected',
                    'event': {
                        'current_tab': 1,
                        'tab_count': 1,
                        'widget_placement': 'top',
                    }
                },
                {
                    'event_type': 'edx.ui.lms.sequence.previous_selected',
                    'event': {
                        'current_tab': 1,
                        'tab_count': 1,
                        'widget_placement': 'bottom',
                    }
                },
                {
                    'event_type': 'seq_prev',
                    'event': {
                        'old': 4,
                        'new': 3,
                        'current_tab': 4,
                        'tab_count': 4,
                        'widget_placement': 'bottom',
                    }
                },
            ],
            sequence_ui_events
        )

    def test_outline_selected_events(self):
        self.course_nav.go_to_section('Test Section 1', 'Test Subsection 1,2')

        self.course_nav.go_to_section('Test Section 2', 'Test Subsection 2,1')

        # test UI events emitted by navigating via the course outline
        filter_selected_events = lambda event: event.get('name', '') == 'edx.ui.lms.outline.selected'
        selected_events = self.wait_for_events(event_filter=filter_selected_events, timeout=2)

        # note: target_url is tested in unit tests, as the url changes here with every test (it includes GUIDs).
        self.assert_events_match(
            [
                {
                    'event_type': 'edx.ui.lms.outline.selected',
                    'name': 'edx.ui.lms.outline.selected',
                    'event': {
                        'target_name': 'Test Subsection 1,2 ',
                        'widget_placement': 'accordion',
                    }
                },
                {
                    'event_type': 'edx.ui.lms.outline.selected',
                    'name': 'edx.ui.lms.outline.selected',
                    'event': {
                        'target_name': 'Test Subsection 2,1 ',
                        'widget_placement': 'accordion',

                    }
                },
            ],
            selected_events
        )

    def test_link_clicked_events(self):
        """
        Given that I am a user in the courseware
        When I navigate via the left-hand nav
        Then a link clicked event is logged
        """
        self.course_nav.go_to_section('Test Section 1', 'Test Subsection 1,2')
        self.course_nav.go_to_section('Test Section 2', 'Test Subsection 2,1')

        filter_link_clicked = lambda event: event.get('name', '') == 'edx.ui.lms.link_clicked'
        link_clicked_events = self.wait_for_events(event_filter=filter_link_clicked, timeout=2)
        self.assertEqual(len(link_clicked_events), 2)

    def assert_navigation_state(
            self, section_title, subsection_title, subsection_position, next_enabled, prev_enabled
    ):
        """
        Verifies that the navigation state is as expected.
        """
        self.assertTrue(self.course_nav.is_on_section(section_title, subsection_title))
        self.assertEquals(self.courseware_page.sequential_position, subsection_position)
        self.assertEquals(self.courseware_page.is_next_button_enabled, next_enabled)
        self.assertEquals(self.courseware_page.is_previous_button_enabled, prev_enabled)

    def test_tab_position(self):
        # test that using the position in the url direct to correct tab in courseware
        self.course_nav.go_to_section('Test Section 1', 'Test Subsection 1,1')
        subsection_url = self.course_nav.active_subsection_url
        url_part_list = subsection_url.split('/')
        self.assertEqual(len(url_part_list), 9)

        course_id = url_part_list[4]
        chapter_id = url_part_list[-3]
        subsection_id = url_part_list[-2]
        problem1_page = CoursewareSequentialTabPage(
            self.browser,
            course_id=course_id,
            chapter=chapter_id,
            subsection=subsection_id,
            position=1
        ).visit()
        self.assertIn('problem 1 dummy body', problem1_page.get_selected_tab_content())

        html1_page = CoursewareSequentialTabPage(
            self.browser,
            course_id=course_id,
            chapter=chapter_id,
            subsection=subsection_id,
            position=2
        ).visit()
        self.assertIn('html 1 dummy body', html1_page.get_selected_tab_content())

        problem2_page = CoursewareSequentialTabPage(
            self.browser,
            course_id=course_id,
            chapter=chapter_id,
            subsection=subsection_id,
            position=3
        ).visit()
        self.assertIn('problem 2 dummy body', problem2_page.get_selected_tab_content())

        html2_page = CoursewareSequentialTabPage(
            self.browser,
            course_id=course_id,
            chapter=chapter_id,
            subsection=subsection_id,
            position=4
        ).visit()
        self.assertIn('html 2 dummy body', html2_page.get_selected_tab_content())

    @attr('a11y')
    def test_courseware_a11y(self):
        """
        Run accessibility audit for the problem type.
        """
        self.course_nav.go_to_section('Test Section 1', 'Test Subsection 1,1')
        # Set the scope to the sequence navigation
        self.courseware_page.a11y_audit.config.set_scope(
            include=['div.sequence-nav'])
        self.courseware_page.a11y_audit.check_for_accessibility_errors()