class CoursewareSearchTest(UniqueCourseTest):
    """
    Test courseware search.
    """
    USERNAME = '******'
    EMAIL = '*****@*****.**'

    STAFF_USERNAME = "******"
    STAFF_EMAIL = "*****@*****.**"

    HTML_CONTENT = """
            Someday I'll wish upon a star
            And wake up where the clouds are far
            Behind me.
            Where troubles melt like lemon drops
            Away above the chimney tops
            That's where you'll find me.
        """
    SEARCH_STRING = "chimney"
    EDITED_CHAPTER_NAME = "Section 2 - edited"
    EDITED_SEARCH_STRING = "edited"

    TEST_INDEX_FILENAME = "test_root/index_file.dat"
    shard = 5

    def setUp(self):
        """
        Create search page and course content to search
        """
        # create test file in which index for this test will live
        with open(self.TEST_INDEX_FILENAME, "w+") as index_file:
            json.dump({}, index_file)
        self.addCleanup(remove_file, self.TEST_INDEX_FILENAME)

        super(CoursewareSearchTest, self).setUp()

        self.course_home_page = CourseHomePage(self.browser, self.course_id)

        self.studio_course_outline = StudioCourseOutlinePage(
            self.browser, self.course_info['org'], self.course_info['number'],
            self.course_info['run'])

        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', 'Section 1').add_children(
                XBlockFixtureDesc('sequential', 'Subsection 1'))).add_children(
                    XBlockFixtureDesc('chapter', 'Section 2').add_children(
                        XBlockFixtureDesc('sequential',
                                          'Subsection 2'))).install()

    def _auto_auth(self, username, email, staff):
        """
        Logout and login with given credentials.
        """
        LogoutPage(self.browser).visit()
        AutoAuthPage(self.browser,
                     username=username,
                     email=email,
                     course_id=self.course_id,
                     staff=staff).visit()

    def _studio_publish_content(self, section_index):
        """
        Publish content on studio course page under specified section
        """
        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        self.studio_course_outline.visit()
        subsection = self.studio_course_outline.section_at(
            section_index).subsection_at(0)
        subsection.expand_subsection()
        unit = subsection.unit_at(0)
        unit.publish()

    def _studio_edit_chapter_name(self, section_index):
        """
        Edit chapter name on studio course page under specified section
        """
        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        self.studio_course_outline.visit()
        section = self.studio_course_outline.section_at(section_index)
        section.change_name(self.EDITED_CHAPTER_NAME)

    def _studio_add_content(self, section_index):
        """
        Add content on studio course page under specified section
        """

        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        # create a unit in course outline
        self.studio_course_outline.visit()
        subsection = self.studio_course_outline.section_at(
            section_index).subsection_at(0)
        subsection.expand_subsection()
        subsection.add_unit()

        # got to unit and create an HTML component and save (not publish)
        unit_page = ContainerPage(self.browser, None)
        unit_page.wait_for_page()
        add_html_component(unit_page, 0)
        unit_page.wait_for_element_presence('.edit-button',
                                            'Edit button is visible')
        click_css(unit_page, '.edit-button', 0, require_notification=False)
        unit_page.wait_for_element_visibility('.modal-editor',
                                              'Modal editor is visible')
        type_in_codemirror(unit_page, 0, self.HTML_CONTENT)
        click_css(unit_page, '.action-save', 0)

    def _studio_reindex(self):
        """
        Reindex course content on studio course page
        """

        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        self.studio_course_outline.visit()
        self.studio_course_outline.start_reindex()
        self.studio_course_outline.wait_for_ajax()

    def _search_for_content(self, search_term):
        """
        Login and search for specific content

        Arguments:
            search_term - term to be searched for

        Returns:
            (bool) True if search term is found in resulting content; False if not found
        """
        self._auto_auth(self.USERNAME, self.EMAIL, False)
        self.course_home_page.visit()
        course_search_results_page = self.course_home_page.search_for_term(
            search_term)
        if len(course_search_results_page.search_results.html) > 0:
            search_string = course_search_results_page.search_results.html[0]
        else:
            search_string = ""
        return search_term in search_string

    # TODO: TNL-6546: Remove usages of sidebar search
    def _search_for_content_in_sidebar(self,
                                       search_term,
                                       perform_auto_auth=True):
        """
        Login and search for specific content in the legacy sidebar search
        Arguments:
            search_term - term to be searched for
            perform_auto_auth - if False, skip auto_auth call.
        Returns:
            (bool) True if search term is found in resulting content; False if not found
        """
        if perform_auto_auth:
            self._auto_auth(self.USERNAME, self.EMAIL, False)
        self.courseware_search_page = CoursewareSearchPage(
            self.browser, self.course_id)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term(search_term)
        return search_term in self.courseware_search_page.search_results.html[
            0]

    def test_search(self):
        """
        Make sure that you can search for something.
        """

        # Create content in studio without publishing.
        self._studio_add_content(0)

        # Do a search, there should be no results shown.
        self.assertFalse(self._search_for_content(self.SEARCH_STRING))

        # Do a search in the legacy sidebar, there should be no results shown.
        self.assertFalse(
            self._search_for_content_in_sidebar(self.SEARCH_STRING, False))

        # Publish in studio to trigger indexing.
        self._studio_publish_content(0)

        # Do the search again, this time we expect results.
        self.assertTrue(self._search_for_content(self.SEARCH_STRING))

        # Do the search again in the legacy sidebar, this time we expect results.
        self.assertTrue(
            self._search_for_content_in_sidebar(self.SEARCH_STRING, False))
