test: replacing snapshot tests with RTL tests part 13 (#2233)
This commit is contained in:
committed by
GitHub
parent
c4f565bf76
commit
2fe24f39ac
@@ -1,165 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`HandoutWidget snapshots snapshots: renders as expected with default props 1`] = `
|
||||
<CollapsibleFormWidget
|
||||
fontSize="x-small"
|
||||
isError={true}
|
||||
subtitle="None"
|
||||
title="Handout"
|
||||
>
|
||||
<ErrorAlert
|
||||
dismissError={[Function]}
|
||||
hideHeading={true}
|
||||
isError={false}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Handout files must be 20 MB or less. Please resize the file and try again."
|
||||
description="Message presented to user when handout file size is larger than 20 MB"
|
||||
id="authoring.videoeditor.handout.error.fileSizeError"
|
||||
/>
|
||||
</ErrorAlert>
|
||||
<UploadErrorAlert
|
||||
message={
|
||||
{
|
||||
"defaultMessage": "Failed to upload handout. Please try again.",
|
||||
"description": "Message presented to user when handout fails to upload",
|
||||
"id": "authoring.videoeditor.handout.error.uploadHandoutError",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<FileInput
|
||||
fileInput={
|
||||
{
|
||||
"addFile": [Function],
|
||||
"click": [Function],
|
||||
"ref": {
|
||||
"current": undefined,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<Stack
|
||||
gap={3}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Add a handout to accompany this video. Learners can download
|
||||
this file by clicking "Download Handout" below the video."
|
||||
description="Message displayed when uploading a handout"
|
||||
id="authoring.videoeditor.handout.upload.addHandoutMessage"
|
||||
/>
|
||||
<Button
|
||||
className="text-primary-500 font-weight-bold justify-content-start pl-0"
|
||||
onClick={[Function]}
|
||||
size="sm"
|
||||
variant="link"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Upload Handout"
|
||||
description="Label for upload button"
|
||||
id="authoring.videoeditor.handout.upload.label"
|
||||
/>
|
||||
</Button>
|
||||
</Stack>
|
||||
</CollapsibleFormWidget>
|
||||
`;
|
||||
|
||||
exports[`HandoutWidget snapshots snapshots: renders as expected with handout 1`] = `
|
||||
<CollapsibleFormWidget
|
||||
fontSize="x-small"
|
||||
isError={true}
|
||||
subtitle="sOMeUrl "
|
||||
title="Handout"
|
||||
>
|
||||
<ErrorAlert
|
||||
dismissError={[Function]}
|
||||
hideHeading={true}
|
||||
isError={false}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Handout files must be 20 MB or less. Please resize the file and try again."
|
||||
description="Message presented to user when handout file size is larger than 20 MB"
|
||||
id="authoring.videoeditor.handout.error.fileSizeError"
|
||||
/>
|
||||
</ErrorAlert>
|
||||
<UploadErrorAlert
|
||||
message={
|
||||
{
|
||||
"defaultMessage": "Failed to upload handout. Please try again.",
|
||||
"description": "Message presented to user when handout fails to upload",
|
||||
"id": "authoring.videoeditor.handout.error.uploadHandoutError",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<FileInput
|
||||
fileInput={
|
||||
{
|
||||
"addFile": [Function],
|
||||
"click": [Function],
|
||||
"ref": {
|
||||
"current": undefined,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<Stack
|
||||
gap={3}
|
||||
>
|
||||
<ActionRow
|
||||
className="border border-gray-300 rounded px-3 py-2"
|
||||
>
|
||||
sOMeUrl
|
||||
<ActionRow.Spacer />
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
alt="Actions dropdown"
|
||||
as="IconButton"
|
||||
iconAs="Icon"
|
||||
id="dropdown-toggle-with-iconbutton-video-transcript-widget"
|
||||
variant="primary"
|
||||
/>
|
||||
<Dropdown.Menu
|
||||
className="video_handout Action Menu"
|
||||
>
|
||||
<Dropdown.Item
|
||||
key="handout-actions-replace"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Replace"
|
||||
description="Message Presented To user for action to replace handout"
|
||||
id="authoring.videoeditor.handout.replaceHandout"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="handout-actions-download"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Download"
|
||||
description="Message Presented To user for action to download handout"
|
||||
id="authoring.videoeditor.handout.downloadHandout"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="handout-actions-delete"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Delete"
|
||||
description="Message Presented To user for action to delete handout"
|
||||
id="authoring.videoeditor.handout.deleteHandout"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</ActionRow>
|
||||
<FormattedMessage
|
||||
defaultMessage="Learners can download this file by clicking "Download Handout" below the video."
|
||||
description="Message presented to user when a handout is present"
|
||||
id="authoring.videoeditor.handout.handoutHelpMessage"
|
||||
/>
|
||||
</Stack>
|
||||
</CollapsibleFormWidget>
|
||||
`;
|
||||
|
||||
exports[`HandoutWidget snapshots snapshots: renders as expected with isLibrary true 1`] = `null`;
|
||||
@@ -1,81 +0,0 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { formatMessage } from '../../../../../../testUtils';
|
||||
import { actions, selectors } from '../../../../../../data/redux';
|
||||
import { HandoutWidgetInternal as HandoutWidget, mapStateToProps, mapDispatchToProps } from '.';
|
||||
|
||||
jest.mock('react', () => ({
|
||||
...jest.requireActual('react'),
|
||||
useContext: jest.fn(() => ({ handout: ['error.handout', jest.fn().mockName('error.setHandout')] })),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../../../data/redux', () => ({
|
||||
actions: {
|
||||
video: {
|
||||
updateField: jest.fn().mockName('actions.video.updateField'),
|
||||
},
|
||||
},
|
||||
selectors: {
|
||||
video: {
|
||||
getHandoutDownloadUrl: jest.fn(args => ({ getHandoutDownloadUrl: args })).mockName('selectors.video.getHandoutDownloadUrl'),
|
||||
handout: jest.fn(state => ({ handout: state })),
|
||||
},
|
||||
app: {
|
||||
isLibrary: jest.fn(args => ({ isLibrary: args })),
|
||||
},
|
||||
requests: {
|
||||
isFailed: jest.fn(args => ({ isFailed: args })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('HandoutWidget', () => {
|
||||
const props = {
|
||||
subtitle: 'SuBTItle',
|
||||
title: 'tiTLE',
|
||||
intl: { formatMessage },
|
||||
isLibrary: false,
|
||||
handout: '',
|
||||
getHandoutDownloadUrl: jest.fn().mockName('args.getHandoutDownloadUrl'),
|
||||
updateField: jest.fn().mockName('args.updateField'),
|
||||
};
|
||||
|
||||
describe('snapshots', () => {
|
||||
test('snapshots: renders as expected with default props', () => {
|
||||
expect(
|
||||
shallow(<HandoutWidget {...props} />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected with isLibrary true', () => {
|
||||
expect(
|
||||
shallow(<HandoutWidget {...props} isLibrary />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected with handout', () => {
|
||||
expect(
|
||||
shallow(<HandoutWidget {...props} handout="sOMeUrl " />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
describe('mapStateToProps', () => {
|
||||
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
|
||||
test('isLibrary from app.isLibrary', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).isLibrary,
|
||||
).toEqual(selectors.app.isLibrary(testState));
|
||||
});
|
||||
test('getHandoutDownloadUrl from video.getHandoutDownloadUrl', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).getHandoutDownloadUrl,
|
||||
).toEqual(selectors.video.getHandoutDownloadUrl(testState));
|
||||
});
|
||||
});
|
||||
describe('mapDispatchToProps', () => {
|
||||
const dispatch = jest.fn();
|
||||
test('updateField from actions.video.updateField', () => {
|
||||
expect(mapDispatchToProps.updateField).toEqual(dispatch(actions.video.updateField));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import { render, screen, initializeMocks } from '@src/testUtils';
|
||||
import { formatMessage } from '@src/editors/testUtils';
|
||||
import { HandoutWidgetInternal as HandoutWidget } from '.';
|
||||
|
||||
jest.mock('@src/editors/data/redux', () => ({
|
||||
actions: {
|
||||
video: {
|
||||
updateField: jest.fn().mockName('actions.video.updateField'),
|
||||
},
|
||||
},
|
||||
selectors: {
|
||||
video: {
|
||||
getHandoutDownloadUrl: jest.fn(args => ({ getHandoutDownloadUrl: args })).mockName('selectors.video.getHandoutDownloadUrl'),
|
||||
handout: jest.fn(state => ({ handout: state })),
|
||||
},
|
||||
app: {
|
||||
isLibrary: jest.fn(args => ({ isLibrary: args })),
|
||||
},
|
||||
requests: {
|
||||
isFailed: jest.fn(args => ({ isFailed: args })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('HandoutWidget', () => {
|
||||
const props = {
|
||||
intl: { formatMessage },
|
||||
isLibrary: false,
|
||||
handout: '',
|
||||
isUploadError: false,
|
||||
getHandoutDownloadUrl: jest.fn().mockName('args.getHandoutDownloadUrl'),
|
||||
updateField: jest.fn().mockName('args.updateField'),
|
||||
};
|
||||
|
||||
describe('renders', () => {
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
test('renders as expected with default props', () => {
|
||||
render(<HandoutWidget {...props} />);
|
||||
expect(screen.getByText('Handout')).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'Upload Handout' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'Handout' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'Collapse' })).toBeInTheDocument();
|
||||
});
|
||||
test('renders as expected with isLibrary true', () => {
|
||||
const { container } = render(<HandoutWidget {...props} isLibrary />);
|
||||
const reduxWrapper = container.firstChild;
|
||||
expect(reduxWrapper?.textContent).toBe('');
|
||||
expect(screen.queryByText('Handout')).not.toBeInTheDocument();
|
||||
});
|
||||
test('renders as expected with handout', () => {
|
||||
const handoutUrl = 'sOMeUrl ';
|
||||
render(<HandoutWidget {...props} handout={handoutUrl} />);
|
||||
expect(screen.getByText('Handout')).toBeInTheDocument();
|
||||
expect(screen.getByText(handoutUrl.trim())).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CodeEditor Component Snapshots Renders and calls Hooks 1`] = `
|
||||
<div>
|
||||
<div
|
||||
id="CodeMirror"
|
||||
/>
|
||||
<Button
|
||||
aria-label="Unescape HTML Literals"
|
||||
onClick={[Function]}
|
||||
variant="tertiary"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Unescape HTML Literals"
|
||||
description="Label For escape special html charectars button"
|
||||
id="authoring.texteditor.codeEditor.escapeHTMLButton"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
`;
|
||||
@@ -1,53 +1,15 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { EditorState } from '@codemirror/state';
|
||||
import { EditorView } from '@codemirror/view';
|
||||
import { html } from '@codemirror/lang-html';
|
||||
import {
|
||||
render, screen, initializeMocks, fireEvent,
|
||||
} from '@src/testUtils';
|
||||
import { formatMessage, MockUseState } from '../../testUtils';
|
||||
import alphanumericMap from './constants';
|
||||
import * as module from './index';
|
||||
import { CodeEditorInternal as CodeEditor } from './index';
|
||||
import * as hooks from './hooks';
|
||||
|
||||
const CodeEditor = module.CodeEditorInternal;
|
||||
|
||||
jest.mock('@codemirror/view');
|
||||
|
||||
jest.mock('react', () => ({
|
||||
...jest.requireActual('react'),
|
||||
useRef: jest.fn(val => ({ current: val })),
|
||||
useEffect: jest.fn(),
|
||||
useCallback: (cb, prereqs) => ({ cb, prereqs }),
|
||||
}));
|
||||
|
||||
jest.mock('@codemirror/state', () => ({
|
||||
...jest.requireActual('@codemirror/state'),
|
||||
EditorState: {
|
||||
create: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('@codemirror/lang-html', () => ({
|
||||
html: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@codemirror/lang-xml', () => ({
|
||||
xml: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@codemirror/lang-markdown', () => ({
|
||||
markdown: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('codemirror', () => ({
|
||||
basicSetup: 'bAsiCSetUp',
|
||||
}));
|
||||
|
||||
const state = new MockUseState(hooks);
|
||||
|
||||
describe('CodeEditor', () => {
|
||||
describe('Hooks', () => {
|
||||
const state = new MockUseState(hooks);
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
@@ -103,30 +65,6 @@ describe('CodeEditor', () => {
|
||||
expect(mockHideBtn).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createCodeMirrorDomNode', () => {
|
||||
const props = {
|
||||
ref: {
|
||||
current: 'sOmEvAlUe',
|
||||
},
|
||||
lang: 'html',
|
||||
initialText: 'sOmEhTmL',
|
||||
upstreamRef: {
|
||||
current: 'sOmEotHERvAlUe',
|
||||
},
|
||||
};
|
||||
beforeEach(() => {
|
||||
hooks.createCodeMirrorDomNode(props);
|
||||
});
|
||||
it('calls useEffect and sets up codemirror objects', () => {
|
||||
const [cb, prereqs] = React.useEffect.mock.calls[0];
|
||||
expect(prereqs).toStrictEqual([]);
|
||||
cb();
|
||||
expect(EditorState.create).toHaveBeenCalled();
|
||||
expect(EditorView).toHaveBeenCalled();
|
||||
expect(html).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('xmlSyntaxChecker', () => {
|
||||
@@ -165,11 +103,12 @@ describe('CodeEditor', () => {
|
||||
});
|
||||
|
||||
describe('Component', () => {
|
||||
describe('Snapshots', () => {
|
||||
const mockHideBtn = jest.fn().mockName('mockHidebtn');
|
||||
let props;
|
||||
beforeAll(() => {
|
||||
props = {
|
||||
describe('renders', () => {
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
test('Renders and calls Hooks ', () => {
|
||||
const props = {
|
||||
intl: { formatMessage },
|
||||
innerRef: {
|
||||
current: 'sOmEvALUE',
|
||||
@@ -177,16 +116,29 @@ describe('CodeEditor', () => {
|
||||
lang: 'html',
|
||||
value: 'mOcKhTmL',
|
||||
};
|
||||
const mockBtnRef = { current: null };
|
||||
const mockDOMRef = { current: null };
|
||||
const mockUseRef = jest.fn()
|
||||
.mockImplementationOnce(() => mockDOMRef) // for DOMref
|
||||
.mockImplementationOnce(() => mockBtnRef); // for btnRef
|
||||
|
||||
jest.spyOn(React, 'useRef').mockImplementation(mockUseRef);
|
||||
|
||||
const mockHideBtn = jest.fn();
|
||||
jest.spyOn(hooks, 'prepareShowBtnEscapeHTML').mockImplementation(() => ({
|
||||
showBtnEscapeHTML: true,
|
||||
hideBtn: mockHideBtn,
|
||||
}));
|
||||
jest.spyOn(hooks, 'createCodeMirrorDomNode').mockImplementation(() => ({}));
|
||||
});
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
test('Renders and calls Hooks ', () => {
|
||||
jest.spyOn(hooks, 'prepareShowBtnEscapeHTML').mockImplementation(() => ({ showBtnEscapeHTML: true, hideBtn: mockHideBtn }));
|
||||
const mockEscapeHTMLSpecialChars = jest.fn();
|
||||
jest.spyOn(hooks, 'escapeHTMLSpecialChars').mockImplementation(mockEscapeHTMLSpecialChars);
|
||||
// Note: ref won't show up as it is not acutaly a DOM attribute.
|
||||
expect(shallow(<CodeEditor {...props} />).snapshot).toMatchSnapshot();
|
||||
render(<CodeEditor {...props} />);
|
||||
expect(screen.getByRole('button', { name: 'Unescape HTML Literals' })).toBeInTheDocument();
|
||||
expect(hooks.prepareShowBtnEscapeHTML).toHaveBeenCalled();
|
||||
expect(hooks.createCodeMirrorDomNode).toHaveBeenCalled();
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Unescape HTML Literals' }));
|
||||
expect(mockEscapeHTMLSpecialChars).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,77 +0,0 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import { selectors } from '../../data/redux';
|
||||
import { formatMessage } from '../../testUtils';
|
||||
import { ErrorPageInternal as ErrorPage, mapStateToProps } from './ErrorPage';
|
||||
|
||||
jest.mock('../../data/redux', () => ({
|
||||
selectors: {
|
||||
app: {
|
||||
unitUrl: jest.fn(state => ({ unitUrl: state })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('Editor Page', () => {
|
||||
const emptyProps = {
|
||||
learningContextId: null,
|
||||
studioEndpointUrl: null,
|
||||
intl: { formatMessage },
|
||||
};
|
||||
const passedProps = {
|
||||
learningContextId: 'course-v1:edX+DemoX+Demo_Course',
|
||||
studioEndpointUrl: 'fakeurl.com',
|
||||
message: 'cUStomMEssagE',
|
||||
intl: { formatMessage },
|
||||
};
|
||||
const unitData = {
|
||||
data: {
|
||||
ancestors: [{ id: 'SomeID' }],
|
||||
},
|
||||
};
|
||||
|
||||
describe('rendered with empty props', () => {
|
||||
it('should only have one button (try again)', () => {
|
||||
const wrapper = shallow(<ErrorPage {...emptyProps} />);
|
||||
const buttonText = wrapper.instance.findByType('Button')[0].children[0].el;
|
||||
expect(wrapper.snapshot).toMatchSnapshot();
|
||||
expect(buttonText).toEqual('Try again');
|
||||
});
|
||||
});
|
||||
|
||||
describe('rendered with pass through props defined', () => {
|
||||
const wrapper = shallow(<ErrorPage {...passedProps} />);
|
||||
describe('shows two buttons', () => {
|
||||
it('the first button should correspond to returning to the course outline', () => {
|
||||
const firstButtonText = wrapper.instance.findByType('Button')[0].children[0].el;
|
||||
const secondButtonText = wrapper.instance.findByType('Button')[1].children[0].el;
|
||||
expect(wrapper.snapshot).toMatchSnapshot();
|
||||
expect(firstButtonText).toEqual('Return to course outline');
|
||||
expect(secondButtonText).toEqual('Try again');
|
||||
});
|
||||
it('the first button should correspond to returning to the unit page', () => {
|
||||
const returnToUnitPageWrapper = shallow(<ErrorPage {...passedProps} unitData={unitData} />);
|
||||
expect(returnToUnitPageWrapper.snapshot).toMatchSnapshot();
|
||||
const firstButtonText = returnToUnitPageWrapper.instance.findByType('Button')[0].children[0].el;
|
||||
const secondButtonText = returnToUnitPageWrapper.instance.findByType('Button')[1].children[0].el;
|
||||
expect(returnToUnitPageWrapper.snapshot).toMatchSnapshot();
|
||||
expect(firstButtonText).toEqual('Return to unit page');
|
||||
expect(secondButtonText).toEqual('Try again');
|
||||
});
|
||||
});
|
||||
it('should have custom message', () => {
|
||||
const customMessageText = wrapper.instance.findByType('div')[0].children[0].children[0].el;
|
||||
expect(wrapper.snapshot).toMatchSnapshot();
|
||||
expect(customMessageText).toEqual('cUStomMEssagE');
|
||||
});
|
||||
});
|
||||
describe('mapStateToProps() function', () => {
|
||||
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
|
||||
test('unitData should equal unitUrl from app.unitUrl', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).unitData,
|
||||
).toEqual(selectors.app.unitUrl(testState));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
import React from 'react';
|
||||
import { render, screen, initializeMocks } from '@src/testUtils';
|
||||
import { formatMessage } from '../../testUtils';
|
||||
import { ErrorPageInternal as ErrorPage } from './ErrorPage';
|
||||
|
||||
jest.mock('../../data/redux', () => ({
|
||||
selectors: {
|
||||
app: {
|
||||
unitUrl: jest.fn(state => ({ unitUrl: state })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('Editor Page', () => {
|
||||
const emptyProps = {
|
||||
learningContextId: 'course-v1:edX+DemoX+Demo_Course',
|
||||
studioEndpointUrl: 'fakeurl.com',
|
||||
intl: { formatMessage },
|
||||
};
|
||||
const passedProps = {
|
||||
learningContextId: 'course-v1:edX+DemoX+Demo_Course',
|
||||
studioEndpointUrl: 'fakeurl.com',
|
||||
message: 'cUStomMEssagE',
|
||||
intl: { formatMessage },
|
||||
};
|
||||
const unitData = {
|
||||
data: {
|
||||
ancestors: [{ id: 'SomeID' }],
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
|
||||
describe('rendered with empty props', () => {
|
||||
it('should only have one button (try again)', () => {
|
||||
render(<ErrorPage {...emptyProps} />);
|
||||
expect(screen.getByRole('button', { name: 'Try again' })).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('rendered with pass through props defined', () => {
|
||||
describe('shows two buttons', () => {
|
||||
it('the first button should correspond to returning to the course outline', () => {
|
||||
render(<ErrorPage {...passedProps} />);
|
||||
const firstButton = screen.getByRole('button', { name: 'Return to course outline' });
|
||||
const secondButton = screen.getByRole('button', { name: 'Try again' });
|
||||
expect(firstButton).toBeInTheDocument();
|
||||
expect(secondButton).toBeInTheDocument();
|
||||
});
|
||||
it('the first button should correspond to returning to the unit page', () => {
|
||||
render(<ErrorPage {...passedProps} unitData={unitData} />);
|
||||
const firstButton = screen.getByRole('button', { name: 'Return to unit page' });
|
||||
const secondButton = screen.getByRole('button', { name: 'Try again' });
|
||||
expect(firstButton).toBeInTheDocument();
|
||||
expect(secondButton).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
it('should have custom message', () => {
|
||||
render(<ErrorPage {...passedProps} />);
|
||||
expect(screen.getByText('cUStomMEssagE')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,196 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Editor Page rendered with empty props should only have one button (try again) 1`] = `
|
||||
<Container
|
||||
className="py-5 justify-content-center align-items-start text-center"
|
||||
fluid={true}
|
||||
>
|
||||
<Row>
|
||||
<Col>
|
||||
<p
|
||||
className="text-muted"
|
||||
>
|
||||
An unexpected error occurred. Please click the button below to refresh the page.
|
||||
</p>
|
||||
<Row
|
||||
className="justify-content-center"
|
||||
>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Try again
|
||||
</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`Editor Page rendered with pass through props defined should have custom message 1`] = `
|
||||
<Container
|
||||
className="py-5 justify-content-center align-items-start text-center"
|
||||
fluid={true}
|
||||
>
|
||||
<Row>
|
||||
<Col>
|
||||
<p
|
||||
className="text-muted"
|
||||
>
|
||||
An unexpected error occurred. Please click the button below to refresh the page.
|
||||
</p>
|
||||
<div
|
||||
className="my-4"
|
||||
role="alert"
|
||||
>
|
||||
<p>
|
||||
cUStomMEssagE
|
||||
</p>
|
||||
</div>
|
||||
<Row
|
||||
className="justify-content-center"
|
||||
>
|
||||
<Button
|
||||
className="mr-2"
|
||||
onClick={[Function]}
|
||||
variant="outline-primary"
|
||||
>
|
||||
Return to course outline
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Try again
|
||||
</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`Editor Page rendered with pass through props defined shows two buttons the first button should correspond to returning to the course outline 1`] = `
|
||||
<Container
|
||||
className="py-5 justify-content-center align-items-start text-center"
|
||||
fluid={true}
|
||||
>
|
||||
<Row>
|
||||
<Col>
|
||||
<p
|
||||
className="text-muted"
|
||||
>
|
||||
An unexpected error occurred. Please click the button below to refresh the page.
|
||||
</p>
|
||||
<div
|
||||
className="my-4"
|
||||
role="alert"
|
||||
>
|
||||
<p>
|
||||
cUStomMEssagE
|
||||
</p>
|
||||
</div>
|
||||
<Row
|
||||
className="justify-content-center"
|
||||
>
|
||||
<Button
|
||||
className="mr-2"
|
||||
onClick={[Function]}
|
||||
variant="outline-primary"
|
||||
>
|
||||
Return to course outline
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Try again
|
||||
</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`Editor Page rendered with pass through props defined shows two buttons the first button should correspond to returning to the unit page 1`] = `
|
||||
<Container
|
||||
className="py-5 justify-content-center align-items-start text-center"
|
||||
fluid={true}
|
||||
>
|
||||
<Row>
|
||||
<Col>
|
||||
<p
|
||||
className="text-muted"
|
||||
>
|
||||
An unexpected error occurred. Please click the button below to refresh the page.
|
||||
</p>
|
||||
<div
|
||||
className="my-4"
|
||||
role="alert"
|
||||
>
|
||||
<p>
|
||||
cUStomMEssagE
|
||||
</p>
|
||||
</div>
|
||||
<Row
|
||||
className="justify-content-center"
|
||||
>
|
||||
<Button
|
||||
className="mr-2"
|
||||
onClick={[Function]}
|
||||
variant="outline-primary"
|
||||
>
|
||||
Return to unit page
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Try again
|
||||
</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`Editor Page rendered with pass through props defined shows two buttons the first button should correspond to returning to the unit page 2`] = `
|
||||
<Container
|
||||
className="py-5 justify-content-center align-items-start text-center"
|
||||
fluid={true}
|
||||
>
|
||||
<Row>
|
||||
<Col>
|
||||
<p
|
||||
className="text-muted"
|
||||
>
|
||||
An unexpected error occurred. Please click the button below to refresh the page.
|
||||
</p>
|
||||
<div
|
||||
className="my-4"
|
||||
role="alert"
|
||||
>
|
||||
<p>
|
||||
cUStomMEssagE
|
||||
</p>
|
||||
</div>
|
||||
<Row
|
||||
className="justify-content-center"
|
||||
>
|
||||
<Button
|
||||
className="mr-2"
|
||||
onClick={[Function]}
|
||||
variant="outline-primary"
|
||||
>
|
||||
Return to unit page
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Try again
|
||||
</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
`;
|
||||
@@ -1,50 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ExpandableTextArea snapshots renders as expected with default behavior 1`] = `
|
||||
<Fragment>
|
||||
<div
|
||||
className="expandable-mce error"
|
||||
>
|
||||
<TinyMceWidget
|
||||
editorContentHtml="text"
|
||||
editorRef={
|
||||
{
|
||||
"current": {
|
||||
"value": "something",
|
||||
},
|
||||
}
|
||||
}
|
||||
editorType="expandable"
|
||||
placeholder={null}
|
||||
setEditorRef={[MockFunction hooks.prepareEditorRef.setEditorRef]}
|
||||
updateContent={[MockFunction]}
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`ExpandableTextArea snapshots renders error message 1`] = `
|
||||
<Fragment>
|
||||
<div
|
||||
className="expandable-mce error"
|
||||
>
|
||||
<TinyMceWidget
|
||||
editorContentHtml="text"
|
||||
editorRef={
|
||||
{
|
||||
"current": {
|
||||
"value": "something",
|
||||
},
|
||||
}
|
||||
}
|
||||
editorType="expandable"
|
||||
placeholder={null}
|
||||
setEditorRef={[MockFunction hooks.prepareEditorRef.setEditorRef]}
|
||||
updateContent={[MockFunction]}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="text-danger-500 x-small"
|
||||
/>
|
||||
</Fragment>
|
||||
`;
|
||||
@@ -28,7 +28,7 @@ const ExpandableTextArea = ({
|
||||
</div>
|
||||
{error && (
|
||||
<div className="text-danger-500 x-small">
|
||||
{props.errorMessage}
|
||||
{errorMessage}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import { render, screen, initializeMocks } from '@src/testUtils';
|
||||
import ExpandableTextArea from '.';
|
||||
|
||||
// Per https://github.com/tinymce/tinymce-react/issues/91 React unit testing in JSDOM is not supported by tinymce.
|
||||
@@ -31,13 +31,27 @@ describe('ExpandableTextArea', () => {
|
||||
error: false,
|
||||
errorMessage: null,
|
||||
};
|
||||
describe('snapshots', () => {
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
describe('renders', () => {
|
||||
test('renders as expected with default behavior', () => {
|
||||
expect(shallow(<ExpandableTextArea {...props} />).snapshot).toMatchSnapshot();
|
||||
const { container } = render(<ExpandableTextArea {...props} />);
|
||||
expect(container.querySelector('TinyMceWidget')).toBeInTheDocument();
|
||||
});
|
||||
test('renders error message', () => {
|
||||
const wrapper = shallow(<ExpandableTextArea {...props} error errorMessage="eRRormeSsaGE" />);
|
||||
expect(wrapper.snapshot).toMatchSnapshot();
|
||||
render(<ExpandableTextArea {...props} error errorMessage="eRRormeSsaGE" />);
|
||||
expect(screen.getByText('eRRormeSsaGE')).toBeInTheDocument();
|
||||
});
|
||||
test('renders nothing when refReady is null', () => {
|
||||
// eslint-disable-next-line global-require
|
||||
jest.spyOn(require('../TinyMceWidget/hooks'), 'prepareEditorRef').mockReturnValue({
|
||||
editorRef: { current: { value: 'something' } },
|
||||
refReady: false,
|
||||
setEditorRef: jest.fn().mockName('hooks.prepareEditorRef.setEditorRef'),
|
||||
});
|
||||
const { container } = render(<ExpandableTextArea {...props} />);
|
||||
expect(container.firstChild?.textContent).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,175 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ImageSettingsModal render snapshot 1`] = `
|
||||
<BaseModal
|
||||
bodyStyle={null}
|
||||
close={[MockFunction props.close]}
|
||||
confirmAction={
|
||||
<Button
|
||||
onClick={
|
||||
{
|
||||
"hooks.onSaveClick": {
|
||||
"altText": {
|
||||
"error": {
|
||||
"dismiss": [MockFunction],
|
||||
"show": true,
|
||||
},
|
||||
"isDecorative": false,
|
||||
"value": "alternative Taxes",
|
||||
},
|
||||
"dimensions": {
|
||||
"height": 13,
|
||||
"width": 12,
|
||||
},
|
||||
"isDecorative": false,
|
||||
"saveToEditor": [MockFunction props.saveToEditor],
|
||||
},
|
||||
}
|
||||
}
|
||||
variant="primary"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Save"
|
||||
description="Label for save button."
|
||||
id="authoring.texteditor.imagesettingsmodal.saveButtonLabel"
|
||||
/>
|
||||
</Button>
|
||||
}
|
||||
footerAction={null}
|
||||
headerComponent={null}
|
||||
hideCancelButton={false}
|
||||
isFullscreenScroll={true}
|
||||
isOpen={false}
|
||||
size="lg"
|
||||
title="Image Settings"
|
||||
>
|
||||
<ErrorAlert
|
||||
dismissError={[MockFunction]}
|
||||
hideHeading={true}
|
||||
isError={true}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Enter alt text or specify that the image is decorative only."
|
||||
description="Message presented to user when user attempts to save unaccepted altText configuration."
|
||||
id="authoring.texteditor.imagesettingsmodal.error.altTextError"
|
||||
/>
|
||||
</ErrorAlert>
|
||||
<Button
|
||||
onClick={[MockFunction props.returnToSelector]}
|
||||
size="inline"
|
||||
variant="link"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Replace image"
|
||||
description="Label for replace image button."
|
||||
id="authoring.texteditor.imagesettingsmodal.replaceImageButtonLabel"
|
||||
/>
|
||||
</Button>
|
||||
<br />
|
||||
<div
|
||||
className="d-flex flex-row m-2 img-settings-form-container"
|
||||
>
|
||||
<div
|
||||
className="img-settings-thumbnail-container"
|
||||
>
|
||||
<Image
|
||||
className="img-settings-thumbnail"
|
||||
onError={
|
||||
{
|
||||
"hooks.dimensions.onImgLoad.callback": {
|
||||
"selection": {
|
||||
"altText": "AlTTExt",
|
||||
"externalUrl": "ExtERNALurL",
|
||||
"url": "UrL",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
onLoad={
|
||||
{
|
||||
"hooks.dimensions.onImgLoad.callback": {
|
||||
"selection": {
|
||||
"altText": "AlTTExt",
|
||||
"externalUrl": "ExtERNALurL",
|
||||
"url": "UrL",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
src="ExtERNALurL"
|
||||
/>
|
||||
</div>
|
||||
<hr
|
||||
className="h-100 bg-primary-200 m-0"
|
||||
/>
|
||||
<div
|
||||
className="img-settings-form-controls"
|
||||
>
|
||||
<DimensionControls
|
||||
onImgLoad={
|
||||
[MockFunction hooks.dimensions.onImgLoad] {
|
||||
"calls": [
|
||||
[
|
||||
{
|
||||
"altText": "AlTTExt",
|
||||
"externalUrl": "ExtERNALurL",
|
||||
"url": "UrL",
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
"altText": "AlTTExt",
|
||||
"externalUrl": "ExtERNALurL",
|
||||
"url": "UrL",
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"type": "return",
|
||||
"value": {
|
||||
"hooks.dimensions.onImgLoad.callback": {
|
||||
"selection": {
|
||||
"altText": "AlTTExt",
|
||||
"externalUrl": "ExtERNALurL",
|
||||
"url": "UrL",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "return",
|
||||
"value": {
|
||||
"hooks.dimensions.onImgLoad.callback": {
|
||||
"selection": {
|
||||
"altText": "AlTTExt",
|
||||
"externalUrl": "ExtERNALurL",
|
||||
"url": "UrL",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
value={
|
||||
{
|
||||
"height": 13,
|
||||
"width": 12,
|
||||
}
|
||||
}
|
||||
/>
|
||||
<AltTextControls
|
||||
error={
|
||||
{
|
||||
"dismiss": [MockFunction],
|
||||
"show": true,
|
||||
}
|
||||
}
|
||||
isDecorative={false}
|
||||
value="alternative Taxes"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</BaseModal>
|
||||
`;
|
||||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import { Button, Image } from '@openedx/paragon';
|
||||
import { ArrowBackIos } from '@openedx/paragon/icons';
|
||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import './index.scss';
|
||||
import * as hooks from './hooks';
|
||||
@@ -29,9 +29,8 @@ const ImageSettingsModal = ({
|
||||
returnToSelection,
|
||||
saveToEditor,
|
||||
selection,
|
||||
// inject
|
||||
intl,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const altText = hooks.altTextHooks(selection.altText);
|
||||
const dimensions = hooks.dimensionHooks(altText);
|
||||
const onSaveClick = hooks.onSaveClick({
|
||||
@@ -99,8 +98,5 @@ ImageSettingsModal.propTypes = {
|
||||
externalUrl: PropTypes.string,
|
||||
url: PropTypes.string,
|
||||
}).isRequired,
|
||||
// inject
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
export const ImageSettingsModalInternal = ImageSettingsModal; // For testing only
|
||||
export default injectIntl(ImageSettingsModal);
|
||||
export default ImageSettingsModal;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { formatMessage } from '../../../testUtils';
|
||||
import { ImageSettingsModalInternal as ImageSettingsModal } from '.';
|
||||
import { render, screen, initializeMocks } from '@src/testUtils';
|
||||
import ImageSettingsModal from '.';
|
||||
|
||||
jest.mock('./AltTextControls', () => 'AltTextControls');
|
||||
jest.mock('./DimensionControls', () => 'DimensionControls');
|
||||
@@ -28,23 +25,21 @@ jest.mock('./hooks', () => ({
|
||||
|
||||
describe('ImageSettingsModal', () => {
|
||||
const props = {
|
||||
isOpen: false,
|
||||
isOpen: true,
|
||||
selection: {
|
||||
altText: 'AlTTExt',
|
||||
externalUrl: 'ExtERNALurL',
|
||||
url: 'UrL',
|
||||
},
|
||||
// inject
|
||||
intl: { formatMessage },
|
||||
close: jest.fn().mockName('props.close'),
|
||||
returnToSelection: jest.fn().mockName('props.returnToSelector'),
|
||||
saveToEditor: jest.fn().mockName('props.saveToEditor'),
|
||||
};
|
||||
beforeEach(() => {
|
||||
props.close = jest.fn().mockName('props.close');
|
||||
props.saveToEditor = jest.fn().mockName('props.saveToEditor');
|
||||
props.returnToSelection = jest.fn().mockName('props.returnToSelector');
|
||||
initializeMocks();
|
||||
});
|
||||
describe('render', () => {
|
||||
test('snapshot', () => {
|
||||
expect(shallow(<ImageSettingsModal {...props} />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
test('renders component', () => {
|
||||
render(<ImageSettingsModal {...props} />);
|
||||
expect(screen.getByText('Image Settings')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user