From 0c71e8b5b7da82eb75047b6e7331b636a18afa3e Mon Sep 17 00:00:00 2001 From: "Adolfo R. Brandes" Date: Wed, 7 Dec 2022 19:15:51 -0300 Subject: [PATCH] feat: Support runtime configuration (second attempt) (This reintroduces the change in 9f84230c that was later reverted by 67b0b33a.) frontend-platform supports runtime configuration since 2.5.0 (see the PR that introduced it[1], but it requires MFE cooperation. This implements just that: by avoiding making configuration values constant, it should now be possible to change them after initialization. Almost all changes here relate to the `LMS_BASE_URL` setting, which in most places was treated as a constant. [1] https://github.com/openedx/frontend-platform/pull/335 --- src/components/NavigationBar/data/api.js | 4 ++-- src/data/api.js | 6 +++--- src/data/constants.js | 2 +- src/data/redux.test.js | 3 ++- src/discussions/cohorts/data/api.js | 4 +--- src/discussions/comments/CommentsView.test.jsx | 9 ++++++--- src/discussions/comments/data/api.js | 14 ++++++-------- src/discussions/comments/data/redux.test.js | 3 ++- src/discussions/common/AuthorLabel.test.jsx | 3 ++- src/discussions/data/api.js | 8 +++----- src/discussions/data/hooks.test.jsx | 3 ++- .../DiscussionSidebar.test.jsx | 3 ++- .../empty-posts/EmptyPosts.test.jsx | 3 ++- .../empty-posts/EmptyTopics.test.jsx | 4 ++-- .../learners/LearnerPostsView.test.jsx | 6 ++++-- src/discussions/learners/LearnersView.test.jsx | 7 +++++-- src/discussions/learners/data/api.js | 12 +++++------- .../breadcrumb-menu/BreadcrumbMenu.test.jsx | 8 ++++---- .../LegacyBreadcrumbMenu.test.jsx | 4 ++-- src/discussions/posts/PostsView.test.jsx | 6 ++++-- src/discussions/posts/data/api.js | 18 ++++++++---------- src/discussions/posts/data/api.test.js | 3 ++- src/discussions/posts/data/redux.test.js | 3 ++- .../posts/post-editor/PostEditor.test.jsx | 7 ++++--- src/discussions/posts/post/PostLink.test.jsx | 3 ++- src/discussions/topics/TopicsView.test.jsx | 10 +++++----- src/discussions/topics/data/api.js | 6 +++--- 27 files changed, 86 insertions(+), 76 deletions(-) diff --git a/src/components/NavigationBar/data/api.js b/src/components/NavigationBar/data/api.js index aa869697..222cbad0 100644 --- a/src/components/NavigationBar/data/api.js +++ b/src/components/NavigationBar/data/api.js @@ -2,7 +2,7 @@ import { camelCaseObject } from '@edx/frontend-platform'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; -import { API_BASE_URL } from '../../../data/constants'; +import { getApiBaseUrl } from '../../../data/constants'; function normalizeCourseHomeCourseMetadata(metadata, rootSlug) { const data = camelCaseObject(metadata); @@ -21,7 +21,7 @@ function normalizeCourseHomeCourseMetadata(metadata, rootSlug) { } export async function getCourseHomeCourseMetadata(courseId, rootSlug) { - const url = `${API_BASE_URL}/api/course_home/course_metadata/${courseId}`; + const url = `${getApiBaseUrl()}/api/course_home/course_metadata/${courseId}`; // don't know the context of adding timezone in url. hence omitting it // url = appendBrowserTimezoneToUrl(url); const { data } = await getAuthenticatedHttpClient().get(url); diff --git a/src/data/api.js b/src/data/api.js index 3f12aec2..67591d89 100644 --- a/src/data/api.js +++ b/src/data/api.js @@ -1,9 +1,9 @@ /* eslint-disable import/prefer-default-export */ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; -import { API_BASE_URL } from './constants'; +import { getApiBaseUrl } from './constants'; -export const blocksAPIURL = `${API_BASE_URL}/api/courses/v1/blocks/`; +export const getBlocksAPIURL = () => `${getApiBaseUrl()}/api/courses/v1/blocks/`; export async function getCourseBlocks(courseId, username) { const params = { course_id: courseId, @@ -14,6 +14,6 @@ export async function getCourseBlocks(courseId, username) { student_view_data: 'discussion', }; const { data } = await getAuthenticatedHttpClient() - .get(blocksAPIURL, { params }); + .get(getBlocksAPIURL(), { params }); return data; } diff --git a/src/data/constants.js b/src/data/constants.js index 357d3b14..ddc35fbf 100644 --- a/src/data/constants.js +++ b/src/data/constants.js @@ -1,6 +1,6 @@ import { getConfig } from '@edx/frontend-platform'; -export const API_BASE_URL = getConfig().LMS_BASE_URL; +export const getApiBaseUrl = () => getConfig().LMS_BASE_URL; /** * Enum for thread types. diff --git a/src/data/redux.test.js b/src/data/redux.test.js index 982a8ce2..0a1329d2 100644 --- a/src/data/redux.test.js +++ b/src/data/redux.test.js @@ -7,10 +7,11 @@ import { initializeMockApp } from '@edx/frontend-platform/testing'; import { initializeStore } from '../store'; import { executeThunk } from '../test-utils'; import { getBlocksAPIResponse } from './__factories__'; -import { blocksAPIURL } from './api'; +import { getBlocksAPIURL } from './api'; import { RequestStatus } from './constants'; import { fetchCourseBlocks } from './thunks'; +const blocksAPIURL = getBlocksAPIURL(); const courseId = 'course-v1:edX+DemoX+Demo_Course'; let axiosMock; diff --git a/src/discussions/cohorts/data/api.js b/src/discussions/cohorts/data/api.js index f5593aec..dab53e24 100644 --- a/src/discussions/cohorts/data/api.js +++ b/src/discussions/cohorts/data/api.js @@ -6,9 +6,7 @@ ensureConfig([ 'LMS_BASE_URL', ], 'Comments API service'); -const apiBaseUrl = getConfig().LMS_BASE_URL; - -export const getCohortsApiUrl = courseId => `${apiBaseUrl}/api/cohorts/v1/courses/${courseId}/cohorts/`; +export const getCohortsApiUrl = courseId => `${getConfig().LMS_BASE_URL}/api/cohorts/v1/courses/${courseId}/cohorts/`; export async function getCourseCohorts(courseId) { const params = snakeCaseObject({ courseId }); diff --git a/src/discussions/comments/CommentsView.test.jsx b/src/discussions/comments/CommentsView.test.jsx index 2c921245..9f8b7910 100644 --- a/src/discussions/comments/CommentsView.test.jsx +++ b/src/discussions/comments/CommentsView.test.jsx @@ -13,16 +13,19 @@ import { AppProvider } from '@edx/frontend-platform/react'; import { initializeStore } from '../../store'; import { executeThunk } from '../../test-utils'; import { DiscussionContext } from '../common/context'; -import { courseConfigApiUrl } from '../data/api'; +import { getCourseConfigApiUrl } from '../data/api'; import { fetchCourseConfig } from '../data/thunks'; import DiscussionContent from '../discussions-home/DiscussionContent'; -import { threadsApiUrl } from '../posts/data/api'; +import { getThreadsApiUrl } from '../posts/data/api'; import { fetchThreads } from '../posts/data/thunks'; -import { commentsApiUrl } from './data/api'; +import { getCommentsApiUrl } from './data/api'; import '../posts/data/__factories__'; import './data/__factories__'; +const courseConfigApiUrl = getCourseConfigApiUrl(); +const commentsApiUrl = getCommentsApiUrl(); +const threadsApiUrl = getThreadsApiUrl(); const discussionPostId = 'thread-1'; const questionPostId = 'thread-2'; const closedPostId = 'thread-2'; diff --git a/src/discussions/comments/data/api.js b/src/discussions/comments/data/api.js index c8e37d7e..87e0ee3d 100644 --- a/src/discussions/comments/data/api.js +++ b/src/discussions/comments/data/api.js @@ -8,9 +8,7 @@ ensureConfig([ 'LMS_BASE_URL', ], 'Comments API service'); -const apiBaseUrl = getConfig().LMS_BASE_URL; - -export const commentsApiUrl = `${apiBaseUrl}/api/discussion/v1/comments/`; +export const getCommentsApiUrl = () => `${getConfig().LMS_BASE_URL}/api/discussion/v1/comments/`; /** * Returns all the comments for the specified thread. @@ -36,7 +34,7 @@ export async function getThreadComments( }); const { data } = await getAuthenticatedHttpClient() - .get(commentsApiUrl, { params }); + .get(getCommentsApiUrl(), { params }); return data; } @@ -53,7 +51,7 @@ export async function getCommentResponses( pageSize, } = {}, ) { - const url = `${commentsApiUrl}${commentId}/`; + const url = `${getCommentsApiUrl()}${commentId}/`; const params = snakeCaseObject({ page, pageSize, @@ -73,7 +71,7 @@ export async function getCommentResponses( */ export async function postComment(comment, threadId, parentId = null) { const { data } = await getAuthenticatedHttpClient() - .post(commentsApiUrl, snakeCaseObject({ threadId, raw_body: comment, parentId })); + .post(getCommentsApiUrl(), snakeCaseObject({ threadId, raw_body: comment, parentId })); return data; } @@ -94,7 +92,7 @@ export async function updateComment(commentId, { endorsed, editReasonCode, }) { - const url = `${commentsApiUrl}${commentId}/`; + const url = `${getCommentsApiUrl()}${commentId}/`; const postData = snakeCaseObject({ raw_body: comment, voted, @@ -113,7 +111,7 @@ export async function updateComment(commentId, { * @param {string} commentId ID of comment to delete */ export async function deleteComment(commentId) { - const url = `${commentsApiUrl}${commentId}/`; + const url = `${getCommentsApiUrl()}${commentId}/`; await getAuthenticatedHttpClient() .delete(url); } diff --git a/src/discussions/comments/data/redux.test.js b/src/discussions/comments/data/redux.test.js index aa46a088..de9d8953 100644 --- a/src/discussions/comments/data/redux.test.js +++ b/src/discussions/comments/data/redux.test.js @@ -7,13 +7,14 @@ import { initializeMockApp } from '@edx/frontend-platform/testing'; import { EndorsementStatus } from '../../../data/constants'; import { initializeStore } from '../../../store'; import { executeThunk } from '../../../test-utils'; -import { commentsApiUrl } from './api'; +import { getCommentsApiUrl } from './api'; import { addComment, editComment, fetchCommentResponses, fetchThreadComments, removeComment, } from './thunks'; import './__factories__'; +const commentsApiUrl = getCommentsApiUrl(); let axiosMock; let store; diff --git a/src/discussions/common/AuthorLabel.test.jsx b/src/discussions/common/AuthorLabel.test.jsx index 1a43c557..57fea13f 100644 --- a/src/discussions/common/AuthorLabel.test.jsx +++ b/src/discussions/common/AuthorLabel.test.jsx @@ -10,12 +10,13 @@ import { AppProvider } from '@edx/frontend-platform/react'; import { initializeStore } from '../../store'; import { executeThunk } from '../../test-utils'; -import { courseConfigApiUrl } from '../data/api'; +import { getCourseConfigApiUrl } from '../data/api'; import { fetchCourseConfig } from '../data/thunks'; import AuthorLabel from './AuthorLabel'; import { DiscussionContext } from './context'; const courseId = 'course-v1:edX+DemoX+Demo_Course'; +const courseConfigApiUrl = getCourseConfigApiUrl(); let store; let axiosMock; let container; diff --git a/src/discussions/data/api.js b/src/discussions/data/api.js index 6dcd3460..045ac180 100644 --- a/src/discussions/data/api.js +++ b/src/discussions/data/api.js @@ -7,16 +7,14 @@ ensureConfig([ 'LMS_BASE_URL', ], 'Posts API service'); -const apiBaseUrl = getConfig().LMS_BASE_URL; - -export const courseConfigApiUrl = `${apiBaseUrl}/api/discussion/v1/courses/`; +export const getCourseConfigApiUrl = () => `${getConfig().LMS_BASE_URL}/api/discussion/v1/courses/`; /** * Get discussions course config * @param {string} courseId */ export async function getDiscussionsConfig(courseId) { - const url = `${courseConfigApiUrl}${courseId}/`; + const url = `${getCourseConfigApiUrl()}${courseId}/`; const { data } = await getAuthenticatedHttpClient().get(url); return data; } @@ -26,7 +24,7 @@ export async function getDiscussionsConfig(courseId) { * @param {string} courseId */ export async function getDiscussionsSettings(courseId) { - const url = `${courseConfigApiUrl}${courseId}/settings`; + const url = `${getCourseConfigApiUrl()}${courseId}/settings`; const { data } = await getAuthenticatedHttpClient().get(url); return data; } diff --git a/src/discussions/data/hooks.test.jsx b/src/discussions/data/hooks.test.jsx index a872b47b..45b29b09 100644 --- a/src/discussions/data/hooks.test.jsx +++ b/src/discussions/data/hooks.test.jsx @@ -10,11 +10,12 @@ import { AppProvider } from '@edx/frontend-platform/react'; import { initializeStore } from '../../store'; import { executeThunk } from '../../test-utils'; import { DiscussionContext } from '../common/context'; -import { courseConfigApiUrl } from './api'; +import { getCourseConfigApiUrl } from './api'; import { useCurrentDiscussionTopic, useUserCanAddThreadInBlackoutDate } from './hooks'; import { fetchCourseConfig } from './thunks'; const courseId = 'course-v1:edX+TestX+Test_Course'; +const courseConfigApiUrl = getCourseConfigApiUrl(); let store; let axiosMock; diff --git a/src/discussions/discussions-home/DiscussionSidebar.test.jsx b/src/discussions/discussions-home/DiscussionSidebar.test.jsx index 97ba6526..653f1f49 100644 --- a/src/discussions/discussions-home/DiscussionSidebar.test.jsx +++ b/src/discussions/discussions-home/DiscussionSidebar.test.jsx @@ -13,7 +13,7 @@ import { AppProvider } from '@edx/frontend-platform/react'; import { initializeStore } from '../../store'; import { DiscussionContext } from '../common/context'; import { fetchConfigSuccess } from '../data/slices'; -import { threadsApiUrl } from '../posts/data/api'; +import { getThreadsApiUrl } from '../posts/data/api'; import DiscussionSidebar from './DiscussionSidebar'; import '../posts/data/__factories__'; @@ -21,6 +21,7 @@ import '../posts/data/__factories__'; let store; let container; const courseId = 'course-v1:edX+DemoX+Demo_Course'; +const threadsApiUrl = getThreadsApiUrl(); let axiosMock; function renderComponent(displaySidebar = true, location = `/${courseId}/`) { diff --git a/src/discussions/empty-posts/EmptyPosts.test.jsx b/src/discussions/empty-posts/EmptyPosts.test.jsx index 27554883..501a6a5b 100644 --- a/src/discussions/empty-posts/EmptyPosts.test.jsx +++ b/src/discussions/empty-posts/EmptyPosts.test.jsx @@ -12,7 +12,7 @@ import { AppProvider } from '@edx/frontend-platform/react'; import { initializeStore } from '../../store'; import { executeThunk } from '../../test-utils'; import messages from '../messages'; -import { threadsApiUrl } from '../posts/data/api'; +import { getThreadsApiUrl } from '../posts/data/api'; import { fetchThreads } from '../posts/data/thunks'; import EmptyPosts from './EmptyPosts'; @@ -20,6 +20,7 @@ import '../posts/data/__factories__'; let store; const courseId = 'course-v1:edX+DemoX+Demo_Course'; +const threadsApiUrl = getThreadsApiUrl(); function renderComponent(location = `/${courseId}/`) { return render( diff --git a/src/discussions/empty-posts/EmptyTopics.test.jsx b/src/discussions/empty-posts/EmptyTopics.test.jsx index caa2a496..0621c115 100644 --- a/src/discussions/empty-posts/EmptyTopics.test.jsx +++ b/src/discussions/empty-posts/EmptyTopics.test.jsx @@ -9,7 +9,7 @@ import { initializeMockApp } from '@edx/frontend-platform'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import { AppProvider } from '@edx/frontend-platform/react'; -import { API_BASE_URL } from '../../data/constants'; +import { getApiBaseUrl } from '../../data/constants'; import { initializeStore } from '../../store'; import { executeThunk } from '../../test-utils'; import messages from '../messages'; @@ -20,7 +20,7 @@ import '../topics/data/__factories__'; let store; const courseId = 'course-v1:edX+DemoX+Demo_Course'; -const topicsApiUrl = `${API_BASE_URL}/api/discussion/v1/course_topics/${courseId}`; +const topicsApiUrl = `${getApiBaseUrl()}/api/discussion/v1/course_topics/${courseId}`; function renderComponent(location = `/${courseId}/topics/`) { return render( diff --git a/src/discussions/learners/LearnerPostsView.test.jsx b/src/discussions/learners/LearnerPostsView.test.jsx index af57e7d7..2ed75ba6 100644 --- a/src/discussions/learners/LearnerPostsView.test.jsx +++ b/src/discussions/learners/LearnerPostsView.test.jsx @@ -14,15 +14,17 @@ import { AppProvider } from '@edx/frontend-platform/react'; import { initializeStore } from '../../store'; import { executeThunk } from '../../test-utils'; import { DiscussionContext } from '../common/context'; -import { courseConfigApiUrl } from '../data/api'; +import { getCourseConfigApiUrl } from '../data/api'; import { fetchCourseConfig } from '../data/thunks'; -import { coursesApiUrl } from './data/api'; +import { getCoursesApiUrl } from './data/api'; import LearnerPostsView from './LearnerPostsView'; import './data/__factories__'; let store; let axiosMock; +const coursesApiUrl = getCoursesApiUrl(); +const courseConfigApiUrl = getCourseConfigApiUrl(); const courseId = 'course-v1:edX+TestX+Test_Course'; const username = 'abc123'; diff --git a/src/discussions/learners/LearnersView.test.jsx b/src/discussions/learners/LearnersView.test.jsx index ccf47286..1bc76414 100644 --- a/src/discussions/learners/LearnersView.test.jsx +++ b/src/discussions/learners/LearnersView.test.jsx @@ -13,9 +13,9 @@ import { AppProvider } from '@edx/frontend-platform/react'; import { initializeStore } from '../../store'; import { executeThunk } from '../../test-utils'; -import { courseConfigApiUrl } from '../data/api'; +import { getCourseConfigApiUrl } from '../data/api'; import { fetchCourseConfig } from '../data/thunks'; -import { coursesApiUrl, userProfileApiUrl } from './data/api'; +import { getCoursesApiUrl, getUserProfileApiUrl } from './data/api'; import { fetchLearners } from './data/thunks'; import LearnersView from './LearnersView'; @@ -23,6 +23,9 @@ import './data/__factories__'; let store; let axiosMock; +const coursesApiUrl = getCoursesApiUrl(); +const courseConfigApiUrl = getCourseConfigApiUrl(); +const userProfileApiUrl = getUserProfileApiUrl(); const courseId = 'course-v1:edX+TestX+Test_Course'; function renderComponent() { diff --git a/src/discussions/learners/data/api.js b/src/discussions/learners/data/api.js index b34f17ed..c1f38a86 100644 --- a/src/discussions/learners/data/api.js +++ b/src/discussions/learners/data/api.js @@ -8,10 +8,8 @@ ensureConfig([ 'LMS_BASE_URL', ], 'Posts API service'); -const apiBaseUrl = getConfig().LMS_BASE_URL; - -export const coursesApiUrl = `${apiBaseUrl}/api/discussion/v1/courses/`; -export const userProfileApiUrl = `${apiBaseUrl}/api/user/v1/accounts`; +export const getCoursesApiUrl = () => `${getConfig().LMS_BASE_URL}/api/discussion/v1/courses/`; +export const getUserProfileApiUrl = () => `${getConfig().LMS_BASE_URL}/api/user/v1/accounts`; /** * Fetches all the learners in the given course. @@ -20,7 +18,7 @@ export const userProfileApiUrl = `${apiBaseUrl}/api/user/v1/accounts`; * @returns {Promise<{}>} */ export async function getLearners(courseId, params) { - const url = `${coursesApiUrl}${courseId}/activity_stats/`; + const url = `${getCoursesApiUrl()}${courseId}/activity_stats/`; const { data } = await getAuthenticatedHttpClient().get(url, { params }); return data; } @@ -30,7 +28,7 @@ export async function getLearners(courseId, params) { * @param {string} usernames */ export async function getUserProfiles(usernames) { - const url = `${userProfileApiUrl}?username=${usernames.join()}`; + const url = `${getUserProfileApiUrl()}?username=${usernames.join()}`; const { data } = await getAuthenticatedHttpClient().get(url); return data; } @@ -67,7 +65,7 @@ export async function getUserPosts(courseId, { countFlagged, cohort, } = {}) { - const learnerPostsApiUrl = `${coursesApiUrl}${courseId}/learner/`; + const learnerPostsApiUrl = `${getCoursesApiUrl()}${courseId}/learner/`; const params = snakeCaseObject({ page, diff --git a/src/discussions/navigation/breadcrumb-menu/BreadcrumbMenu.test.jsx b/src/discussions/navigation/breadcrumb-menu/BreadcrumbMenu.test.jsx index b02b1519..31eafaa4 100644 --- a/src/discussions/navigation/breadcrumb-menu/BreadcrumbMenu.test.jsx +++ b/src/discussions/navigation/breadcrumb-menu/BreadcrumbMenu.test.jsx @@ -13,8 +13,8 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import { AppProvider } from '@edx/frontend-platform/react'; import { getBlocksAPIResponse } from '../../../data/__factories__'; -import { blocksAPIURL } from '../../../data/api'; -import { API_BASE_URL, Routes } from '../../../data/constants'; +import { getBlocksAPIURL } from '../../../data/api'; +import { getApiBaseUrl, Routes } from '../../../data/constants'; import { fetchCourseBlocks } from '../../../data/thunks'; import { initializeStore } from '../../../store'; import { executeThunk } from '../../../test-utils'; @@ -25,7 +25,7 @@ import { BreadcrumbMenu } from '../index'; import '../../topics/data/__factories__'; const courseId = 'course-v1:edX+DemoX+Demo_Course'; -const topicsApiUrl = `${API_BASE_URL}/api/discussion/v2/course_topics/${courseId}`; +const topicsApiUrl = `${getApiBaseUrl()}/api/discussion/v2/course_topics/${courseId}`; let store; let axiosMock; @@ -78,7 +78,7 @@ describe('BreadcrumbMenu', () => { Factory.resetAll(); axiosMock = new MockAdapter(getAuthenticatedHttpClient()); blocksAPIResponse = getBlocksAPIResponse(); - axiosMock.onGet(blocksAPIURL) + axiosMock.onGet(getBlocksAPIURL()) .reply(200, blocksAPIResponse); await executeThunk(fetchCourseBlocks(courseId, 'test-user'), store.dispatch, store.getState); const data = [ diff --git a/src/discussions/navigation/breadcrumb-menu/LegacyBreadcrumbMenu.test.jsx b/src/discussions/navigation/breadcrumb-menu/LegacyBreadcrumbMenu.test.jsx index 841cc567..1e9e9e08 100644 --- a/src/discussions/navigation/breadcrumb-menu/LegacyBreadcrumbMenu.test.jsx +++ b/src/discussions/navigation/breadcrumb-menu/LegacyBreadcrumbMenu.test.jsx @@ -12,7 +12,7 @@ import { initializeMockApp } from '@edx/frontend-platform'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import { AppProvider } from '@edx/frontend-platform/react'; -import { API_BASE_URL, Routes } from '../../../data/constants'; +import { getApiBaseUrl, Routes } from '../../../data/constants'; import { initializeStore } from '../../../store'; import { executeThunk } from '../../../test-utils'; import { fetchCourseTopics } from '../../topics/data/thunks'; @@ -21,7 +21,7 @@ import { LegacyBreadcrumbMenu } from '../index'; import '../../topics/data/__factories__'; const courseId = 'course-v1:edX+TestX+Test_Course'; -const topicsApiUrl = `${API_BASE_URL}/api/discussion/v1/course_topics/${courseId}`; +const topicsApiUrl = `${getApiBaseUrl()}/api/discussion/v1/course_topics/${courseId}`; let store; let axiosMock; diff --git a/src/discussions/posts/PostsView.test.jsx b/src/discussions/posts/PostsView.test.jsx index e2f8b6a6..ca954a33 100644 --- a/src/discussions/posts/PostsView.test.jsx +++ b/src/discussions/posts/PostsView.test.jsx @@ -18,14 +18,16 @@ import { initializeStore } from '../../store'; import { getCohortsApiUrl } from '../cohorts/data/api'; import { DiscussionContext } from '../common/context'; import { fetchConfigSuccess } from '../data/slices'; -import { coursesApiUrl } from '../learners/data/api'; -import { threadsApiUrl } from './data/api'; +import { getCoursesApiUrl } from '../learners/data/api'; +import { getThreadsApiUrl } from './data/api'; import { PostsView } from './index'; import './data/__factories__'; import '../cohorts/data/__factories__'; const courseId = 'course-v1:edX+TestX+Test_Course'; +const coursesApiUrl = getCoursesApiUrl(); +const threadsApiUrl = getThreadsApiUrl(); let store; let axiosMock; const username = 'abc123'; diff --git a/src/discussions/posts/data/api.js b/src/discussions/posts/data/api.js index 04f2b326..a465415f 100644 --- a/src/discussions/posts/data/api.js +++ b/src/discussions/posts/data/api.js @@ -8,10 +8,8 @@ ensureConfig([ 'LMS_BASE_URL', ], 'Posts API service'); -const apiBaseUrl = getConfig().LMS_BASE_URL; - -export const threadsApiUrl = `${apiBaseUrl}/api/discussion/v1/threads/`; -export const coursesApiUrl = `${apiBaseUrl}/api/discussion/v1/courses/`; +export const getThreadsApiUrl = () => `${getConfig().LMS_BASE_URL}/api/discussion/v1/threads/`; +export const getCoursesApiUrl = () => `${getConfig().LMS_BASE_URL}/api/discussion/v1/courses/`; /** * Fetches all the threads in the given course and topic. @@ -62,7 +60,7 @@ export async function getThreads( countFlagged, groupId: cohort, }); - const { data } = await getAuthenticatedHttpClient().get(threadsApiUrl, { params }); + const { data } = await getAuthenticatedHttpClient().get(getThreadsApiUrl(), { params }); return data; } @@ -73,7 +71,7 @@ export async function getThreads( */ export async function getThread(threadId, courseId) { const params = { requested_fields: 'profile_image', course_id: courseId }; - const url = `${threadsApiUrl}${threadId}/`; + const url = `${getThreadsApiUrl()}${threadId}/`; const { data } = await getAuthenticatedHttpClient().get(url, { params }); return data; } @@ -117,7 +115,7 @@ export async function postThread( }); const { data } = await getAuthenticatedHttpClient() - .post(threadsApiUrl, postData); + .post(getThreadsApiUrl(), postData); return data; } @@ -152,7 +150,7 @@ export async function updateThread(threadId, { editReasonCode, closeReasonCode, } = {}) { - const url = `${threadsApiUrl}${threadId}/`; + const url = `${getThreadsApiUrl()}${threadId}/`; const patchData = snakeCaseObject({ topicId, abuse_flagged: flagged, @@ -177,7 +175,7 @@ export async function updateThread(threadId, { * @param {string} threadId */ export async function deleteThread(threadId) { - const url = `${threadsApiUrl}${threadId}/`; + const url = `${getThreadsApiUrl()}${threadId}/`; await getAuthenticatedHttpClient() .delete(url); } @@ -191,7 +189,7 @@ export async function deleteThread(threadId) { * @returns {Promise<{ location: string }>} */ export async function uploadFile(blob, filename, courseId, threadKey) { - const uploadUrl = `${coursesApiUrl}${courseId}/upload`; + const uploadUrl = `${getCoursesApiUrl()}${courseId}/upload`; const formData = new FormData(); formData.append('thread_key', threadKey); formData.append('uploaded_file', blob, filename); diff --git a/src/discussions/posts/data/api.test.js b/src/discussions/posts/data/api.test.js index adc89bbd..ea31b31b 100644 --- a/src/discussions/posts/data/api.test.js +++ b/src/discussions/posts/data/api.test.js @@ -3,9 +3,10 @@ import MockAdapter from 'axios-mock-adapter'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import { initializeMockApp } from '@edx/frontend-platform/testing'; -import { coursesApiUrl, uploadFile } from './api'; +import { getCoursesApiUrl, uploadFile } from './api'; const courseId = 'course-v1:edX+TestX+Test_Course'; +const coursesApiUrl = getCoursesApiUrl(); let axiosMock = null; diff --git a/src/discussions/posts/data/redux.test.js b/src/discussions/posts/data/redux.test.js index 2a3b14fb..b4508e2e 100644 --- a/src/discussions/posts/data/redux.test.js +++ b/src/discussions/posts/data/redux.test.js @@ -6,7 +6,7 @@ import { initializeMockApp } from '@edx/frontend-platform/testing'; import { initializeStore } from '../../../store'; import { executeThunk } from '../../../test-utils'; -import { threadsApiUrl } from './api'; +import { getThreadsApiUrl } from './api'; import { createNewThread, fetchThread, fetchThreads, removeThread, updateExistingThread, } from './thunks'; @@ -14,6 +14,7 @@ import { import './__factories__'; const courseId = 'course-v1:edX+TestX+Test_Course'; +const threadsApiUrl = getThreadsApiUrl(); let axiosMock; let store; diff --git a/src/discussions/posts/post-editor/PostEditor.test.jsx b/src/discussions/posts/post-editor/PostEditor.test.jsx index 7522c9f9..8f2f82c2 100644 --- a/src/discussions/posts/post-editor/PostEditor.test.jsx +++ b/src/discussions/posts/post-editor/PostEditor.test.jsx @@ -12,13 +12,13 @@ import { initializeMockApp } from '@edx/frontend-platform'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import { AppProvider } from '@edx/frontend-platform/react'; -import { API_BASE_URL, Routes } from '../../../data/constants'; +import { getApiBaseUrl, Routes } from '../../../data/constants'; import { initializeStore } from '../../../store'; import { executeThunk } from '../../../test-utils'; import { getCohortsApiUrl } from '../../cohorts/data/api'; import { DiscussionContext } from '../../common/context'; import { fetchCourseTopics } from '../../topics/data/thunks'; -import { threadsApiUrl } from '../data/api'; +import { getThreadsApiUrl } from '../data/api'; import { fetchThread } from '../data/thunks'; import { PostEditor } from '../index'; @@ -28,7 +28,8 @@ import '../../topics/data/__factories__'; import '../data/__factories__'; const courseId = 'course-v1:edX+DemoX+Demo_Course'; -const topicsApiUrl = `${API_BASE_URL}/api/discussion/v1/course_topics/${courseId}`; +const topicsApiUrl = `${getApiBaseUrl()}/api/discussion/v1/course_topics/${courseId}`; +const threadsApiUrl = getThreadsApiUrl(); let store; let axiosMock; diff --git a/src/discussions/posts/post/PostLink.test.jsx b/src/discussions/posts/post/PostLink.test.jsx index 1060295e..03bbbda2 100644 --- a/src/discussions/posts/post/PostLink.test.jsx +++ b/src/discussions/posts/post/PostLink.test.jsx @@ -11,11 +11,12 @@ import { AppProvider } from '@edx/frontend-platform/react'; import { initializeStore } from '../../../store'; import { executeThunk } from '../../../test-utils'; import { DiscussionContext } from '../../common/context'; -import { courseConfigApiUrl } from '../../data/api'; +import { getCourseConfigApiUrl } from '../../data/api'; import { fetchCourseConfig } from '../../data/thunks'; import PostLink from './PostLink'; const courseId = 'course-v1:edX+DemoX+Demo_Course'; +const courseConfigApiUrl = getCourseConfigApiUrl(); let store; let axiosMock; diff --git a/src/discussions/topics/TopicsView.test.jsx b/src/discussions/topics/TopicsView.test.jsx index 430d795d..4874a03a 100644 --- a/src/discussions/topics/TopicsView.test.jsx +++ b/src/discussions/topics/TopicsView.test.jsx @@ -11,8 +11,8 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import { AppProvider } from '@edx/frontend-platform/react'; import { getBlocksAPIResponse } from '../../data/__factories__'; -import { blocksAPIURL } from '../../data/api'; -import { API_BASE_URL, DiscussionProvider } from '../../data/constants'; +import { getBlocksAPIURL } from '../../data/api'; +import { DiscussionProvider, getApiBaseUrl } from '../../data/constants'; import { selectSequences } from '../../data/selectors'; import { fetchCourseBlocks } from '../../data/thunks'; import { initializeStore } from '../../store'; @@ -26,8 +26,8 @@ import './data/__factories__'; const courseId = 'course-v1:edX+DemoX+Demo_Course'; -const topicsApiUrl = `${API_BASE_URL}/api/discussion/v1/course_topics/${courseId}`; -const topicsv2ApiUrl = `${API_BASE_URL}/api/discussion/v2/course_topics/${courseId}`; +const topicsApiUrl = `${getApiBaseUrl()}/api/discussion/v1/course_topics/${courseId}`; +const topicsv2ApiUrl = `${getApiBaseUrl()}/api/discussion/v2/course_topics/${courseId}`; let store; let axiosMock; let lastLocation; @@ -113,7 +113,7 @@ describe('TopicsView', () => { axiosMock .onGet(topicsv2ApiUrl) .reply(200, data); - axiosMock.onGet(blocksAPIURL) + axiosMock.onGet(getBlocksAPIURL()) .reply(200, getBlocksAPIResponse(true)); axiosMock.onAny().networkError(); await executeThunk(fetchCourseBlocks(courseId, 'abc123'), store.dispatch, store.getState); diff --git a/src/discussions/topics/data/api.js b/src/discussions/topics/data/api.js index bb0c0432..ec0fecbf 100644 --- a/src/discussions/topics/data/api.js +++ b/src/discussions/topics/data/api.js @@ -1,10 +1,10 @@ /* eslint-disable import/prefer-default-export */ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; -import { API_BASE_URL } from '../../../data/constants'; +import { getApiBaseUrl } from '../../../data/constants'; export async function getCourseTopics(courseId, topicIds) { - const url = `${API_BASE_URL}/api/discussion/v1/course_topics/${courseId}`; + const url = `${getApiBaseUrl()}/api/discussion/v1/course_topics/${courseId}`; const params = {}; if (topicIds) { params.topic_id = topicIds.join(','); @@ -15,7 +15,7 @@ export async function getCourseTopics(courseId, topicIds) { } export async function getCourseTopicsV2(courseId, topicIds) { - const url = `${API_BASE_URL}/api/discussion/v2/course_topics/${courseId}`; + const url = `${getApiBaseUrl()}/api/discussion/v2/course_topics/${courseId}`; const params = {}; if (topicIds) { params.topic_id = topicIds.join(',');