test: replacing snapshot tests with RTL tests part 9 (#2206)

This commit is contained in:
jacobo-dominguez-wgu
2025-06-20 13:05:34 -06:00
committed by GitHub
parent 75ea7500e1
commit 962b30bed9
13 changed files with 161 additions and 826 deletions

View File

@@ -1,55 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Checker component with disabled 1`] = `
<Fragment>
<Radio
checked={true}
className="pt-2.5"
disabled={true}
isValid={true}
onChange={[Function]}
value="A"
/>
<Form.Label
className="pt-2"
>
A
</Form.Label>
</Fragment>
`;
exports[`Checker component with multiple answers 1`] = `
<Fragment>
<Form.Checkbox
checked={true}
className="pt-2.5"
disabled={false}
isValid={true}
onChange={[Function]}
value="A"
/>
<Form.Label
className="pt-2"
>
A
</Form.Label>
</Fragment>
`;
exports[`Checker component with single answer 1`] = `
<Fragment>
<Radio
checked={true}
className="pt-2.5"
disabled={false}
isValid={true}
onChange={[Function]}
value="A"
/>
<Form.Label
className="pt-2"
>
A
</Form.Label>
</Fragment>
`;

View File

@@ -1,27 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import { shallow } from '@edx/react-unit-test-utils';
import Checker from '.';
const props = {
hasSingleAnswer: true,
answer: {
id: 'A',
title: 'Answer 1',
correct: true,
selectedFeedback: 'some feedback',
},
setAnswer: jest.fn(),
};
describe('Checker component', () => {
test('with single answer', () => {
expect(shallow(<Checker {...props} />).snapshot).toMatchSnapshot();
});
test('with multiple answers', () => {
expect(shallow(<Checker {...props} hasSingleAnswer={false} />).snapshot).toMatchSnapshot();
});
test('with disabled', () => {
expect(shallow(<Checker {...props} disabled />).snapshot).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,43 @@
import {
render, screen, initializeMocks, fireEvent,
} from '@src/testUtils';
import Checker from '.';
const props = {
hasSingleAnswer: true,
answer: {
id: 1,
correct: true,
},
setAnswer: jest.fn(),
};
describe('Checker component', () => {
beforeEach(() => {
initializeMocks();
});
test('renders with single answer', () => {
render(<Checker {...props} />);
expect(screen.getByText('1')).toBeInTheDocument();
expect(screen.getByRole('radio')).toBeInTheDocument();
expect(screen.queryByRole('checkbox')).not.toBeInTheDocument();
});
test('renders with multiple answers', () => {
render(<Checker {...props} hasSingleAnswer={false} />);
expect(screen.getByRole('checkbox')).toBeInTheDocument();
expect(screen.queryByRole('radio')).not.toBeInTheDocument();
});
test('renders with disabled radio', () => {
render(<Checker {...props} disabled />);
expect(screen.getByRole('radio')).toBeInTheDocument();
});
test('calls setAnswer when radio button is clicked', () => {
render(<Checker {...props} />);
expect(screen.getByRole('radio')).toBeInTheDocument();
fireEvent.click(screen.getByRole('radio'), { target: { checked: !props.answer.correct } });
expect(props.setAnswer).toHaveBeenCalledWith({ correct: true });
});
});

View File

@@ -1,14 +1,11 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { formatMessage } from '../../../../../../testUtils';
import {
render, screen, initializeMocks,
} from '@src/testUtils';
import { formatMessage } from '@src/editors/testUtils';
import { selectors } from '../../../../../../data/redux';
import { ShowAnswerCardInternal as ShowAnswerCard, mapStateToProps, mapDispatchToProps } from './ShowAnswerCard';
import { useAnswerSettings } from '../hooks';
jest.mock('../hooks', () => ({
useAnswerSettings: jest.fn(),
}));
import * as hooks from '../hooks';
jest.mock('../../../../../../data/redux', () => ({
selectors: {
@@ -30,33 +27,34 @@ describe('ShowAnswerCard', () => {
updateSettings: jest.fn().mockName('args.updateSettings'),
intl: { formatMessage },
};
const props = {
showAnswer,
defaultValue: 'finished',
updateSettings: jest.fn(),
// injected
intl: { formatMessage },
// redux
studioEndpointUrl: 'SoMEeNDpOinT',
learningContextId: 'sOMEcouRseId',
isLibrary: false,
};
const useAnswerSettingsProps = {
handleShowAnswerChange: jest.fn().mockName('useAnswerSettings.handleShowAnswerChange'),
handleAttemptsChange: jest.fn().mockName('useAnswerSettings.handleAttemptsChange'),
};
useAnswerSettings.mockReturnValue(useAnswerSettingsProps);
describe('behavior', () => {
it(' calls useAnswerSettings when initialized', () => {
shallow(<ShowAnswerCard {...props} />);
expect(useAnswerSettings).toHaveBeenCalledWith(showAnswer, props.updateSettings);
describe('renders', () => {
beforeEach(() => {
initializeMocks();
});
});
describe('snapshot', () => {
test('snapshot: show answer setting card', () => {
expect(shallow(<ShowAnswerCard {...props} />).snapshot).toMatchSnapshot();
test('show answer setting card', () => {
render(<ShowAnswerCard {...props} />);
expect(screen.getByText('Show answer')).toBeInTheDocument();
});
test('calls useAnswerSettings when initialized', () => {
jest.spyOn(hooks, 'useAnswerSettings');
render(<ShowAnswerCard {...props} />);
expect(screen.getByText('Show answer')).toBeInTheDocument();
expect(hooks.useAnswerSettings).toHaveBeenCalledWith(showAnswer, props.updateSettings);
});
});
describe('mapStateToProps', () => {
@@ -64,11 +62,13 @@ describe('ShowAnswerCard', () => {
test('studioEndpointUrl from app.studioEndpointUrl', () => {
expect(
mapStateToProps(testState).studioEndpointUrl,
// @ts-ignore
).toEqual(selectors.app.studioEndpointUrl(testState));
});
test('learningContextId from app.learningContextId', () => {
expect(
mapStateToProps(testState).learningContextId,
// @ts-ignore
).toEqual(selectors.app.learningContextId(testState));
});
});

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import SettingsOption from '../SettingsOption';
import { ProblemTypeKeys, ProblemTypes } from '../../../../../../data/constants/problem';
import messages from '../messages';
@@ -14,9 +14,8 @@ const TypeCard = ({
setBlockTitle,
updateField,
updateAnswer,
// inject
intl,
}) => {
const intl = useIntl();
const problemTypeKeysArray = Object.values(ProblemTypeKeys).filter(key => key !== ProblemTypeKeys.ADVANCED);
if (problemType === ProblemTypeKeys.ADVANCED) { return null; }
@@ -60,9 +59,6 @@ TypeCard.propTypes = {
setBlockTitle: PropTypes.func.isRequired,
updateField: PropTypes.func.isRequired,
updateAnswer: PropTypes.func.isRequired,
// injected
intl: intlShape.isRequired,
};
export const TypeCardInternal = TypeCard; // For testing only
export default injectIntl(TypeCard);
export default TypeCard;

View File

@@ -1,26 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { formatMessage } from '../../../../../../testUtils';
import { TypeCardInternal as TypeCard } from './TypeCard';
import { ProblemTypeKeys } from '../../../../../../data/constants/problem';
describe('TypeCard', () => {
const props = {
answers: [],
blockTitle: 'BLocktiTLE',
correctAnswerCount: 0,
problemType: ProblemTypeKeys.TEXTINPUT,
setBlockTitle: jest.fn().mockName('args.setBlockTitle'),
updateField: jest.fn().mockName('args.updateField'),
updateAnswer: jest.fn().mockName('args.updateAnswer'),
// injected
intl: { formatMessage },
};
describe('snapshot', () => {
test('snapshot: renders type setting card', () => {
expect(shallow(<TypeCard {...props} />).snapshot).toMatchSnapshot();
});
});
});

View File

@@ -0,0 +1,32 @@
import React from 'react';
import { render, screen, initializeMocks } from '@src/testUtils';
import TypeCard from './TypeCard';
import { ProblemTypeKeys } from '../../../../../../data/constants/problem';
describe('TypeCard', () => {
const props = {
answers: [],
blockTitle: 'BLocktiTLE',
correctAnswerCount: 0,
problemType: ProblemTypeKeys.TEXTINPUT,
setBlockTitle: jest.fn().mockName('args.setBlockTitle'),
updateField: jest.fn().mockName('args.updateField'),
updateAnswer: jest.fn().mockName('args.updateAnswer'),
};
beforeEach(() => {
initializeMocks();
});
test('renders type setting card', () => {
render(<TypeCard {...props} />);
expect(screen.getByText('Type')).toBeInTheDocument();
expect(screen.getByText('Text input')).toBeInTheDocument();
});
test('renders nothing if problemType is advanced', () => {
const { container } = render(<TypeCard {...props} problemType={ProblemTypeKeys.ADVANCED} />);
expect(screen.queryByText('Type')).not.toBeInTheDocument();
expect(container.firstChild?.textContent).toBe('');
});
});

View File

@@ -1,121 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ShowAnswerCard snapshot snapshot: show answer setting card 1`] = `
<SettingsOption
className=""
extraSections={[]}
hasExpandableTextArea={false}
summary="After Some Number of Attempts"
title="Show answer"
>
<Fragment>
<div
className="pb-2"
>
<span>
<FormattedMessage
defaultMessage="Define when learners can see the correct answer."
description="Show Answer settings card text"
id="authoring.problemeditor.settings.showAnswer.text"
/>
</span>
</div>
<div
className="pb-4"
>
<Hyperlink
destination="SoMEeNDpOinT/settings/advanced/sOMEcouRseId#showanswer"
target="_blank"
>
<FormattedMessage
defaultMessage="Set a default value in advanced settings"
description="Advanced settings link text"
id="authoring.problemeditor.settings.advancedSettingLink.text"
/>
</Hyperlink>
</div>
<Form.Group
className="pb-0 mb-0"
>
<Form.Control
as="select"
onChange={[MockFunction useAnswerSettings.handleShowAnswerChange]}
value="after_attempts"
>
<option
key="always"
value="always"
>
Always
</option>
<option
key="answered"
value="answered"
>
Answered
</option>
<option
key="attempted"
value="attempted"
>
Attempted or Past Due
</option>
<option
key="closed"
value="closed"
>
Closed
</option>
<option
key="finished"
value="finished"
>
Finished (Default)
</option>
<option
key="correct_or_past_due"
value="correct_or_past_due"
>
Correct or Past Due
</option>
<option
key="past_due"
value="past_due"
>
Past Due
</option>
<option
key="never"
value="never"
>
Never
</option>
<option
key="after_attempts"
value="after_attempts"
>
After Some Number of Attempts
</option>
<option
key="after_all_attempts"
value="after_all_attempts"
>
After All Attempts
</option>
<option
key="after_all_attempts_or_correct"
value="after_all_attempts_or_correct"
>
After All Attempts or Correct
</option>
<option
key="attempted_no_past_due"
value="attempted_no_past_due"
>
Attempted
</option>
</Form.Control>
</Form.Group>
</Fragment>
</SettingsOption>
`;

