From 22ad64fa003c5034164fe833b2fe20d94f0790cf Mon Sep 17 00:00:00 2001 From: Taimoor Ahmed Date: Thu, 16 Jul 2026 14:51:13 +0500 Subject: [PATCH] refactor: migrate Studio Home courses caller to standardized v4 API (FC-0118) FC-0118 (ADR 0028/0037): point the Studio Home course list at the new standardized `/api/contentstore/v4/home/courses/` endpoint instead of v2. The v4 `HomeCoursesViewSet` is served by a DRF DefaultRouter, so the URL now carries the required trailing slash. The default (full) payload shape is unchanged, so this is a behaviour-preserving swap for the paginated caller. The deprecated non-paginated v1 `home/courses` fallback (`getStudioHomeCourses`) had no remaining callers and is removed; pagination, filtering, and ordering are handled natively by v4. Test mocks updated to expect the v4 URL. Refs openedx/frontend-app-authoring#3127 Co-Authored-By: Claude Opus 4.8 --- src/studio-home/data/api.test.js | 13 +------------ src/studio-home/data/api.ts | 17 ++++++----------- src/studio-home/data/thunks.test.js | 2 +- .../tabs-section/TabsSection.test.tsx | 2 +- 4 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/studio-home/data/api.test.js b/src/studio-home/data/api.test.js index febc5d07e2..4c7a112dcc 100644 --- a/src/studio-home/data/api.test.js +++ b/src/studio-home/data/api.test.js @@ -10,7 +10,6 @@ import { handleCourseNotification, sendRequestForCourseCreator, getApiBaseUrl, - getStudioHomeCourses, getStudioHomeCoursesV2, getStudioHomeLibraries, } from './api'; @@ -48,18 +47,8 @@ describe('studio-home api calls', () => { expect(result).toEqual(expected); }); - it('should get studio courses data', async () => { - const apiLink = `${getApiBaseUrl()}/api/contentstore/v1/home/courses`; - axiosMock.onGet(apiLink).reply(200, generateGetStudioCoursesApiResponseV2()); - const result = await getStudioHomeCourses(''); - const expected = generateGetStudioCoursesApiResponseV2(); - - expect(axiosMock.history.get[0].url).toEqual(apiLink); - expect(result).toEqual(expected); - }); - it('should get studio courses data v2', async () => { - const apiLink = `${getApiBaseUrl()}/api/contentstore/v2/home/courses`; + const apiLink = `${getApiBaseUrl()}/api/contentstore/v4/home/courses/`; axiosMock.onGet(apiLink).reply(200, generateGetStudioCoursesApiResponseV2()); const result = await getStudioHomeCoursesV2(''); const expected = generateGetStudioCoursesApiResponseV2(); diff --git a/src/studio-home/data/api.ts b/src/studio-home/data/api.ts index b9b43253d8..a715ba771e 100644 --- a/src/studio-home/data/api.ts +++ b/src/studio-home/data/api.ts @@ -14,23 +14,18 @@ export async function getStudioHomeData(): Promise { return camelCaseObject(data); } -/** Get list of courses from the deprecated non-paginated API */ -export async function getStudioHomeCourses(search: string) { - const { data } = await getAuthenticatedHttpClient().get( - `${getApiBaseUrl()}/api/contentstore/v1/home/courses${search}`, - ); - return camelCaseObject(data); -} /** * Get's studio home courses. - * Note: We are changing /api/contentstore/v1 to /api/contentstore/v2 due to upcoming breaking changes. - * Features such as pagination, filtering, and ordering are better handled in the new version. - * Please refer to this PR for further details: https://github.com/openedx/edx-platform/pull/34173 + * + * FC-0118 (ADR 0028/0037): migrated to the standardized v4 `home/courses` + * endpoint. The trailing slash is required by the DRF DefaultRouter that serves + * the v4 ViewSet. The deprecated non-paginated v1 `home/courses` fallback has + * been dropped; pagination, filtering, and ordering are handled natively by v4. */ export async function getStudioHomeCoursesV2(search: string, customParams: object): Promise { const customParamsFormat = snakeCaseObject(customParams); const { data } = await getAuthenticatedHttpClient().get( - `${getApiBaseUrl()}/api/contentstore/v2/home/courses${search}`, + `${getApiBaseUrl()}/api/contentstore/v4/home/courses/${search}`, { params: customParamsFormat }, ); return camelCaseObject(data); diff --git a/src/studio-home/data/thunks.test.js b/src/studio-home/data/thunks.test.js index 2030be2d8b..f3c8d6f2c1 100644 --- a/src/studio-home/data/thunks.test.js +++ b/src/studio-home/data/thunks.test.js @@ -26,7 +26,7 @@ describe('fetchStudioHomeData thunk', () => { dispatch = jest.fn(); axiosMock.onGet(getStudioHomeApiUrl()).reply(200, generateGetStudioHomeDataApiResponse()); - axiosMock.onGet(new RegExp(`${getApiBaseUrl()}/api/contentstore/v2/home/courses.*`)) + axiosMock.onGet(new RegExp(`${getApiBaseUrl()}/api/contentstore/v4/home/courses.*`)) .reply(200, generateGetStudioCoursesApiResponseV2()); }); diff --git a/src/studio-home/tabs-section/TabsSection.test.tsx b/src/studio-home/tabs-section/TabsSection.test.tsx index d20d8a6850..be10eabf0b 100644 --- a/src/studio-home/tabs-section/TabsSection.test.tsx +++ b/src/studio-home/tabs-section/TabsSection.test.tsx @@ -28,7 +28,7 @@ const { studioShortName } = studioHomeMock; let axiosMock; let store; -const courseApiLinkV2 = `${getApiBaseUrl()}/api/contentstore/v2/home/courses`; +const courseApiLinkV2 = `${getApiBaseUrl()}/api/contentstore/v4/home/courses/`; const tabSectionComponent = (overrideProps) => (