test: replacing snapshot tests with RTL tests part 14 (#2236)

This commit is contained in:
jacobo-dominguez-wgu
2025-07-08 10:37:07 -06:00
committed by GitHub
parent 2fe24f39ac
commit 3673c5f561
11 changed files with 201 additions and 500 deletions

View File

@@ -1,34 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`QuestionWidget render snapshot: renders correct default 1`] = `
<div
className="tinyMceWidget"
>
<div
className="h4 mb-3"
>
<FormattedMessage
defaultMessage="Question"
description="Question Title"
id="authoring.questionwidget.question.questionWidgetTitle"
/>
</div>
<TinyMceWidget
disabled={false}
editorContentHtml="This is my question"
editorRef={null}
editorType="question"
enableImageUpload={true}
id="question"
images={{}}
isLibrary={false}
learningContextId="course+org+run"
lmsEndpointUrl=""
minHeight={150}
onChange={[Function]}
placeholder="Enter your question"
setEditorRef={[MockFunction prepareEditorRef.setEditorRef]}
studioEndpointUrl=""
/>
</div>
`;

View File

@@ -1,76 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { formatMessage } from '../../../../../testUtils';
import { selectors } from '../../../../../data/redux';
import { QuestionWidgetInternal as QuestionWidget, mapStateToProps } from '.';
jest.mock('../../../../../data/redux', () => ({
__esModule: true,
default: jest.fn(),
actions: {
problem: {
updateQuestion: jest.fn().mockName('actions.problem.updateQuestion'),
},
},
selectors: {
app: {
learningContextId: jest.fn(state => ({ learningContextId: state })),
images: jest.fn(state => ({ images: state })),
isLibrary: jest.fn(state => ({ isLibrary: state })),
blockId: jest.fn(state => ({ blockId: state })),
},
problem: {
question: jest.fn(state => ({ question: state })),
},
},
thunkActions: {
video: {
importTranscript: jest.fn(),
},
},
}));
jest.mock('../../../../../sharedComponents/TinyMceWidget/hooks', () => ({
...jest.requireActual('../../../../../sharedComponents/TinyMceWidget/hooks'),
prepareEditorRef: jest.fn(() => ({
refReady: true,
setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'),
})),
}));
describe('QuestionWidget', () => {
const props = {
question: 'This is my question',
updateQuestion: jest.fn(),
learningContextId: 'course+org+run',
images: {},
isLibrary: false,
// injected
intl: { formatMessage },
};
describe('render', () => {
test('snapshot: renders correct default', () => {
expect(shallow(<QuestionWidget {...props} />).snapshot).toMatchSnapshot();
});
});
describe('mapStateToProps', () => {
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
test('question from problem.question', () => {
expect(mapStateToProps(testState).question).toEqual(selectors.problem.question(testState));
});
test('learningContextId from app.learningContextId', () => {
expect(mapStateToProps(testState).learningContextId).toEqual(selectors.app.learningContextId(testState));
});
test('images from app.images', () => {
expect(
mapStateToProps(testState).images,
).toEqual(selectors.app.images(testState));
});
test('isLibrary from app.isLibrary', () => {
expect(
mapStateToProps(testState).isLibrary,
).toEqual(selectors.app.isLibrary(testState));
});
});
});

View File

