test: replacing snapshot tests with RTL tests part 2 (#2132)
This commit is contained in:
committed by
GitHub
parent
acef2e70cc
commit
3097976b7b
@@ -1,224 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`EditorProblemView component renders markdown editor when isMarkdownEditorEnabled is true 1`] = `
|
||||
<EditorContainer
|
||||
getContent={[Function]}
|
||||
isDirty={[Function]}
|
||||
returnFunction={null}
|
||||
>
|
||||
<AlertModal
|
||||
footerNode={
|
||||
<ActionRow>
|
||||
<Button
|
||||
onClick={[Function]}
|
||||
variant="tertiary"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Cancel"
|
||||
description="Label for cancel button in the save warning modal"
|
||||
id="authoring.problemEditor.editProblemView.saveWarningModal.cancelButton.label"
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
onClick={[Function]}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Ok"
|
||||
description="Label for save button in the save warning modal"
|
||||
id="authoring.problemEditor.editProblemView.saveWarningModal.saveButton.label"
|
||||
/>
|
||||
</Button>
|
||||
</ActionRow>
|
||||
}
|
||||
isOpen={false}
|
||||
onClose={[Function]}
|
||||
title="No answer specified"
|
||||
>
|
||||
<Fragment>
|
||||
<div>
|
||||
<FormattedMessage
|
||||
defaultMessage="Are you sure you want to exit the editor?"
|
||||
description="Question in body of save warning modal"
|
||||
id="authoring.problemEditor.editProblemView.saveWarningModal.body.question"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<FormattedMessage
|
||||
defaultMessage="No correct answer has been specified."
|
||||
description="Explanation in body of no answer modal"
|
||||
id="authoring.problemEditor.editProblemView.saveWarningModal.noAnswer.body.explanation"
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
</AlertModal>
|
||||
<div
|
||||
className="editProblemView d-flex flex-row flex-nowrap justify-content-end"
|
||||
>
|
||||
<Container
|
||||
className="advancedEditorTopMargin p-0"
|
||||
fluid={true}
|
||||
>
|
||||
<RawEditor
|
||||
content="# Markdown content"
|
||||
editorRef={
|
||||
{
|
||||
"current": null,
|
||||
}
|
||||
}
|
||||
lang="markdown"
|
||||
/>
|
||||
</Container>
|
||||
<span
|
||||
className="editProblemView-settingsColumn"
|
||||
>
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
problemType="multiplechoiceresponse"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</EditorContainer>
|
||||
`;
|
||||
|
||||
exports[`EditorProblemView component renders raw editor for advanced problem type 1`] = `
|
||||
<EditorContainer
|
||||
getContent={[Function]}
|
||||
isDirty={[Function]}
|
||||
returnFunction={null}
|
||||
>
|
||||
<AlertModal
|
||||
footerNode={
|
||||
<ActionRow>
|
||||
<Button
|
||||
onClick={[Function]}
|
||||
variant="tertiary"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Cancel"
|
||||
description="Label for cancel button in the save warning modal"
|
||||
id="authoring.problemEditor.editProblemView.saveWarningModal.cancelButton.label"
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
onClick={[Function]}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Ok"
|
||||
description="Label for save button in the save warning modal"
|
||||
id="authoring.problemEditor.editProblemView.saveWarningModal.saveButton.label"
|
||||
/>
|
||||
</Button>
|
||||
</ActionRow>
|
||||
}
|
||||
isOpen={false}
|
||||
onClose={[Function]}
|
||||
title="OLX settings discrepancy"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="A discrepancy was found between the settings defined in the OLX's problem tag and the
|
||||
settings selected in the sidebar. The settings defined in the OLX's problem tag will be saved and
|
||||
corresponding values in the sidebar will be discarded."
|
||||
description="Explanation in body of mismatched settings modal"
|
||||
id="authoring.problemEditor.editProblemView.saveWarningModal.olxSettingDiscrepancy.body.explanation"
|
||||
/>
|
||||
</AlertModal>
|
||||
<div
|
||||
className="editProblemView d-flex flex-row flex-nowrap justify-content-end"
|
||||
>
|
||||
<Container
|
||||
className="advancedEditorTopMargin p-0"
|
||||
fluid={true}
|
||||
>
|
||||
<RawEditor
|
||||
content="<problem>...</problem>"
|
||||
editorRef={
|
||||
{
|
||||
"current": null,
|
||||
}
|
||||
}
|
||||
lang="xml"
|
||||
/>
|
||||
</Container>
|
||||
<span
|
||||
className="editProblemView-settingsColumn"
|
||||
>
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
problemType="advanced"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</EditorContainer>
|
||||
`;
|
||||
|
||||
exports[`EditorProblemView component renders simple view 1`] = `
|
||||
<EditorContainer
|
||||
getContent={[Function]}
|
||||
isDirty={[Function]}
|
||||
returnFunction={null}
|
||||
>
|
||||
<AlertModal
|
||||
footerNode={
|
||||
<ActionRow>
|
||||
<Button
|
||||
onClick={[Function]}
|
||||
variant="tertiary"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Cancel"
|
||||
description="Label for cancel button in the save warning modal"
|
||||
id="authoring.problemEditor.editProblemView.saveWarningModal.cancelButton.label"
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
onClick={[Function]}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Ok"
|
||||
description="Label for save button in the save warning modal"
|
||||
id="authoring.problemEditor.editProblemView.saveWarningModal.saveButton.label"
|
||||
/>
|
||||
</Button>
|
||||
</ActionRow>
|
||||
}
|
||||
isOpen={false}
|
||||
onClose={[Function]}
|
||||
title="No answer specified"
|
||||
>
|
||||
<Fragment>
|
||||
<div>
|
||||
<FormattedMessage
|
||||
defaultMessage="Are you sure you want to exit the editor?"
|
||||
description="Question in body of save warning modal"
|
||||
id="authoring.problemEditor.editProblemView.saveWarningModal.body.question"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<FormattedMessage
|
||||
defaultMessage="No correct answer has been specified."
|
||||
description="Explanation in body of no answer modal"
|
||||
id="authoring.problemEditor.editProblemView.saveWarningModal.noAnswer.body.explanation"
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
</AlertModal>
|
||||
<div
|
||||
className="editProblemView d-flex flex-row flex-nowrap justify-content-end"
|
||||
>
|
||||
<span
|
||||
className="flex-grow-1 mb-5"
|
||||
>
|
||||
<injectIntl(ShimmedIntlComponent) />
|
||||
<injectIntl(ShimmedIntlComponent) />
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
problemType="multiplechoiceresponse"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
className="editProblemView-settingsColumn"
|
||||
>
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
problemType="multiplechoiceresponse"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</EditorContainer>
|
||||
`;
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect, useDispatch } from 'react-redux';
|
||||
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import {
|
||||
Container,
|
||||
@@ -36,17 +36,15 @@ const EditProblemView = ({
|
||||
returnUrl,
|
||||
analytics,
|
||||
isDirty,
|
||||
// injected
|
||||
intl,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useDispatch();
|
||||
const editorRef = useRef(null);
|
||||
const isAdvancedProblemType = problemType === ProblemTypeKeys.ADVANCED;
|
||||
const { isSaveWarningModalOpen, openSaveWarningModal, closeSaveWarningModal } = saveWarningModalToggle();
|
||||
|
||||
/* istanbul ignore next */
|
||||
const checkIfDirty = () => {
|
||||
if (isAdvancedProblemType && editorRef && editorRef?.current) {
|
||||
/* istanbul ignore next */
|
||||
return editorRef.current.observer?.lastChange !== 0;
|
||||
}
|
||||
return isDirty || checkIfEditorsDirty();
|
||||
@@ -145,8 +143,6 @@ EditProblemView.propTypes = {
|
||||
returnUrl: PropTypes.string.isRequired,
|
||||
isDirty: PropTypes.bool,
|
||||
isMarkdownEditorEnabled: PropTypes.bool,
|
||||
// injected
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export const mapStateToProps = (state) => ({
|
||||
@@ -161,4 +157,4 @@ export const mapStateToProps = (state) => ({
|
||||
});
|
||||
|
||||
export const EditProblemViewInternal = EditProblemView; // For testing only
|
||||
export default injectIntl(connect(mapStateToProps)(EditProblemView));
|
||||
export default connect(mapStateToProps)(EditProblemView);
|
||||
|
||||
@@ -1,62 +1,147 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import { EditProblemViewInternal as EditProblemView } from '.';
|
||||
import { AnswerWidgetInternal as AnswerWidget } from './AnswerWidget';
|
||||
import { Provider } from 'react-redux';
|
||||
import {
|
||||
render as baseRender, screen, fireEvent, initializeMocks,
|
||||
} from '../../../../../testUtils';
|
||||
import { EditProblemViewInternal, mapStateToProps } from './index';
|
||||
import { ProblemTypeKeys } from '../../../../data/constants/problem';
|
||||
import RawEditor from '../../../../sharedComponents/RawEditor';
|
||||
import { formatMessage } from '../../../../testUtils';
|
||||
import { EditorContextProvider } from '../../../../EditorContext';
|
||||
import editorStore from '../../../../data/store';
|
||||
import { selectors } from '../../../../data/redux';
|
||||
|
||||
describe('EditorProblemView component', () => {
|
||||
test('renders simple view', () => {
|
||||
const wrapper = shallow(<EditProblemView
|
||||
problemType={ProblemTypeKeys.SINGLESELECT}
|
||||
problemState={{}}
|
||||
assets={{}}
|
||||
intl={{ formatMessage }}
|
||||
/>);
|
||||
expect(wrapper.snapshot).toMatchSnapshot();
|
||||
const { saveBlock } = require('../../../../hooks');
|
||||
const { saveWarningModalToggle } = require('./hooks');
|
||||
|
||||
const AnswerWidgetComponent = wrapper.shallowWrapper.props.children[1].props.children[1].props.children;
|
||||
expect(AnswerWidgetComponent.props.problemType).toBe(ProblemTypeKeys.SINGLESELECT);
|
||||
expect(wrapper.instance.findByType(RawEditor).length).toBe(0);
|
||||
jest.mock('./AnswerWidget', () => function mockAnswerWidget() {
|
||||
return <div>AnswerWidget</div>;
|
||||
});
|
||||
jest.mock('./SettingsWidget', () => function mockSettingsWidget() {
|
||||
return <div>SettingsWidget</div>;
|
||||
});
|
||||
jest.mock('./QuestionWidget', () => function mmockQuestionWidget() {
|
||||
return <div>QuestionWidget</div>;
|
||||
});
|
||||
jest.mock('../../../EditorContainer', () => function mockEditorContainer({ children }) {
|
||||
return <section>{children}</section>;
|
||||
});
|
||||
jest.mock('../../../../sharedComponents/RawEditor', () => function mockRawEditor({ lang, content }) {
|
||||
return <div>{lang}:{content}</div>;
|
||||
});
|
||||
jest.mock('./ExplanationWidget', () => function mockExplanationWidget() {
|
||||
return <div>ExplanationWidget</div>;
|
||||
});
|
||||
jest.mock('../../../../hooks', () => ({
|
||||
saveBlock: jest.fn(),
|
||||
}));
|
||||
jest.mock('./hooks', () => ({
|
||||
checkIfEditorsDirty: jest.fn(() => false),
|
||||
parseState: jest.fn(() => () => 'parsed-content'),
|
||||
saveWarningModalToggle: jest.fn(() => ({
|
||||
isSaveWarningModalOpen: true,
|
||||
openSaveWarningModal: jest.fn(),
|
||||
closeSaveWarningModal: jest.fn(),
|
||||
})),
|
||||
getContent: jest.fn(() => 'content'),
|
||||
}));
|
||||
|
||||
const render = (ui) => baseRender(ui, {
|
||||
extraWrapper: ({ children }) => (
|
||||
<EditorContextProvider learningContextId="course-v1:Org+COURSE+RUN">
|
||||
<Provider store={editorStore}>
|
||||
{children}
|
||||
</Provider>
|
||||
</EditorContextProvider>
|
||||
),
|
||||
});
|
||||
|
||||
describe('EditProblemView', () => {
|
||||
const baseProps = {
|
||||
problemType: 'standard',
|
||||
isMarkdownEditorEnabled: false,
|
||||
problemState: { rawOLX: '<problem></problem>', rawMarkdown: '## Problem' },
|
||||
lmsEndpointUrl: null,
|
||||
returnUrl: '/return',
|
||||
analytics: {},
|
||||
isDirty: false,
|
||||
returnFunction: jest.fn(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
|
||||
test('renders raw editor for advanced problem type', () => {
|
||||
const wrapper = shallow(<EditProblemView
|
||||
problemType={ProblemTypeKeys.ADVANCED}
|
||||
isMarkdownEditorEnabled={false}
|
||||
problemState={{ rawOLX: '<problem>...</problem>' }}
|
||||
assets={{}}
|
||||
intl={{ formatMessage }}
|
||||
/>);
|
||||
|
||||
expect(wrapper.snapshot).toMatchSnapshot();
|
||||
|
||||
const rawEditor = wrapper.instance.findByType(RawEditor);
|
||||
expect(rawEditor.length).toBe(1);
|
||||
expect(rawEditor[0].props.lang).toBe('xml');
|
||||
|
||||
const answerWidget = wrapper.instance.findByType(AnswerWidget);
|
||||
expect(answerWidget.length).toBe(0); // since advanced problem type skips AnswerWidget
|
||||
it('renders standard problem widgets', () => {
|
||||
render(<EditProblemViewInternal {...baseProps} />);
|
||||
expect(screen.getByText('QuestionWidget')).toBeInTheDocument();
|
||||
expect(screen.getByText('ExplanationWidget')).toBeInTheDocument();
|
||||
expect(screen.getByText('AnswerWidget')).toBeInTheDocument();
|
||||
expect(screen.getByText('SettingsWidget')).toBeInTheDocument();
|
||||
expect(screen.queryByText(/xml:/)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(/markdown:/)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('renders markdown editor when isMarkdownEditorEnabled is true', () => {
|
||||
const wrapper = shallow(<EditProblemView
|
||||
problemType={ProblemTypeKeys.SINGLESELECT}
|
||||
isMarkdownEditorEnabled
|
||||
problemState={{ rawMarkdown: '# Markdown content' }}
|
||||
assets={{}}
|
||||
intl={{ formatMessage }}
|
||||
/>);
|
||||
it('renders advanced problem with RawEditor', () => {
|
||||
render(<EditProblemViewInternal {...baseProps} problemType={ProblemTypeKeys.ADVANCED} />);
|
||||
expect(screen.getByText('xml:<problem></problem>')).toBeInTheDocument();
|
||||
expect(screen.getByText('SettingsWidget')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(wrapper.snapshot).toMatchSnapshot();
|
||||
it('renders markdown editor with RawEditor', () => {
|
||||
render(<EditProblemViewInternal {...baseProps} isMarkdownEditorEnabled />);
|
||||
expect(screen.getByText('markdown:## Problem')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const rawEditor = wrapper.instance.findByType(RawEditor);
|
||||
expect(rawEditor.length).toBe(1);
|
||||
expect(rawEditor[0].props.lang).toBe('markdown');
|
||||
it('shows AlertModal with correct title/body for standard', () => {
|
||||
render(<EditProblemViewInternal {...baseProps} />);
|
||||
expect(screen.getAllByText('No correct answer has been specified.').length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
const answerWidget = wrapper.instance.findByType(AnswerWidget);
|
||||
expect(answerWidget.length).toBe(0); // since markdown view skips AnswerWidget
|
||||
it('calls saveBlock when save button is clicked', () => {
|
||||
render(<EditProblemViewInternal {...baseProps} />);
|
||||
const saveBtn = screen.getByRole('button', { name: 'Ok' });
|
||||
fireEvent.click(saveBtn);
|
||||
expect(saveBlock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls closeSaveWarningModal when cancel button is clicked', () => {
|
||||
const closeSaveWarningModal = jest.fn();
|
||||
saveWarningModalToggle.mockReturnValue({
|
||||
isSaveWarningModalOpen: true,
|
||||
openSaveWarningModal: jest.fn(),
|
||||
closeSaveWarningModal,
|
||||
});
|
||||
render(<EditProblemViewInternal {...baseProps} />);
|
||||
const cancelBtn = screen.getByRole('button', { name: 'Cancel' });
|
||||
fireEvent.click(cancelBtn);
|
||||
expect(closeSaveWarningModal).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('sets isMarkdownEditorEnabled true only if both selectors return true', () => {
|
||||
const state = { };
|
||||
|
||||
selectors.problem = {
|
||||
isMarkdownEditorEnabled: jest.fn(() => true),
|
||||
problemType: jest.fn(),
|
||||
completeState: jest.fn(),
|
||||
isDirty: jest.fn(),
|
||||
};
|
||||
selectors.app = {
|
||||
isMarkdownEditorEnabledForCourse: jest.fn(() => true),
|
||||
analytics: jest.fn(),
|
||||
lmsEndpointUrl: jest.fn(),
|
||||
returnUrl: jest.fn(),
|
||||
};
|
||||
|
||||
const props = mapStateToProps(state);
|
||||
expect(selectors.problem.isMarkdownEditorEnabled).toHaveBeenCalledWith(state);
|
||||
expect(selectors.app.isMarkdownEditorEnabledForCourse).toHaveBeenCalledWith(state);
|
||||
expect(props.isMarkdownEditorEnabled).toBe(true);
|
||||
|
||||
selectors.problem.isMarkdownEditorEnabled.mockReturnValue(false);
|
||||
expect(mapStateToProps(state).isMarkdownEditorEnabled).toBe(false);
|
||||
|
||||
selectors.problem.isMarkdownEditorEnabled.mockReturnValue(true);
|
||||
selectors.app.isMarkdownEditorEnabledForCourse.mockReturnValue(false);
|
||||
expect(mapStateToProps(state).isMarkdownEditorEnabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,39 +1,42 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import React from 'react';
|
||||
import {
|
||||
render, screen, fireEvent, initializeMocks,
|
||||
} from '../../../../../../testUtils';
|
||||
import { ProblemTypeKeys } from '../../../../../data/constants/problem';
|
||||
import ProblemTypeSelect from './ProblemTypeSelect';
|
||||
|
||||
describe('ProblemTypeSelect', () => {
|
||||
const props = {
|
||||
setSelected: jest.fn(),
|
||||
};
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
|
||||
describe('snapshot', () => {
|
||||
test('SINGLESELECT', () => {
|
||||
expect(shallow(
|
||||
<ProblemTypeSelect {...props} selected={ProblemTypeKeys.SINGLESELECT} />,
|
||||
).snapshot).toMatchSnapshot();
|
||||
});
|
||||
test('MULTISELECT', () => {
|
||||
expect(shallow(
|
||||
<ProblemTypeSelect {...props} selected={ProblemTypeKeys.MULTISELECT} />,
|
||||
).snapshot).toMatchSnapshot();
|
||||
});
|
||||
test('DROPDOWN', () => {
|
||||
expect(shallow(
|
||||
<ProblemTypeSelect {...props} selected={ProblemTypeKeys.DROPDOWN} />,
|
||||
).snapshot).toMatchSnapshot();
|
||||
});
|
||||
test('NUMERIC', () => {
|
||||
expect(shallow(
|
||||
<ProblemTypeSelect {...props} selected={ProblemTypeKeys.NUMERIC} />,
|
||||
).snapshot).toMatchSnapshot();
|
||||
});
|
||||
test('TEXTINPUT', () => {
|
||||
expect(shallow(
|
||||
<ProblemTypeSelect {...props} selected={ProblemTypeKeys.TEXTINPUT} />,
|
||||
).snapshot).toMatchSnapshot();
|
||||
});
|
||||
it('renders the component with the selected element checked', () => {
|
||||
render(<ProblemTypeSelect setSelected={jest.fn()} selected={ProblemTypeKeys.SINGLESELECT} />);
|
||||
expect(screen.getByRole('radiogroup')).toBeInTheDocument();
|
||||
const radioSingle = screen.getByDisplayValue('multiplechoiceresponse');
|
||||
expect(radioSingle).toBeChecked();
|
||||
});
|
||||
|
||||
it('does not render advanced element', () => {
|
||||
render(<ProblemTypeSelect setSelected={jest.fn()} selected={ProblemTypeKeys.MULTISELECT} />);
|
||||
expect(screen.getByRole('radiogroup')).toBeInTheDocument();
|
||||
expect(screen.queryByText('advanced')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call setSelected with correct value when clicking one option', () => {
|
||||
const mockSetSelected = jest.fn();
|
||||
render(<ProblemTypeSelect setSelected={mockSetSelected} selected={ProblemTypeKeys.NUMERIC} />);
|
||||
const multiSelectOption = screen.getByRole('button', { name: 'Multi-select' });
|
||||
fireEvent.click(multiSelectOption);
|
||||
expect(mockSetSelected).toHaveBeenCalledWith('choiceresponse');
|
||||
});
|
||||
|
||||
it('should call setSelected with blankadvanced when clicking the advanced button', () => {
|
||||
const mockSetSelected = jest.fn();
|
||||
render(<ProblemTypeSelect setSelected={mockSetSelected} selected={ProblemTypeKeys.MULTISELECT} />);
|
||||
const button = screen.getByRole('button', { name: 'Advanced problem types' });
|
||||
expect(button).toBeInTheDocument();
|
||||
fireEvent.click(button);
|
||||
expect(mockSetSelected).toHaveBeenCalledWith('blankadvanced');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,531 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ProblemTypeSelect snapshot DROPDOWN 1`] = `
|
||||
<Container
|
||||
style={
|
||||
{
|
||||
"height": "400px",
|
||||
"width": "494px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
columns={1}
|
||||
name="problem-type"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="optionresponse"
|
||||
>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="multiplechoiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="multiplechoiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="multiplechoiceresponse"
|
||||
>
|
||||
Single select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="choiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="choiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="choiceresponse"
|
||||
>
|
||||
Multi-select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="optionresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="optionresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="optionresponse"
|
||||
>
|
||||
Dropdown
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="numericalresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="numericalresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="numericalresponse"
|
||||
>
|
||||
Numerical input
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="stringresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="stringresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="stringresponse"
|
||||
>
|
||||
Text input
|
||||
</ForwardRef>
|
||||
</ForwardRef>
|
||||
<Button
|
||||
className="pl-0 mt-2"
|
||||
onClick={[Function]}
|
||||
variant="link"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Advanced problem types"
|
||||
description="Button label for advance problem types option"
|
||||
id="authoring.problemEditor.problemSelect.advanceButton.label"
|
||||
/>
|
||||
</Button>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`ProblemTypeSelect snapshot MULTISELECT 1`] = `
|
||||
<Container
|
||||
style={
|
||||
{
|
||||
"height": "400px",
|
||||
"width": "494px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
columns={1}
|
||||
name="problem-type"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="choiceresponse"
|
||||
>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="multiplechoiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="multiplechoiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="multiplechoiceresponse"
|
||||
>
|
||||
Single select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="choiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="choiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="choiceresponse"
|
||||
>
|
||||
Multi-select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="optionresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="optionresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="optionresponse"
|
||||
>
|
||||
Dropdown
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="numericalresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="numericalresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="numericalresponse"
|
||||
>
|
||||
Numerical input
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="stringresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="stringresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="stringresponse"
|
||||
>
|
||||
Text input
|
||||
</ForwardRef>
|
||||
</ForwardRef>
|
||||
<Button
|
||||
className="pl-0 mt-2"
|
||||
onClick={[Function]}
|
||||
variant="link"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Advanced problem types"
|
||||
description="Button label for advance problem types option"
|
||||
id="authoring.problemEditor.problemSelect.advanceButton.label"
|
||||
/>
|
||||
</Button>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`ProblemTypeSelect snapshot NUMERIC 1`] = `
|
||||
<Container
|
||||
style={
|
||||
{
|
||||
"height": "400px",
|
||||
"width": "494px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
columns={1}
|
||||
name="problem-type"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="numericalresponse"
|
||||
>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="multiplechoiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="multiplechoiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="multiplechoiceresponse"
|
||||
>
|
||||
Single select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="choiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="choiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="choiceresponse"
|
||||
>
|
||||
Multi-select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="optionresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="optionresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="optionresponse"
|
||||
>
|
||||
Dropdown
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="numericalresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="numericalresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="numericalresponse"
|
||||
>
|
||||
Numerical input
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="stringresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="stringresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="stringresponse"
|
||||
>
|
||||
Text input
|
||||
</ForwardRef>
|
||||
</ForwardRef>
|
||||
<Button
|
||||
className="pl-0 mt-2"
|
||||
onClick={[Function]}
|
||||
variant="link"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Advanced problem types"
|
||||
description="Button label for advance problem types option"
|
||||
id="authoring.problemEditor.problemSelect.advanceButton.label"
|
||||
/>
|
||||
</Button>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`ProblemTypeSelect snapshot SINGLESELECT 1`] = `
|
||||
<Container
|
||||
style={
|
||||
{
|
||||
"height": "400px",
|
||||
"width": "494px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
columns={1}
|
||||
name="problem-type"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="multiplechoiceresponse"
|
||||
>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="multiplechoiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="multiplechoiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="multiplechoiceresponse"
|
||||
>
|
||||
Single select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="choiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="choiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="choiceresponse"
|
||||
>
|
||||
Multi-select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="optionresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="optionresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="optionresponse"
|
||||
>
|
||||
Dropdown
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="numericalresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="numericalresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="numericalresponse"
|
||||
>
|
||||
Numerical input
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="stringresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="stringresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="stringresponse"
|
||||
>
|
||||
Text input
|
||||
</ForwardRef>
|
||||
</ForwardRef>
|
||||
<Button
|
||||
className="pl-0 mt-2"
|
||||
onClick={[Function]}
|
||||
variant="link"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Advanced problem types"
|
||||
description="Button label for advance problem types option"
|
||||
id="authoring.problemEditor.problemSelect.advanceButton.label"
|
||||
/>
|
||||
</Button>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`ProblemTypeSelect snapshot TEXTINPUT 1`] = `
|
||||
<Container
|
||||
style={
|
||||
{
|
||||
"height": "400px",
|
||||
"width": "494px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ForwardRef
|
||||
columns={1}
|
||||
name="problem-type"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="stringresponse"
|
||||
>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="multiplechoiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="multiplechoiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="multiplechoiceresponse"
|
||||
>
|
||||
Single select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="choiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="choiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="choiceresponse"
|
||||
>
|
||||
Multi-select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="optionresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="optionresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="optionresponse"
|
||||
>
|
||||
Dropdown
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="numericalresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="numericalresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="numericalresponse"
|
||||
>
|
||||
Numerical input
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="stringresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="stringresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value="stringresponse"
|
||||
>
|
||||
Text input
|
||||
</ForwardRef>
|
||||
</ForwardRef>
|
||||
<Button
|
||||
className="pl-0 mt-2"
|
||||
onClick={[Function]}
|
||||
variant="link"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Advanced problem types"
|
||||
description="Button label for advance problem types option"
|
||||
id="authoring.problemEditor.problemSelect.advanceButton.label"
|
||||
/>
|
||||
</Button>
|
||||
</Container>
|
||||
`;
|
||||
@@ -1,84 +0,0 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import ErrorAlert, { hooks } from './ErrorAlert';
|
||||
import { MockUseState } from '../../testUtils';
|
||||
|
||||
jest.mock('react', () => ({
|
||||
...jest.requireActual('react'),
|
||||
useRef: jest.fn(val => ({ current: val })),
|
||||
useEffect: jest.fn(),
|
||||
useCallback: (cb, prereqs) => ({ cb, prereqs }),
|
||||
}));
|
||||
|
||||
const state = new MockUseState(hooks);
|
||||
let hook;
|
||||
const testValue = 'testVALUE';
|
||||
|
||||
describe('ErrorAlert component', () => {
|
||||
describe('Hooks', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
describe('state hooks', () => {
|
||||
state.testGetter(state.keys.isDismissed);
|
||||
});
|
||||
describe('using state', () => {
|
||||
beforeEach(() => { state.mock(); });
|
||||
afterEach(() => { state.restore(); });
|
||||
describe('dismissalHooks', () => {
|
||||
const props = {
|
||||
dismissError: jest.fn(),
|
||||
isError: testValue,
|
||||
};
|
||||
beforeEach(() => {
|
||||
hook = hooks.dismissalHooks(props);
|
||||
});
|
||||
it('returns isDismissed value, initialized to false', () => {
|
||||
expect(state.stateVals.isDismissed).toEqual(hook.isDismissed);
|
||||
});
|
||||
test('dismissAlert sets isDismissed to true and calls dismissError', () => {
|
||||
hook.dismissAlert();
|
||||
expect(state.setState.isDismissed).toHaveBeenCalledWith(true);
|
||||
expect(props.dismissError).toHaveBeenCalled();
|
||||
});
|
||||
test('On Render, calls setIsDismissed', () => {
|
||||
expect(React.useEffect.mock.calls.length).toEqual(1);
|
||||
const [cb, prereqs] = React.useEffect.mock.calls[0];
|
||||
expect(prereqs[0]).toEqual(testValue);
|
||||
cb();
|
||||
expect(state.setState.isDismissed).toHaveBeenCalledWith(state.stateVals.isDismissed && !testValue);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('Component', () => {
|
||||
describe('Snapshots', () => {
|
||||
let props;
|
||||
const msg = <p> An Error Message </p>;
|
||||
beforeAll(() => {
|
||||
props = {
|
||||
dismissError: jest.fn(),
|
||||
};
|
||||
jest.spyOn(hooks, 'dismissalHooks').mockImplementation(() => ({
|
||||
isDismissed: false,
|
||||
dismissAlert: jest.fn().mockName('dismissAlert'),
|
||||
}));
|
||||
});
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
test('snapshot: is Null when no error (ErrorAlert)', () => {
|
||||
expect(shallow(<ErrorAlert {...props}> <p> An Error Message </p> </ErrorAlert>).snapshot).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: Loads children and component when error (ErrorAlert)', () => {
|
||||
expect(
|
||||
shallow(<ErrorAlert {...props} isError hideHeading={false}>{msg}</ErrorAlert>).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: Does not load heading when hideHeading is true', () => {
|
||||
expect(shallow(<ErrorAlert {...props} isError hideHeading>{msg}</ErrorAlert>).snapshot).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
84
src/editors/sharedComponents/ErrorAlerts/ErrorAlert.test.tsx
Normal file
84
src/editors/sharedComponents/ErrorAlerts/ErrorAlert.test.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
render, screen, fireEvent, initializeMocks,
|
||||
} from '../../../testUtils';
|
||||
import ErrorAlert, { hooks } from './ErrorAlert';
|
||||
|
||||
describe('ErrorAlert (integration, no Paragon mocks)', () => {
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('renders nothing if isError is false', () => {
|
||||
render(<ErrorAlert isError={false}>Some error</ErrorAlert>);
|
||||
expect(screen.queryByRole('alert')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders nothing if isDismissed is true', () => {
|
||||
jest.spyOn(hooks, 'dismissalHooks').mockReturnValue({
|
||||
isDismissed: true,
|
||||
dismissAlert: jest.fn(),
|
||||
});
|
||||
render(<ErrorAlert isError>Some error</ErrorAlert>);
|
||||
expect(screen.queryByRole('alert')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders alert with heading and children when isError is true', () => {
|
||||
jest.spyOn(hooks, 'dismissalHooks').mockReturnValue({
|
||||
isDismissed: false,
|
||||
dismissAlert: jest.fn(),
|
||||
});
|
||||
render(<ErrorAlert isError>Some error</ErrorAlert>);
|
||||
expect(screen.getByRole('alert')).toBeInTheDocument();
|
||||
expect(screen.getByText('Error')).toBeInTheDocument();
|
||||
expect(screen.getByText('Some error')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders alert without heading when hideHeading is true', () => {
|
||||
render(<ErrorAlert isError hideHeading>Some error</ErrorAlert>);
|
||||
expect(screen.getByRole('alert')).toBeInTheDocument();
|
||||
expect(screen.queryByText('Error')).toBeNull();
|
||||
expect(screen.getByText('Some error')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls dismissError when dismiss button is clicked', () => {
|
||||
const dismissError = jest.fn();
|
||||
render(<ErrorAlert isError dismissError={dismissError}>Some error</ErrorAlert>);
|
||||
const closeBtn = screen.getByRole('button');
|
||||
fireEvent.click(closeBtn);
|
||||
expect(dismissError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not throw if dismissError is not provided and dismiss button is clicked', () => {
|
||||
render(<ErrorAlert isError>Some error</ErrorAlert>);
|
||||
const closeBtn = screen.getByRole('button');
|
||||
expect(() => fireEvent.click(closeBtn)).not.toThrow();
|
||||
});
|
||||
|
||||
it('renders children as array', () => {
|
||||
render(<ErrorAlert isError>{['foo', <span key="bar">bar</span>]}</ErrorAlert>);
|
||||
expect(screen.getByText('foo')).toBeInTheDocument();
|
||||
expect(screen.getByText('bar')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('resets isDismissed when isError changes from false to true', () => {
|
||||
const { rerender } = render(<ErrorAlert isError={false}>err</ErrorAlert>);
|
||||
expect(screen.queryByRole('alert')).toBeNull();
|
||||
rerender(<ErrorAlert isError>err</ErrorAlert>);
|
||||
expect(screen.getByRole('alert')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('dismisses alert when dismiss button is clicked (integration)', () => {
|
||||
const dismissError = jest.fn();
|
||||
render(<ErrorAlert isError dismissError={dismissError}>err</ErrorAlert>);
|
||||
const closeBtn = screen.getByRole('button');
|
||||
fireEvent.click(closeBtn);
|
||||
|
||||
expect(screen.queryByRole('alert')).toBeNull();
|
||||
expect(dismissError).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import FetchErrorAlert from './FetchErrorAlert';
|
||||
|
||||
jest.mock('../../data/redux', () => ({
|
||||
selectors: {
|
||||
requests: {
|
||||
isFailed: jest.fn((state, params) => ({ isFailed: { state, params } })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('FetchErrorAlert', () => {
|
||||
describe('Snapshots', () => {
|
||||
test('snapshot: is ErrorAlert with Message error (ErrorAlert)', () => {
|
||||
expect(shallow(<FetchErrorAlert isFetchError />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import { render, screen, initializeMocks } from '../../../testUtils';
|
||||
import FetchErrorAlert from './FetchErrorAlert';
|
||||
|
||||
const message = {
|
||||
id: 'test.error',
|
||||
defaultMessage: 'Something went wrong!',
|
||||
description: 'Test error message',
|
||||
};
|
||||
|
||||
describe('FetchErrorAlert', () => {
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
|
||||
it('renders the error message when isFetchError is true', () => {
|
||||
render(
|
||||
<FetchErrorAlert message={message} isFetchError />,
|
||||
);
|
||||
expect(screen.getByText('Something went wrong!')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not render the error message when isFetchError is false', () => {
|
||||
render(
|
||||
<FetchErrorAlert message={message} isFetchError={false} />,
|
||||
);
|
||||
expect(screen.queryByText('Something went wrong!')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders error with a custom message', () => {
|
||||
const customMessage = {
|
||||
id: 'another.error',
|
||||
defaultMessage: 'Another error occurred.',
|
||||
description: 'Another error',
|
||||
};
|
||||
render(
|
||||
<FetchErrorAlert message={customMessage} isFetchError />,
|
||||
);
|
||||
expect(screen.getByText('Another error occurred.')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,34 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ErrorAlert component Component Snapshots snapshot: Does not load heading when hideHeading is true 1`] = `
|
||||
<Alert
|
||||
dismissible={true}
|
||||
onClose={[MockFunction dismissAlert]}
|
||||
variant="danger"
|
||||
>
|
||||
<p>
|
||||
An Error Message
|
||||
</p>
|
||||
</Alert>
|
||||
`;
|
||||
|
||||
exports[`ErrorAlert component Component Snapshots snapshot: Loads children and component when error (ErrorAlert) 1`] = `
|
||||
<Alert
|
||||
dismissible={true}
|
||||
onClose={[MockFunction dismissAlert]}
|
||||
variant="danger"
|
||||
>
|
||||
<Alert.Heading>
|
||||
<FormattedMessage
|
||||
defaultMessage="Error"
|
||||
description="Title of message presented to user when something goes wrong"
|
||||
id="authoring.texteditor.selectimagemodal.error.errorTitle"
|
||||
/>
|
||||
</Alert.Heading>
|
||||
<p>
|
||||
An Error Message
|
||||
</p>
|
||||
</Alert>
|
||||
`;
|
||||
|
||||
exports[`ErrorAlert component Component Snapshots snapshot: is Null when no error (ErrorAlert) 1`] = `null`;
|
||||
@@ -1,11 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`FetchErrorAlert Snapshots snapshot: is ErrorAlert with Message error (ErrorAlert) 1`] = `
|
||||
<ErrorAlert
|
||||
dismissError={null}
|
||||
hideHeading={false}
|
||||
isError={true}
|
||||
>
|
||||
<FormattedMessage />
|
||||
</ErrorAlert>
|
||||
`;
|
||||
@@ -1,26 +0,0 @@
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import VideoSelectorContainer from './VideoSelectorContainer';
|
||||
|
||||
jest.mock('../editors/VideoSelectorPage', () => ({
|
||||
default: function VideoSelectorPage() { return 'HeaderTitle'; },
|
||||
__esModule: true, // Required to mock a default export
|
||||
}));
|
||||
|
||||
jest.mock('react-router', () => ({
|
||||
...jest.requireActual('react-router'), // use actual for all non-hook parts
|
||||
useParams: () => ({
|
||||
blockId: 'company-id1',
|
||||
blockType: 'html',
|
||||
}),
|
||||
}));
|
||||
|
||||
const props = { courseId: 'cOuRsEId' };
|
||||
|
||||
describe('Video Selector Container', () => {
|
||||
describe('snapshots', () => {
|
||||
test('rendering correctly with expected Input', () => {
|
||||
expect(shallow(<VideoSelectorContainer {...props} />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
14
src/selectors/VideoSelectorContainer.test.tsx
Normal file
14
src/selectors/VideoSelectorContainer.test.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import { render, initializeMocks } from '../testUtils';
|
||||
import VideoSelectorContainer from './VideoSelectorContainer';
|
||||
|
||||
describe('VideoSelectorContainer', () => {
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
|
||||
it('renders the wrapper div with correct class', () => {
|
||||
const { container } = render(<VideoSelectorContainer courseId="course-v1:edX+Test+2024" />);
|
||||
expect(container.querySelector('.selector-page')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Video Selector Container snapshots rendering correctly with expected Input 1`] = `
|
||||
<div
|
||||
className="selector-page"
|
||||
>
|
||||
<VideoSelectorPage
|
||||
blockId="company-id1"
|
||||
courseId="cOuRsEId"
|
||||
lmsEndpointUrl="http://localhost:18000"
|
||||
studioEndpointUrl="http://localhost:18010"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
Reference in New Issue
Block a user