class CoursewareSearchTest(UniqueCourseTest):
    """
    Test courseware search.
    """
    USERNAME = '******'
    EMAIL = '*****@*****.**'

    STAFF_USERNAME = "******"
    STAFF_EMAIL = "*****@*****.**"

    HTML_CONTENT = """
            Someday I'll wish upon a star
            And wake up where the clouds are far
            Behind me.
            Where troubles melt like lemon drops
            Away above the chimney tops
            That's where you'll find me.
        """
    SEARCH_STRING = "chimney"
    EDITED_CHAPTER_NAME = "Section 2 - edited"
    EDITED_SEARCH_STRING = "edited"

    TEST_INDEX_FILENAME = "test_root/index_file.dat"
    shard = 5

    def setUp(self):
        """
        Create search page and course content to search
        """
        # create test file in which index for this test will live
        with open(self.TEST_INDEX_FILENAME, "w+") as index_file:
            json.dump({}, index_file)
        self.addCleanup(remove_file, self.TEST_INDEX_FILENAME)

        super(CoursewareSearchTest, self).setUp()

        self.course_home_page = CourseHomePage(self.browser, self.course_id)

        self.studio_course_outline = StudioCourseOutlinePage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )

        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', 'Section 1').add_children(
                XBlockFixtureDesc('sequential', 'Subsection 1')
            )
        ).add_children(
            XBlockFixtureDesc('chapter', 'Section 2').add_children(
                XBlockFixtureDesc('sequential', 'Subsection 2')
            )
        ).install()

    def _auto_auth(self, username, email, staff):
        """
        Logout and login with given credentials.
        """
        LogoutPage(self.browser).visit()
        AutoAuthPage(self.browser, username=username, email=email,
                     course_id=self.course_id, staff=staff).visit()

    def _studio_publish_content(self, section_index):
        """
        Publish content on studio course page under specified section
        """
        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        self.studio_course_outline.visit()
        subsection = self.studio_course_outline.section_at(section_index).subsection_at(0)
        subsection.expand_subsection()
        unit = subsection.unit_at(0)
        unit.publish()

    def _studio_edit_chapter_name(self, section_index):
        """
        Edit chapter name on studio course page under specified section
        """
        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        self.studio_course_outline.visit()
        section = self.studio_course_outline.section_at(section_index)
        section.change_name(self.EDITED_CHAPTER_NAME)

    def _studio_add_content(self, section_index):
        """
        Add content on studio course page under specified section
        """

        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        # create a unit in course outline
        self.studio_course_outline.visit()
        subsection = self.studio_course_outline.section_at(section_index).subsection_at(0)
        subsection.expand_subsection()
        subsection.add_unit()

        # got to unit and create an HTML component and save (not publish)
        unit_page = ContainerPage(self.browser, None)
        unit_page.wait_for_page()
        add_html_component(unit_page, 0)
        unit_page.wait_for_element_presence('.edit-button', 'Edit button is visible')
        click_css(unit_page, '.edit-button', 0, require_notification=False)
        unit_page.wait_for_element_visibility('.modal-editor', 'Modal editor is visible')
        type_in_codemirror(unit_page, 0, self.HTML_CONTENT)
        click_css(unit_page, '.action-save', 0)

    def _studio_reindex(self):
        """
        Reindex course content on studio course page
        """

        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        self.studio_course_outline.visit()
        self.studio_course_outline.start_reindex()
        self.studio_course_outline.wait_for_ajax()

    def _search_for_content(self, search_term):
        """
        Login and search for specific content

        Arguments:
            search_term - term to be searched for

        Returns:
            (bool) True if search term is found in resulting content; False if not found
        """
        self._auto_auth(self.USERNAME, self.EMAIL, False)
        self.course_home_page.visit()
        course_search_results_page = self.course_home_page.search_for_term(search_term)
        if len(course_search_results_page.search_results.html) > 0:
            search_string = course_search_results_page.search_results.html[0]
        else:
            search_string = ""
        return search_term in search_string

    # TODO: TNL-6546: Remove usages of sidebar search
    def _search_for_content_in_sidebar(self, search_term, perform_auto_auth=True):
        """
        Login and search for specific content in the legacy sidebar search
        Arguments:
            search_term - term to be searched for
            perform_auto_auth - if False, skip auto_auth call.
        Returns:
            (bool) True if search term is found in resulting content; False if not found
        """
        if perform_auto_auth:
            self._auto_auth(self.USERNAME, self.EMAIL, False)
        self.courseware_search_page = CoursewareSearchPage(self.browser, self.course_id)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term(search_term)
        return search_term in self.courseware_search_page.search_results.html[0]

    def test_search(self):
        """
        Make sure that you can search for something.
        """

        # Create content in studio without publishing.
        self._studio_add_content(0)

        # Do a search, there should be no results shown.
        self.assertFalse(self._search_for_content(self.SEARCH_STRING))

        # Do a search in the legacy sidebar, there should be no results shown.
        self.assertFalse(self._search_for_content_in_sidebar(self.SEARCH_STRING, False))

        # Publish in studio to trigger indexing.
        self._studio_publish_content(0)

        # Do the search again, this time we expect results.
        self.assertTrue(self._search_for_content(self.SEARCH_STRING))

        # Do the search again in the legacy sidebar, this time we expect results.
        self.assertTrue(self._search_for_content_in_sidebar(self.SEARCH_STRING, False))