@@ -0,0 +1,62 @@
import React from 'react';
import { render, screen, initializeMocks } from '@src/testUtils';
import { formatMessage } from '@src/editors/testUtils';
import { QuestionWidgetInternal as QuestionWidget } from '.';
jest.mock('@src/editors/data/redux', () => ({
__esModule: true,
default: jest.fn(),
actions: {
problem: {
updateQuestion: jest.fn().mockName('actions.problem.updateQuestion'),
},
},
selectors: {
app: {
learningContextId: jest.fn(state => ({ learningContextId: state })),
images: jest.fn(state => ({ images: state })),
isLibrary: jest.fn(state => ({ isLibrary: state })),
blockId: jest.fn(state => ({ blockId: state })),
},
problem: {
question: jest.fn(state => ({ question: state })),
},
},
thunkActions: {
video: {
importTranscript: jest.fn(),
},
},
}));
jest.mock('@src/editors/sharedComponents/TinyMceWidget/hooks', () => ({
...jest.requireActual('../../../../../sharedComponents/TinyMceWidget/hooks'),
prepareEditorRef: jest.fn(() => ({
refReady: true,
setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'),
})),
}));
jest.mock('@src/editors/sharedComponents/TinyMceWidget', () => ('TinyMceWidget'));
describe('QuestionWidget', () => {
const props = {
question: 'This is my question',
updateQuestion: jest.fn(),
learningContextId: 'course+org+run',
images: {},
isLibrary: false,
blockId: '',
// injected
intl: { formatMessage },
};
describe('render', () => {
beforeEach(() => {
initializeMocks();
});
test('renders correct default', () => {
render(<QuestionWidget {...props} />);
expect(screen.getByText('Question')).toBeInTheDocument();
});
});
});

View File

@@ -1,26 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`VideoEditor snapshots renders as expected with default behavior 1`] = `
<ErrorContext.Provider
value="hooks.errorsHook.error"
>
<EditorContainer
isDirty={[Function]}
onClose={[MockFunction props.onClose]}
validateEntry={[MockFunction validateEntry]}
>
<div
className="video-editor"
>
<VideoEditorModal
isLibrary={
{
"useSelector": [MockFunction],
}
}
onClose={[MockFunction props.onClose]}
/>
</div>
</EditorContainer>
</ErrorContext.Provider>
`;

View File

