test: deprecate react-unit-test-utils part-8 (#444)
* test: deprecate react-unit-test-utils part-8 * test: change fireEvent to userEvent * test: rebase fixes * test: change fireEvent to userEvent * test: fixes and adress review * test: improve description test --------- Co-authored-by: diana-villalvazo-wgu <diana.villalvazo@wgu.edu>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { ConfirmModal } from './ConfirmModal';
|
||||
|
||||
jest.unmock('@openedx/paragon');
|
||||
@@ -29,15 +30,17 @@ describe('ConfirmModal', () => {
|
||||
expect(getByText(props.content)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onCancel when cancel button is clicked', () => {
|
||||
it('should call onCancel when cancel button is clicked', async () => {
|
||||
render(<ConfirmModal {...props} isOpen />);
|
||||
fireEvent.click(screen.getByText(props.cancelText));
|
||||
const user = userEvent.setup();
|
||||
await user.click(screen.getByText(props.cancelText));
|
||||
expect(props.onCancel).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should call onConfirm when confirm button is clicked', () => {
|
||||
it('should call onConfirm when confirm button is clicked', async () => {
|
||||
render(<ConfirmModal {...props} isOpen />);
|
||||
fireEvent.click(screen.getByText(props.confirmText));
|
||||
const user = userEvent.setup();
|
||||
await user.click(screen.getByText(props.confirmText));
|
||||
expect(props.onConfirm).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import FileInfo from './FileInfo';
|
||||
|
||||
@@ -20,10 +21,10 @@ describe('FileInfo component', () => {
|
||||
expect(screen.getByText('FormattedMessage')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls onClick when button is clicked', () => {
|
||||
it('calls onClick when button is clicked', async () => {
|
||||
render(<FileInfo {...props}>{children}</FileInfo>);
|
||||
|
||||
fireEvent.click(screen.getByText('FormattedMessage'));
|
||||
const user = userEvent.setup();
|
||||
await user.click(screen.getByText('FormattedMessage'));
|
||||
expect(props.onClick).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { render, fireEvent } from '@testing-library/react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import { actions, selectors } from 'data/redux';
|
||||
import {
|
||||
@@ -49,26 +50,26 @@ describe('Criterion Feedback', () => {
|
||||
describe('component', () => {
|
||||
describe('render', () => {
|
||||
it('shows a non-disabled input when grading', () => {
|
||||
const { getByTestId } = render(<CriterionFeedback {...props} />);
|
||||
const input = getByTestId('criterion-feedback-input');
|
||||
render(<CriterionFeedback {...props} />);
|
||||
const input = screen.getByTestId('criterion-feedback-input');
|
||||
expect(input).toBeInTheDocument();
|
||||
expect(input).not.toBeDisabled();
|
||||
expect(input).toHaveValue(props.value);
|
||||
});
|
||||
|
||||
it('shows a disabled input when not grading', () => {
|
||||
const { getByTestId } = render(
|
||||
render(
|
||||
<CriterionFeedback {...props} isGrading={false} gradeStatus={gradeStatuses.graded} />,
|
||||
);
|
||||
const input = getByTestId('criterion-feedback-input');
|
||||
const input = screen.getByTestId('criterion-feedback-input');
|
||||
expect(input).toBeInTheDocument();
|
||||
expect(input).toBeDisabled();
|
||||
expect(input).toHaveValue(props.value);
|
||||
});
|
||||
|
||||
it('displays an error message when feedback is invalid', () => {
|
||||
const { getByTestId } = render(<CriterionFeedback {...props} isInvalid />);
|
||||
expect(getByTestId('criterion-feedback-error-msg')).toBeInTheDocument();
|
||||
render(<CriterionFeedback {...props} isInvalid />);
|
||||
expect(screen.getByTestId('criterion-feedback-error-msg')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not render anything when config is set to disabled', () => {
|
||||
@@ -80,12 +81,13 @@ describe('Criterion Feedback', () => {
|
||||
});
|
||||
|
||||
describe('behavior', () => {
|
||||
it('calls setValue when input value changes', () => {
|
||||
const { getByTestId } = render(<CriterionFeedback {...props} />);
|
||||
const input = getByTestId('criterion-feedback-input');
|
||||
fireEvent.change(input, { target: { value: 'some value' } });
|
||||
it('calls setValue when input value changes', async () => {
|
||||
render(<CriterionFeedback {...props} />);
|
||||
const user = userEvent.setup();
|
||||
const input = screen.getByTestId('criterion-feedback-input');
|
||||
await user.clear(input);
|
||||
expect(props.setValue).toHaveBeenCalledWith({
|
||||
value: 'some value',
|
||||
value: '',
|
||||
orderNum: props.orderNum,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`StartGradingButton component component snapshots hide: renders empty component if hook.hide is true 1`] = `null`;
|
||||
|
||||
exports[`StartGradingButton component component snapshots smoke test: forwards props to components from hooks 1`] = `
|
||||
<Fragment>
|
||||
<Button
|
||||
props="hooks.buttonArgs"
|
||||
variant="primary"
|
||||
/>
|
||||
<OverrideGradeConfirmModal
|
||||
props="hooks.overrideGradeArgs"
|
||||
/>
|
||||
<StopGradingConfirmModal
|
||||
props="hooks.stopGradingArgs"
|
||||
/>
|
||||
</Fragment>
|
||||
`;
|
||||
@@ -1,49 +1,131 @@
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import * as hooks from './hooks';
|
||||
import { StartGradingButton } from '.';
|
||||
import messages from '../messages';
|
||||
|
||||
jest.mock('../OverrideGradeConfirmModal', () => 'OverrideGradeConfirmModal');
|
||||
jest.mock('../StopGradingConfirmModal', () => 'StopGradingConfirmModal');
|
||||
jest.unmock('@openedx/paragon');
|
||||
jest.unmock('react');
|
||||
jest.unmock('@edx/frontend-platform/i18n');
|
||||
|
||||
jest.mock('react-redux', () => ({
|
||||
useDispatch: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('./hooks', () => ({
|
||||
buttonHooks: jest.fn(),
|
||||
}));
|
||||
|
||||
let el;
|
||||
describe('StartGradingButton component', () => {
|
||||
describe('component', () => {
|
||||
const dispatch = useDispatch();
|
||||
const buttonHooks = {
|
||||
hide: false,
|
||||
buttonArgs: { props: 'hooks.buttonArgs' },
|
||||
overrideGradeArgs: { props: 'hooks.overrideGradeArgs' },
|
||||
stopGradingArgs: { props: 'hooks.stopGradingArgs' },
|
||||
};
|
||||
describe('behavior', () => {
|
||||
it('initializes buttonHooks with dispatch and intl fields', () => {
|
||||
hooks.buttonHooks.mockReturnValueOnce(buttonHooks);
|
||||
el = shallow(<StartGradingButton />);
|
||||
const expected = { dispatch, intl: { formatMessage: expect.any(Function), formatDate: expect.any(Function) } };
|
||||
expect(hooks.buttonHooks).toHaveBeenCalledWith(expected);
|
||||
});
|
||||
describe('StartGradingButton', () => {
|
||||
const mockDispatch = jest.fn();
|
||||
|
||||
const renderWithIntl = (component) => render(
|
||||
<IntlProvider locale="en" messages={{}}>
|
||||
{component}
|
||||
</IntlProvider>,
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
useDispatch.mockReturnValue(mockDispatch);
|
||||
});
|
||||
|
||||
it('does not render when hide is true', () => {
|
||||
hooks.buttonHooks.mockReturnValue({
|
||||
hide: true,
|
||||
buttonArgs: {},
|
||||
overrideGradeArgs: {},
|
||||
stopGradingArgs: {},
|
||||
});
|
||||
describe('snapshots', () => {
|
||||
test('hide: renders empty component if hook.hide is true', () => {
|
||||
hooks.buttonHooks.mockReturnValueOnce({ ...buttonHooks, hide: true });
|
||||
el = shallow(<StartGradingButton />);
|
||||
expect(el.snapshot).toMatchSnapshot();
|
||||
expect(el.isEmptyRender()).toEqual(true);
|
||||
});
|
||||
test('smoke test: forwards props to components from hooks', () => {
|
||||
hooks.buttonHooks.mockReturnValueOnce(buttonHooks);
|
||||
el = shallow(<StartGradingButton />);
|
||||
expect(el.snapshot).toMatchSnapshot();
|
||||
expect(el.isEmptyRender()).toEqual(false);
|
||||
});
|
||||
const { container } = renderWithIntl(<StartGradingButton />);
|
||||
expect(container.firstChild).toBeNull();
|
||||
});
|
||||
|
||||
it('renders primary button when visible', () => {
|
||||
hooks.buttonHooks.mockReturnValue({
|
||||
hide: false,
|
||||
buttonArgs: { children: 'Start Grading' },
|
||||
overrideGradeArgs: {
|
||||
isOpen: false,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
stopGradingArgs: {
|
||||
isOpen: false,
|
||||
isOverride: false,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
});
|
||||
renderWithIntl(<StartGradingButton />);
|
||||
const button = screen.getByRole('button', { name: 'Start Grading' });
|
||||
expect(button).toBeInTheDocument();
|
||||
expect(button).toHaveClass('btn-primary');
|
||||
});
|
||||
|
||||
it('renders override grade modal components', () => {
|
||||
hooks.buttonHooks.mockReturnValue({
|
||||
hide: false,
|
||||
buttonArgs: { children: 'Start Grading' },
|
||||
overrideGradeArgs: {
|
||||
isOpen: true,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
stopGradingArgs: {
|
||||
isOpen: false,
|
||||
isOverride: false,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
});
|
||||
renderWithIntl(<StartGradingButton />);
|
||||
const overrideModalTitle = screen.getByText(messages.overrideConfirmTitle.defaultMessage);
|
||||
expect(overrideModalTitle).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders stop grading modal components', () => {
|
||||
hooks.buttonHooks.mockReturnValue({
|
||||
hide: false,
|
||||
buttonArgs: { children: 'Start Grading' },
|
||||
overrideGradeArgs: {
|
||||
isOpen: false,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
stopGradingArgs: {
|
||||
isOpen: true,
|
||||
isOverride: false,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
});
|
||||
renderWithIntl(<StartGradingButton />);
|
||||
const stopGradingModalTitle = screen.getByText(messages.confirmStopGradingTitle.defaultMessage);
|
||||
expect(stopGradingModalTitle).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls buttonHooks with dispatch and intl', () => {
|
||||
hooks.buttonHooks.mockReturnValue({
|
||||
hide: false,
|
||||
buttonArgs: { children: 'Start Grading' },
|
||||
overrideGradeArgs: {
|
||||
isOpen: false,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
stopGradingArgs: {
|
||||
isOpen: false,
|
||||
isOverride: false,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
});
|
||||
renderWithIntl(<StartGradingButton />);
|
||||
expect(hooks.buttonHooks).toHaveBeenCalledWith({
|
||||
dispatch: mockDispatch,
|
||||
intl: expect.any(Object),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,60 +1,89 @@
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { selectors } from 'data/redux';
|
||||
import { RequestKeys } from 'data/constants/requests';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import {
|
||||
ReviewContent,
|
||||
mapStateToProps,
|
||||
} from './ReviewContent';
|
||||
|
||||
jest.unmock('@openedx/paragon');
|
||||
jest.unmock('react');
|
||||
jest.unmock('@edx/frontend-platform/i18n');
|
||||
|
||||
// Since we are only testing the ReviewContent component,
|
||||
// we can mock the child components to avoid unnecessary complexity on mocking the redux store.
|
||||
jest.mock('containers/ReviewModal/ReviewErrors/FetchErrors', () => {
|
||||
const FetchErrors = () => <div>FetchErrors</div>;
|
||||
return FetchErrors;
|
||||
});
|
||||
jest.mock('containers/ReviewModal/ReviewErrors/SubmitErrors', () => {
|
||||
const SubmitErrors = () => <div>SubmitErrors</div>;
|
||||
return SubmitErrors;
|
||||
});
|
||||
jest.mock('containers/ReviewModal/ReviewErrors/LockErrors', () => {
|
||||
const LockErrors = () => <div>LockErrors</div>;
|
||||
return LockErrors;
|
||||
});
|
||||
jest.mock('containers/ReviewModal/ReviewErrors/DownloadErrors', () => {
|
||||
const DownloadErrors = () => <div>DownloadErrors</div>;
|
||||
return DownloadErrors;
|
||||
});
|
||||
|
||||
jest.mock('containers/ResponseDisplay', () => {
|
||||
const ResponseDisplay = () => <div>ResponseDisplay</div>;
|
||||
return ResponseDisplay;
|
||||
});
|
||||
|
||||
jest.mock('containers/Rubric', () => {
|
||||
const Rubric = () => <div>Rubric</div>;
|
||||
return Rubric;
|
||||
});
|
||||
|
||||
jest.mock('data/redux', () => ({
|
||||
selectors: {
|
||||
app: {
|
||||
showRubric: (...args) => ({ showRubric: args }),
|
||||
showRubric: jest.fn(() => true),
|
||||
},
|
||||
requests: {
|
||||
isCompleted: (...args) => ({ isCompleted: args }),
|
||||
isFailed: (...args) => ({ isFailed: args }),
|
||||
isCompleted: jest.fn(() => false),
|
||||
isFailed: jest.fn(() => false),
|
||||
},
|
||||
},
|
||||
}));
|
||||
jest.mock('containers/ResponseDisplay', () => 'ResponseDisplay');
|
||||
jest.mock('containers/Rubric', () => 'Rubric');
|
||||
jest.mock('./ReviewErrors', () => 'ReviewErrors');
|
||||
|
||||
describe('ReviewContent component', () => {
|
||||
describe('component', () => {
|
||||
describe('render tests', () => {
|
||||
test('snapshot: not loaded, no error', () => {
|
||||
expect(shallow(<ReviewContent />).isEmptyRender()).toEqual(true);
|
||||
});
|
||||
test('snapshot: show rubric', () => {
|
||||
expect(shallow(<ReviewContent isLoaded />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: hide rubric', () => {
|
||||
expect(shallow(<ReviewContent isLoaded showRubric />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: failed, showRubric (errors only)', () => {
|
||||
expect(shallow(<ReviewContent showRubric isFailed />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
const renderWithIntl = (component) => render(
|
||||
<IntlProvider locale="en" messages={{}}>
|
||||
{component}
|
||||
</IntlProvider>,
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
describe('mapStateToProps', () => {
|
||||
let mapped;
|
||||
const testState = { some: 'test-state' };
|
||||
beforeEach(() => {
|
||||
mapped = mapStateToProps(testState);
|
||||
|
||||
describe('behavior', () => {
|
||||
it('renders nothing when not loaded and no error', () => {
|
||||
const { container } = renderWithIntl(<ReviewContent />);
|
||||
expect(container.querySelector('.content-block')).not.toBeInTheDocument();
|
||||
});
|
||||
const requestKey = RequestKeys.fetchSubmission;
|
||||
test('showRubric loads from app.showRubric', () => {
|
||||
expect(mapped.showRubric).toEqual(selectors.app.showRubric(testState));
|
||||
|
||||
it('renders review errors when failed', () => {
|
||||
renderWithIntl(<ReviewContent isFailed />);
|
||||
expect(screen.getByText('FetchErrors')).toBeInTheDocument();
|
||||
expect(screen.getByText('SubmitErrors')).toBeInTheDocument();
|
||||
expect(screen.getByText('LockErrors')).toBeInTheDocument();
|
||||
expect(screen.getByText('DownloadErrors')).toBeInTheDocument();
|
||||
});
|
||||
test('isFailed loads from requests.isFailed(fetchSubmission)', () => {
|
||||
expect(mapped.isFailed).toEqual(selectors.requests.isFailed(testState, { requestKey }));
|
||||
|
||||
it('renders response display when loaded', () => {
|
||||
renderWithIntl(<ReviewContent isLoaded />);
|
||||
expect(screen.getByText('ResponseDisplay')).toBeInTheDocument();
|
||||
});
|
||||
test('isLoaded loads from requests.isCompleted(fetchSubmission)', () => {
|
||||
expect(mapped.isLoaded).toEqual(selectors.requests.isCompleted(testState, { requestKey }));
|
||||
|
||||
it('renders with rubric when showRubric is true and loaded', () => {
|
||||
const { container, getByText } = renderWithIntl(<ReviewContent isLoaded showRubric />);
|
||||
expect(container.querySelector('.content-block')).toBeInTheDocument();
|
||||
expect(container.querySelector('.flex-nowrap')).toBeInTheDocument();
|
||||
expect(getByText('Rubric')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { selectors, actions, thunkActions } from 'data/redux';
|
||||
import { RequestKeys } from 'data/constants/requests';
|
||||
import { DownloadErrors, mapStateToProps, mapDispatchToProps } from './DownloadErrors';
|
||||
|
||||
import {
|
||||
DownloadErrors,
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
} from './DownloadErrors';
|
||||
|
||||
let el;
|
||||
jest.unmock('@openedx/paragon');
|
||||
jest.unmock('react');
|
||||
jest.unmock('@edx/frontend-platform/i18n');
|
||||
|
||||
jest.mock('data/redux', () => ({
|
||||
selectors: {
|
||||
requests: {
|
||||
isFailed: (...args) => ({ isFailed: args }),
|
||||
error: (...args) => ({ error: args }),
|
||||
isFailed: jest.fn((state) => state.isFailed || false),
|
||||
error: jest.fn((state) => state.error || { files: [] }),
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
@@ -26,62 +23,101 @@ jest.mock('data/redux', () => ({
|
||||
download: { downloadFiles: jest.fn() },
|
||||
},
|
||||
}));
|
||||
jest.mock('./ReviewError', () => 'ReviewError');
|
||||
|
||||
const renderWithIntl = (component) => render(
|
||||
<IntlProvider locale="en" messages={{}}>
|
||||
{component}
|
||||
</IntlProvider>,
|
||||
);
|
||||
|
||||
describe('DownloadErrors component', () => {
|
||||
const props = {
|
||||
const defaultProps = {
|
||||
isFailed: false,
|
||||
error: {
|
||||
files: [],
|
||||
},
|
||||
error: { files: [] },
|
||||
clearState: jest.fn(),
|
||||
downloadFiles: jest.fn(),
|
||||
};
|
||||
describe('component', () => {
|
||||
beforeEach(() => {
|
||||
props.clearState = jest.fn();
|
||||
props.downloadFiles = jest.fn().mockName('this.props.downloadFiles');
|
||||
el = shallow(<DownloadErrors {...props} />);
|
||||
});
|
||||
describe('snapshots', () => {
|
||||
test('failed: show error', () => {
|
||||
el = shallow(<DownloadErrors {...props} isFailed error={{ files: ['file-1-failed.error', 'file-2.failed'] }} />);
|
||||
expect(el.snapshot).toMatchSnapshot();
|
||||
expect(el.isEmptyRender()).toEqual(false);
|
||||
});
|
||||
test('not failed: hide error', () => {
|
||||
expect(el.snapshot).toMatchSnapshot();
|
||||
expect(el.isEmptyRender()).toEqual(true);
|
||||
});
|
||||
});
|
||||
describe('behavior', () => {
|
||||
describe('clearState', () => {
|
||||
it('calls props.clearState with requestKey: downloadFiles', () => {
|
||||
el = shallow(<DownloadErrors {...props} isFailed error={{ files: ['file-1-failed.error', 'file-2.failed'] }} />);
|
||||
el.instance.props.actions.cancel.onClick();
|
||||
expect(props.clearState).toHaveBeenCalledWith({ requestKey: RequestKeys.downloadFiles });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should not render when isFailed is false', () => {
|
||||
const { container } = renderWithIntl(<DownloadErrors {...defaultProps} />);
|
||||
expect(container.firstChild).toBeNull();
|
||||
});
|
||||
|
||||
it('should render error message when isFailed is true', () => {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
isFailed: true,
|
||||
error: { files: ['file-1-failed.error', 'file-2.failed'] },
|
||||
};
|
||||
const { getByText } = renderWithIntl(<DownloadErrors {...props} />);
|
||||
expect(getByText("Couldn't download files")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display list of failed files', () => {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
isFailed: true,
|
||||
error: { files: ['file-1-failed.error', 'file-2.failed'] },
|
||||
};
|
||||
const { getByText } = renderWithIntl(<DownloadErrors {...props} />);
|
||||
expect(getByText('file-1-failed.error')).toBeInTheDocument();
|
||||
expect(getByText('file-2.failed')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call clearState when dismiss button is clicked', async () => {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
isFailed: true,
|
||||
error: { files: ['test-file.error'] },
|
||||
};
|
||||
renderWithIntl(<DownloadErrors {...props} />);
|
||||
const user = userEvent.setup();
|
||||
await user.click(screen.getByText('Dismiss'));
|
||||
expect(props.clearState).toHaveBeenCalledWith({ requestKey: RequestKeys.downloadFiles });
|
||||
});
|
||||
|
||||
it('should call downloadFiles when retry button is clicked', async () => {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
isFailed: true,
|
||||
error: { files: ['test-file.error'] },
|
||||
};
|
||||
renderWithIntl(<DownloadErrors {...props} />);
|
||||
const user = userEvent.setup();
|
||||
await user.click(screen.getByText('Retry download'));
|
||||
expect(props.downloadFiles).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('mapStateToProps', () => {
|
||||
let mapped;
|
||||
const testState = { some: 'test-state' };
|
||||
beforeEach(() => {
|
||||
mapped = mapStateToProps(testState);
|
||||
it('should map isFailed from requests selector', () => {
|
||||
const testState = { some: 'test-state' };
|
||||
const mapped = mapStateToProps(testState);
|
||||
expect(selectors.requests.isFailed).toHaveBeenCalledWith(testState, { requestKey: RequestKeys.downloadFiles });
|
||||
expect(mapped.isFailed).toEqual(
|
||||
selectors.requests.isFailed(testState, { requestKey: RequestKeys.downloadFiles }),
|
||||
);
|
||||
});
|
||||
test('isFailed loads from requests.isFailed(downloadFiles)', () => {
|
||||
const requestKey = RequestKeys.downloadFiles;
|
||||
expect(mapped.isFailed).toEqual(selectors.requests.isFailed(testState, { requestKey }));
|
||||
});
|
||||
test('error loads from requests.error(downloadFiles)', () => {
|
||||
const requestKey = RequestKeys.downloadFiles;
|
||||
expect(mapped.error).toEqual(selectors.requests.error(testState, { requestKey }));
|
||||
|
||||
it('should map error from requests selector', () => {
|
||||
const testState = { some: 'test-state' };
|
||||
const mapped = mapStateToProps(testState);
|
||||
expect(selectors.requests.error).toHaveBeenCalledWith(testState, { requestKey: RequestKeys.downloadFiles });
|
||||
expect(mapped.error).toEqual(
|
||||
selectors.requests.error(testState, { requestKey: RequestKeys.downloadFiles }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mapDispatchToProps', () => {
|
||||
it('loads clearState from actions.requests.clearRequest', () => {
|
||||
it('should map clearState to actions.requests.clearRequest', () => {
|
||||
expect(mapDispatchToProps.clearState).toEqual(actions.requests.clearRequest);
|
||||
});
|
||||
it('loads downloadFiles from thunkActions.download.downloadFiles', () => {
|
||||
|
||||
it('should map downloadFiles to thunkActions.download.downloadFiles', () => {
|
||||
expect(mapDispatchToProps.downloadFiles).toEqual(thunkActions.download.downloadFiles);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DownloadErrors component component snapshots failed: show error 1`] = `
|
||||
<ReviewError
|
||||
actions={
|
||||
{
|
||||
"cancel": {
|
||||
"message": {
|
||||
"defaultMessage": "Dismiss",
|
||||
"description": "Dismiss error action button text",
|
||||
"id": "ora-grading.ReviewModal.dismiss",
|
||||
},
|
||||
"onClick": [Function],
|
||||
},
|
||||
"confirm": {
|
||||
"message": {
|
||||
"defaultMessage": "Retry download",
|
||||
"description": "Failed download retry button text",
|
||||
"id": "ora-grading.ReviewModal.errorRetryDownload",
|
||||
},
|
||||
"onClick": [MockFunction this.props.downloadFiles],
|
||||
},
|
||||
}
|
||||
}
|
||||
headingMessage={
|
||||
{
|
||||
"defaultMessage": "Couldn't download files",
|
||||
"id": "ora-grading.ReviewModal.errorDownloadFailed",
|
||||
}
|
||||
}
|
||||
key="downloadFailed"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="We're sorry, something went wrong when we tried to download these files. Please try again."
|
||||
description="Failed download error content"
|
||||
id="ora-grading.ReviewModal.errorDownloadFailedContent"
|
||||
/>
|
||||
<br />
|
||||
<FormattedMessage
|
||||
defaultMessage="Failed files:"
|
||||
description="List header for file download failure alert"
|
||||
id="ora-grading.ReviewModal.errorDownloadFailedFiles"
|
||||
/>
|
||||
<ul>
|
||||
<li
|
||||
key="file-1-failed.error"
|
||||
>
|
||||
file-1-failed.error
|
||||
</li>
|
||||
<li
|
||||
key="file-2.failed"
|
||||
>
|
||||
file-2.failed
|
||||
</li>
|
||||
</ul>
|
||||
</ReviewError>
|
||||
`;
|
||||
|
||||
exports[`DownloadErrors component component snapshots not failed: hide error 1`] = `null`;
|
||||
@@ -1,56 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ReviewContent component component render tests snapshot: failed, showRubric (errors only) 1`] = `
|
||||
<div
|
||||
className="content-block"
|
||||
>
|
||||
<div
|
||||
className="content-wrapper"
|
||||
>
|
||||
<ReviewErrors />
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`ReviewContent component component render tests snapshot: hide rubric 1`] = `
|
||||
<div
|
||||
className="content-block"
|
||||
>
|
||||
<div
|
||||
className="content-wrapper"
|
||||
>
|
||||
<ReviewErrors />
|
||||
<Row
|
||||
className="flex-nowrap m-0"
|
||||
>
|
||||
<Col
|
||||
className="p-0"
|
||||
>
|
||||
<ResponseDisplay />
|
||||
</Col>
|
||||
<Rubric />
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`ReviewContent component component render tests snapshot: show rubric 1`] = `
|
||||
<div
|
||||
className="content-block"
|
||||
>
|
||||
<div
|
||||
className="content-wrapper"
|
||||
>
|
||||
<ReviewErrors />
|
||||
<Row
|
||||
className="flex-nowrap m-0"
|
||||
>
|
||||
<Col
|
||||
className="p-0"
|
||||
>
|
||||
<ResponseDisplay />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -1,72 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ReviewModal component component snapshots closed 1`] = `
|
||||
<FullscreenModal
|
||||
beforeBodyNode={
|
||||
<React.Fragment>
|
||||
<ReviewActions />
|
||||
<DemoWarning />
|
||||
</React.Fragment>
|
||||
}
|
||||
className="review-modal"
|
||||
isOpen={false}
|
||||
modalBodyClassName="review-modal-body"
|
||||
onClose={[MockFunction hooks.onClose]}
|
||||
title="test-ora-name"
|
||||
>
|
||||
<CloseReviewConfirmModal
|
||||
prop="hooks.closeConfirmModalProps"
|
||||
/>
|
||||
</FullscreenModal>
|
||||
`;
|
||||
|
||||
exports[`ReviewModal component component snapshots loading 1`] = `
|
||||
<FullscreenModal
|
||||
beforeBodyNode={
|
||||
<React.Fragment>
|
||||
<ReviewActions />
|
||||
<DemoWarning />
|
||||
</React.Fragment>
|
||||
}
|
||||
className="review-modal"
|
||||
isOpen={true}
|
||||
modalBodyClassName="review-modal-body"
|
||||
onClose={[MockFunction hooks.onClose]}
|
||||
title="test-ora-name"
|
||||
>
|
||||
<ReviewContent />
|
||||
<LoadingMessage
|
||||
message={
|
||||
{
|
||||
"defaultMessage": "Loading response",
|
||||
"description": "loading text for submission response review screen",
|
||||
"id": "ora-grading.ReviewModal.loadingResponse",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<CloseReviewConfirmModal
|
||||
prop="hooks.closeConfirmModalProps"
|
||||
/>
|
||||
</FullscreenModal>
|
||||
`;
|
||||
|
||||
exports[`ReviewModal component component snapshots success 1`] = `
|
||||
<FullscreenModal
|
||||
beforeBodyNode={
|
||||
<React.Fragment>
|
||||
<ReviewActions />
|
||||
<DemoWarning />
|
||||
</React.Fragment>
|
||||
}
|
||||
className="review-modal"
|
||||
isOpen={true}
|
||||
modalBodyClassName="review-modal-body"
|
||||
onClose={[MockFunction hooks.onClose]}
|
||||
title="test-ora-name"
|
||||
>
|
||||
<ReviewContent />
|
||||
<CloseReviewConfirmModal
|
||||
prop="hooks.closeConfirmModalProps"
|
||||
/>
|
||||
</FullscreenModal>
|
||||
`;
|
||||
@@ -1,22 +1,51 @@
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import CloseReviewConfirmModal from './CloseReviewConfirmModal';
|
||||
|
||||
import { CloseReviewConfirmModal } from './CloseReviewConfirmModal';
|
||||
jest.unmock('@openedx/paragon');
|
||||
jest.unmock('react');
|
||||
jest.unmock('@edx/frontend-platform/i18n');
|
||||
|
||||
jest.mock('components/ConfirmModal', () => 'ConfirmModal');
|
||||
const renderWithIntl = (component) => render(
|
||||
<IntlProvider locale="en" messages={{}}>
|
||||
{component}
|
||||
</IntlProvider>,
|
||||
);
|
||||
|
||||
describe('CloseReviewConfirmModal', () => {
|
||||
const props = {
|
||||
isOpen: false,
|
||||
onCancel: jest.fn().mockName('this.props.onCancel'),
|
||||
onConfirm: jest.fn().mockName('this.props.onConfirm'),
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
};
|
||||
|
||||
describe('snapshot', () => {
|
||||
test('closed', () => {
|
||||
expect(shallow(<CloseReviewConfirmModal {...props} />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
test('open', () => {
|
||||
expect(shallow(<CloseReviewConfirmModal {...props} isOpen />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should not render content when modal is closed', () => {
|
||||
const { queryByText } = renderWithIntl(<CloseReviewConfirmModal {...props} />);
|
||||
expect(queryByText('This cannot be undone')).toBeNull();
|
||||
});
|
||||
|
||||
it('should display content when modal is open', () => {
|
||||
const { getByText } = renderWithIntl(<CloseReviewConfirmModal {...props} isOpen />);
|
||||
expect(getByText('Are you sure you want to close this modal?')).toBeInTheDocument();
|
||||
expect(getByText(/This cannot be undone.*This will discard unsaved work/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onCancel when cancel button is clicked', async () => {
|
||||
renderWithIntl(<CloseReviewConfirmModal {...props} isOpen />);
|
||||
const user = userEvent.setup();
|
||||
await user.click(screen.getByText('Go back'));
|
||||
expect(props.onCancel).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should call onConfirm when confirm button is clicked', async () => {
|
||||
renderWithIntl(<CloseReviewConfirmModal {...props} isOpen />);
|
||||
const user = userEvent.setup();
|
||||
await user.click(screen.getByText('Close Modal'));
|
||||
expect(props.onConfirm).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CloseReviewConfirmModal snapshot closed 1`] = `
|
||||
<ConfirmModal
|
||||
cancelText="Go back"
|
||||
confirmText="Close Modal"
|
||||
content="This cannot be undone. This will discard unsaved work and stop this grading process."
|
||||
isOpen={false}
|
||||
onCancel={[MockFunction this.props.onCancel]}
|
||||
onConfirm={[MockFunction this.props.onConfirm]}
|
||||
title="Are you sure you want to close this modal?"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`CloseReviewConfirmModal snapshot open 1`] = `
|
||||
<ConfirmModal
|
||||
cancelText="Go back"
|
||||
confirmText="Close Modal"
|
||||
content="This cannot be undone. This will discard unsaved work and stop this grading process."
|
||||
isOpen={true}
|
||||
onCancel={[MockFunction this.props.onCancel]}
|
||||
onConfirm={[MockFunction this.props.onConfirm]}
|
||||
title="Are you sure you want to close this modal?"
|
||||
/>
|
||||
`;
|
||||
@@ -1,60 +1,133 @@
|
||||
import React from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { formatMessage } from 'testUtils';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import * as hooks from './hooks';
|
||||
import { ReviewModal } from '.';
|
||||
import messages from './messages';
|
||||
|
||||
jest.useFakeTimers('modern');
|
||||
jest.unmock('@openedx/paragon');
|
||||
jest.unmock('react');
|
||||
jest.unmock('@edx/frontend-platform/i18n');
|
||||
|
||||
jest.mock('components/LoadingMessage', () => 'LoadingMessage');
|
||||
jest.mock('containers/DemoWarning', () => 'DemoWarning');
|
||||
jest.mock('containers/ReviewActions', () => 'ReviewActions');
|
||||
jest.mock('./ReviewContent', () => 'ReviewContent');
|
||||
jest.mock('./components/CloseReviewConfirmModal', () => 'CloseReviewConfirmModal');
|
||||
jest.mock('react-redux', () => ({
|
||||
useDispatch: jest.fn(),
|
||||
connect: jest.fn(() => (Component) => Component),
|
||||
}));
|
||||
|
||||
jest.mock('./hooks', () => ({
|
||||
rendererHooks: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('ReviewModal component', () => {
|
||||
const dispatch = useDispatch();
|
||||
const hookProps = {
|
||||
isLoading: false,
|
||||
title: 'test-ora-name',
|
||||
onClose: jest.fn().mockName('hooks.onClose'),
|
||||
isOpen: false,
|
||||
closeConfirmModalProps: {
|
||||
prop: 'hooks.closeConfirmModalProps',
|
||||
},
|
||||
};
|
||||
jest.mock('containers/ReviewModal/ReviewContent', () => {
|
||||
const ReviewContent = () => <div>ReviewContent</div>;
|
||||
return ReviewContent;
|
||||
});
|
||||
|
||||
const render = (newVals) => {
|
||||
hooks.rendererHooks.mockReturnValueOnce({ ...hookProps, ...newVals });
|
||||
return shallow(<ReviewModal />);
|
||||
};
|
||||
describe('component', () => {
|
||||
describe('snapshots', () => {
|
||||
test('closed', () => {
|
||||
expect(render().snapshot).toMatchSnapshot();
|
||||
});
|
||||
test('loading', () => {
|
||||
expect(render({ isOpen: true, isLoading: true }).snapshot).toMatchSnapshot();
|
||||
});
|
||||
test('success', () => {
|
||||
expect(render({ isOpen: true }).snapshot).toMatchSnapshot();
|
||||
});
|
||||
jest.mock('containers/ReviewActions', () => {
|
||||
const ReviewActions = () => <div>ReviewActions</div>;
|
||||
return ReviewActions;
|
||||
});
|
||||
|
||||
jest.mock('containers/DemoWarning', () => {
|
||||
const DemoWarning = () => <div>DemoWarning</div>;
|
||||
return DemoWarning;
|
||||
});
|
||||
|
||||
jest.mock('containers/ReviewModal/components/CloseReviewConfirmModal', () => {
|
||||
const CloseReviewConfirmModal = () => <div>CloseReviewConfirmModal</div>;
|
||||
return CloseReviewConfirmModal;
|
||||
});
|
||||
|
||||
describe('ReviewModal', () => {
|
||||
const mockDispatch = jest.fn();
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
useDispatch.mockReturnValue(mockDispatch);
|
||||
});
|
||||
|
||||
it('calls rendererHooks with dispatch and intl', () => {
|
||||
hooks.rendererHooks.mockReturnValue({
|
||||
isLoading: false,
|
||||
title: 'test-ora-name',
|
||||
onClose: jest.fn(),
|
||||
isOpen: false,
|
||||
closeConfirmModalProps: {
|
||||
isOpen: false,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
});
|
||||
|
||||
render(<IntlProvider locale="en" messages={{}}><ReviewModal /></IntlProvider>);
|
||||
|
||||
expect(hooks.rendererHooks).toHaveBeenCalledWith({
|
||||
dispatch: mockDispatch,
|
||||
intl: expect.any(Object),
|
||||
});
|
||||
});
|
||||
describe('behavior', () => {
|
||||
it('initializes renderer hook with dispatch and intl props', () => {
|
||||
render();
|
||||
expect(hooks.rendererHooks).toHaveBeenCalledWith({
|
||||
dispatch,
|
||||
intl: { formatMessage, formatDate: expect.any(Function) },
|
||||
});
|
||||
|
||||
it('calls useDispatch hook', () => {
|
||||
hooks.rendererHooks.mockReturnValue({
|
||||
isLoading: false,
|
||||
title: 'test-ora-name',
|
||||
onClose: jest.fn(),
|
||||
isOpen: false,
|
||||
closeConfirmModalProps: {
|
||||
isOpen: false,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
});
|
||||
|
||||
render(<IntlProvider locale="en" messages={{}}><ReviewModal /></IntlProvider>);
|
||||
screen.debug();
|
||||
expect(useDispatch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('renders correctly when open', () => {
|
||||
hooks.rendererHooks.mockReturnValue({
|
||||
isLoading: false,
|
||||
title: 'test-ora-name',
|
||||
onClose: jest.fn(),
|
||||
isOpen: true,
|
||||
closeConfirmModalProps: {
|
||||
isOpen: false,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
});
|
||||
|
||||
render(<IntlProvider locale="en" messages={{}}><ReviewModal /></IntlProvider>);
|
||||
const reviewActions = screen.getByText('ReviewActions');
|
||||
expect(reviewActions).toBeInTheDocument();
|
||||
|
||||
const demoWarning = screen.getByText('DemoWarning');
|
||||
expect(demoWarning).toBeInTheDocument();
|
||||
|
||||
const reviewContent = screen.getByText('ReviewContent');
|
||||
expect(reviewContent).toBeInTheDocument();
|
||||
|
||||
const closeReviewConfirmModal = screen.getByText('CloseReviewConfirmModal');
|
||||
expect(closeReviewConfirmModal).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders correctly loading message', () => {
|
||||
hooks.rendererHooks.mockReturnValue({
|
||||
isLoading: true,
|
||||
title: 'test-ora-name',
|
||||
onClose: jest.fn(),
|
||||
isOpen: true,
|
||||
closeConfirmModalProps: {
|
||||
isOpen: false,
|
||||
onCancel: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
},
|
||||
});
|
||||
|
||||
render(<IntlProvider locale="en" messages={{}}><ReviewModal /></IntlProvider>);
|
||||
screen.debug();
|
||||
const loadingMessage = screen.getByText(messages.loadingResponse.defaultMessage);
|
||||
expect(loadingMessage).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user