class SplitTestCoursewareSearchTest(ContainerBase):
    """
    Test courseware search on Split Test Module.
    """
    USERNAME = '******'
    EMAIL = '*****@*****.**'

    TEST_INDEX_FILENAME = "test_root/index_file.dat"

    def setUp(self, is_staff=True):
        """
        Create search page and course content to search
        """
        # create test file in which index for this test will live
        with open(self.TEST_INDEX_FILENAME, "w+") as index_file:
            json.dump({}, index_file)
        self.addCleanup(remove_file, self.TEST_INDEX_FILENAME)

        super(SplitTestCoursewareSearchTest, self).setUp(is_staff=is_staff)
        self.staff_user = self.user

        self.courseware_search_page = CoursewareSearchPage(
            self.browser, self.course_id)
        self.course_navigation_page = CourseNavPage(self.browser)
        self.course_outline = CourseOutlinePage(self.browser,
                                                self.course_info['org'],
                                                self.course_info['number'],
                                                self.course_info['run'])

        self._create_group_configuration()
        self._studio_reindex()

    def _auto_auth(self, username, email, staff):
        """
        Logout and login with given credentials.
        """
        LogoutPage(self.browser).visit()
        StudioAutoAuthPage(self.browser,
                           username=username,
                           email=email,
                           course_id=self.course_id,
                           staff=staff).visit()

    def _studio_reindex(self):
        """
        Reindex course content on studio course page
        """
        self._auto_auth(self.staff_user["username"], self.staff_user["email"],
                        True)
        self.course_outline.visit()
        self.course_outline.start_reindex()
        self.course_outline.wait_for_ajax()

    def _create_group_configuration(self):
        """
        Create a group configuration for course
        """
        # pylint: disable=protected-access
        self.course_fixture._update_xblock(
            self.course_fixture._course_location, {
                "metadata": {
                    u"user_partitions": [
                        create_user_partition_json(
                            0, "Configuration A/B", "Content Group Partition.",
                            [Group("0", "Group A"),
                             Group("1", "Group B")])
                    ]
                }
            })

    def populate_course_fixture(self, course_fixture):
        """
        Populate the children of the test course fixture.
        """
        course_fixture.add_advanced_settings({
            u"advanced_modules": {
                "value": ["split_test"]
            },
        })

        course_fixture.add_children(
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc(
                    'sequential', 'Test Subsection').add_children(
                        XBlockFixtureDesc(
                            'vertical', 'Test Unit').add_children(
                                XBlockFixtureDesc(
                                    'html',
                                    'VISIBLE TO A',
                                    data='<html>VISIBLE TO A</html>',
                                    metadata={"group_access": {
                                        0: [0]
                                    }}),
                                XBlockFixtureDesc(
                                    'html',
                                    'VISIBLE TO B',
                                    data='<html>VISIBLE TO B</html>',
                                    metadata={"group_access": {
                                        0: [1]
                                    }})))))

    def test_page_existence(self):
        """
        Make sure that the page is accessible.
        """
        self._auto_auth(self.USERNAME, self.EMAIL, False)
        self.courseware_search_page.visit()

    def test_search_for_experiment_content_user_assigned_to_one_group(self):
        """
        Test user can search for experiment content restricted to his group
        when assigned to just one experiment group
        """
        self._auto_auth(self.USERNAME, self.EMAIL, False)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term("VISIBLE TO")
        assert "1 result" in self.courseware_search_page.search_results.html[0]
