test: deprecate react-unit-test-utils part-7 (#442)

* test: deprecate react-unit-test-utils part-7

* test: change fireEvent for userEvent

---------

Co-authored-by: diana-villalvazo-wgu <diana.villalvazo@wgu.edu>
This commit is contained in:
Victor Navarro
2025-08-29 18:27:15 -06:00
committed by GitHub
parent 480262a7a2
commit e4c0b1843d
10 changed files with 358 additions and 424 deletions

View File

@@ -1,37 +1,59 @@
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { render } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import FilePopoverContent from 'components/FilePopoverContent';
import FilePopoverCell from './FilePopoverCell';
jest.mock('components/InfoPopover', () => 'InfoPopover');
jest.mock('components/FilePopoverContent', () => 'FilePopoverContent');
const mockMessages = {
en: {},
};
const renderWithIntl = (component) => render(
<IntlProvider locale="en" messages={mockMessages}>
{component}
</IntlProvider>,
);
describe('FilePopoverCell', () => {
describe('component', () => {
const props = {
const props = {
row: {
original: {
name: 'some file name',
description: 'long descriptive text...',
downloadURL: 'this-url-is.working',
size: 1024,
},
},
};
it('renders the component without errors', () => {
const { container } = renderWithIntl(<FilePopoverCell {...props} />);
expect(container.firstChild).toBeInTheDocument();
});
it('renders the info icon button', () => {
const { getByTestId } = renderWithIntl(<FilePopoverCell {...props} />);
expect(getByTestId('esg-help-icon')).toBeInTheDocument();
});
it('info button has correct alt text', () => {
const { getByTestId } = renderWithIntl(<FilePopoverCell {...props} />);
const button = getByTestId('esg-help-icon');
expect(button).toHaveAttribute('alt', 'Display more info');
});
it('handles empty row.original object', () => {
const emptyProps = {
row: {
original: {
name: 'some file name',
description: 'long descriptive text...',
downloadURL: 'this-url-is.working',
},
original: {},
},
};
let el;
beforeEach(() => {
el = shallow(<FilePopoverCell {...props} />);
});
test('snapshot', () => {
expect(el.snapshot).toMatchSnapshot();
});
describe('behavior', () => {
test('content', () => {
const { original } = props.row;
const content = el.instance.findByType(FilePopoverContent)[0];
expect(content.props).toEqual({ ...original });
});
});
const { container } = renderWithIntl(<FilePopoverCell {...emptyProps} />);
expect(container.firstChild).toBeInTheDocument();
});
it('handles missing row prop', () => {
const { container } = renderWithIntl(<FilePopoverCell />);
expect(container.firstChild).toBeInTheDocument();
});
});

View File

@@ -1,11 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FilePopoverCell component snapshot 1`] = `
<InfoPopover>
<FilePopoverContent
description="long descriptive text..."
downloadURL="this-url-is.working"
name="some file name"
/>
</InfoPopover>
`;

View File

@@ -1,141 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ReviewActions component component snapshot: do not show rubric 1`] = `
<div>
<ActionRow
className="review-actions"
>
<span
className="review-actions-username"
>
<span
className="lead"
>
test-userDisplay
</span>
<StatusBadge
className="review-actions-status mr-3"
status="grading-status"
/>
<span
className="small"
>
<FormattedMessage
defaultMessage="Score: {pointsEarned}/{pointsPossible}"
description="Review pane action bar score display"
id="ora-grading.ReviewActions.pointsDisplay"
values={
{
"pointsEarned": 3,
"pointsPossible": 10,
}
}
/>
</span>
</span>
<div
className="review-actions-group"
>
<Fragment>
<Button
onClick={[MockFunction this.props.toggleShowRubric]}
variant="outline-primary mr-2"
>
<FormattedMessage
defaultMessage="Show Rubric"
description="Review pane action bar Show Rubric button text"
id="ora-grading.ReviewActions.showRubric"
/>
</Button>
<StartGradingButton />
</Fragment>
<SubmissionNavigation />
</div>
</ActionRow>
</div>
`;
exports[`ReviewActions component component snapshot: loading 1`] = `
<div>
<ActionRow
className="review-actions"
>
<span
className="review-actions-username"
>
<span
className="lead"
>
test-userDisplay
</span>
<StatusBadge
className="review-actions-status mr-3"
status="grading-status"
/>
<span
className="small"
>
<FormattedMessage
defaultMessage="Score: {pointsEarned}/{pointsPossible}"
description="Review pane action bar score display"
id="ora-grading.ReviewActions.pointsDisplay"
values={
{
"pointsEarned": 3,
"pointsPossible": 10,
}
}
/>
</span>
</span>
<div
className="review-actions-group"
>
<SubmissionNavigation />
</div>
</ActionRow>
</div>
`;
exports[`ReviewActions component component snapshot: show rubric, no score 1`] = `
<div>
<ActionRow
className="review-actions"
>
<span
className="review-actions-username"
>
<span
className="lead"
>
test-userDisplay
</span>
<StatusBadge
className="review-actions-status mr-3"
status="grading-status"
/>
<span
className="small"
/>
</span>
<div
className="review-actions-group"
>
<Fragment>
<Button
onClick={[MockFunction this.props.toggleShowRubric]}
variant="outline-primary mr-2"
>
<FormattedMessage
defaultMessage="Hide Rubric"
description="Review pane action bar Hide Rubric button text"
id="ora-grading.ReviewActions.hideRubric"
/>
</Button>
<StartGradingButton />
</Fragment>
<SubmissionNavigation />
</div>
</ActionRow>
</div>
`;

View File

@@ -1,8 +1,16 @@
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 OverrideGradeConfirmModal from './OverrideGradeConfirmModal';
import { OverrideGradeConfirmModal } from './OverrideGradeConfirmModal';
jest.unmock('@openedx/paragon');
jest.unmock('react');
jest.mock('components/ConfirmModal', () => 'ConfirmModal');
const renderWithIntl = (component) => render(
<IntlProvider locale="en">
{component}
</IntlProvider>,
);
describe('OverrideGradeConfirmModal', () => {
const props = {
@@ -10,10 +18,33 @@ describe('OverrideGradeConfirmModal', () => {
onCancel: jest.fn().mockName('this.props.onCancel'),
onConfirm: jest.fn().mockName('this.props.onConfirm'),
};
test('snapshot: closed', () => {
expect(shallow(<OverrideGradeConfirmModal {...props} />).snapshot).toMatchSnapshot();
beforeEach(() => {
jest.clearAllMocks();
});
test('snapshot: open', () => {
expect(shallow(<OverrideGradeConfirmModal {...props} isOpen />).snapshot).toMatchSnapshot();
it('should not render content when modal is closed', () => {
const { queryByText } = renderWithIntl(<OverrideGradeConfirmModal {...props} />);
expect(queryByText('This cannot be undone')).toBeNull();
});
it('should display content when modal is open', () => {
const { getByText } = renderWithIntl(<OverrideGradeConfirmModal {...props} isOpen />);
expect(getByText('Are you sure you want to override this grade?')).toBeInTheDocument();
expect(getByText(/This cannot be undone.*The learner may have already received their grade/)).toBeInTheDocument();
});
it('should call onCancel when cancel button is clicked', async () => {
renderWithIntl(<OverrideGradeConfirmModal {...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(<OverrideGradeConfirmModal {...props} isOpen />);
const user = userEvent.setup();
await user.click(screen.getByText('Continue grade override'));
expect(props.onConfirm).toHaveBeenCalledTimes(1);
});
});

View File

@@ -1,8 +1,16 @@
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 StopGradingConfirmModal from './StopGradingConfirmModal';
import { StopGradingConfirmModal } from './StopGradingConfirmModal';
jest.unmock('@openedx/paragon');
jest.unmock('react');
jest.mock('components/ConfirmModal', () => 'ConfirmModal');
const renderWithIntl = (component) => render(
<IntlProvider locale="en">
{component}
</IntlProvider>,
);
describe('StopGradingConfirmModal', () => {
const props = {
@@ -11,13 +19,46 @@ describe('StopGradingConfirmModal', () => {
onCancel: jest.fn().mockName('this.props.onCancel'),
onConfirm: jest.fn().mockName('this.props.onConfirm'),
};
test('snapshot: closed', () => {
expect(shallow(<StopGradingConfirmModal {...props} />).snapshot).toMatchSnapshot();
beforeEach(() => {
jest.clearAllMocks();
});
test('snapshot: open', () => {
expect(shallow(<StopGradingConfirmModal {...props} isOpen />).snapshot).toMatchSnapshot();
it('should not render content when modal is closed', () => {
const { queryByText } = renderWithIntl(<StopGradingConfirmModal {...props} />);
expect(queryByText('Your progress will be lost.')).toBeNull();
});
test('snapshot: open, isOverride', () => {
expect(shallow(<StopGradingConfirmModal {...props} isOverride />).snapshot).toMatchSnapshot();
it('should display stop grading content when modal is open', () => {
const { getByText } = renderWithIntl(<StopGradingConfirmModal {...props} isOpen />);
expect(getByText('Are you sure you want to stop grading this response?')).toBeInTheDocument();
expect(getByText('Your progress will be lost.')).toBeInTheDocument();
});
it('should display stop override content when modal is open and isOverride is true', () => {
const { getByText } = renderWithIntl(<StopGradingConfirmModal {...props} isOpen isOverride />);
expect(getByText('Are you sure you want to stop grade override?')).toBeInTheDocument();
expect(getByText('Your progress will be lost.')).toBeInTheDocument();
});
it('should call onCancel when cancel button is clicked', async () => {
renderWithIntl(<StopGradingConfirmModal {...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 for regular grading', async () => {
renderWithIntl(<StopGradingConfirmModal {...props} isOpen />);
const user = userEvent.setup();
await user.click(screen.getByText('Cancel grading'));
expect(props.onConfirm).toHaveBeenCalledTimes(1);
});
it('should call onConfirm when confirm button is clicked for override', async () => {
renderWithIntl(<StopGradingConfirmModal {...props} isOpen isOverride />);
const user = userEvent.setup();
await user.click(screen.getByText('Stop grade override'));
expect(props.onConfirm).toHaveBeenCalledTimes(1);
});
});

View File

@@ -1,73 +1,108 @@
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, thunkActions } from 'data/redux';
import { thunkActions } from 'data/redux';
import {
SubmissionNavigation,
mapStateToProps,
mapDispatchToProps,
} from './SubmissionNavigation';
jest.mock('data/redux/grading/selectors', () => ({
prev: {
doesExist: (state) => ({ prevDoesExist: state }),
},
next: {
doesExist: (state) => ({ nextDoesExist: state }),
},
activeIndex: (state) => ({ activeIndex: state }),
selectionLength: (state) => ({ selectionLength: state }),
}));
jest.mock('data/redux/requests/selectors', () => ({
allowNavigation: (state) => ({ allowNavigation: state }),
}));
jest.unmock('@openedx/paragon');
jest.unmock('react');
const mockMessages = {
'ora-grading.ReviewActions.loadPrevious': 'Load previous submission',
'ora-grading.ReviewActions.loadNext': 'Load next submission',
'ora-grading.ReviewActions.navigationLabel': '{current} of {total}',
};
const renderWithIntl = (component) => render(
<IntlProvider locale="en" messages={mockMessages}>
{component}
</IntlProvider>,
);
describe('SubmissionNavigation component', () => {
describe('component', () => {
const props = {
const defaultProps = {
activeIndex: 4,
selectionLength: 5,
loadNext: jest.fn(),
loadPrev: jest.fn(),
hasPrevSubmission: true,
hasNextSubmission: true,
allowNavigation: true,
};
beforeEach(() => {
props.loadNext = jest.fn().mockName('this.props.loadNext');
props.loadPrev = jest.fn().mockName('this.props.loadPrev');
defaultProps.loadNext.mockClear();
defaultProps.loadPrev.mockClear();
});
test('snapshot: no prev submission (disabled)', () => {
expect(shallow(
<SubmissionNavigation {...props} activeIndex={0} hasNextSubmission />,
).snapshot).toMatchSnapshot();
it('renders navigation with current position and total submissions', () => {
renderWithIntl(<SubmissionNavigation {...defaultProps} />);
expect(screen.getByText('FormattedMessage')).toBeInTheDocument();
});
test('snapshot: no next submission (disabled)', () => {
expect(shallow(
<SubmissionNavigation {...props} hasPrevSubmission />,
).snapshot).toMatchSnapshot();
});
});
describe('mapStateToProps', () => {
let mapped;
const testState = { some: 'test-state' };
beforeEach(() => {
mapped = mapStateToProps(testState);
});
test('activeIndex loads from grading.activeIndex', () => {
expect(mapped.activeIndex).toEqual(selectors.grading.activeIndex(testState));
});
test('hasNextSubmission loads from grading.next.doesExist', () => {
expect(mapped.hasNextSubmission).toEqual(selectors.grading.next.doesExist(testState));
});
test('hasPrevSubmission loads from grading.prev.doesExist', () => {
expect(mapped.hasPrevSubmission).toEqual(selectors.grading.prev.doesExist(testState));
});
test('selectionLength loads from grading.selectionLength', () => {
expect(mapped.selectionLength).toEqual(selectors.grading.selectionLength(testState));
it('disables previous button when no previous submission exists', () => {
renderWithIntl(
<SubmissionNavigation {...defaultProps} hasPrevSubmission={false} />,
);
const prevButton = screen.getByRole('button', { name: /load previous submission/i });
expect(prevButton).toBeDisabled();
});
it('disables next button when no next submission exists', () => {
renderWithIntl(
<SubmissionNavigation {...defaultProps} hasNextSubmission={false} />,
);
const nextButton = screen.getByRole('button', { name: /load next submission/i });
expect(nextButton).toBeDisabled();
});
it('disables both buttons when navigation is not allowed', () => {
renderWithIntl(
<SubmissionNavigation {...defaultProps} allowNavigation={false} />,
);
const prevButton = screen.getByRole('button', { name: /load previous submission/i });
const nextButton = screen.getByRole('button', { name: /load next submission/i });
expect(prevButton).toBeDisabled();
expect(nextButton).toBeDisabled();
});
it('calls loadPrev when previous button is clicked', async () => {
renderWithIntl(<SubmissionNavigation {...defaultProps} />);
const prevButton = screen.getByRole('button', { name: /load previous submission/i });
const user = userEvent.setup();
await user.click(prevButton);
expect(defaultProps.loadPrev).toHaveBeenCalledTimes(1);
});
it('calls loadNext when next button is clicked', async () => {
renderWithIntl(<SubmissionNavigation {...defaultProps} />);
const nextButton = screen.getByRole('button', { name: /load next submission/i });
const user = userEvent.setup();
await user.click(nextButton);
expect(defaultProps.loadNext).toHaveBeenCalledTimes(1);
});
it('shows correct position when at first submission', () => {
render(
<SubmissionNavigation {...defaultProps} activeIndex={0} hasPrevSubmission={false} />,
);
expect(screen.getByText('FormattedMessage')).toBeInTheDocument();
});
});
describe('mapDispatchToProps', () => {
it('loads loadNext from thunkActions.grading.loadNext', () => {
it('loads loadNext from thunk actions', () => {
expect(mapDispatchToProps.loadNext).toEqual(thunkActions.grading.loadNext);
});
it('loads loadPrev from thunkActions.grading.loadPrev', () => {
it('loads loadPrev from thunk actions', () => {
expect(mapDispatchToProps.loadPrev).toEqual(thunkActions.grading.loadPrev);
});
});

View File

@@ -1,25 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`OverrideGradeConfirmModal snapshot: closed 1`] = `
<ConfirmModal
cancelText="Go back"
confirmText="Continue grade override"
content="This cannot be undone. The learner may have already received their grade."
isOpen={false}
onCancel={[MockFunction this.props.onCancel]}
onConfirm={[MockFunction this.props.onConfirm]}
title="Are you sure you want to override this grade?"
/>
`;
exports[`OverrideGradeConfirmModal snapshot: open 1`] = `
<ConfirmModal
cancelText="Go back"
confirmText="Continue grade override"
content="This cannot be undone. The learner may have already received their grade."
isOpen={true}
onCancel={[MockFunction this.props.onCancel]}
onConfirm={[MockFunction this.props.onConfirm]}
title="Are you sure you want to override this grade?"
/>
`;

View File

@@ -1,37 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`StopGradingConfirmModal snapshot: closed 1`] = `
<ConfirmModal
cancelText="Go back"
confirmText="Cancel grading"
content="Your progress will be lost."
isOpen={false}
onCancel={[MockFunction this.props.onCancel]}
onConfirm={[MockFunction this.props.onConfirm]}
title="Are you sure you want to stop grading this response?"
/>
`;
exports[`StopGradingConfirmModal snapshot: open 1`] = `
<ConfirmModal
cancelText="Go back"
confirmText="Cancel grading"
content="Your progress will be lost."
isOpen={true}
onCancel={[MockFunction this.props.onCancel]}
onConfirm={[MockFunction this.props.onConfirm]}
title="Are you sure you want to stop grading this response?"
/>
`;
exports[`StopGradingConfirmModal snapshot: open, isOverride 1`] = `
<ConfirmModal
cancelText="Go back"
confirmText="Stop grade override"
content="Your progress will be lost."
isOpen={false}
onCancel={[MockFunction this.props.onCancel]}
onConfirm={[MockFunction this.props.onConfirm]}
title="Are you sure you want to stop grade override?"
/>
`;

View File

@@ -1,81 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SubmissionNavigation component component snapshot: no next submission (disabled) 1`] = `
<span
className="submission-navigation"
>
<IconButton
alt="Load previous submission"
className="ml-1"
disabled={true}
iconAs="Icon"
onClick={[MockFunction this.props.loadPrev]}
size="inline"
src={[MockFunction icons.ChevronLeft]}
/>
<span
className="ml-1"
>
<FormattedMessage
defaultMessage="{current} of {total}"
description="Submission navigation location label"
id="ora-grading.ReviewActions.navigationLabel"
values={
{
"current": 5,
"total": 5,
}
}
/>
</span>
<IconButton
alt="Load next submission"
className="ml-1"
disabled={true}
iconAs="Icon"
onClick={[MockFunction this.props.loadNext]}
size="inline"
src={[MockFunction icons.ChevronRight]}
/>
</span>
`;
exports[`SubmissionNavigation component component snapshot: no prev submission (disabled) 1`] = `
<span
className="submission-navigation"
>
<IconButton
alt="Load previous submission"
className="ml-1"
disabled={true}
iconAs="Icon"
onClick={[MockFunction this.props.loadPrev]}
size="inline"
src={[MockFunction icons.ChevronLeft]}
/>
<span
className="ml-1"
>
<FormattedMessage
defaultMessage="{current} of {total}"
description="Submission navigation location label"
id="ora-grading.ReviewActions.navigationLabel"
values={
{
"current": 1,
"total": 5,
}
}
/>
</span>
<IconButton
alt="Load next submission"
className="ml-1"
disabled={true}
iconAs="Icon"
onClick={[MockFunction this.props.loadNext]}
size="inline"
src={[MockFunction icons.ChevronRight]}
/>
</span>
`;

View File

@@ -1,74 +1,174 @@
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 { actions, selectors } from 'data/redux';
import { RequestKeys } from 'data/constants/requests';
import { ReviewActions, mapStateToProps, mapDispatchToProps } from '.';
jest.mock('data/redux/app/selectors', () => ({
showRubric: (state) => ({ showRubric: state }),
}));
jest.mock('data/redux/grading/selectors', () => ({
selected: {
gradingStatus: (state) => ({ gradingStatus: state }),
score: (state) => ({ score: state }),
userDisplay: (state) => ({ userDisplay: state }),
jest.unmock('@openedx/paragon');
jest.unmock('react');
jest.unmock('@edx/frontend-platform/i18n');
jest.mock('data/redux', () => ({
actions: {
app: {
toggleShowRubric: jest.fn().mockName('actions.app.toggleShowRubric'),
},
},
selectors: {
app: {
showRubric: jest.fn(state => state.showRubric).mockName('selectors.app.showRubric'),
},
grading: {
selected: {
userDisplay: jest.fn(state => state.userDisplay).mockName('selectors.grading.selected.userDisplay'),
gradingStatus: jest.fn(state => state.gradingStatus).mockName('selectors.grading.selected.gradingStatus'),
score: jest.fn(state => state.score).mockName('selectors.grading.selected.score'),
gradeStatus: jest.fn(state => state.gradeStatus).mockName('selectors.grading.selected.gradeStatus'),
},
selectionLength: jest.fn(state => state.selectionLength).mockName('selectors.grading.selectionLength'),
activeIndex: jest.fn(() => 0).mockName('selectors.grading.activeIndex'),
next: {
doesExist: jest.fn(() => false).mockName('selectors.grading.next.doesExist'),
},
prev: {
doesExist: jest.fn(() => false).mockName('selectors.grading.prev.doesExist'),
},
},
requests: {
isCompleted: jest.fn((state, { requestKey }) => state.requests?.[requestKey]).mockName('selectors.requests.isCompleted'),
isPending: jest.fn(() => false).mockName('selectors.requests.isPending'),
allowNavigation: jest.fn(() => true).mockName('selectors.requests.allowNavigation'),
},
},
thunkActions: {
app: {
toggleShowRubric: jest.fn().mockName('thunkActions.app.toggleShowRubric'),
},
grading: {
loadNext: jest.fn().mockName('thunkActions.grading.loadNext'),
loadPrev: jest.fn().mockName('thunkActions.grading.loadPrev'),
startGrading: jest.fn().mockName('thunkActions.grading.startGrading'),
cancelGrading: jest.fn().mockName('thunkActions.grading.cancelGrading'),
},
},
}));
jest.mock('data/redux/requests/selectors', () => ({
isCompleted: (state) => ({ isCompleted: state }),
}));
jest.mock('components/StatusBadge', () => 'StatusBadge');
jest.mock('./components/StartGradingButton', () => 'StartGradingButton');
jest.mock('./components/SubmissionNavigation', () => 'SubmissionNavigation');
jest.mock('./components/StartGradingButton', () => {
const MockStartGradingButton = () => null;
return MockStartGradingButton;
});
jest.mock('./components/SubmissionNavigation', () => {
const MockSubmissionNavigation = () => null;
return MockSubmissionNavigation;
});
describe('ReviewActions component', () => {
const renderWithIntl = (component) => render(
<IntlProvider locale="en" messages={{}}>
{component}
</IntlProvider>,
);
describe('component', () => {
const props = {
gradingStatus: 'grading-status',
gradingStatus: 'ungraded',
userDisplay: 'test-userDisplay',
showRubric: false,
score: { pointsEarned: 3, pointsPossible: 10 },
toggleShowRubric: jest.fn(),
};
beforeEach(() => {
props.toggleShowRubric = jest.fn().mockName('this.props.toggleShowRubric');
jest.clearAllMocks();
});
test('snapshot: loading', () => {
expect(shallow(<ReviewActions {...props} />).snapshot).toMatchSnapshot();
it('displays user display name', () => {
renderWithIntl(<ReviewActions {...props} />);
expect(screen.getByText('test-userDisplay')).toBeInTheDocument();
});
test('snapshot: do not show rubric', () => {
expect(shallow(<ReviewActions {...props} isLoaded />).snapshot).toMatchSnapshot();
it('does not show rubric button when not loaded', () => {
renderWithIntl(<ReviewActions {...props} />);
const buttons = screen.queryAllByRole('button');
expect(buttons).toHaveLength(0);
});
test('snapshot: show rubric, no score', () => {
expect(shallow(<ReviewActions {...props} isLoaded showRubric score={{}} />).snapshot).toMatchSnapshot();
it('shows rubric button when loaded', () => {
renderWithIntl(<ReviewActions {...props} isLoaded />);
const buttons = screen.getAllByRole('button');
expect(buttons.length).toBeGreaterThan(0);
});
it('calls toggleShowRubric when button is clicked', async () => {
renderWithIntl(<ReviewActions {...props} isLoaded />);
const button = screen.getByRole('button');
const user = userEvent.setup();
await user.click(button);
expect(props.toggleShowRubric).toHaveBeenCalledTimes(1);
});
it('displays points when pointsPossible is provided', () => {
renderWithIntl(<ReviewActions {...props} />);
const pointsElement = screen.getByText('Score: 3/10');
expect(pointsElement).toBeInTheDocument();
});
it('does not display points when pointsPossible is not provided', () => {
const propsWithoutPoints = {
...props,
score: { pointsEarned: 3, pointsPossible: null },
};
renderWithIntl(<ReviewActions {...propsWithoutPoints} />);
const pointsElement = screen.queryByText(text => text.includes('3'));
expect(pointsElement).toBeNull();
});
});
describe('mapStateToProps', () => {
let mapped;
const testState = { some: 'test-state' };
const testState = {
showRubric: true,
userDisplay: 'test-user',
gradingStatus: 'test-status',
score: { pointsEarned: 5, pointsPossible: 10 },
requests: { [RequestKeys.fetchSubmission]: true },
};
beforeEach(() => {
mapped = mapStateToProps(testState);
});
test('isLoaded loads from requests.isCompleted for fetchSubmissions', () => {
const requestKey = RequestKeys.fetchSubmission;
expect(mapped.isLoaded).toEqual(selectors.requests.isCompleted(testState, { requestKey }));
it('maps isLoaded from requests.isCompleted for fetchSubmissions', () => {
expect(selectors.requests.isCompleted).toHaveBeenCalledWith(
testState,
{ requestKey: RequestKeys.fetchSubmission },
);
expect(mapped.isLoaded).toBe(true);
});
test('userDisplay loads from grading.selected.userDisplay', () => {
expect(mapped.userDisplay).toEqual(selectors.grading.selected.userDisplay(testState));
it('maps userDisplay from grading.selected.userDisplay', () => {
expect(selectors.grading.selected.userDisplay).toHaveBeenCalledWith(testState);
expect(mapped.userDisplay).toBe('test-user');
});
test('gradingStatus loads from grading.selected.gradingStatus', () => {
expect(mapped.gradingStatus).toEqual(selectors.grading.selected.gradingStatus(testState));
it('maps gradingStatus from grading.selected.gradingStatus', () => {
expect(selectors.grading.selected.gradingStatus).toHaveBeenCalledWith(testState);
expect(mapped.gradingStatus).toBe('test-status');
});
test('score loads from grading.selected.score', () => {
expect(mapped.score).toEqual(selectors.grading.selected.score(testState));
it('maps score from grading.selected.score', () => {
expect(selectors.grading.selected.score).toHaveBeenCalledWith(testState);
expect(mapped.score).toEqual({ pointsEarned: 5, pointsPossible: 10 });
});
test('showRubric loads from app.showRubric', () => {
expect(mapped.showRubric).toEqual(selectors.app.showRubric(testState));
it('maps showRubric from app.showRubric', () => {
expect(selectors.app.showRubric).toHaveBeenCalledWith(testState);
expect(mapped.showRubric).toBe(true);
});
});
describe('mapDispatchToProps', () => {
it('loads toggleShowRubric from actions.app.toggleShowRubric', () => {
it('maps toggleShowRubric to actions.app.toggleShowRubric', () => {
expect(mapDispatchToProps.toggleShowRubric).toEqual(actions.app.toggleShowRubric);
});
});