Esempio n. 1
0
    def test_models_category_get_courses_snapshots(self):
        """
        Snapshot courses should be excluded from the list of courses returned.
        The new filter query we added to exclude snapshots should not create duplicates.
        Indeed, we had to add a "distinct" clause to the query so this test enforces it.
        """
        # We create a root page because it was responsible for duplicate results when the
        # distinct clause is not applied.
        # This is because of the clause "extended_object__node__parent__cms_pages__..."
        # which is there to exclude snapshots but also acts on the main course page and
        # checks its parent (so the root page) and the duplicate comes from the fact that
        # the parent has a draft and a public page... so "cms_pages" has a cardinality of 2
        root_page = create_i18n_page("my title", published=True)

        category = CategoryFactory(should_publish=True)
        course = CourseFactory(
            page_parent=root_page, fill_categories=[category], should_publish=True
        )
        CourseFactory(
            page_parent=course.extended_object,
            fill_categories=[category],
            should_publish=True,
        )

        self.assertEqual(Course.objects.count(), 4)
        self.assertEqual(category.get_courses().count(), 1)
        self.assertEqual(category.public_extension.get_courses().count(), 1)
Esempio n. 2
0
    def test_models_category_get_courses_ordering(self):
        """The related courses should be sorted by their position in the pages tree."""
        category = CategoryFactory(should_publish=True)
        course1, course2, course3 = CourseFactory.create_batch(
            3, fill_categories=[category], should_publish=True)
        self.assertEqual(list(category.get_courses()),
                         [course1, course2, course3])

        # Move pages in the tree and check that they are returned in the new order
        course3.extended_object.move_page(course1.extended_object.node,
                                          position="left")
        self.assertEqual(list(category.get_courses()),
                         [course3, course1, course2])

        course1.extended_object.move_page(course3.extended_object.node,
                                          position="left")
        self.assertEqual(list(category.get_courses()),
                         [course1, course3, course2])
Esempio n. 3
0
 def test_models_category_get_courses_several_languages(self):
     """
     The courses should not be duplicated if they exist in several languages.
     """
     category = CategoryFactory(should_publish=True)
     CourseFactory(
         page_title={"en": "my title", "fr": "mon titre"},
         fill_categories=[category],
         should_publish=True,
     )
     self.assertEqual(Course.objects.count(), 2)
     self.assertEqual(category.get_courses().count(), 1)
Esempio n. 4
0
    def test_templates_category_detail_cms_published_content_max_courses(
            self, _mock_page_url):
        """
        Make sure the category detail page does not display too many courses, even when a large
        number are related to the current category, as this can cause the page to load very slowly
        and is not a great experience for the user anyway.
        """
        # Create our dummy category and the 3 courses we'll attach to it
        meta = CategoryFactory(
            page_parent=create_i18n_page(
                {
                    "en": "Categories",
                    "fr": "Catégories"
                }, published=True),
            page_reverse_id="subjects",
            page_title={
                "en": "Subjects",
                "fr": "Sujets"
            },
            should_publish=True,
        )
        category = CategoryFactory(page_parent=meta.extended_object,
                                   should_publish=True)
        courses = CourseFactory.create_batch(3,
                                             fill_categories=[category],
                                             should_publish=True)
        # Link the 3 courses with our category through the relevant placeholder
        for course in courses:
            add_plugin(
                course.extended_object.placeholders.get(
                    slot="course_categories"),
                CategoryPlugin,
                "en",
                page=category.extended_object,
            )
        # Make sure we do have 3 courses on the category
        self.assertEqual(category.get_courses().count(), 3)

        # Only the first two are rendered in the template
        response = self.client.get(category.extended_object.get_absolute_url())
        self.assertContains(response, courses[0].extended_object.get_title())
        self.assertContains(response, courses[1].extended_object.get_title())
        self.assertNotContains(response,
                               courses[2].extended_object.get_title())

        # There is a link to view more related courses directly in the Search view
        self.assertContains(
            response,
            f'href="/the/courses/?subjects={category.get_es_id():s}"')
        self.assertContains(
            response,
            f"See all courses related to {category.extended_object.get_title():s}",
        )