class CoursewareSearchCohortTest(ContainerBase):
    """
    Test courseware search.
    """

    TEST_INDEX_FILENAME = "test_root/index_file.dat"

    def setUp(self, is_staff=True):
        """
        Create search page and course content to search
        """
        # create test file in which index for this test will live
        with open(self.TEST_INDEX_FILENAME, "w+") as index_file:
            json.dump({}, index_file)
        self.addCleanup(remove_file, self.TEST_INDEX_FILENAME)

        super(CoursewareSearchCohortTest, self).setUp(is_staff=is_staff)
        self.staff_user = self.user

        self.studio_course_outline = StudioCourseOutlinePage(
            self.browser, self.course_info['org'], self.course_info['number'],
            self.course_info['run'])

        self.content_group_a = "Content Group A"
        self.content_group_b = "Content Group B"

        # Create a student who will be in "Cohort A"
        self.cohort_a_student_username = "******" + str(
            uuid.uuid4().hex)[:12]
        self.cohort_a_student_email = self.cohort_a_student_username + "@example.com"
        StudioAutoAuthPage(self.browser,
                           username=self.cohort_a_student_username,
                           email=self.cohort_a_student_email,
                           no_login=True).visit()

        # Create a student who will be in "Cohort B"
        self.cohort_b_student_username = "******" + str(
            uuid.uuid4().hex)[:12]
        self.cohort_b_student_email = self.cohort_b_student_username + "@example.com"
        StudioAutoAuthPage(self.browser,
                           username=self.cohort_b_student_username,
                           email=self.cohort_b_student_email,
                           no_login=True).visit()

        # Create a student who will end up in the default cohort group
        self.cohort_default_student_username = "******"
        self.cohort_default_student_email = "*****@*****.**"
        StudioAutoAuthPage(self.browser,
                           username=self.cohort_default_student_username,
                           email=self.cohort_default_student_email,
                           no_login=True).visit()

        self.courseware_search_page = CoursewareSearchPage(
            self.browser, self.course_id)

        # Enable Cohorting and assign cohorts and content groups
        self._auto_auth(self.staff_user["username"], self.staff_user["email"],
                        True)
        self.enable_cohorting(self.course_fixture)
        self.create_content_groups()
        self.link_html_to_content_groups_and_publish()
        self.create_cohorts_and_assign_students()

        self._studio_reindex()

    def _auto_auth(self, username, email, staff):
        """
        Logout and login with given credentials.
        """
        LogoutPage(self.browser).visit()
        StudioAutoAuthPage(self.browser,
                           username=username,
                           email=email,
                           course_id=self.course_id,
                           staff=staff).visit()

    def _studio_reindex(self):
        """
        Reindex course content on studio course page
        """
        self._auto_auth(self.staff_user["username"], self.staff_user["email"],
                        True)
        self.studio_course_outline.visit()
        self.studio_course_outline.start_reindex()
        self.studio_course_outline.wait_for_ajax()

    def _goto_staff_page(self):
        """
        Open staff page with assertion
        """
        self.courseware_search_page.visit()
        staff_page = StaffPage(self.browser, self.course_id)
        self.assertEqual(staff_page.staff_view_mode, 'Staff')
        return staff_page

    def populate_course_fixture(self, course_fixture):
        """
        Populate the children of the test course fixture.
        """
        self.group_a_html = 'GROUPACONTENT'
        self.group_b_html = 'GROUPBCONTENT'
        self.group_a_and_b_html = 'GROUPAANDBCONTENT'
        self.visible_to_all_html = 'VISIBLETOALLCONTENT'

        course_fixture.add_children(
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection').
                add_children(
                    XBlockFixtureDesc('vertical', 'Test Unit').add_children(
                        XBlockFixtureDesc('html',
                                          self.group_a_html,
                                          data='<html>GROUPACONTENT</html>'),
                        XBlockFixtureDesc('html',
                                          self.group_b_html,
                                          data='<html>GROUPBCONTENT</html>'),
                        XBlockFixtureDesc(
                            'html',
                            self.group_a_and_b_html,
                            data='<html>GROUPAANDBCONTENT</html>'),
                        XBlockFixtureDesc(
                            'html',
                            self.visible_to_all_html,
                            data='<html>VISIBLETOALLCONTENT</html>')))))

    def enable_cohorting(self, course_fixture):
        """
        Enables cohorting for the current course.
        """
        url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + '/cohorts/settings'  # pylint: disable=protected-access
        data = json.dumps({'is_cohorted': True})
        response = course_fixture.session.patch(url,
                                                data=data,
                                                headers=course_fixture.headers)
        self.assertTrue(response.ok, "Failed to enable cohorts")

    def create_content_groups(self):
        """
        Creates two content groups in Studio Group Configurations Settings.
        """
        group_configurations_page = GroupConfigurationsPage(
            self.browser, self.course_info['org'], self.course_info['number'],
            self.course_info['run'])
        group_configurations_page.visit()

        group_configurations_page.create_first_content_group()
        config = group_configurations_page.content_groups[0]
        config.name = self.content_group_a
        config.save()

        group_configurations_page.add_content_group()
        config = group_configurations_page.content_groups[1]
        config.name = self.content_group_b
        config.save()

    def link_html_to_content_groups_and_publish(self):
        """
        Updates 3 of the 4 existing html to limit their visibility by content group.
        Publishes the modified units.
        """
        container_page = self.go_to_unit_page()

        def set_visibility(html_block_index,
                           content_group,
                           second_content_group=None):
            """
            Set visibility on html blocks to specified groups.
            """
            html_block = container_page.xblocks[html_block_index]
            html_block.edit_visibility()
            if second_content_group:
                ComponentVisibilityEditorView(
                    self.browser,
                    html_block.locator).select_option(second_content_group,
                                                      save=False)
            ComponentVisibilityEditorView(
                self.browser, html_block.locator).select_option(content_group)

        set_visibility(1, self.content_group_a)
        set_visibility(2, self.content_group_b)
        set_visibility(3, self.content_group_a, self.content_group_b)
        set_visibility(4,
                       'All Students and Staff')  # Does not work without this

        container_page.publish_action.click()

    def create_cohorts_and_assign_students(self):
        """
        Adds 2 manual cohorts, linked to content groups, to the course.
        Each cohort is assigned one student.
        """
        instructor_dashboard_page = InstructorDashboardPage(
            self.browser, self.course_id)
        instructor_dashboard_page.visit()
        cohort_management_page = instructor_dashboard_page.select_cohort_management(
        )

        def add_cohort_with_student(cohort_name, content_group, student):
            """
            Create cohort and assign student to it.
            """
            cohort_management_page.add_cohort(cohort_name,
                                              content_group=content_group)
            cohort_management_page.add_students_to_selected_cohort([student])

        add_cohort_with_student("Cohort A", self.content_group_a,
                                self.cohort_a_student_username)
        add_cohort_with_student("Cohort B", self.content_group_b,
                                self.cohort_b_student_username)
        cohort_management_page.wait_for_ajax()

    def test_page_existence(self):
        """
        Make sure that the page is accessible.
        """
        self._auto_auth(self.cohort_default_student_username,
                        self.cohort_default_student_email, False)
        self.courseware_search_page.visit()

    def test_cohorted_search_user_a_a_content(self):
        """
        Test user can search content restricted to his cohort.
        """
        self._auto_auth(self.cohort_a_student_username,
                        self.cohort_a_student_email, False)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term(self.group_a_html)
        assert self.group_a_html in self.courseware_search_page.search_results.html[
            0]

    def test_cohorted_search_user_b_a_content(self):
        """
        Test user can not search content restricted to his cohort.
        """
        self._auto_auth(self.cohort_b_student_username,
                        self.cohort_b_student_email, False)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term(self.group_a_html)
        assert self.group_a_html not in self.courseware_search_page.search_results.html[
            0]

    def test_cohorted_search_user_default_ab_content(self):
        """
        Test user not enrolled in any cohorts can't see any of restricted content.
        """
        self._auto_auth(self.cohort_default_student_username,
                        self.cohort_default_student_email, False)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term(self.group_a_and_b_html)
        assert self.group_a_and_b_html not in self.courseware_search_page.search_results.html[
            0]

    def test_cohorted_search_user_default_all_content(self):
        """
        Test user can search public content if cohorts used on course.
        """
        self._auto_auth(self.cohort_default_student_username,
                        self.cohort_default_student_email, False)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term(self.visible_to_all_html)
        assert self.visible_to_all_html in self.courseware_search_page.search_results.html[
            0]

    def test_cohorted_search_user_staff_all_content(self):
        """
        Test staff user can search all public content if cohorts used on course.
        """
        self._auto_auth(self.staff_user["username"], self.staff_user["email"],
                        False)
        self._goto_staff_page().set_staff_view_mode('Staff')
        self.courseware_search_page.search_for_term(self.visible_to_all_html)
        assert self.visible_to_all_html in self.courseware_search_page.search_results.html[
            0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_and_b_html)
        assert self.group_a_and_b_html in self.courseware_search_page.search_results.html[
            0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_html)
        assert self.group_a_html in self.courseware_search_page.search_results.html[
            0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_b_html)
        assert self.group_b_html in self.courseware_search_page.search_results.html[
            0]

    def test_cohorted_search_user_staff_masquerade_student_content(self):
        """
        Test staff user can search just student public content if selected from preview menu.
        """
        self._auto_auth(self.staff_user["username"], self.staff_user["email"],
                        False)
        self._goto_staff_page().set_staff_view_mode('Student')
        self.courseware_search_page.search_for_term(self.visible_to_all_html)
        assert self.visible_to_all_html in self.courseware_search_page.search_results.html[
            0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_and_b_html)
        assert self.group_a_and_b_html not in self.courseware_search_page.search_results.html[
            0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_html)
        assert self.group_a_html not in self.courseware_search_page.search_results.html[
            0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_b_html)
        assert self.group_b_html not in self.courseware_search_page.search_results.html[
            0]

    def test_cohorted_search_user_staff_masquerade_cohort_content(self):
        """
        Test staff user can search cohort and public content if selected from preview menu.
        """
        self._auto_auth(self.staff_user["username"], self.staff_user["email"],
                        False)
        self._goto_staff_page().set_staff_view_mode('Student in ' +
                                                    self.content_group_a)
        self.courseware_search_page.search_for_term(self.visible_to_all_html)
        assert self.visible_to_all_html in self.courseware_search_page.search_results.html[
            0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_and_b_html)
        assert self.group_a_and_b_html in self.courseware_search_page.search_results.html[
            0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_html)
        assert self.group_a_html in self.courseware_search_page.search_results.html[
            0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_b_html)
        assert self.group_b_html not in self.courseware_search_page.search_results.html[
            0]