@@ -1,49 +1,85 @@
import 'CourseAuthoring/editors/setupEditorTest';
import { shallow } from '@edx/react-unit-test-utils';
import { formatMessage } from '../../testUtils';
import { render, initializeMocks } from '@src/testUtils';
import VideoEditor from '.';
import * as hooks from './hooks';
const reduxSelectors = require('../../data/redux').selectors;
jest.mock('../EditorContainer', () => 'EditorContainer');
jest.mock('./components/VideoEditorModal', () => 'VideoEditorModal');
jest.mock('./hooks', () => ({
ErrorContext: {
Provider: 'ErrorContext.Provider',
},
errorsHook: jest.fn(() => ({
error: 'hooks.errorsHook.error',
validateEntry: jest.fn().mockName('validateEntry'),
})),
fetchVideoContent: jest.fn().mockName('fetchVideoContent'),
}));
jest.mock('../../data/redux', () => ({
selectors: {
requests: {
isFinished: jest.fn((state, params) => ({ isFailed: { state, params } })),
},
app: {
isLibrary: jest.fn(state => ({ isLibrary: state })),
},
},
}));
jest.mock('@openedx/paragon', () => ({
...jest.requireActual('@openedx/paragon'),
Spinner: 'Spinner',
}));
describe('VideoEditor', () => {
const props = {
onClose: jest.fn().mockName('props.onClose'),
intl: { formatMessage },
studioViewFinished: false,
isLibrary: false,
returnFunction: jest.fn().mockName('props.returnFunction'),
};
describe('snapshots', () => {
test('renders as expected with default behavior', () => {
expect(shallow(<VideoEditor {...props} />).snapshot).toMatchSnapshot();
describe('conditional rendering', () => {
let isFinishedSpy: jest.SpyInstance;
let isLibrarySpy: jest.SpyInstance;
let shouldCreateBlockSpy: jest.SpyInstance;
let errorsHookSpy: jest.SpyInstance;
let fetchVideoContentSpy: jest.SpyInstance;
beforeEach(() => {
isFinishedSpy = jest.spyOn(reduxSelectors.requests, 'isFinished');
isLibrarySpy = jest.spyOn(reduxSelectors.app, 'isLibrary');
shouldCreateBlockSpy = jest.spyOn(reduxSelectors.app, 'shouldCreateBlock');
errorsHookSpy = jest.spyOn(hooks, 'errorsHook');
fetchVideoContentSpy = jest.spyOn(hooks, 'fetchVideoContent');
errorsHookSpy.mockReturnValue({ error: null, validateEntry: jest.fn() });
fetchVideoContentSpy.mockReturnValue(jest.fn());
isLibrarySpy.mockReturnValue(false);
initializeMocks();
});
afterEach(() => {
jest.clearAllMocks();
});
test('shows spinner when neither create workflow nor studio view finished', () => {
isFinishedSpy.mockReturnValue(false);
shouldCreateBlockSpy.mockReturnValue(false);
const { container } = render(<VideoEditor {...props} />);
expect(container.querySelector('.pgn__spinner')).toBeInTheDocument();
expect(container.querySelector('EditorContainer')).toBeInTheDocument();
expect(container.querySelector('VideoEditorModal')).not.toBeInTheDocument();
});
test('shows VideoEditorModal when isCreateWorkflow is true', () => {
isFinishedSpy.mockReturnValue(false);
shouldCreateBlockSpy.mockReturnValue(true);
const { container } = render(<VideoEditor {...props} />);
expect(container.querySelector('.pgn__spinner')).not.toBeInTheDocument();
expect(container.querySelector('EditorContainer')).toBeInTheDocument();
expect(container.querySelector('VideoEditorModal')).toBeInTheDocument();
});
test('shows VideoEditorModal when studioViewFinished is true', () => {
isFinishedSpy.mockReturnValue(true);
shouldCreateBlockSpy.mockReturnValue(false);
const { container } = render(<VideoEditor {...props} />);
expect(container.querySelector('.pgn__spinner')).not.toBeInTheDocument();
expect(container.querySelector('EditorContainer')).toBeInTheDocument();
expect(container.querySelector('VideoEditorModal')).toBeInTheDocument();
});
test('passes isLibrary, onClose, and returnFunction to VideoEditorModal', () => {
isFinishedSpy.mockReturnValue(true);
shouldCreateBlockSpy.mockReturnValue(false);
isLibrarySpy.mockReturnValue(true);
const { container } = render(<VideoEditor {...props} />);
expect(container.querySelector('.video-editor')).toBeInTheDocument();
});
test('calls fetchVideoContent and passes validateEntry to EditorContainer', () => {
isFinishedSpy.mockReturnValue(true);
shouldCreateBlockSpy.mockReturnValue(false);
render(<VideoEditor {...props} />);
expect(fetchVideoContentSpy).toHaveBeenCalled();
expect(errorsHookSpy).toHaveBeenCalled();
});
});
});

View File

@@ -1,96 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SelectImageModal component snapshot 1`] = `
<SelectionModal
acceptedFiles={
{
"gif": ".gif",
"ico": ".ico",
"jpeg": ".jpeg",
"jpg": ".jpg",
"png": ".png",
"svg": ".svg",
"tif": ".tif",
"tiff": ".tiff",
"webp": ".webp",
}
}
close={[MockFunction props.close]}
fileInput={
{
"addFile": "imgHooks.fileInput.addFile",
"click": "imgHooks.fileInput.click",
"ref": "imgHooks.fileInput.ref",
}
}
galleryError={
{
"dismiss": [MockFunction],
"message": {
"defaultMessage": "Gallery error",
"description": "Gallery error",
"id": "Gallery error id",
},
"set": [MockFunction],
"show": "ShoWERror gAlLery",
}
}
galleryProps={
{
"gallery": "props",
}
}
inputError={
{
"dismiss": [MockFunction],
"message": {
"defaultMessage": "Input error",
"description": "Input error",
"id": "Input error id",
},
"set": [MockFunction],
"show": "ShoWERror inPUT",
}
}
isOpen={true}
modalMessages={
{
"confirmMsg": {
"defaultMessage": "Next",
"description": "Label for Next button",
"id": "authoring.texteditor.selectimagemodal.next.label",
},
"fetchError": {
"defaultMessage": "Failed to obtain images. Please try again.",
"description": "Message presented to user when images are not found",
"id": "authoring.texteditor.selectimagemodal.error.fetchImagesError",
},
"titleMsg": {
"defaultMessage": "Add an image",
"description": "Title for the select image modal",
"id": "authoring.texteditor.selectimagemodal.title.label",
},
"uploadButtonMsg": {
"defaultMessage": "Upload a new image (10 MB max)",
"description": "Label for upload button",
"id": "authoring.texteditor.selectimagemodal.upload.label",
},
"uploadError": {
"defaultMessage": "Failed to upload image. Please try again.",
"description": "Message presented to user when image fails to upload",
"id": "authoring.texteditor.selectimagemodal.error.uploadImageError",
},
}
}
searchSortProps={
{
"search": "sortProps",
}
}
selectBtnProps={
{
"select": "btnProps",
}
}
/>
`;

View File

@@ -1,28 +1,8 @@
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { formatMessage } from '../../../testUtils';
import SelectionModal from '../../SelectionModal';
import * as hooks from './hooks';
import { render, initializeMocks } from '@src/testUtils';
import { formatMessage } from '@src/editors/testUtils';
import { SelectImageModalInternal as SelectImageModal } from '.';
const mockImage = {
displayName: 'DALL·E 2023-03-10.png',
contentType: 'image/png',
dateAdded: 1682009100000,
url: '/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png',
externalUrl: 'http://localhost:18000/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png',
portableUrl: '/static/DALL_E_2023-03-10.png',
thumbnail: '/asset-v1:TestX+Test01+Test0101+type@thumbnail+block@DALL_E_2023-03-10.jpg',
locked: false,
staticFullUrl: '/assets/courseware/v1/af2bf9ac70804e54c534107160a8e51e/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png',
id: 'asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png',
width: 100,
height: 150,
};
const mockImagesRef = { current: [mockImage] };
jest.mock('../../BaseModal', () => 'BaseModal');
jest.mock('../../FileInput', () => 'FileInput');
jest.mock('../../SelectionModal/Gallery', () => 'Gallery');
@@ -80,35 +60,35 @@ describe('SelectImageModal', () => {
close: jest.fn().mockName('props.close'),
setSelection: jest.fn().mockName('props.setSelection'),
clearSelection: jest.fn().mockName('props.clearSelection'),
images: mockImagesRef,
isLoaded: true,
isFetchError: false,
isUploadError: false,
imageCount: 1,
images: ['image.pgn'],
intl: { formatMessage },
};
let el;
const imgHooks = hooks.imgHooks();
beforeEach(() => {
el = shallow(<SelectImageModal {...props} />);
initializeMocks();
});
test('snapshot', () => {
expect(el.snapshot).toMatchSnapshot();
test('renders correctly', () => {
const { container } = render(<SelectImageModal {...props} />);
expect(container.querySelector('SelectionModal')).toBeInTheDocument();
});
it('provides confirm action, forwarding selectBtnProps from imgHooks', () => {
expect(el.instance.findByType(SelectionModal)[0].props.selectBtnProps).toEqual(
expect.objectContaining({ ...hooks.imgHooks().selectBtnProps }),
);
const { container } = render(<SelectImageModal {...props} />);
expect(container.querySelector('SelectionModal')?.getAttribute('selectBtnProps')).toBeTruthy();
});
it('provides file upload button linked to fileInput.click', () => {
expect(el.instance.findByType(SelectionModal)[0].props.fileInput.click).toEqual(
imgHooks.fileInput.click,
);
const { container } = render(<SelectImageModal {...props} />);
expect(container.querySelector('SelectionModal')?.getAttribute('fileInput')).toBeTruthy();
});
it('provides a SearchSort component with searchSortProps from imgHooks', () => {
expect(el.instance.findByType(SelectionModal)[0].props.searchSortProps).toEqual(imgHooks.searchSortProps);
const { container } = render(<SelectImageModal {...props} />);
expect(container.querySelector('SelectionModal')?.getAttribute('searchSortProps')).toBeTruthy();
});
it('provides a Gallery component with galleryProps from imgHooks', () => {
expect(el.instance.findByType(SelectionModal)[0].props.galleryProps).toEqual(imgHooks.galleryProps);
});
it('provides a FileInput component with fileInput props from imgHooks', () => {
expect(el.instance.findByType(SelectionModal)[0].props.fileInput).toMatchObject(imgHooks.fileInput);
const { container } = render(<SelectImageModal {...props} />);
expect(container.querySelector('SelectionModal')?.getAttribute('galleryProps')).toBeTruthy();
});
});
});

View File

@@ -1,92 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ImageUploadModal component snapshot: no selection (Select Image Modal) 1`] = `
<SelectImageModal
clearSelection={[MockFunction props.clearSelection]}
close={[MockFunction props.close]}
images={
{
"current": [
{
"contentType": "image/png",
"dateAdded": 1682009100000,
"displayName": "DALL·E 2023-03-10.png",
"externalUrl": "http://localhost:18000/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"height": 150,
"id": "asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"locked": false,
"portableUrl": "/static/DALL_E_2023-03-10.png",
"staticFullUrl": "/assets/courseware/v1/af2bf9ac70804e54c534107160a8e51e/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"thumbnail": "/asset-v1:TestX+Test01+Test0101+type@thumbnail+block@DALL_E_2023-03-10.jpg",
"url": "/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"width": 100,
},
],
}
}
isOpen={false}
setSelection={[MockFunction props.setSelection]}
/>
`;
exports[`ImageUploadModal component snapshot: selection has no externalUrl (Select Image Modal) 1`] = `
<SelectImageModal
clearSelection={[MockFunction props.clearSelection]}
close={[MockFunction props.close]}
images={
{
"current": [
{
"contentType": "image/png",
"dateAdded": 1682009100000,
"displayName": "DALL·E 2023-03-10.png",
"externalUrl": "http://localhost:18000/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"height": 150,
"id": "asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"locked": false,
"portableUrl": "/static/DALL_E_2023-03-10.png",
"staticFullUrl": "/assets/courseware/v1/af2bf9ac70804e54c534107160a8e51e/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"thumbnail": "/asset-v1:TestX+Test01+Test0101+type@thumbnail+block@DALL_E_2023-03-10.jpg",
"url": "/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"width": 100,
},
],
}
}
isOpen={false}
setSelection={[MockFunction props.setSelection]}
/>
`;
exports[`ImageUploadModal component snapshot: with selection content (ImageSettingsUpload) 1`] = `
<ImageSettingsModal
images={
{
"current": [
{
"contentType": "image/png",
"dateAdded": 1682009100000,
"displayName": "DALL·E 2023-03-10.png",
"externalUrl": "http://localhost:18000/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"height": 150,
"id": "asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"locked": false,
"portableUrl": "/static/DALL_E_2023-03-10.png",
"staticFullUrl": "/assets/courseware/v1/af2bf9ac70804e54c534107160a8e51e/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"thumbnail": "/asset-v1:TestX+Test01+Test0101+type@thumbnail+block@DALL_E_2023-03-10.jpg",
"url": "/asset-v1:TestX+Test01+Test0101+type@asset+block@DALL_E_2023-03-10.png",
"width": 100,
},
],
}
}
isOpen={false}
returnToSelection={[MockFunction props.clearSelection]}
selection={
{
"externalUrl": "sOmEuRl.cOm",
"some": "images",
}
}
/>
`;

View File

@@ -1,21 +1,19 @@
/* eslint-disable no-import-assign */
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { render, initializeMocks } from '@src/testUtils';
import { keyStore } from '../../utils';
import * as tinyMCEKeys from '../../data/constants/tinyMCE';
// This 'module' self-import hack enables mocking during tests.
// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
// should be re-thought and cleaned up to avoid this pattern.
// eslint-disable-next-line import/no-self-import
import * as module from '.';
import { ImageUploadModalInternal as ImageUploadModal, hooks, propsString } from '.';
import * as tinyMceHooks from '../TinyMceWidget/hooks';
jest.mock('./ImageSettingsModal', () => 'ImageSettingsModal');
jest.mock('./SelectImageModal', () => 'SelectImageModal');
const { ImageUploadModalInternal: ImageUploadModal } = module;
const hookKeys = keyStore(module.hooks);
const hookKeys = keyStore(hooks);
const settings = {
altText: 'aLt tExt',
@@ -59,12 +57,14 @@ describe('ImageUploadModal', () => {
height: settings.dimensions.height,
};
const testImgTag = (args) => {
const output = module.hooks.imgTag({
const output = hooks.imgTag({
settings: args.settings,
selection,
lmsEndpointUrl: 'sOmE',
editorType: 'tinyMCE',
isLibrary: true,
});
expect(output).toEqual(`<img ${module.propsString(args.expected)} />`);
expect(output).toEqual(`<img ${propsString(args.expected)} />`);
};
test('It returns a html string which matches an image tag', () => {
testImgTag({ settings, expected });
@@ -94,7 +94,7 @@ describe('ImageUploadModal', () => {
};
beforeEach(() => {
output = module.hooks.createSaveCallback({
output = hooks.createSaveCallback({
close, settings, images, editorRef, setSelection, selection, lmsEndpointUrl,
});
});
@@ -105,8 +105,13 @@ describe('ImageUploadModal', () => {
`It creates a callback, that when called, inserts to the editor, sets the selection to the current element,
adds new image to the images ref, and calls close`,
() => {
jest.spyOn(module.hooks, hookKeys.imgTag)
.mockImplementationOnce((props) => ({ selection, settings: props.settings, lmsEndpointUrl }));
const imgTagResult = '<img src="sOmEuRl.cOm" alt="aLt tExt" />';
jest.spyOn(hooks, hookKeys.imgTag)
.mockImplementationOnce((props) => {
if (!props) { return ''; }
// Return a string as the real imgTag would
return `<img src="${props.selection?.externalUrl ?? ''}" alt="${props.settings?.altText ?? ''}" />`;
});
expect(execCommandMock).not.toBeCalled();
expect(setSelection).not.toBeCalled();
@@ -118,7 +123,7 @@ describe('ImageUploadModal', () => {
expect(execCommandMock).toBeCalledWith(
tinyMCEKeys.commands.insertContent,
false,
{ selection, settings, lmsEndpointUrl },
imgTagResult,
);
expect(setSelection).toBeCalledWith(newImage);
expect(updateImageDimensionsSpy.mock.calls.length).toBe(1);
@@ -139,7 +144,7 @@ describe('ImageUploadModal', () => {
it('takes and calls clearSelection and close callbacks', () => {
const clearSelection = jest.fn();
const close = jest.fn();
module.hooks.onClose({ clearSelection, close })();
hooks.onClose({ clearSelection, close })();
expect(clearSelection).toHaveBeenCalled();
expect(close).toHaveBeenCalled();
});
@@ -147,38 +152,36 @@ describe('ImageUploadModal', () => {
});
describe('component', () => {
let props;
let hooks;
beforeAll(() => {
hooks = module.hooks;
props = {
editorRef: { current: null },
isOpen: false,
close: jest.fn().mockName('props.close'),
clearSelection: jest.fn().mockName('props.clearSelection'),
selection: { some: 'images', externalUrl: 'sOmEuRl.cOm' },
setSelection: jest.fn().mockName('props.setSelection'),
lmsEndpointUrl: 'sOmE',
images: {
current: [mockImage],
},
};
module.hooks = {
createSaveCallback: jest.fn().mockName('hooks.createSaveCallback'),
onClose: jest.fn().mockName('hooks.onClose'),
};
const props = {
editorRef: { current: null },
isOpen: false,
close: jest.fn().mockName('props.close'),
clearSelection: jest.fn().mockName('props.clearSelection'),
selection: { some: 'images', externalUrl: 'sOmEuRl.cOm' },
setSelection: jest.fn().mockName('props.setSelection'),
lmsEndpointUrl: 'sOmE',
images: {
current: [mockImage],
},
};
beforeEach(() => {
initializeMocks();
});
afterAll(() => {
module.hooks = hooks;
beforeAll(() => {
jest.spyOn(hooks, 'createSaveCallback').mockImplementation(jest.fn().mockName('hooks.createSaveCallback'));
jest.spyOn(hooks, 'onClose').mockImplementation(jest.fn().mockName('hooks.onClose'));
});
test('snapshot: with selection content (ImageSettingsUpload)', () => {
expect(shallow(<ImageUploadModal {...props} />).snapshot).toMatchSnapshot();
const { container } = render(<ImageUploadModal {...props} selection={{ externalUrl: 'url.url' }} />);
expect(container.querySelector('ImageSettingsModal')).toBeInTheDocument();
});
test('snapshot: selection has no externalUrl (Select Image Modal)', () => {
expect(shallow(<ImageUploadModal {...props} selection={null} />).snapshot).toMatchSnapshot();
const { container } = render(<ImageUploadModal {...props} selection={{ }} />);
expect(container.querySelector('SelectImageModal')).toBeInTheDocument();
});
test('snapshot: no selection (Select Image Modal)', () => {
expect(shallow(<ImageUploadModal {...props} selection={null} />).snapshot).toMatchSnapshot();
const { container } = render(<ImageUploadModal {...props} selection={null} />);
expect(container.querySelector('SelectImageModal')).toBeInTheDocument();
});
});
});

View File

@@ -1,58 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CourseOutlineHeaderActionsSlot pluginProps are set correctly 1`] = `
<PluginSlot
id="org.openedx.frontend.authoring.course_outline_header_actions.v1"
idAliases={
[
"course_outline_header_actions_slot",
]
}
pluginProps={
{
"courseActions": {
"childAddable": true,
"deletable": true,
"draggable": true,
"duplicable": true,
},
"errors": {},
"hasSections": false,
"headerNavigationsActions": {
"handleExpandAll": [MockFunction],
"handleNewSection": [MockFunction],
"handleReIndex": [MockFunction],
"lmsLink": "",
},
"isDisabledReindexButton": false,
"isReIndexShow": false,
"isSectionsExpanded": false,
"sections": [],
}
}
>
<HeaderNavigations
courseActions={
{
"childAddable": true,
"deletable": true,
"draggable": true,
"duplicable": true,
}
}
errors={{}}
hasSections={false}
headerNavigationsActions={
{
"handleExpandAll": [MockFunction],
"handleNewSection": [MockFunction],
"handleReIndex": [MockFunction],
"lmsLink": "",
}
}
isDisabledReindexButton={false}
isReIndexShow={false}
isSectionsExpanded={false}
/>
</PluginSlot>
`;

View File

@@ -1,5 +1,4 @@
import { shallow } from '@edx/react-unit-test-utils';
import { render, initializeMocks } from '@src/testUtils';
import CourseOutlineHeaderActionsSlot from '.';
jest.mock('CourseAuthoring/course-outline/header-navigations/HeaderNavigations', () => 'HeaderNavigations');
@@ -29,14 +28,17 @@ const headerNavProps = {
};
describe('CourseOutlineHeaderActionsSlot', () => {
beforeEach(() => jest.resetAllMocks());
beforeEach(() => initializeMocks());
test('pluginProps are set correctly', () => {
const wrapper = shallow(<CourseOutlineHeaderActionsSlot
const { container } = render(<CourseOutlineHeaderActionsSlot
sections={[]}
hasSections={false}
{...headerNavProps}
/>);
expect(wrapper.snapshot).toMatchSnapshot();
expect(container.querySelector('pluginslot')).toBeInTheDocument();
expect(container.querySelector('pluginslot')?.getAttribute('idaliases')).toBe('course_outline_header_actions_slot');
expect(container.querySelector('pluginslot')?.getAttribute('id')).toBe('org.openedx.frontend.authoring.course_outline_header_actions.v1');
expect(container.querySelector('HeaderNavigations')).toBeInTheDocument();
});
});