test: replacing snapshot tests with RTL tests part 14 (#2236)
This commit is contained in:
committed by
GitHub
parent
2fe24f39ac
commit
3673c5f561
@@ -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>
|
||||
`;
|
||||
@@ -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));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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>
|
||||
`;
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
}
|
||||
/>
|
||||
`;
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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",
|
||||
}
|
||||
}
|
||||
/>
|
||||
`;
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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>
|
||||
`;
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user