class CoursewareSearchCohortTest(ContainerBase):
    """
    Test courseware search.
    """

    TEST_INDEX_FILENAME = "test_root/index_file.dat"

    def setUp(self, is_staff=True):
        """
        Create search page and course content to search
        """
        # create test file in which index for this test will live
        with open(self.TEST_INDEX_FILENAME, "w+") as index_file:
            json.dump({}, index_file)
        self.addCleanup(remove_file, self.TEST_INDEX_FILENAME)

        super(CoursewareSearchCohortTest, self).setUp(is_staff=is_staff)
        self.staff_user = self.user

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

        self.content_group_a = "Content Group A"
        self.content_group_b = "Content Group B"

        # Create a student who will be in "Cohort A"
        self.cohort_a_student_username = "******" + str(uuid.uuid4().hex)[:12]
        self.cohort_a_student_email = self.cohort_a_student_username + "@example.com"
        StudioAutoAuthPage(
            self.browser, username=self.cohort_a_student_username, email=self.cohort_a_student_email, no_login=True
        ).visit()

        # Create a student who will be in "Cohort B"
        self.cohort_b_student_username = "******" + str(uuid.uuid4().hex)[:12]
        self.cohort_b_student_email = self.cohort_b_student_username + "@example.com"
        StudioAutoAuthPage(
            self.browser, username=self.cohort_b_student_username, email=self.cohort_b_student_email, no_login=True
        ).visit()

        # Create a student who will end up in the default cohort group
        self.cohort_default_student_username = "******"
        self.cohort_default_student_email = "*****@*****.**"
        StudioAutoAuthPage(
            self.browser, username=self.cohort_default_student_username,
            email=self.cohort_default_student_email, no_login=True
        ).visit()

        self.courseware_search_page = CoursewareSearchPage(self.browser, self.course_id)

        # Enable Cohorting and assign cohorts and content groups
        self._auto_auth(self.staff_user["username"], self.staff_user["email"], True)
        self.enable_cohorting(self.course_fixture)
        self.create_content_groups()
        self.link_html_to_content_groups_and_publish()
        self.create_cohorts_and_assign_students()

        self._studio_reindex()

    def _auto_auth(self, username, email, staff):
        """
        Logout and login with given credentials.
        """
        LogoutPage(self.browser).visit()
        StudioAutoAuthPage(self.browser, username=username, email=email,
                           course_id=self.course_id, staff=staff).visit()

    def _studio_reindex(self):
        """
        Reindex course content on studio course page
        """
        self._auto_auth(self.staff_user["username"], self.staff_user["email"], True)
        self.course_outline.visit()
        self.course_outline.start_reindex()
        self.course_outline.wait_for_ajax()

    def _goto_staff_page(self):
        """
        Open staff page with assertion
        """
        self.courseware_search_page.visit()
        staff_page = StaffPage(self.browser, self.course_id)
        self.assertEqual(staff_page.staff_view_mode, 'Staff')
        return staff_page

    def populate_course_fixture(self, course_fixture):
        """
        Populate the children of the test course fixture.
        """
        self.group_a_html = 'GROUPACONTENT'
        self.group_b_html = 'GROUPBCONTENT'
        self.group_a_and_b_html = 'GROUPAANDBCONTENT'
        self.visible_to_all_html = 'VISIBLETOALLCONTENT'

        course_fixture.add_children(
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
                    XBlockFixtureDesc('vertical', 'Test Unit').add_children(
                        XBlockFixtureDesc('html', self.group_a_html, data='<html>GROUPACONTENT</html>'),
                        XBlockFixtureDesc('html', self.group_b_html, data='<html>GROUPBCONTENT</html>'),
                        XBlockFixtureDesc('html', self.group_a_and_b_html, data='<html>GROUPAANDBCONTENT</html>'),
                        XBlockFixtureDesc('html', self.visible_to_all_html, data='<html>VISIBLETOALLCONTENT</html>')
                    )
                )
            )
        )

    def enable_cohorting(self, course_fixture):
        """
        Enables cohorting for the current course.
        """
        url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + '/cohorts/settings'  # pylint: disable=protected-access
        data = json.dumps({'is_cohorted': True})
        response = course_fixture.session.patch(url, data=data, headers=course_fixture.headers)
        self.assertTrue(response.ok, "Failed to enable cohorts")

    def create_content_groups(self):
        """
        Creates two content groups in Studio Group Configurations Settings.
        """
        group_configurations_page = GroupConfigurationsPage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )
        group_configurations_page.visit()

        group_configurations_page.create_first_content_group()
        config = group_configurations_page.content_groups[0]
        config.name = self.content_group_a
        config.save()

        group_configurations_page.add_content_group()
        config = group_configurations_page.content_groups[1]
        config.name = self.content_group_b
        config.save()

    def link_html_to_content_groups_and_publish(self):
        """
        Updates 3 of the 4 existing html to limit their visibility by content group.
        Publishes the modified units.
        """
        container_page = self.go_to_unit_page()

        def set_visibility(html_block_index, content_group, second_content_group=None):
            """
            Set visibility on html blocks to specified groups.
            """
            html_block = container_page.xblocks[html_block_index]
            html_block.edit_visibility()
            if second_content_group:
                ComponentVisibilityEditorView(self.browser, html_block.locator).select_option(
                    second_content_group, save=False
                )
            ComponentVisibilityEditorView(self.browser, html_block.locator).select_option(content_group)

        set_visibility(1, self.content_group_a)
        set_visibility(2, self.content_group_b)
        set_visibility(3, self.content_group_a, self.content_group_b)
        set_visibility(4, 'All Students and Staff')  # Does not work without this

        container_page.publish_action.click()

    def create_cohorts_and_assign_students(self):
        """
        Adds 2 manual cohorts, linked to content groups, to the course.
        Each cohort is assigned one student.
        """
        instructor_dashboard_page = InstructorDashboardPage(self.browser, self.course_id)
        instructor_dashboard_page.visit()
        cohort_management_page = instructor_dashboard_page.select_cohort_management()

        def add_cohort_with_student(cohort_name, content_group, student):
            """
            Create cohort and assign student to it.
            """
            cohort_management_page.add_cohort(cohort_name, content_group=content_group)
            cohort_management_page.add_students_to_selected_cohort([student])
        add_cohort_with_student("Cohort A", self.content_group_a, self.cohort_a_student_username)
        add_cohort_with_student("Cohort B", self.content_group_b, self.cohort_b_student_username)
        cohort_management_page.wait_for_ajax()

    def test_page_existence(self):
        """
        Make sure that the page is accessible.
        """
        self._auto_auth(self.cohort_default_student_username, self.cohort_default_student_email, False)
        self.courseware_search_page.visit()

    def test_cohorted_search_user_a_a_content(self):
        """
        Test user can search content restricted to his cohort.
        """
        self._auto_auth(self.cohort_a_student_username, self.cohort_a_student_email, False)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term(self.group_a_html)
        assert self.group_a_html in self.courseware_search_page.search_results.html[0]

    def test_cohorted_search_user_b_a_content(self):
        """
        Test user can not search content restricted to his cohort.
        """
        self._auto_auth(self.cohort_b_student_username, self.cohort_b_student_email, False)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term(self.group_a_html)
        assert self.group_a_html not in self.courseware_search_page.search_results.html[0]

    def test_cohorted_search_user_default_ab_content(self):
        """
        Test user not enrolled in any cohorts can't see any of restricted content.
        """
        self._auto_auth(self.cohort_default_student_username, self.cohort_default_student_email, False)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term(self.group_a_and_b_html)
        assert self.group_a_and_b_html not in self.courseware_search_page.search_results.html[0]

    def test_cohorted_search_user_default_all_content(self):
        """
        Test user can search public content if cohorts used on course.
        """
        self._auto_auth(self.cohort_default_student_username, self.cohort_default_student_email, False)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term(self.visible_to_all_html)
        assert self.visible_to_all_html in self.courseware_search_page.search_results.html[0]

    def test_cohorted_search_user_staff_all_content(self):
        """
        Test staff user can search all public content if cohorts used on course.
        """
        self._auto_auth(self.staff_user["username"], self.staff_user["email"], False)
        self._goto_staff_page().set_staff_view_mode('Staff')
        self.courseware_search_page.search_for_term(self.visible_to_all_html)
        assert self.visible_to_all_html in self.courseware_search_page.search_results.html[0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_and_b_html)
        assert self.group_a_and_b_html in self.courseware_search_page.search_results.html[0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_html)
        assert self.group_a_html in self.courseware_search_page.search_results.html[0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_b_html)
        assert self.group_b_html in self.courseware_search_page.search_results.html[0]

    def test_cohorted_search_user_staff_masquerade_student_content(self):
        """
        Test staff user can search just student public content if selected from preview menu.
        """
        self._auto_auth(self.staff_user["username"], self.staff_user["email"], False)
        self._goto_staff_page().set_staff_view_mode('Student')
        self.courseware_search_page.search_for_term(self.visible_to_all_html)
        assert self.visible_to_all_html in self.courseware_search_page.search_results.html[0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_and_b_html)
        assert self.group_a_and_b_html not in self.courseware_search_page.search_results.html[0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_html)
        assert self.group_a_html not in self.courseware_search_page.search_results.html[0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_b_html)
        assert self.group_b_html not in self.courseware_search_page.search_results.html[0]

    def test_cohorted_search_user_staff_masquerade_cohort_content(self):
        """
        Test staff user can search cohort and public content if selected from preview menu.
        """
        self._auto_auth(self.staff_user["username"], self.staff_user["email"], False)
        self._goto_staff_page().set_staff_view_mode('Student in ' + self.content_group_a)
        self.courseware_search_page.search_for_term(self.visible_to_all_html)
        assert self.visible_to_all_html in self.courseware_search_page.search_results.html[0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_and_b_html)
        assert self.group_a_and_b_html in self.courseware_search_page.search_results.html[0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_a_html)
        assert self.group_a_html in self.courseware_search_page.search_results.html[0]
        self.courseware_search_page.clear_search()
        self.courseware_search_page.search_for_term(self.group_b_html)
        assert self.group_b_html not in self.courseware_search_page.search_results.html[0]