View File

@@ -1,82 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TypeCard snapshot snapshot: renders type setting card 1`] = `
<SettingsOption
className=""
extraSections={[]}
hasExpandableTextArea={false}
summary="Text input"
title="Type"
>
<TypeRow
answers={[]}
blockTitle="BLocktiTLE"
correctAnswerCount={0}
key="multiplechoiceresponse"
label="Single select"
lastRow={false}
problemType="stringresponse"
selected={true}
setBlockTitle={[MockFunction args.setBlockTitle]}
typeKey="multiplechoiceresponse"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}
/>
<TypeRow
answers={[]}
blockTitle="BLocktiTLE"
correctAnswerCount={0}
key="choiceresponse"
label="Multi-select"
lastRow={false}
problemType="stringresponse"
selected={true}
setBlockTitle={[MockFunction args.setBlockTitle]}
typeKey="choiceresponse"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}
/>
<TypeRow
answers={[]}
blockTitle="BLocktiTLE"
correctAnswerCount={0}
key="optionresponse"
label="Dropdown"
lastRow={false}
problemType="stringresponse"
selected={true}
setBlockTitle={[MockFunction args.setBlockTitle]}
typeKey="optionresponse"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}
/>
<TypeRow
answers={[]}
blockTitle="BLocktiTLE"
correctAnswerCount={0}
key="numericalresponse"
label="Numerical input"
lastRow={false}
problemType="stringresponse"
selected={true}
setBlockTitle={[MockFunction args.setBlockTitle]}
typeKey="numericalresponse"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}
/>
<TypeRow
answers={[]}
blockTitle="BLocktiTLE"
correctAnswerCount={0}
key="stringresponse"
label="Text input"
lastRow={true}
problemType="stringresponse"
selected={false}
setBlockTitle={[MockFunction args.setBlockTitle]}
typeKey="stringresponse"
updateAnswer={[MockFunction args.updateAnswer]}
updateField={[MockFunction args.updateField]}
/>
</SettingsOption>
`;

View File

@@ -1,309 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = `
<EditorContainer
getContent={
{
"getContent": {
"editorRef": {
"current": {
"value": "something",
},
},
"showRawEditor": false,
},
}
}
isDirty={
{
"isDirty": {
"editorRef": {
"current": {
"value": "something",
},
},
"showRawEditor": false,
},
}
}
onClose={[MockFunction props.onClose]}
returnFunction={null}
>
<div
className="editor-body h-75 overflow-auto"
>
<Toast
onClose={[MockFunction hooks.nullMethod]}
show={true}
>
Error: Could Not Load Text Content
</Toast>
<TinyMceWidget
disabled={false}
editorContentHtml="eDiTablE Text"
editorRef={
{
"current": {
"value": "something",
},
}
}
editorType="text"
enableImageUpload={true}
id={null}
images={{}}
initializeEditor={[MockFunction args.intializeEditor]}
isLibrary={null}
learningContextId="course+org+run"
lmsEndpointUrl=""
maxHeight={500}
minHeight={500}
onChange={[Function]}
setEditorRef={[MockFunction hooks.prepareEditorRef.setEditorRef]}
studioEndpointUrl=""
/>
</div>
</EditorContainer>
`;
exports[`TextEditor snapshots loaded, raw editor 1`] = `
<EditorContainer
getContent={
{
"getContent": {
"editorRef": {
"current": {
"value": "something",
},
},
"showRawEditor": true,
},
}
}
isDirty={
{
"isDirty": {
"editorRef": {
"current": {
"value": "something",
},
},
"showRawEditor": true,
},
}
}
onClose={[MockFunction props.onClose]}
returnFunction={null}
>
<div
className="editor-body h-75 overflow-auto"
>
<Toast
onClose={[MockFunction hooks.nullMethod]}
show={false}
>
Error: Could Not Load Text Content
</Toast>
<RawEditor
content={
{
"data": {
"data": "eDiTablE Text",
},
}
}
editorRef={
{
"current": {
"value": "something",
},
}
}
lang="html"
/>
</div>
</EditorContainer>
`;
exports[`TextEditor snapshots not yet loaded, Spinner appears 1`] = `
<EditorContainer
getContent={
{
"getContent": {
"editorRef": {
"current": {
"value": "something",
},
},
"showRawEditor": false,
},
}
}
isDirty={
{
"isDirty": {
"editorRef": {
"current": {
"value": "something",
},
},
"showRawEditor": false,
},
}
}
onClose={[MockFunction props.onClose]}
returnFunction={null}
>
<div
className="editor-body h-75 overflow-auto"
>
<Toast
onClose={[MockFunction hooks.nullMethod]}
show={false}
>
Error: Could Not Load Text Content
</Toast>
<div
className="text-center p-6"
>
<Spinner
animation="border"
className="m-3"
screenreadertext="loading"
/>
</div>
</div>
</EditorContainer>
`;
exports[`TextEditor snapshots renders as expected with default behavior 1`] = `
<EditorContainer
getContent={
{
"getContent": {
"editorRef": {
"current": {
"value": "something",
},
},
"showRawEditor": false,
},
}
}
isDirty={
{
"isDirty": {
"editorRef": {
"current": {
"value": "something",
},
},
"showRawEditor": false,
},
}
}
onClose={[MockFunction props.onClose]}
returnFunction={null}
>
<div
className="editor-body h-75 overflow-auto"
>
<Toast
onClose={[MockFunction hooks.nullMethod]}
show={false}
>
Error: Could Not Load Text Content
</Toast>
<TinyMceWidget
disabled={false}
editorContentHtml="eDiTablE Text"
editorRef={
{
"current": {
"value": "something",
},
}
}
editorType="text"
enableImageUpload={true}
id={null}
images={{}}
initializeEditor={[MockFunction args.intializeEditor]}
isLibrary={null}
learningContextId="course+org+run"
lmsEndpointUrl=""
maxHeight={500}
minHeight={500}
onChange={[Function]}
setEditorRef={[MockFunction hooks.prepareEditorRef.setEditorRef]}
studioEndpointUrl=""
/>
</div>
</EditorContainer>
`;
exports[`TextEditor snapshots renders static images with relative paths 1`] = `
<EditorContainer
getContent={
{
"getContent": {
"editorRef": {
"current": {
"value": "something",
},
},
"showRawEditor": false,
},
}
}
isDirty={
{
"isDirty": {
"editorRef": {
"current": {
"value": "something",
},
},
"showRawEditor": false,
},
}
}
onClose={[MockFunction props.onClose]}
returnFunction={null}
>
<div
className="editor-body h-75 overflow-auto"
>
<Toast
onClose={[MockFunction hooks.nullMethod]}
show={false}
>
Error: Could Not Load Text Content
</Toast>
<TinyMceWidget
disabled={false}
editorContentHtml="eDiTablE Text with <img src="/asset+org+run+type@asset+block@img.jpg" />"
editorRef={
{
"current": {
"value": "something",
},
}
}
editorType="text"
enableImageUpload={true}
id={null}
images={{}}
initializeEditor={[MockFunction args.intializeEditor]}
isLibrary={null}
learningContextId="course+org+run"
lmsEndpointUrl=""
maxHeight={500}
minHeight={500}
onChange={[Function]}
setEditorRef={[MockFunction hooks.prepareEditorRef.setEditorRef]}
studioEndpointUrl=""
/>
</div>
</EditorContainer>
`;

View File

@@ -1,49 +1,14 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { render, screen, initializeMocks } from '@src/testUtils';
import { formatMessage } from '../../testUtils';
import { actions, selectors } from '../../data/redux';
import { RequestKeys } from '../../data/constants/requests';
import { TextEditorInternal as TextEditor, mapStateToProps, mapDispatchToProps } from '.';
// Per https://github.com/tinymce/tinymce-react/issues/91 React unit testing in JSDOM is not supported by tinymce.
// Consequently, mock the Editor out.
jest.mock('@tinymce/tinymce-react', () => {
const originalModule = jest.requireActual('@tinymce/tinymce-react');
return {
__esModule: true,
...originalModule,
Editor: () => 'TiNYmCE EDitOR',
};
});
jest.mock('../../sharedComponents/TinyMceWidget', () => 'TinyMceWidget');
jest.mock('../EditorContainer', () => 'EditorContainer');
jest.mock('./hooks', () => ({
getContent: jest.fn(args => ({ getContent: args })),
isDirty: jest.fn(args => ({ isDirty: args })),
nullMethod: jest.fn().mockName('hooks.nullMethod'),
}));
jest.mock('../../sharedComponents/TinyMceWidget/hooks', () => ({
...jest.requireActual('../../sharedComponents/TinyMceWidget/hooks'),
prepareEditorRef: jest.fn(() => ({
editorRef: { current: { value: 'something' } },
refReady: true,
setEditorRef: jest.fn().mockName('hooks.prepareEditorRef.setEditorRef'),
})),
}));
jest.mock('react', () => {
const updateState = jest.fn();
return {
...jest.requireActual('react'),
updateState,
useState: jest.fn(val => ([{ state: val }, jest.fn().mockName('setState')])),
};
});
jest.mock('../../data/redux', () => ({
__esModule: true,
default: jest.fn(),
@@ -87,33 +52,52 @@ describe('TextEditor', () => {
blockFinished: true,
learningContextId: 'course+org+run',
images: {},
isLibrary: false,
// inject
intl: { formatMessage },
};
describe('snapshots', () => {
test('renders as expected with default behavior', () => {
expect(shallow(<TextEditor {...props} />).snapshot).toMatchSnapshot();
afterAll(() => jest.restoreAllMocks());
describe('renders', () => {
beforeEach(() => {
initializeMocks();
});
test('renders as expected with default behavior', () => {
const { container } = render(<TextEditor {...props} />);
const element = container.querySelector('tinymcewidget');
expect(element).toBeInTheDocument();
expect(element?.getAttribute('editorcontenthtml')).toBe('eDiTablE Text');
});
test('renders static images with relative paths', () => {
const updatedProps = {
...props,
blockValue: { data: { data: 'eDiTablE Text with <img src="/static/img.jpg" />' } },
};
expect(shallow(<TextEditor {...updatedProps} />).snapshot).toMatchSnapshot();
const { container } = render(<TextEditor {...updatedProps} />);
const element = container.querySelector('tinymcewidget');
expect(element).toBeInTheDocument();
expect(element?.getAttribute('editorcontenthtml')).toBe('eDiTablE Text with <img src="/asset+org+run+type@asset+block@img.jpg" />');
});
test('not yet loaded, Spinner appears', () => {
expect(shallow(<TextEditor {...props} blockFinished={false} />).snapshot).toMatchSnapshot();
const { container } = render(<TextEditor {...props} blockFinished={false} />);
expect(container.querySelector('.pgn__spinner')).toBeInTheDocument();
});
test('loaded, raw editor', () => {
expect(shallow(<TextEditor {...props} showRawEditor />).snapshot).toMatchSnapshot();
render(<TextEditor {...props} showRawEditor />);
expect(screen.getByText('You are using the raw html editor.')).toBeInTheDocument();
});
test('block failed to load, Toast is shown', () => {
expect(shallow(<TextEditor {...props} blockFailed />).snapshot).toMatchSnapshot();
render(<TextEditor {...props} blockFailed isLibrary />);
expect(screen.getByRole('alert')).toBeInTheDocument();
expect(screen.getByText('Error: Could Not Load Text Content')).toBeInTheDocument();
});
});
describe('mapStateToProps', () => {
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
// type set to any to prevent warning on not matchig expected type on the selectors
const testState: any = { A: 'pple', B: 'anana', C: 'ucumber' };
test('blockValue from app.blockValue', () => {
expect(
mapStateToProps(testState).blockValue,

View File

@@ -1,12 +1,12 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import {
render, screen, initializeMocks, fireEvent,
} from '@src/testUtils';
import { thunkActions, selectors } from '../../../../../../data/redux';
import * as module from './TranscriptActionMenu';
import * as componentModule from './TranscriptActionMenu';
const TranscriptActionMenu = module.TranscriptActionMenuInternal;
const TranscriptActionMenu = componentModule.TranscriptActionMenuInternal;
jest.mock('react-redux', () => {
const dispatchFn = jest.fn().mockName('mockUseDispatch');
@@ -49,7 +49,7 @@ describe('TranscriptActionMenu', () => {
const result = { newFile: { mockFile, name: mockFileName }, newFilename: mockFileName, language: lang1Code };
test('it dispatches the correct thunk', () => {
const cb = module.hooks.replaceFileCallback({
const cb = componentModule.hooks.replaceFileCallback({
dispatch: mockDispatch, language: lang1Code,
});
cb(mockEvent);
@@ -59,42 +59,51 @@ describe('TranscriptActionMenu', () => {
});
});
describe('Snapshots', () => {
describe('renders', () => {
const props = {
index: 'sOmenUmBer',
index: 1,
language: 'lAnG',
launchDeleteConfirmation: jest.fn().mockName('launchDeleteConfirmation'),
// redux
getTranscriptDownloadUrl: jest.fn().mockName('selectors.video.getTranscriptDownloadUrl'),
buildTranscriptUrl: jest.fn().mockName('selectors.video.buildTranscriptUrl'),
buildTranscriptUrl: jest.fn().mockName('selectors.video.buildTranscriptUrl').mockImplementation((url) => url.transcriptUrl),
};
beforeEach(() => {
initializeMocks();
});
afterAll(() => {
jest.clearAllMocks();
});
test('snapshots: renders as expected with default props: dont show confirm delete', () => {
jest.spyOn(module.hooks, 'replaceFileCallback').mockImplementationOnce(() => jest.fn().mockName('module.hooks.replaceFileCallback'));
expect(
shallow(<TranscriptActionMenu {...props} />).snapshot,
).toMatchSnapshot();
test('renders as expected with default props', () => {
render(<TranscriptActionMenu {...props} />);
expect(screen.getByRole('button', { name: 'Actions dropdown' })).toBeInTheDocument();
});
test('snapshots: renders as expected with transcriptUrl props: dont show confirm delete', () => {
jest.spyOn(module.hooks, 'replaceFileCallback').mockImplementationOnce(() => jest.fn().mockName('module.hooks.replaceFileCallback'));
expect(
shallow(<TranscriptActionMenu {...props} transcriptUrl="url" />).snapshot,
).toMatchSnapshot();
test('snapshots: renders as expected with transcriptUrl props', () => {
render(<TranscriptActionMenu {...props} transcriptUrl="url" />);
const actionsDropdown = screen.getByRole('button', { name: 'Actions dropdown' });
expect(actionsDropdown).toBeInTheDocument();
fireEvent.click(actionsDropdown);
const downloadOption = screen.getByRole('link', { name: 'Download' });
expect(downloadOption).toBeInTheDocument();
expect(downloadOption).toHaveAttribute('href', 'url');
});
});
describe('mapStateToProps', () => {
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
// type set to any to prevent warning on not matchig expected type on the selectors
const testState: any = { A: 'pple', B: 'anana', C: 'ucumber' };
test('getTranscriptDownloadUrl from video.getTranscriptDownloadUrl', () => {
expect(
module.mapStateToProps(testState).getTranscriptDownloadUrl,
componentModule.mapStateToProps(testState).getTranscriptDownloadUrl,
).toEqual(selectors.video.getTranscriptDownloadUrl(testState));
});
});
describe('mapDispatchToProps', () => {
test('deleteTranscript from thunkActions.video.deleteTranscript', () => {
expect(module.mapDispatchToProps.downloadTranscript).toEqual(thunkActions.video.downloadTranscript);
expect(componentModule.mapDispatchToProps.downloadTranscript).toEqual(thunkActions.video.downloadTranscript);
});
});
});

View File

@@ -1,109 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TranscriptActionMenu Snapshots snapshots: renders as expected with default props: dont show confirm delete 1`] = `
<Dropdown>
<Dropdown.Toggle
alt="Actions dropdown"
as="IconButton"
iconAs="Icon"
id="dropdown-toggle-with-iconbutton-video-transcript-widget"
variant="primary"
/>
<Dropdown.Menu
className="video_transcript Action Menu"
>
<Dropdown.Item
key="transcript-actions-sOmenUmBer-replace"
onClick={[MockFunction click input]}
>
<FormattedMessage
defaultMessage="Replace"
description="Message Presented To user for action to replace transcript"
id="authoring.videoeditor.transcript.replaceTranscript"
/>
</Dropdown.Item>
<Dropdown.Item
key="transcript-actions-sOmenUmBer-download"
>
<FormattedMessage
defaultMessage="Download"
description="Message Presented To user for action to download transcript"
id="authoring.videoeditor.transcript.downloadTranscript"
/>
</Dropdown.Item>
<Dropdown.Item
key="transcript-actions-sOmenUmBer-delete"
onClick={[MockFunction launchDeleteConfirmation]}
>
<FormattedMessage
defaultMessage="Delete"
description="Message Presented To user for action to delete transcript"
id="authoring.videoeditor.transcript.deleteTranscript"
/>
</Dropdown.Item>
</Dropdown.Menu>
<FileInput
acceptedFiles=".srt"
fileInput={
{
"click": [MockFunction click input],
"onAddFile": [MockFunction module.hooks.replaceFileCallback],
}
}
/>
</Dropdown>
`;
exports[`TranscriptActionMenu Snapshots snapshots: renders as expected with transcriptUrl props: dont show confirm delete 1`] = `
<Dropdown>
<Dropdown.Toggle
alt="Actions dropdown"
as="IconButton"
iconAs="Icon"
id="dropdown-toggle-with-iconbutton-video-transcript-widget"
variant="primary"
/>
<Dropdown.Menu
className="video_transcript Action Menu"
>
<Dropdown.Item
key="transcript-actions-sOmenUmBer-replace"
onClick={[MockFunction click input]}
>
<FormattedMessage
defaultMessage="Replace"
description="Message Presented To user for action to replace transcript"
id="authoring.videoeditor.transcript.replaceTranscript"
/>
</Dropdown.Item>
<Dropdown.Item
key="transcript-actions-sOmenUmBer-download"
>
<FormattedMessage
defaultMessage="Download"
description="Message Presented To user for action to download transcript"
id="authoring.videoeditor.transcript.downloadTranscript"
/>
</Dropdown.Item>
<Dropdown.Item
key="transcript-actions-sOmenUmBer-delete"
onClick={[MockFunction launchDeleteConfirmation]}
>
<FormattedMessage
defaultMessage="Delete"
description="Message Presented To user for action to delete transcript"
id="authoring.videoeditor.transcript.deleteTranscript"
/>
</Dropdown.Item>
</Dropdown.Menu>
<FileInput
acceptedFiles=".srt"
fileInput={
{
"click": [MockFunction click input],
"onAddFile": [MockFunction module.hooks.replaceFileCallback],
}
}
/>
</Dropdown>
`;