Esempio n. 5
0
    def test_templates_category_detail_cms_published_content_max_courses_on_meta(
            self, _mock_page_url):
        """
        Meta categories are a special case: technically, any page linked to one of their children
        is linked to the meta-category too. This means in a lot of cases we just want a link to
        *all* courses not just their related courses.
        The Search view is also not equipped to filter on a meta-category. In this case, we just
        link to it with a different link text.
        """
        # Create our dummy category and the 3 courses we'll attach to it
        meta = CategoryFactory(
            page_parent=create_i18n_page(
                {
                    "en": "Categories",
                    "fr": "Catégories"
                }, published=True),
            page_reverse_id="subjects",
            page_title={
                "en": "Subjects",
                "fr": "Sujets"
            },
            should_publish=True,
        )
        category = CategoryFactory(page_parent=meta.extended_object,
                                   should_publish=True)
        courses = CourseFactory.create_batch(3,
                                             fill_categories=[category],
                                             should_publish=True)
        # Link the 3 courses with our category through the relevant placeholder
        for course in courses:
            add_plugin(
                course.extended_object.placeholders.get(
                    slot="course_categories"),
                CategoryPlugin,
                "en",
                page=category.extended_object,
            )
        # Make sure we do have 3 courses on the category
        self.assertEqual(category.get_courses().count(), 3)

        # NB: here we are requesting the meta category's page, not the child category
        # Only the first two are rendered in the template
        response = self.client.get(meta.extended_object.get_absolute_url())
        self.assertContains(response, courses[0].extended_object.get_title())
        self.assertContains(response, courses[1].extended_object.get_title())
        self.assertNotContains(response,
                               courses[2].extended_object.get_title())

        # There is a link to view all courses
        self.assertContains(response, 'href="/the/courses/')
        self.assertContains(response, "See all courses")
Esempio n. 6
0
    def test_models_category_get_courses_descendants(self):
        """
        Related courses should include the courses linked to the category's descendants,
        unless specifically deactivated by the "include_descendants" argument.
        """
        category_page = create_page("Subjects",
                                    "courses/cms/category_detail.html",
                                    "en",
                                    published=True)
        category = CategoryFactory(extended_object=category_page,
                                   should_publish=True)
        courses = CourseFactory.create_batch(2,
                                             fill_categories=[category],
                                             should_publish=True)

        child_category_page = create_page(
            "Literature",
            "courses/cms/category_detail.html",
            "en",
            parent=category_page,
            published=True,
        )
        child_category = CategoryFactory(extended_object=child_category_page,
                                         should_publish=True)
        courses_child = CourseFactory.create_batch(
            2, fill_categories=[child_category], should_publish=True)

        grand_child_category_page = create_page(
            "Literature",
            "courses/cms/category_detail.html",
            "en",
            parent=child_category_page,
            published=True,
        )
        grand_child_category = CategoryFactory(
            extended_object=grand_child_category_page, should_publish=True)
        courses_grand_child = CourseFactory.create_batch(
            2, fill_categories=[grand_child_category], should_publish=True)

        # Check that each category gets courses from its descendants
        # ...unless we pass an argument to deactivate it
        self.assertEqual(list(category.get_courses()),
                         courses + courses_child + courses_grand_child)
        self.assertEqual(list(category.get_courses(include_descendants=False)),
                         courses)

        self.assertEqual(list(child_category.get_courses()),
                         courses_child + courses_grand_child)
        self.assertEqual(
            list(child_category.get_courses(include_descendants=False)),
            courses_child)

        self.assertEqual(
            list(grand_child_category.get_courses(include_descendants=False)),
            courses_grand_child,
        )
        self.assertEqual(list(grand_child_category.get_courses()),
                         courses_grand_child)
Esempio n. 7
0
    def test_models_category_get_courses(self):
        """
        It should be possible to retrieve the list of related courses on the category instance.
        The number of queries should be minimal.
        """
        category = CategoryFactory(should_publish=True)
        courses = CourseFactory.create_batch(
            3, page_title="my title", fill_categories=[category], should_publish=True
        )
        retrieved_courses = category.get_courses()

        with self.assertNumQueries(2):
            self.assertEqual(set(retrieved_courses), set(courses))

        with self.assertNumQueries(0):
            for course in retrieved_courses:
                self.assertEqual(
                    course.extended_object.prefetched_titles[0].title, "my title"
                )
Esempio n. 8
0
    def test_models_category_get_courses_public_category_page(self):
        """
        When a category is added on a draft course, the course should not be visible on
        the public category page until the course is published.
        """
        category = CategoryFactory(should_publish=True)
        category_page = category.extended_object
        course = CourseFactory(page_title="my title", should_publish=True)
        course_page = course.extended_object

        # Add a category to the course but don't publish the modification
        placeholder = course_page.placeholders.get(slot="course_categories")
        add_plugin(placeholder, CategoryPlugin, "en", page=category_page)

        self.assertEqual(list(category.get_courses()), [course])
        self.assertEqual(list(category.public_extension.get_courses()), [])

        # Now publish the modification and check that the course is displayed
        # on the public category page
        course.extended_object.publish("en")
        self.assertEqual(list(category.public_extension.get_courses()),
                         [course.public_extension])