Skip to content

Commit 21f3493

Browse files
test: tests to confirm courses stay in sync with CatalogCourse/CourseRun
1 parent 08950bf commit 21f3493

2 files changed

Lines changed: 149 additions & 0 deletions

File tree

openedx/core/djangoapps/content/course_overviews/signals.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ def _listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable
6565
# Keep the CourseRun up to date as the course is edited:
6666
if updated_course_overview.display_name != course_run.display_name:
6767
catalog_api.sync_course_run_details(course_key, display_name=updated_course_overview.display_name)
68+
# If this course is the only run in the CatalogCourse, should we update the display_name of
69+
# the CatalogCourse to match the run's new name? Currently the only way to edit the name of
70+
# a CatalogCourse is via the Django admin. But it's also not used anywhere yet.
6871

6972
if (
7073
updated_course_overview.language
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
"""
2+
Test that changes to courses get synced into the new openedx_catalog models.
3+
"""
4+
5+
from openedx_catalog import api as catalog_api
6+
7+
from cms.djangoapps.contentstore.views.course import rerun_course
8+
from xmodule.modulestore import ModuleStoreEnum
9+
from xmodule.modulestore.tests.django_utils import (
10+
TEST_DATA_ONLY_SPLIT_MODULESTORE_DRAFT_PREFERRED,
11+
ModuleStoreTestCase,
12+
ImmediateOnCommitMixin,
13+
)
14+
from xmodule.modulestore.tests.factories import CourseFactory
15+
16+
17+
class CourseOverviewSyncTestCase(ImmediateOnCommitMixin, ModuleStoreTestCase):
18+
"""
19+
Test that changes to courses get synced into the new openedx_catalog models.
20+
"""
21+
22+
MODULESTORE = TEST_DATA_ONLY_SPLIT_MODULESTORE_DRAFT_PREFERRED
23+
ENABLED_SIGNALS = ["course_published"]
24+
25+
def test_courserun_creation(self) -> None:
26+
"""
27+
Tests that when a course is created, the `CourseRun` record gets created.
28+
29+
(Also the corresponding `CatalogCourse`.)
30+
"""
31+
course = CourseFactory.create(display_name="Intro to Testing", emit_signals=True)
32+
course_id = course.location.context_key
33+
34+
run = catalog_api.get_course_run(course_id)
35+
assert run.display_name == "Intro to Testing"
36+
assert run.course_id == course_id
37+
assert run.catalog_course.course_code == course_id.course
38+
assert run.catalog_course.org_code == course_id.org
39+
40+
def test_courserun_sync(self) -> None:
41+
"""
42+
Tests that when a course is updated, the catalog records get updated.
43+
44+
Because the "language" of a course cannot be set in Studio before you
45+
create the course, when a Catalog Course has only a single run, we need
46+
to keep the language of the catalog course in sync with any changes to
47+
the language field of the course run. (Because authors necessarily
48+
create a new course with the default language then edit it to have the
49+
correct language that they actually intended to use for that [catalog]
50+
course.) This is in contrast with display_name, which can actually be
51+
set before creating a course.
52+
"""
53+
# Create a course
54+
course = CourseFactory.create(display_name="Intro to Testing", emit_signals=True)
55+
course_id = course.location.context_key
56+
run = catalog_api.get_course_run(course_id)
57+
assert run.display_name == "Intro to Testing"
58+
assert run.catalog_course.language_short == "en"
59+
60+
# Update the course's display_name and language:
61+
course.language = "es"
62+
course.display_name = "Introducción a las pruebas"
63+
self.store.update_item(course, ModuleStoreEnum.UserID.test)
64+
65+
# Check if the catalog data is updated:
66+
run.refresh_from_db()
67+
assert run.display_name == "Introducción a las pruebas"
68+
assert run.catalog_course.language_short == "es"
69+
# Note: for now we don't update the display_name of the catalog course after it has been created.
70+
# We _could_ decide to sync the name from run -> catalog course if there is only one run.
71+
assert run.catalog_course.display_name == "Intro to Testing"
72+
73+
def test_courserun_sync(self) -> None:
74+
"""
75+
Tests that when a course is updated, the catalog records get updated.
76+
77+
Because the "language" of a course cannot be set in Studio before you
78+
create the course, when a Catalog Course has only a single run, we need
79+
to keep the language of the catalog course in sync with any changes to
80+
the language field of the course run. (Because authors necessarily
81+
create a new course with the default language then edit it to have the
82+
correct language that they actually intended to use for that [catalog]
83+
course.) This is in contrast with display_name, which can actually be
84+
set before creating a course.
85+
"""
86+
# Create a course
87+
course = CourseFactory.create(display_name="Intro to Testing", emit_signals=True)
88+
course_id = course.location.context_key
89+
run = catalog_api.get_course_run(course_id)
90+
assert run.display_name == "Intro to Testing"
91+
assert run.catalog_course.language_short == "en"
92+
93+
# Update the course's display_name and language:
94+
course.language = "es"
95+
course.display_name = "Introducción a las pruebas"
96+
self.store.update_item(course, ModuleStoreEnum.UserID.test)
97+
98+
# Check if the catalog data is updated:
99+
run.refresh_from_db()
100+
assert run.display_name == "Introducción a las pruebas"
101+
assert run.catalog_course.language_short == "es"
102+
# Note: for now we don't update the display_name of the catalog course after it has been created.
103+
# We _could_ decide to sync the name from run -> catalog course if there is only one run.
104+
assert run.catalog_course.display_name == "Intro to Testing"
105+
106+
def test_courserun_of_many_sync(self) -> None:
107+
"""
108+
Tests that when a course is updated, the catalog records get updated,
109+
but if there are several runs of the same course, the changes don't
110+
propagate to the `CatalogCourse` and only affect the `CourseRun.
111+
"""
112+
# Create a course
113+
course = CourseFactory.create(display_name="Intro to Testing", emit_signals=True)
114+
course_id = course.location.context_key
115+
run = catalog_api.get_course_run(course_id)
116+
assert run.display_name == "Intro to Testing"
117+
assert run.catalog_course.language_short == "en"
118+
119+
# re-run the course:
120+
new_run_course_id = rerun_course(
121+
self.user,
122+
source_course_key=course_id,
123+
org=course_id.org,
124+
number=course_id.course,
125+
run="newRUN",
126+
fields={"display_name": "Intro to Testing TEMPORARY NAME"},
127+
background=False,
128+
)
129+
130+
# Update the re-run's display_name and language:
131+
new_course = self.store.get_course(new_run_course_id)
132+
new_course.language = "es"
133+
new_course.display_name = "Introducción a las pruebas"
134+
self.store.update_item(new_course, self.user.id)
135+
136+
# Check if the catalog data is updated correctly.
137+
# The original CourseRun object should be unchanged:
138+
run.refresh_from_db()
139+
assert run.display_name == "Intro to Testing"
140+
assert run.catalog_course.language_short == "en"
141+
# The new CourseRun object should be created:
142+
new_run = catalog_api.get_course_run(new_run_course_id)
143+
assert new_run.display_name == "Introducción a las pruebas"
144+
# Changing the language of the second run doesn't affect the lanugage of the overall catalog course (since the
145+
# first run is still in English)
146+
assert new_run.catalog_course.language_short == "en"

0 commit comments

Comments
 (0)