fix: library editor not working locally (#448)

Internal issue: https://2u-internal.atlassian.net/browse/TNL-11299

In library-authoring, content blocks could not be edited locally due to some problem with the Accept header. This caused some 404s. Visually you would get an infinite loading spinner.

This depends on openedx/frontend-app-library-authoring#399.
This commit is contained in:
Jesper Hodge
2024-01-04 14:36:07 -05:00
committed by GitHub
parent 70581c54ab
commit 8833f7bfca
2 changed files with 75 additions and 13 deletions

View File

@@ -5,12 +5,23 @@ import * as module from './api';
import * as mockApi from './mockApi';
import { durationStringFromValue } from '../../../containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks';
const fetchByUnitIdOptions = {};
// For some reason, the local webpack-dev-server of library-authoring does not accept the normal Accept header.
// This is a workaround only for that specific case; the idea is to only do this locally and only for library-authoring.
if (process.env.NODE_ENV === 'development' && process.env.MFE_NAME === 'frontend-app-library-authoring') {
fetchByUnitIdOptions.headers = {
Accept: '*/*',
};
}
export const apiMethods = {
fetchBlockById: ({ blockId, studioEndpointUrl }) => get(
urls.block({ blockId, studioEndpointUrl }),
),
fetchByUnitId: ({ blockId, studioEndpointUrl }) => get(
urls.blockAncestor({ studioEndpointUrl, blockId }),
fetchByUnitIdOptions,
),
fetchStudioView: ({ blockId, studioEndpointUrl }) => get(
urls.blockStudioView({ studioEndpointUrl, blockId }),

View File

@@ -15,18 +15,18 @@ jest.mock('../../../utils', () => {
});
jest.mock('./urls', () => ({
block: jest.fn().mockName('urls.block'),
blockAncestor: jest.fn().mockName('urls.blockAncestor'),
blockStudioView: jest.fn().mockName('urls.StudioView'),
courseAssets: jest.fn().mockName('urls.courseAssets'),
videoTranscripts: jest.fn().mockName('urls.videoTranscripts'),
allowThumbnailUpload: jest.fn().mockName('urls.allowThumbnailUpload'),
thumbnailUpload: jest.fn().mockName('urls.thumbnailUpload'),
checkTranscriptsForImport: jest.fn().mockName('urls.checkTranscriptsForImport'),
courseDetailsUrl: jest.fn().mockName('urls.courseDetailsUrl'),
courseAdvanceSettings: jest.fn().mockName('urls.courseAdvanceSettings'),
replaceTranscript: jest.fn().mockName('urls.replaceTranscript'),
videoFeatures: jest.fn().mockName('urls.videoFeatures'),
block: jest.fn().mockReturnValue('urls.block'),
blockAncestor: jest.fn().mockReturnValue('urls.blockAncestor'),
blockStudioView: jest.fn().mockReturnValue('urls.StudioView'),
courseAssets: jest.fn().mockReturnValue('urls.courseAssets'),
videoTranscripts: jest.fn().mockReturnValue('urls.videoTranscripts'),
allowThumbnailUpload: jest.fn().mockReturnValue('urls.allowThumbnailUpload'),
thumbnailUpload: jest.fn().mockReturnValue('urls.thumbnailUpload'),
checkTranscriptsForImport: jest.fn().mockReturnValue('urls.checkTranscriptsForImport'),
courseDetailsUrl: jest.fn().mockReturnValue('urls.courseDetailsUrl'),
courseAdvanceSettings: jest.fn().mockReturnValue('urls.courseAdvanceSettings'),
replaceTranscript: jest.fn().mockReturnValue('urls.replaceTranscript'),
videoFeatures: jest.fn().mockReturnValue('urls.videoFeatures'),
courseVideos: jest.fn()
.mockName('urls.courseVideos')
.mockImplementation(
@@ -64,7 +64,58 @@ describe('cms api', () => {
describe('fetchByUnitId', () => {
it('should call get with url.blockAncestor', () => {
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
expect(get).toHaveBeenCalledWith(urls.blockAncestor({ studioEndpointUrl, blockId }));
expect(get).toHaveBeenCalledWith(urls.blockAncestor({ studioEndpointUrl, blockId }), {});
});
describe('when called in different contexts', () => {
// To mock env variables, you need to use dynamic imports for the tested methods
// and then reset the env variables afterwards.
const OLD_ENV = process.env;
beforeEach(() => {
jest.resetModules();
process.env = { ...OLD_ENV };
});
afterEach(() => {
process.env = OLD_ENV;
});
it('should call get with normal accept header for prod', async () => {
process.env.NODE_ENV = 'production';
process.env.MFE_NAME = 'frontend-app-library-authoring';
// eslint-disable-next-line no-shadow
const { apiMethods } = await import('./api');
// eslint-disable-next-line no-shadow
const utils = await import('./utils');
const getSpy = jest.spyOn(utils, 'get');
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
expect(getSpy).toHaveBeenCalledWith(urls.blockAncestor({ studioEndpointUrl, blockId }), {});
});
it('should call get with normal accept header for course-authoring', async () => {
process.env.NODE_ENV = 'development';
process.env.MFE_NAME = 'frontend-app-course-authoring';
// eslint-disable-next-line no-shadow
const { apiMethods } = await import('./api');
// eslint-disable-next-line no-shadow
const utils = await import('./utils');
const getSpy = jest.spyOn(utils, 'get');
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
expect(getSpy).toHaveBeenCalledWith(urls.blockAncestor({ studioEndpointUrl, blockId }), {});
});
it('should call get with special accept header "*/*" for course-authoring', async () => {
process.env.NODE_ENV = 'development';
process.env.MFE_NAME = 'frontend-app-library-authoring';
// eslint-disable-next-line no-shadow
const { apiMethods } = await import('./api');
// eslint-disable-next-line no-shadow
const utils = await import('./utils');
const getSpy = jest.spyOn(utils, 'get');
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
expect(getSpy).toHaveBeenCalledWith(urls.blockAncestor({ studioEndpointUrl, blockId }), { headers: { Accept: '*/*' } });
});
});
});