class CoursewareSearchTest(UniqueCourseTest):
    """
    Test courseware search.
    """

    USERNAME = "******"
    EMAIL = "*****@*****.**"

    STAFF_USERNAME = "******"
    STAFF_EMAIL = "*****@*****.**"

    HTML_CONTENT = """
            Someday I'll wish upon a star
            And wake up where the clouds are far
            Behind me.
            Where troubles melt like lemon drops
            Away above the chimney tops
            That's where you'll find me.
        """
    SEARCH_STRING = "chimney"
    EDITED_CHAPTER_NAME = "Section 2 - edited"
    EDITED_SEARCH_STRING = "edited"

    TEST_INDEX_FILENAME = "test_root/index_file.dat"

    def setUp(self):
        """
        Create search page and course content to search
        """
        # create test file in which index for this test will live
        with open(self.TEST_INDEX_FILENAME, "w+") as index_file:
            json.dump({}, index_file)
        self.addCleanup(remove_file, self.TEST_INDEX_FILENAME)

        super(CoursewareSearchTest, self).setUp()
        self.courseware_search_page = CoursewareSearchPage(self.browser, self.course_id)

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

        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", "Section 1").add_children(XBlockFixtureDesc("sequential", "Subsection 1"))
        ).add_children(
            XBlockFixtureDesc("chapter", "Section 2").add_children(XBlockFixtureDesc("sequential", "Subsection 2"))
        ).install()

    def _auto_auth(self, username, email, staff):
        """
        Logout and login with given credentials.
        """
        LogoutPage(self.browser).visit()
        AutoAuthPage(self.browser, username=username, email=email, course_id=self.course_id, staff=staff).visit()

    def _studio_publish_content(self, section_index):
        """
        Publish content on studio course page under specified section
        """
        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        self.course_outline.visit()
        subsection = self.course_outline.section_at(section_index).subsection_at(0)
        subsection.expand_subsection()
        unit = subsection.unit_at(0)
        unit.publish()

    def _studio_edit_chapter_name(self, section_index):
        """
        Edit chapter name on studio course page under specified section
        """
        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        self.course_outline.visit()
        section = self.course_outline.section_at(section_index)
        section.change_name(self.EDITED_CHAPTER_NAME)

    def _studio_add_content(self, section_index):
        """
        Add content on studio course page under specified section
        """

        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        # create a unit in course outline
        self.course_outline.visit()
        subsection = self.course_outline.section_at(section_index).subsection_at(0)
        subsection.expand_subsection()
        subsection.add_unit()

        # got to unit and create an HTML component and save (not publish)
        unit_page = ContainerPage(self.browser, None)
        unit_page.wait_for_page()
        add_html_component(unit_page, 0)
        unit_page.wait_for_element_presence(".edit-button", "Edit button is visible")
        click_css(unit_page, ".edit-button", 0, require_notification=False)
        unit_page.wait_for_element_visibility(".modal-editor", "Modal editor is visible")
        type_in_codemirror(unit_page, 0, self.HTML_CONTENT)
        click_css(unit_page, ".action-save", 0)

    def _studio_reindex(self):
        """
        Reindex course content on studio course page
        """

        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        self.course_outline.visit()
        self.course_outline.start_reindex()
        self.course_outline.wait_for_ajax()

    def _search_for_content(self, search_term):
        """
        Login and search for specific content

        Arguments:
            search_term - term to be searched for

        Returns:
            (bool) True if search term is found in resulting content; False if not found
        """
        self._auto_auth(self.USERNAME, self.EMAIL, False)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term(search_term)
        return search_term in self.courseware_search_page.search_results.html[0]

    def test_page_existence(self):
        """
        Make sure that the page is accessible.
        """
        self._auto_auth(self.USERNAME, self.EMAIL, False)
        self.courseware_search_page.visit()

    def test_search(self):
        """
        Make sure that you can search for something.
        """

        # Create content in studio without publishing.
        self._studio_add_content(0)

        # Do a search, there should be no results shown.
        self.assertFalse(self._search_for_content(self.SEARCH_STRING))

        # Publish in studio to trigger indexing.
        self._studio_publish_content(0)

        # Do the search again, this time we expect results.
        self.assertTrue(self._search_for_content(self.SEARCH_STRING))

    def test_reindex(self):
        """
        Make sure new content gets reindexed on button press.
        """

        # Create content in studio without publishing.
        self._studio_add_content(1)

        # Do a search, there should be no results shown.
        self.assertFalse(self._search_for_content(self.EDITED_SEARCH_STRING))

        # Publish in studio to trigger indexing, and edit chapter name afterwards.
        self._studio_publish_content(1)

        # Do a ReIndex from studio to ensure that our stuff is updated before the next stage of the test
        self._studio_reindex()

        # Search after publish, there should still be no results shown.
        self.assertFalse(self._search_for_content(self.EDITED_SEARCH_STRING))

        self._studio_edit_chapter_name(1)

        # Do a ReIndex from studio to ensure that our stuff is updated before the next stage of the test
        self._studio_reindex()

        # Do the search again, this time we expect results.
        self.assertTrue(self._search_for_content(self.EDITED_SEARCH_STRING))
