def test_models_course_get_course_runs_empty(self): """ For a course without course runs the methods `get_course_runs` should return an empty query. """ course = CourseFactory(should_publish=True) self.assertFalse(course.get_course_runs().exists()) self.assertFalse(course.public_extension.get_course_runs().exists())
def test_models_course_get_course_runs(self): """ The `get_course_runs` and `get_course_runs_for_language` methods should return all descendants ranked by path, not only children and should respect publication status. """ course = CourseFactory(page_languages=["en", "fr"], should_publish=True) # Create draft and published course runs for this course # We want to test 4 situations: # - a draft course run # - a course run published in the current language # - a course run published in another language # - a course run published in the current language that was then unpublished course_runs = CourseRunFactory.create_batch( 3, page_parent=course.extended_object, page_languages=["en"]) self.assertTrue(course_runs[0].extended_object.publish("en")) self.assertTrue(course_runs[1].extended_object.publish("en")) self.assertTrue(course_runs[1].extended_object.unpublish("en")) course_run_fr = CourseRunFactory( page_parent=course.extended_object, page_languages=["fr"], should_publish=True, ) # Create a child course with draft and published course runs (what results from # snapshotting a course) child_course = CourseFactory( page_languages=["en", "fr"], page_parent=course.extended_object, should_publish=True, ) child_course_runs = CourseRunFactory.create_batch( 3, page_parent=child_course.extended_object, page_languages=["en"]) self.assertTrue(child_course_runs[0].extended_object.publish("en")) self.assertTrue(child_course_runs[1].extended_object.publish("en")) self.assertTrue(child_course_runs[1].extended_object.unpublish("en")) child_course_run_fr = CourseRunFactory( page_parent=child_course.extended_object, page_languages=["fr"], should_publish=True, ) # Create another course, not related to the first one, with draft and published course runs other_course = CourseFactory(page_languages=["en", "fr"], should_publish=True) other_course_runs = CourseRunFactory.create_batch( 3, page_parent=other_course.extended_object, page_languages=["en"]) self.assertTrue(other_course_runs[0].extended_object.publish("en")) self.assertTrue(other_course_runs[1].extended_object.publish("en")) self.assertTrue(other_course_runs[1].extended_object.unpublish("en")) CourseRunFactory( page_parent=other_course.extended_object, page_languages=["fr"], should_publish=True, ) # Check that the draft course retrieves all its descendant course runs # 3 draft course runs and 2 published course runs per course self.assertEqual(CourseRun.objects.count(), 3 * (4 + 3)) with self.assertNumQueries(2): self.assertEqual( list(course.get_course_runs()), course_runs + [course_run_fr] + child_course_runs + [child_course_run_fr], ) with self.assertNumQueries(1): self.assertEqual( list(course.get_course_runs_for_language(language="en")), course_runs + child_course_runs, ) # Check that the published course retrieves only the published descendant course runs course_runs[0].refresh_from_db() child_course_runs[0].refresh_from_db() public_course = course.public_extension with self.assertNumQueries(3): result = list(public_course.get_course_runs()) self.assertEqual( result, [ course_runs[0].public_extension, course_run_fr.public_extension, child_course_runs[0].public_extension, child_course_run_fr.public_extension, ], ) with self.assertNumQueries(1): result = list( public_course.get_course_runs_for_language(language="en")) self.assertEqual( result, [ course_runs[0].public_extension, child_course_runs[0].public_extension ], )
def test_indexers_courses_get_es_documents_from_models(self, _mock_picture): """ Happy path: the data is retrieved from the models properly formatted """ # Create a course with a page in both english and french published_categories = [ CategoryFactory( # L-0001 fill_icon=True, page_title={"en": "Title L-0001", "fr": "Titre L-0001"}, should_publish=True, ), CategoryFactory( # L-0002 fill_icon=True, page_title={"en": "Title L-0002", "fr": "Titre L-0002"}, should_publish=True, ), ] draft_category = CategoryFactory(fill_icon=True) # L-0003 main_organization = OrganizationFactory( # L-0004 page_title={ "en": "english main organization title", "fr": "titre organisation principale français", }, should_publish=True, ) other_draft_organization = OrganizationFactory( # L-0005 page_title={ "en": "english other organization title", "fr": "titre autre organisation français", } ) other_published_organization = OrganizationFactory( # L-0006 page_title={ "en": "english other organization title", "fr": "titre autre organisation français", }, should_publish=True, ) person1 = PersonFactory( page_title={"en": "Eugène Delacroix", "fr": "Eugène Delacroix"}, should_publish=True, ) person2 = PersonFactory( page_title={"en": "Comte de Saint-Germain", "fr": "Earl of Saint-Germain"}, should_publish=True, ) person_draft = PersonFactory( page_title={"en": "Jules de Polignac", "fr": "Jules de Polignac"} ) course = CourseFactory( duration=[3, WEEK], effort=[2, HOUR, WEEK], fill_categories=published_categories + [draft_category], fill_cover=True, fill_icons=published_categories + [draft_category], fill_organizations=[ main_organization, other_draft_organization, other_published_organization, ], fill_team=[person1, person_draft, person2], page_title={ "en": "an english course title", "fr": "un titre cours français", }, ) CourseRunFactory.create_batch(2, direct_course=course) course.extended_object.publish("en") course.extended_object.publish("fr") course.refresh_from_db() # Add a description in several languages placeholder = course.public_extension.extended_object.placeholders.get( slot="course_description" ) plugin_params = {"placeholder": placeholder, "plugin_type": "CKEditorPlugin"} add_plugin(body="english description line 1.", language="en", **plugin_params) add_plugin(body="english description line 2.", language="en", **plugin_params) add_plugin(body="a propos français ligne 1.", language="fr", **plugin_params) add_plugin(body="a propos français ligne 2.", language="fr", **plugin_params) # The results were properly formatted and passed to the consumer expected_course = { "_id": str(course.public_extension.extended_object_id), "_index": "some_index", "_op_type": "some_action", "_type": "course", "absolute_url": { "en": "/en/an-english-course-title/", "fr": "/fr/un-titre-cours-francais/", }, "categories": ["L-0001", "L-0002"], "categories_names": { "en": ["Title L-0001", "Title L-0002"], "fr": ["Titre L-0001", "Titre L-0002"], }, "complete": { "en": [ "an english course title", "english course title", "course title", "title", ], "fr": [ "un titre cours français", "titre cours français", "cours français", "français", ], }, "course_runs": [ { "start": course_run.public_course_run.start, "end": course_run.public_course_run.end, "enrollment_start": course_run.public_course_run.enrollment_start, "enrollment_end": course_run.public_course_run.enrollment_end, "languages": course_run.public_course_run.languages, } for course_run in course.get_course_runs().order_by("-end") ], "cover_image": { "en": {"info": "picture info"}, "fr": {"info": "picture info"}, }, "description": { "en": "english description line 1. english description line 2.", "fr": "a propos français ligne 1. a propos français ligne 2.", }, "duration": {"en": "3 weeks", "fr": "3 semaines"}, "effort": {"en": "2 hours/week", "fr": "2 heures/semaine"}, "icon": { "en": { "color": published_categories[0].color, "info": "picture info", "title": "Title L-0001", }, "fr": { "color": published_categories[0].color, "info": "picture info", "title": "Titre L-0001", }, }, "is_new": False, "is_listed": True, "organization_highlighted": { "en": "english main organization title", "fr": "titre organisation principale français", }, "organizations": ["L-0004", "L-0006"], "organizations_names": { "en": [ "english main organization title", "english other organization title", ], "fr": [ "titre organisation principale français", "titre autre organisation français", ], }, "persons": [ str(person1.public_extension.extended_object_id), str(person2.public_extension.extended_object_id), ], "persons_names": { "en": ["Eugène Delacroix", "Comte de Saint-Germain"], "fr": ["Eugène Delacroix", "Earl of Saint-Germain"], }, "title": {"fr": "un titre cours français", "en": "an english course title"}, } indexed_courses = list( CoursesIndexer.get_es_documents(index="some_index", action="some_action") ) self.assertEqual(len(indexed_courses), 1) self.assertEqual(indexed_courses[0], expected_course)
def test_models_course_get_course_runs(self): """ The `get_course_runs` method should return all descendants ranked by start date, not only direct children. """ course = CourseFactory(page_languages=["en", "fr"]) # Create draft and published course runs for this course course_run = CourseRunFactory(direct_course=course) self.assertTrue(course.extended_object.publish("en")) self.assertTrue(course.extended_object.publish("fr")) course_run_draft = CourseRunFactory(direct_course=course) # Create a child course with draft and published course runs (what results from # snapshotting a course) child_course = CourseFactory(page_languages=["en", "fr"], page_parent=course.extended_object) child_course_run = CourseRunFactory(direct_course=child_course) self.assertTrue(child_course.extended_object.publish("en")) self.assertTrue(child_course.extended_object.publish("fr")) child_course_run_draft = CourseRunFactory(direct_course=child_course) # Create another course, not related to the first one, with draft and published course runs other_course = CourseFactory(page_languages=["en", "fr"]) CourseRunFactory(direct_course=other_course) self.assertTrue(other_course.extended_object.publish("en")) self.assertTrue(other_course.extended_object.publish("fr")) CourseRunFactory(direct_course=other_course) # Check that the draft course retrieves all its descendant course runs # 3 draft course runs and 2 published course runs per course self.assertEqual(CourseRun.objects.count(), 3 * 3) sorted_runs = sorted( [ course_run, course_run_draft, child_course_run, child_course_run_draft ], key=lambda o: o.start, reverse=True, ) for run in sorted_runs: run.refresh_from_db() with self.assertNumQueries(2): self.assertEqual(list(course.get_course_runs()), sorted_runs) # Check that the published course retrieves only the published descendant course runs course.refresh_from_db() public_course = course.public_extension with self.assertNumQueries(3): result = list(public_course.get_course_runs()) expected_public_course_runs = sorted( [course_run.public_course_run, child_course_run.public_course_run], key=lambda o: o.start, reverse=True, ) self.assertEqual(result, expected_public_course_runs)