From f0f5ad3424ba531e385cbf0a92fa5e8e84a440b8 Mon Sep 17 00:00:00 2001 From: KristinAoki Date: Mon, 11 Dec 2023 10:26:00 -0500 Subject: [PATCH 1/5] feat: separate home api call into load, course, and library info --- .../rest_api/v1/serializers/__init__.py | 2 +- .../rest_api/v1/serializers/home.py | 10 ++ .../contentstore/rest_api/v1/urls.py | 8 + .../rest_api/v1/views/__init__.py | 2 +- .../contentstore/rest_api/v1/views/home.py | 160 ++++++++++++++---- cms/djangoapps/contentstore/utils.py | 78 +++++---- 6 files changed, 194 insertions(+), 66 deletions(-) diff --git a/cms/djangoapps/contentstore/rest_api/v1/serializers/__init__.py b/cms/djangoapps/contentstore/rest_api/v1/serializers/__init__.py index ac1f2cd1fb54..5c1dbf662417 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/serializers/__init__.py +++ b/cms/djangoapps/contentstore/rest_api/v1/serializers/__init__.py @@ -5,7 +5,7 @@ from .course_rerun import CourseRerunSerializer from .course_team import CourseTeamSerializer from .grading import CourseGradingModelSerializer, CourseGradingSerializer -from .home import CourseHomeSerializer +from .home import CourseHomeSerializer, CourseTabSerializer, LibraryTabSerializer from .proctoring import ( LimitedProctoredExamSettingsSerializer, ProctoredExamConfigurationSerializer, diff --git a/cms/djangoapps/contentstore/rest_api/v1/serializers/home.py b/cms/djangoapps/contentstore/rest_api/v1/serializers/home.py index 12816a8cbd1d..80296b9a766c 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/serializers/home.py +++ b/cms/djangoapps/contentstore/rest_api/v1/serializers/home.py @@ -31,6 +31,16 @@ class LibraryViewSerializer(serializers.Serializer): can_edit = serializers.BooleanField() +class CourseTabSerializer(serializers.Serializer): + archived_courses = CourseCommonSerializer(required=False, many=True) + courses = CourseCommonSerializer(required=False, many=True) + in_process_course_actions = UnsucceededCourseSerializer(many=True, required=False, allow_null=True) + + +class LibraryTabSerializer(serializers.Serializer): + libraries = LibraryViewSerializer(many=True, required=False, allow_null=True) + + class CourseHomeSerializer(serializers.Serializer): """Serializer for course home""" allow_course_reruns = serializers.BooleanField() diff --git a/cms/djangoapps/contentstore/rest_api/v1/urls.py b/cms/djangoapps/contentstore/rest_api/v1/urls.py index ad5765a67396..d2360e4dd9c9 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/urls.py +++ b/cms/djangoapps/contentstore/rest_api/v1/urls.py @@ -12,6 +12,8 @@ CourseSettingsView, CourseVideosView, HomePageView, + HomePageCoursesView, + HomePageLibrariesView, ProctoredExamSettingsView, ProctoringErrorsView, HelpUrlsView, @@ -28,6 +30,12 @@ HomePageView.as_view(), name="home" ), + path('home/courses', + HomePageCoursesView.as_view(), + name="courses"), + path('home/libraries', + HomePageLibrariesView.as_view(), + name="libraries"), re_path( fr'^videos/{COURSE_ID_PATTERN}$', CourseVideosView.as_view(), diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/__init__.py b/cms/djangoapps/contentstore/rest_api/v1/views/__init__.py index 780f0059aaed..ae4026175915 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/__init__.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/__init__.py @@ -6,7 +6,7 @@ from .course_rerun import CourseRerunView from .grading import CourseGradingView from .proctoring import ProctoredExamSettingsView, ProctoringErrorsView -from .home import HomePageView +from .home import HomePageView, HomePageCoursesView, HomePageLibrariesView from .settings import CourseSettingsView from .videos import ( CourseVideosView, diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/home.py b/cms/djangoapps/contentstore/rest_api/v1/views/home.py index ea0724e8e2df..3dd0fb109478 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/home.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/home.py @@ -7,8 +7,8 @@ from rest_framework.views import APIView from openedx.core.lib.api.view_utils import view_auth_classes -from ....utils import get_home_context -from ..serializers import CourseHomeSerializer +from ....utils import get_home_context, get_course_context, get_library_context +from ..serializers import CourseHomeSerializer, CourseTabSerializer, LibraryTabSerializer @view_auth_classes(is_authenticated=True) @@ -51,6 +51,80 @@ def get(self, request: Request): "allow_to_create_new_org": true, "allow_unicode_course_id": false, "allowed_organizations": [], + "archived_courses": [], + "can_create_organizations": true, + "course_creator_status": "granted", + "courses": [], + "in_process_course_actions": [], + "libraries": [], + "libraries_enabled": true, + "library_authoring_mfe_url": "//localhost:3001/course/course-v1:edX+P315+2T2023", + "optimization_enabled": true, + "redirect_to_library_authoring_mfe": false, + "request_course_creator_url": "/request_course_creator", + "rerun_creator_status": true, + "show_new_library_button": true, + "split_studio_home": false, + "studio_name": "Studio", + "studio_short_name": "Studio", + "studio_request_email": "", + "tech_support_email": "technical@example.com", + "platform_name": "Your Platform Name Here" + "user_is_active": true, + } + ``` + """ + + home_context = get_home_context(request, True) + home_context.update({ + 'allow_to_create_new_org': settings.FEATURES.get('ENABLE_CREATOR_GROUP', True) and request.user.is_staff, + 'studio_name': settings.STUDIO_NAME, + 'studio_short_name': settings.STUDIO_SHORT_NAME, + 'studio_request_email': settings.FEATURES.get('STUDIO_REQUEST_EMAIL', ''), + 'tech_support_email': settings.TECH_SUPPORT_EMAIL, + 'platform_name': settings.PLATFORM_NAME, + 'user_is_active': request.user.is_active, + }) + serializer = CourseHomeSerializer(home_context) + return Response(serializer.data) + + +@view_auth_classes(is_authenticated=True) +class HomePageCoursesView(APIView): + """ + View for getting all courses and libraries available to the logged in user. + """ + @apidocs.schema( + parameters=[ + apidocs.string_parameter( + "org", + apidocs.ParameterLocation.QUERY, + description="Query param to filter by course org", + )], + responses={ + 200: CourseTabSerializer, + 401: "The requester is not authenticated.", + }, + ) + def get(self, request: Request): + """ + Get an object containing all courses. + + **Example Request** + + GET /api/contentstore/v1/home/courses + + **Response Values** + + If the request is successful, an HTTP 200 "OK" response is returned. + + The HTTP 200 response contains a single dict that contains keys that + are the course's home. + + **Example Response** + + ```json + { "archived_courses": [ { "course_key": "course-v1:edX+P315+2T2023", @@ -63,8 +137,6 @@ def get(self, request: Request): "url": "/course/course-v1:edX+P315+2T2023" }, ], - "can_create_organizations": true, - "course_creator_status": "granted", "courses": [ { "course_key": "course-v1:edX+E2E-101+course", @@ -78,6 +150,56 @@ def get(self, request: Request): }, ], "in_process_course_actions": [], + } + ``` + """ + + active_courses, archived_courses, in_process_course_actions = get_course_context(request) + courses_context = { + "courses": active_courses, + "archived_course": archived_courses, + "in_process_course_actions": in_process_course_actions, + } + serializer = CourseTabSerializer(courses_context) + return Response(serializer.data) + + +@view_auth_classes(is_authenticated=True) +class HomePageLibrariesView(APIView): + """ + View for getting all courses and libraries available to the logged in user. + """ + @apidocs.schema( + parameters=[ + apidocs.string_parameter( + "org", + apidocs.ParameterLocation.QUERY, + description="Query param to filter by course org", + )], + responses={ + 200: LibraryTabSerializer, + 401: "The requester is not authenticated.", + }, + ) + def get(self, request: Request): + """ + Get an object containing all libraries on home page. + + **Example Request** + + GET /api/contentstore/v1/home/libraries + + **Response Values** + + If the request is successful, an HTTP 200 "OK" response is returned. + + The HTTP 200 response contains a single dict that contains keys that + are the course's home. + + **Example Response** + + ```json + { "libraries": [ { "display_name": "My First Library", @@ -87,34 +209,10 @@ def get(self, request: Request): "number": "CPSPR", "can_edit": true } - ], - "libraries_enabled": true, - "library_authoring_mfe_url": "//localhost:3001/course/course-v1:edX+P315+2T2023", - "optimization_enabled": true, - "redirect_to_library_authoring_mfe": false, - "request_course_creator_url": "/request_course_creator", - "rerun_creator_status": true, - "show_new_library_button": true, - "split_studio_home": false, - "studio_name": "Studio", - "studio_short_name": "Studio", - "studio_request_email": "", - "tech_support_email": "technical@example.com", - "platform_name": "Your Platform Name Here" - "user_is_active": true, - } + ], } ``` """ - home_context = get_home_context(request) - home_context.update({ - 'allow_to_create_new_org': settings.FEATURES.get('ENABLE_CREATOR_GROUP', True) and request.user.is_staff, - 'studio_name': settings.STUDIO_NAME, - 'studio_short_name': settings.STUDIO_SHORT_NAME, - 'studio_request_email': settings.FEATURES.get('STUDIO_REQUEST_EMAIL', ''), - 'tech_support_email': settings.TECH_SUPPORT_EMAIL, - 'platform_name': settings.PLATFORM_NAME, - 'user_is_active': request.user.is_active, - }) - serializer = CourseHomeSerializer(home_context) + library_context = get_library_context(request) + serializer = LibraryTabSerializer(library_context) return Response(serializer.data) diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py index 112431b6125b..b8243dcd6013 100644 --- a/cms/djangoapps/contentstore/utils.py +++ b/cms/djangoapps/contentstore/utils.py @@ -1472,44 +1472,12 @@ def get_library_context(request, request_is_json=False): return data -def get_home_context(request): - """ - Utils is used to get context of course home. - It is used for both DRF and django views. - """ - +def get_course_context(request): from cms.djangoapps.contentstore.views.course import ( - get_allowed_organizations, - get_allowed_organizations_for_libraries, get_courses_accessible_to_user, - user_can_create_organizations, - _accessible_libraries_iter, - _get_course_creator_status, - _format_library_for_view, _process_courses_list, ENABLE_GLOBAL_STAFF_OPTIMIZATION, ) - from cms.djangoapps.contentstore.views.library import ( - LIBRARY_AUTHORING_MICROFRONTEND_URL, - LIBRARIES_ENABLED, - should_redirect_to_library_authoring_mfe, - user_can_create_library, - ) - - optimization_enabled = GlobalStaff().has_user(request.user) and ENABLE_GLOBAL_STAFF_OPTIMIZATION.is_enabled() - - org = request.GET.get('org', '') if optimization_enabled else None - courses_iter, in_process_course_actions = get_courses_accessible_to_user(request, org) - user = request.user - libraries = [] - response_format = get_response_format(request) - - if not split_library_view_on_dashboard() and LIBRARIES_ENABLED: - accessible_libraries = _accessible_libraries_iter(user) - libraries = [_format_library_for_view(lib, request) for lib in accessible_libraries] - - if split_library_view_on_dashboard() and request_response_format_is_json(request, response_format): - libraries = get_library_context(request, True)['libraries'] def format_in_process_course_view(uca): """ @@ -1531,10 +1499,54 @@ def format_in_process_course_view(uca): }, ) if uca.state == CourseRerunUIStateManager.State.FAILED else '' } + + optimization_enabled = GlobalStaff().has_user(request.user) and ENABLE_GLOBAL_STAFF_OPTIMIZATION.is_enabled() + org = request.GET.get('org', '') if optimization_enabled else None + courses_iter, in_process_course_actions = get_courses_accessible_to_user(request, org) split_archived = settings.FEATURES.get('ENABLE_SEPARATE_ARCHIVED_COURSES', False) active_courses, archived_courses = _process_courses_list(courses_iter, in_process_course_actions, split_archived) in_process_course_actions = [format_in_process_course_view(uca) for uca in in_process_course_actions] + return active_courses, archived_courses, in_process_course_actions + + +def get_home_context(request, no_course=False): + """ + Utils is used to get context of course home. + It is used for both DRF and django views. + """ + + from cms.djangoapps.contentstore.views.course import ( + get_allowed_organizations, + get_allowed_organizations_for_libraries, + user_can_create_organizations, + _accessible_libraries_iter, + _get_course_creator_status, + _format_library_for_view, + ENABLE_GLOBAL_STAFF_OPTIMIZATION, + ) + from cms.djangoapps.contentstore.views.library import ( + LIBRARY_AUTHORING_MICROFRONTEND_URL, + LIBRARIES_ENABLED, + should_redirect_to_library_authoring_mfe, + user_can_create_library, + ) + + active_courses = [] + archived_courses = [] + in_process_course_actions = [] + + + optimization_enabled = GlobalStaff().has_user(request.user) and ENABLE_GLOBAL_STAFF_OPTIMIZATION.is_enabled() + + user = request.user + libraries = [] + + if not no_course: + active_courses, archived_courses, in_process_course_actions = get_course_context(request) + + if not split_library_view_on_dashboard() and LIBRARIES_ENABLED and not no_course: + libraries = get_library_context(request, True)['libraries'] home_context = { 'courses': active_courses, From 193c9f85dde61c42bcd993201d4a961e275c9180 Mon Sep 17 00:00:00 2001 From: KristinAoki Date: Mon, 11 Dec 2023 16:36:38 -0500 Subject: [PATCH 2/5] fix: failing tests and formatting --- .../contentstore/rest_api/v1/urls.py | 6 +- .../contentstore/rest_api/v1/views/home.py | 2 +- .../rest_api/v1/views/tests/test_home.py | 97 +++++++++++++++---- cms/djangoapps/contentstore/utils.py | 8 +- 4 files changed, 88 insertions(+), 25 deletions(-) diff --git a/cms/djangoapps/contentstore/rest_api/v1/urls.py b/cms/djangoapps/contentstore/rest_api/v1/urls.py index d2360e4dd9c9..a6244b6b1391 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/urls.py +++ b/cms/djangoapps/contentstore/rest_api/v1/urls.py @@ -30,10 +30,12 @@ HomePageView.as_view(), name="home" ), - path('home/courses', + path( + 'home/courses', HomePageCoursesView.as_view(), name="courses"), - path('home/libraries', + path( + 'home/libraries', HomePageLibrariesView.as_view(), name="libraries"), re_path( diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/home.py b/cms/djangoapps/contentstore/rest_api/v1/views/home.py index 3dd0fb109478..f8ee907d2e9f 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/home.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/home.py @@ -157,7 +157,7 @@ def get(self, request: Request): active_courses, archived_courses, in_process_course_actions = get_course_context(request) courses_context = { "courses": active_courses, - "archived_course": archived_courses, + "archived_courses": archived_courses, "in_process_course_actions": in_process_course_actions, } serializer = CourseTabSerializer(courses_context) diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py index 99f1b450cc0d..adf72c3603e8 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py @@ -11,6 +11,7 @@ from rest_framework import status from cms.djangoapps.contentstore.tests.utils import CourseTestCase +from cms.djangoapps.contentstore.tests.test_libraries import LibraryTestCase from cms.djangoapps.contentstore.views.course import ENABLE_GLOBAL_STAFF_OPTIMIZATION from cms.djangoapps.contentstore.toggles import ENABLE_TAGGING_TAXONOMY_LIST_PAGE from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory @@ -20,17 +21,16 @@ @ddt.ddt class HomePageViewTest(CourseTestCase): """ - Tests for HomePageView. + Tests for HomePageCoursesView. """ def setUp(self): super().setUp() self.url = reverse("cms.djangoapps.contentstore:v1:home") - def test_home_page_response(self): + def test_home_page_courses_response(self): """Check successful response content""" response = self.client.get(self.url) - course_id = str(self.course.id) expected_response = { "allow_course_reruns": True, @@ -40,16 +40,7 @@ def test_home_page_response(self): "archived_courses": [], "can_create_organizations": True, "course_creator_status": "granted", - "courses": [{ - "course_key": course_id, - "display_name": self.course.display_name, - "lms_link": f'//{settings.LMS_BASE}/courses/{course_id}/jump_to/{self.course.location}', - "number": self.course.number, - "org": self.course.org, - "rerun_link": f'/course_rerun/{course_id}', - "run": self.course.id.run, - "url": f'/course/{course_id}', - }], + "courses": [], "in_process_course_actions": [], "libraries": [], "libraries_enabled": True, @@ -73,6 +64,51 @@ def test_home_page_response(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertDictEqual(expected_response, response.data) + @override_waffle_flag(ENABLE_TAGGING_TAXONOMY_LIST_PAGE, True) + def test_taxonomy_list_link(self): + response = self.client.get(self.url) + self.assertTrue(response.data['taxonomies_enabled']) + self.assertEqual( + response.data['taxonomy_list_mfe_url'], + f'{settings.COURSE_AUTHORING_MICROFRONTEND_URL}/taxonomy-list' + ) + + +@ddt.ddt +class HomePageCoursesViewTest(CourseTestCase): + """ + Tests for HomePageView. + """ + + def setUp(self): + super().setUp() + self.url = reverse("cms.djangoapps.contentstore:v1:courses") + + def test_home_page_response(self): + """Check successful response content""" + response = self.client.get(self.url) + course_id = str(self.course.id) + + expected_response = { + "archived_courses": [], + "courses": [{ + "course_key": course_id, + "display_name": self.course.display_name, + "lms_link": f'//{settings.LMS_BASE}/courses/{course_id}/jump_to/{self.course.location}', + "number": self.course.number, + "org": self.course.org, + "rerun_link": f'/course_rerun/{course_id}', + "run": self.course.id.run, + "url": f'/course/{course_id}', + }], + "in_process_course_actions": [], + # "libraries": [], + } + + self.assertEqual(response.status_code, status.HTTP_200_OK) + print(response.data) + self.assertDictEqual(expected_response, response.data) + @override_waffle_switch(ENABLE_GLOBAL_STAFF_OPTIMIZATION, True) def test_org_query_if_passed(self): """Test home page when org filter passed as a query param""" @@ -94,11 +130,32 @@ def test_org_query_if_empty(self): self.assertEqual(len(response.data['courses']), 0) self.assertEqual(response.status_code, status.HTTP_200_OK) - @override_waffle_flag(ENABLE_TAGGING_TAXONOMY_LIST_PAGE, True) - def test_taxonomy_list_link(self): + +@ddt.ddt +class HomePageLibrariesViewTest(LibraryTestCase): + """ + Tests for HomePageLibrariesView. + """ + + def setUp(self): + super().setUp() + self.url = reverse("cms.djangoapps.contentstore:v1:libraries") + + def test_home_page_libraries_response(self): + """Check successful response content""" response = self.client.get(self.url) - self.assertTrue(response.data['taxonomies_enabled']) - self.assertEqual( - response.data['taxonomy_list_mfe_url'], - f'{settings.COURSE_AUTHORING_MICROFRONTEND_URL}/taxonomy-list' - ) + + expected_response = { + "libraries": [{ + 'display_name': 'Test Library', + 'library_key': 'library-v1:org+lib', + 'url': '/library/library-v1:org+lib', + 'org': 'org', + 'number': 'lib', + 'can_edit': True + }], + } + + self.assertEqual(response.status_code, status.HTTP_200_OK) + print(response.data) + self.assertDictEqual(expected_response, response.data) diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py index b8243dcd6013..4bac04eb0027 100644 --- a/cms/djangoapps/contentstore/utils.py +++ b/cms/djangoapps/contentstore/utils.py @@ -1473,6 +1473,11 @@ def get_library_context(request, request_is_json=False): def get_course_context(request): + """ + Utils is used to get context of course home library tab. + It is used for both DRF and django views. + """ + from cms.djangoapps.contentstore.views.course import ( get_courses_accessible_to_user, _process_courses_list, @@ -1499,7 +1504,7 @@ def format_in_process_course_view(uca): }, ) if uca.state == CourseRerunUIStateManager.State.FAILED else '' } - + optimization_enabled = GlobalStaff().has_user(request.user) and ENABLE_GLOBAL_STAFF_OPTIMIZATION.is_enabled() org = request.GET.get('org', '') if optimization_enabled else None @@ -1536,7 +1541,6 @@ def get_home_context(request, no_course=False): archived_courses = [] in_process_course_actions = [] - optimization_enabled = GlobalStaff().has_user(request.user) and ENABLE_GLOBAL_STAFF_OPTIMIZATION.is_enabled() user = request.user From 744619913a884295fea5af88f01711b5c99661ba Mon Sep 17 00:00:00 2001 From: KristinAoki Date: Mon, 18 Dec 2023 15:42:36 -0500 Subject: [PATCH 3/5] chore: update branch with master --- cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py index adf72c3603e8..1be2e817b698 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py @@ -102,7 +102,6 @@ def test_home_page_response(self): "url": f'/course/{course_id}', }], "in_process_course_actions": [], - # "libraries": [], } self.assertEqual(response.status_code, status.HTTP_200_OK) From 9eb167cbd60558f3a1c9df1a32c87ad37096d6a4 Mon Sep 17 00:00:00 2001 From: KristinAoki Date: Mon, 18 Dec 2023 16:34:54 -0500 Subject: [PATCH 4/5] fix: failing test --- .../contentstore/rest_api/v1/views/tests/test_home.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py index 1be2e817b698..78b17d3eadf5 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py @@ -70,7 +70,7 @@ def test_taxonomy_list_link(self): self.assertTrue(response.data['taxonomies_enabled']) self.assertEqual( response.data['taxonomy_list_mfe_url'], - f'{settings.COURSE_AUTHORING_MICROFRONTEND_URL}/taxonomy-list' + f'{settings.COURSE_AUTHORING_MICROFRONTEND_URL}/taxonomy' ) From f69851931859ad1382fdf5beb9b52b330cc8e638 Mon Sep 17 00:00:00 2001 From: KristinAoki Date: Mon, 18 Dec 2023 16:52:46 -0500 Subject: [PATCH 5/5] fix: failing test --- .../contentstore/rest_api/v1/views/tests/test_home.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py index 78b17d3eadf5..5279af0b1297 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py @@ -70,7 +70,7 @@ def test_taxonomy_list_link(self): self.assertTrue(response.data['taxonomies_enabled']) self.assertEqual( response.data['taxonomy_list_mfe_url'], - f'{settings.COURSE_AUTHORING_MICROFRONTEND_URL}/taxonomy' + f'{settings.COURSE_AUTHORING_MICROFRONTEND_URL}/taxonomies' )