class SplitTestCoursewareSearchTest(ContainerBase):
    """
    Test courseware search on Split Test Module.
    """
    USERNAME = '******'
    EMAIL = '*****@*****.**'

    TEST_INDEX_FILENAME = "test_root/index_file.dat"

    def setUp(self, is_staff=True):
        """
        Create search page and course content to search
        """
        # create test file in which index for this test will live
        with open(self.TEST_INDEX_FILENAME, "w+") as index_file:
            json.dump({}, index_file)
        self.addCleanup(remove_file, self.TEST_INDEX_FILENAME)

        super(SplitTestCoursewareSearchTest, self).setUp(is_staff=is_staff)
        self.staff_user = self.user

        self.courseware_search_page = CoursewareSearchPage(self.browser, self.course_id)
        self.course_navigation_page = CourseNavPage(self.browser)
        self.course_outline = CourseOutlinePage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )

        self._create_group_configuration()
        self._studio_reindex()

    def _auto_auth(self, username, email, staff):
        """
        Logout and login with given credentials.
        """
        LogoutPage(self.browser).visit()
        StudioAutoAuthPage(self.browser, username=username, email=email,
                           course_id=self.course_id, staff=staff).visit()

    def _studio_reindex(self):
        """
        Reindex course content on studio course page
        """
        self._auto_auth(self.staff_user["username"], self.staff_user["email"], True)
        self.course_outline.visit()
        self.course_outline.start_reindex()
        self.course_outline.wait_for_ajax()

    def _create_group_configuration(self):
        """
        Create a group configuration for course
        """
        # pylint: disable=protected-access
        self.course_fixture._update_xblock(self.course_fixture._course_location, {
            "metadata": {
                u"user_partitions": [
                    create_user_partition_json(
                        0,
                        "Configuration A/B",
                        "Content Group Partition.",
                        [Group("0", "Group A"), Group("1", "Group B")]
                    )
                ]
            }
        })

    def populate_course_fixture(self, course_fixture):
        """
        Populate the children of the test course fixture.
        """
        course_fixture.add_advanced_settings({
            u"advanced_modules": {"value": ["split_test"]},
        })

        course_fixture.add_children(
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
                    XBlockFixtureDesc('vertical', 'Test Unit').add_children(
                        XBlockFixtureDesc(
                            'html',
                            'VISIBLE TO A',
                            data='<html>VISIBLE TO A</html>',
                            metadata={"group_access": {0: [0]}}
                        ),
                        XBlockFixtureDesc(
                            'html',
                            'VISIBLE TO B',
                            data='<html>VISIBLE TO B</html>',
                            metadata={"group_access": {0: [1]}}
                        )
                    )
                )
            )
        )

    def test_page_existence(self):
        """
        Make sure that the page is accessible.
        """
        self._auto_auth(self.USERNAME, self.EMAIL, False)
        self.courseware_search_page.visit()

    def test_search_for_experiment_content_user_assigned_to_one_group(self):
        """
        Test user can search for experiment content restricted to his group
        when assigned to just one experiment group
        """
        self._auto_auth(self.USERNAME, self.EMAIL, False)
        self.courseware_search_page.visit()
        self.courseware_search_page.search_for_term("VISIBLE TO")
        assert "1 result" in self.courseware_search_page.search_results.html[0]