test: replacing snapshot tests with RTL tests part 11 (#2214)

This commit is contained in:
jacobo-dominguez-wgu
2025-06-24 04:04:03 -06:00
committed by GitHub
parent 31fc0453b4
commit 71fa247c61
14 changed files with 185 additions and 465 deletions

View File

@@ -1,31 +0,0 @@
import { shallow } from '@edx/react-unit-test-utils';
import { FeedbackBox } from './FeedbackBox';
const answerWithFeedback = {
id: 'A',
title: 'Answer 1',
correct: true,
selectedFeedback: 'some feedback',
unselectedFeedback: 'unselectedFeedback',
problemType: 'sOMepRObleM',
images: {},
isLibrary: false,
learningContextId: 'course+org+run',
};
const props = {
answer: answerWithFeedback,
intl: {},
};
describe('FeedbackBox component', () => {
test('renders as expected with default props', () => {
expect(shallow(<FeedbackBox {...props} />).snapshot).toMatchSnapshot();
});
test('renders as expected with a numeric input problem', () => {
expect(shallow(<FeedbackBox {...props} problemType="numericalresponse" />).snapshot).toMatchSnapshot();
});
test('renders as expected with a multi select problem', () => {
expect(shallow(<FeedbackBox {...props} problemType="choiceresponse" />).snapshot).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,49 @@
import { render, screen, initializeMocks } from '@src/testUtils';
import { FeedbackBox } from './FeedbackBox';
jest.mock('../../../../../../../sharedComponents/ExpandableTextArea', () => jest.fn(({
id, value, setContent, placeholder,
}) => (
<textarea id={id} value={value} placeholder={placeholder} onChange={e => setContent(e.target.value)} />
)));
const answerWithFeedback = {
id: 'A',
title: 'Answer 1',
correct: true,
selectedFeedback: 'some feedback',
unselectedFeedback: 'unselectedFeedback',
problemType: 'sOMepRObleM',
images: {},
isLibrary: false,
learningContextId: 'course+org+run',
};
const props = {
answer: answerWithFeedback,
problemType: '',
setAnswer: jest.fn(),
setSelectedFeedback: jest.fn(),
setUnselectedFeedback: jest.fn(),
images: {},
learningContextId: 'id',
isLibrary: false,
};
describe('FeedbackBox', () => {
beforeEach(() => initializeMocks());
test('renders as expected with default props', () => {
render(<FeedbackBox {...props} />);
expect(screen.getByText(/Show following feedback when A/)).toBeInTheDocument();
});
test('renders as expected with a numeric input problem', () => {
render(<FeedbackBox {...props} problemType="numericalresponse" />);
expect(screen.getByText(/Show following feedback when A/)).toBeInTheDocument();
expect(screen.getAllByText(/Show following feedback when A/)).toHaveLength(1);
});
test('renders as expected with a multi select problem', () => {
render(<FeedbackBox {...props} problemType="choiceresponse" />);
expect(screen.getAllByText(/Show following feedback when A/)).toHaveLength(2);
});
});

View File

@@ -1,154 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FeedbackBox component renders as expected with a multi select problem 1`] = `
<div
className="bg-light-300 p-4 mt-3 rounded text-primary-500"
>
<FeedbackControl
answer={
{
"correct": true,
"id": "A",
"images": {},
"isLibrary": false,
"learningContextId": "course+org+run",
"problemType": "sOMepRObleM",
"selectedFeedback": "some feedback",
"title": "Answer 1",
"unselectedFeedback": "unselectedFeedback",
}
}
feedback="some feedback"
intl={{}}
key="selectedfeedback-A"
labelMessage={
{
"defaultMessage": "Show following feedback when {answerId} {boldunderline}:",
"description": "Label text for feedback if option is selected",
"id": "authoring.answerwidget.feedback.selected.label",
}
}
labelMessageBoldUnderline={
{
"defaultMessage": "is selected",
"description": "Bold & underlined text for feedback if option is selected",
"id": "authoring.answerwidget.feedback.selected.label.boldunderline",
}
}
type="selected"
/>
<FeedbackControl
answer={
{
"correct": true,
"id": "A",
"images": {},
"isLibrary": false,
"learningContextId": "course+org+run",
"problemType": "sOMepRObleM",
"selectedFeedback": "some feedback",
"title": "Answer 1",
"unselectedFeedback": "unselectedFeedback",
}
}
feedback="unselectedFeedback"
intl={{}}
key="unselectedfeedback-A"
labelMessage={
{
"defaultMessage": "Show following feedback when {answerId} {boldunderline}:",
"description": "Label text for feedback if option is not selected",
"id": "authoring.answerwidget.feedback.unselected.label",
}
}
labelMessageBoldUnderline={
{
"defaultMessage": "is not selected",
"description": "Bold & underlined text for feedback if option is not selected",
"id": "authoring.answerwidget.feedback.unselected.label.boldunderline",
}
}
type="unselected"
/>
</div>
`;
exports[`FeedbackBox component renders as expected with a numeric input problem 1`] = `
<div
className="bg-light-300 p-4 mt-3 rounded text-primary-500"
>
<FeedbackControl
answer={
{
"correct": true,
"id": "A",
"images": {},
"isLibrary": false,
"learningContextId": "course+org+run",
"problemType": "sOMepRObleM",
"selectedFeedback": "some feedback",
"title": "Answer 1",
"unselectedFeedback": "unselectedFeedback",
}
}
feedback="some feedback"
intl={{}}
key="selectedfeedback-A"
labelMessage={
{
"defaultMessage": "Show following feedback when {answerId} {boldunderline}:",
"description": "Label text for feedback if option is selected",
"id": "authoring.answerwidget.feedback.selected.label",
}
}
labelMessageBoldUnderline={
{
"defaultMessage": "is selected",
"description": "Bold & underlined text for feedback if option is selected",
"id": "authoring.answerwidget.feedback.selected.label.boldunderline",
}
}
type="selected"
/>
</div>
`;
exports[`FeedbackBox component renders as expected with default props 1`] = `
<div
className="bg-light-300 p-4 mt-3 rounded text-primary-500"
>
<FeedbackControl
answer={
{
"correct": true,
"id": "A",
"images": {},
"isLibrary": false,
"learningContextId": "course+org+run",
"problemType": "sOMepRObleM",
"selectedFeedback": "some feedback",
"title": "Answer 1",
"unselectedFeedback": "unselectedFeedback",
}
}
feedback="some feedback"
intl={{}}
key="selectedfeedback-A"
labelMessage={
{
"defaultMessage": "Show following feedback when {answerId} {boldunderline}:",
"description": "Label text for feedback if option is selected",
"id": "authoring.answerwidget.feedback.selected.label",
}
}
labelMessageBoldUnderline={
{
"defaultMessage": "is selected",
"description": "Bold & underlined text for feedback if option is selected",
"id": "authoring.answerwidget.feedback.selected.label.boldunderline",
}
}
type="selected"
/>
</div>
`;

View File

@@ -1,15 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import { shallow } from '@edx/react-unit-test-utils';
import CardSection from './CardSection';
describe('CardSection', () => {
test('open', () => {
expect(shallow(<CardSection summary="summary" isCardCollapsibleOpen><h1>Section Text</h1></CardSection>).snapshot).toMatchSnapshot();
});
test('closed', () => {
expect(
shallow(<CardSection isCardCollapsibleOpen={false}><h1>Section Text</h1></CardSection>).snapshot,
).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,23 @@
import { render, screen, initializeMocks } from '@src/testUtils';
import CardSection from './CardSection';
describe('CardSection', () => {
beforeEach(() => initializeMocks());
test('renders children when open', () => {
render(<CardSection summary="summary" isCardCollapsibleOpen><h1>Section Text</h1></CardSection>);
expect(screen.getByText('Section Text')).toBeInTheDocument();
expect(screen.queryByText('summary')).not.toBeInTheDocument();
});
test('renders summary when closed', () => {
render(<CardSection summary="summary" isCardCollapsibleOpen={false}><h1>Section Text</h1></CardSection>);
expect(screen.queryByText('Section Text')).not.toBeInTheDocument();
expect(screen.getByText('summary')).toBeInTheDocument();
});
test('renders nothing when closed and not summary', () => {
const { container } = render(<CardSection isCardCollapsibleOpen={false}><h1>Not showing text</h1></CardSection>);
expect(screen.queryByText('Not showing text')).not.toBeInTheDocument();
expect(container.textContent).toBe('');
});
});

View File

@@ -1,34 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CardSection closed 1`] = `null`;
exports[`CardSection open 1`] = `
<Card.Section
className="pt-0"
>
<Advanced
open={false}
>
<Body
className="collapsible-body"
>
<span
className="small text-primary-500"
>
summary
</span>
</Body>
</Advanced>
<Advanced
open={true}
>
<Body
className="collapsible-body text-primary-500 x-small"
>
<h1>
Section Text
</h1>
</Body>
</Advanced>
</Card.Section>
`;

View File

@@ -1,30 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { SwitchEditorCardInternal as SwitchEditorCard, mapDispatchToProps } from './SwitchEditorCard';
import { thunkActions } from '../../../../../../data/redux';
describe('SwitchEditorCard snapshot', () => {
const mockSwitchEditor = jest.fn().mockName('switchEditor');
test('snapshot: SwitchEditorCard', () => {
expect(
shallow(<SwitchEditorCard switchEditor={mockSwitchEditor} problemType="stringresponse" />).snapshot,
).toMatchSnapshot();
});
test('snapshot: SwitchEditorCard returns null for advanced problems', () => {
expect(
shallow(<SwitchEditorCard switchEditor={mockSwitchEditor} problemType="advanced" />).snapshot,
).toMatchSnapshot();
});
test('snapshot: SwitchEditorCard returns null when editor is Markdown', () => {
expect(
shallow(<SwitchEditorCard switchEditor={mockSwitchEditor} problemType="stringresponse" editorType="markdown" isMarkdownEditorEnabled />).snapshot,
).toMatchSnapshot();
});
describe('mapDispatchToProps', () => {
test('updateField from actions.problem.updateField', () => {
expect(mapDispatchToProps.switchEditor).toEqual(thunkActions.problem.switchEditor);
});
});
});

View File

@@ -0,0 +1,58 @@
import React from 'react';
import {
render, screen, initializeMocks, fireEvent,
} from '@src/testUtils';
import { SwitchEditorCardInternal as SwitchEditorCard, mapDispatchToProps } from './SwitchEditorCard';
import { thunkActions } from '../../../../../../data/redux';
describe('SwitchEditorCard', () => {
const mockSwitchEditor = jest.fn().mockName('switchEditor');
const baseProps = {
switchEditor: mockSwitchEditor,
problemType: 'stringresponse',
editorType: 'markdown',
isMarkdownEditorEnabled: false,
};
beforeEach(() => {
initializeMocks();
});
test('renders SwitchEditorCard', () => {
render(<SwitchEditorCard {...baseProps} />);
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
const switchButton = screen.getByRole('button', { name: 'Switch to markdown editor' });
expect(switchButton).toBeInTheDocument();
fireEvent.click(switchButton);
expect(screen.getByRole('dialog')).toBeInTheDocument();
});
test('calls switchEditor function when confirm button is clicked', () => {
render(<SwitchEditorCard {...baseProps} />);
const switchButton = screen.getByRole('button', { name: 'Switch to markdown editor' });
expect(switchButton).toBeInTheDocument();
fireEvent.click(switchButton);
const confirmButton = screen.getByRole('button', { name: 'Switch to markdown editor' });
expect(confirmButton).toBeInTheDocument();
fireEvent.click(confirmButton);
expect(mockSwitchEditor).toHaveBeenCalledWith('markdown');
});
test('renders nothing for advanced problemType', () => {
const { container } = render(<SwitchEditorCard {...baseProps} problemType="advanced" />);
const reduxWrapper = (container.firstChild as HTMLElement | null);
expect(reduxWrapper?.innerHTML).toBe('');
});
test('snapshot: SwitchEditorCard returns null when editor is Markdown', () => {
const { container } = render(<SwitchEditorCard {...baseProps} editorType="markdown" isMarkdownEditorEnabled />);
const reduxWrapper = (container.firstChild as HTMLElement | null);
expect(reduxWrapper?.innerHTML).toBe('');
});
describe('mapDispatchToProps', () => {
test('updateField from actions.problem.updateField', () => {
expect(mapDispatchToProps.switchEditor).toEqual(thunkActions.problem.switchEditor);
});
});
});

View File

@@ -1,44 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SwitchEditorCard snapshot snapshot: SwitchEditorCard 1`] = `
<Card
className="border border-light-700 shadow-none"
>
<BaseModal
bodyStyle={null}
close={[Function]}
confirmAction={
<Button
className={null}
onClick={[Function]}
text={null}
variant="primary"
>
<FormattedMessage />
</Button>
}
footerAction={null}
headerComponent={null}
hideCancelButton={false}
isFullscreenScroll={true}
isOpen={false}
size="md"
title={<FormattedMessage />}
>
<FormattedMessage />
</BaseModal>
<Button
className="my-3 ml-2 py-0"
onClick={[Function]}
size="sm"
text={null}
variant="link"
>
<FormattedMessage />
</Button>
</Card>
`;
exports[`SwitchEditorCard snapshot snapshot: SwitchEditorCard returns null for advanced problems 1`] = `null`;
exports[`SwitchEditorCard snapshot snapshot: SwitchEditorCard returns null when editor is Markdown 1`] = `null`;

View File

@@ -1,64 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DurationWidget render snapshots: renders as expected with default props 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
subtitle="Custom: 00:00:00"
title="Duration"
>
<FormattedMessage
defaultMessage="Set a specific section of the video to play."
description="Description of Duration widget"
id="authoring.videoeditor.duration.description"
/>
<Form.Row
className="mt-4.5"
>
<Form.Group
as="Col"
>
<Form.Control
floatingLabel="Start time"
onBlur={[Function]}
onChange={[Function]}
onKeyDown={[Function]}
value="00:00:00"
/>
<Form.Control.Feedback>
<FormattedMessage
defaultMessage="Enter time as HH:MM:SS"
description="Hint text for start and stop time input fields"
id="authoring.videoeditor.duration.hint"
/>
</Form.Control.Feedback>
</Form.Group>
<Form.Group
as="Col"
>
<Form.Control
floatingLabel="Stop time"
onBlur={[Function]}
onChange={[Function]}
onKeyDown={[Function]}
value="00:00:00"
/>
<Form.Control.Feedback>
<FormattedMessage
defaultMessage="Enter time as HH:MM:SS"
description="Hint text for start and stop time input fields"
id="authoring.videoeditor.duration.hint"
/>
</Form.Control.Feedback>
</Form.Group>
</Form.Row>
<div
className="mt-4 mx-2 text-right"
>
<span
className="p-2 total-label rounded"
>
Total: 00:00:00
</span>
</div>
</CollapsibleFormWidget>
`;

View File

@@ -1,52 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { actions, selectors } from '../../../../../../data/redux';
import { formatMessage } from '../../../../../../testUtils';
import { DurationWidgetInternal as DurationWidget, mapStateToProps, mapDispatchToProps } from '.';
jest.mock('../../../../../../data/redux', () => ({
actions: {
video: {
updateField: jest.fn().mockName('actions.video.updateField'),
},
},
selectors: {
video: {
duration: jest.fn(state => ({ duration: state })),
},
},
}));
describe('DurationWidget', () => {
const props = {
duration: {
startTime: '00:00:00',
stopTime: '00:00:10',
},
updateField: jest.fn().mockName('updateField'),
// inject
intl: { formatMessage },
};
describe('render', () => {
test('snapshots: renders as expected with default props', () => {
expect(
shallow(<DurationWidget {...props} />).snapshot,
).toMatchSnapshot();
});
});
describe('mapStateToProps', () => {
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
test('duration from video.duration', () => {
expect(
mapStateToProps(testState).duration,
).toEqual(selectors.video.duration(testState));
});
});
describe('mapDispatchToProps', () => {
test('updateField from actions.video.updateField', () => {
expect(mapDispatchToProps.updateField).toEqual(actions.video.updateField);
});
});
});

View File

@@ -0,0 +1,47 @@
import React from 'react';
import { render, screen, initializeMocks } from '@src/testUtils';
import { actions, selectors } from '../../../../../../data/redux';
import { formatMessage } from '../../../../../../testUtils';
import { DurationWidgetInternal as DurationWidget, mapStateToProps, mapDispatchToProps } from '.';
describe('DurationWidget', () => {
describe('render', () => {
beforeEach(() => initializeMocks());
test('renders as expected with default props', () => {
const props = {
duration: {
startTime: 0,
stopTime: 10,
},
updateField: jest.fn().mockName('updateField'),
// inject
intl: { formatMessage },
};
render(<DurationWidget {...props} />);
expect(screen.getByText('Set a specific section of the video to play.')).toBeInTheDocument();
expect(screen.getByText('Duration')).toBeInTheDocument();
});
});
describe('mapStateToProps', () => {
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
beforeAll(() => {
selectors.video = {
// @ts-expect-error: test override for selector
duration: jest.fn().mockReturnValue({ startTime: 0, stopTime: 10 }),
};
});
test('duration from video.duration', () => {
expect(
mapStateToProps(testState).duration,
// @ts-expect-error: test override for selector
).toEqual(selectors.video.duration(testState));
});
});
describe('mapDispatchToProps', () => {
test('updateField from actions.video.updateField', () => {
expect(mapDispatchToProps.updateField).toEqual(actions.video.updateField);
});
});
});

View File

@@ -1,36 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CourseUnitHeaderActionsSlot pluginProps are set correctly 1`] = `
<PluginSlot
id="org.openedx.frontend.authoring.course_unit_header_actions.v1"
idAliases={
[
"course_unit_header_actions_slot",
]
}
pluginProps={
{
"category": "vertical",
"headerNavigationsActions": {
"handleEdit": [MockFunction],
"handlePreview": [MockFunction],
"handleViewLive": [MockFunction],
},
"isUnitVerticalType": true,
"unitTitle": "Mock Unit",
"verticalBlocks": [],
}
}
>
<HeaderNavigations
category="vertical"
headerNavigationsActions={
{
"handleEdit": [MockFunction],
"handlePreview": [MockFunction],
"handleViewLive": [MockFunction],
}
}
/>
</PluginSlot>
`;

View File

@@ -1,7 +1,7 @@
import { shallow } from '@edx/react-unit-test-utils';
import { render, initializeMocks } from '@src/testUtils';
import renderer from 'react-test-renderer';
import { COURSE_BLOCK_NAMES } from 'CourseAuthoring/constants';
import { COURSE_BLOCK_NAMES } from '@src/constants';
import CourseUnitHeaderActionsSlot from '.';
jest.mock('CourseAuthoring/course-unit/header-navigations/HeaderNavigations', () => 'HeaderNavigations');
@@ -19,15 +19,18 @@ const headerNavProps = {
},
category: 'vertical',
unitTitle: 'Mock Unit',
isUnitVerticalType: false,
verticalBlocks: [],
};
describe('CourseUnitHeaderActionsSlot', () => {
beforeEach(() => jest.resetAllMocks());
beforeEach(() => initializeMocks());
test('pluginProps are set correctly', () => {
const wrapper = shallow(<CourseUnitHeaderActionsSlot unitTitle="Mock Title" verticalBlocks={[]} {...headerNavProps} />);
expect(wrapper.snapshot).toMatchSnapshot();
const { container } = render(<CourseUnitHeaderActionsSlot {...headerNavProps} />);
expect(container.querySelector('pluginslot')).toBeInTheDocument();
expect(container.querySelector('headernavigations')).toBeInTheDocument();
expect(container.querySelector('headernavigations')?.getAttribute('category')).toBe('vertical');
});
test('isUnitVerticalType is set correctly', () => {