Skip to content

Commit f745954

Browse files
authored
Lk/unit test (#185)
* chore: add tests * test: confirm dialog * test: criterion container * test: file preview * test: update some unaccounted error * test: file upload * chore: linting * test: hotjar survey * test: info popover * test: instructions * chore: linting * test: modal actions * test: progress bar * test: prompt * test: action button and modal container * test: text response * test: assessment view * test: grade view view * chore: add more ignore list for coverage * test: update file card * test: xblock view * test: xblock studio view * test: submission view * chore: fix format date consistency * chore: add file size * chore: update linting
1 parent ecca975 commit f745954

File tree

169 files changed

+8232
-92
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

169 files changed

+8232
-92
lines changed

jest.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const config = createConfig('jest', {
1212
'src/hooks/testHooks', // don't check coverage for jest mocking tools
1313
// 'src/data/services/lms/fakeData', // don't check coverage for mock data
1414
'src/test', // don't check coverage for test integration test utils
15+
'messages.js', // don't check coverage for i18n messages
16+
'src/data/services/lms/fakeData', // don't check coverage for fake data
1517
],
1618
testTimeout: 120000,
1719
});

src/components/ActionButton.test.jsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { shallow } from '@edx/react-unit-test-utils';
2+
3+
import ActionButton from './ActionButton';
4+
5+
describe('<ActionButton />', () => {
6+
const props = {
7+
state: 'arbitraryState',
8+
};
9+
10+
it('render empty when no onClick or href', () => {
11+
const wrapper = shallow(<ActionButton {...props} />);
12+
expect(wrapper.isEmptyRender()).toBe(true);
13+
});
14+
15+
it('render StatefulButton when state is provided', () => {
16+
const wrapper = shallow(<ActionButton href="some-href" state="loading" />);
17+
expect(wrapper.snapshot).toMatchSnapshot();
18+
expect(wrapper.instance.findByType('StatefulButton')).toHaveLength(1);
19+
expect(wrapper.instance.findByType('Button')).toHaveLength(0);
20+
});
21+
22+
it('render Button when state is not provided', () => {
23+
const wrapper = shallow(<ActionButton onClick={jest.fn().mockName('onClick')} />);
24+
expect(wrapper.snapshot).toMatchSnapshot();
25+
expect(wrapper.instance.findByType('StatefulButton')).toHaveLength(0);
26+
expect(wrapper.instance.findByType('Button')).toHaveLength(1);
27+
});
28+
});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`<AppContainer /> render default 1`] = `
4+
<div
5+
className="w-100 h-100"
6+
>
7+
<div>
8+
children
9+
</div>
10+
</div>
11+
`;
12+
13+
exports[`<AppContainer /> render error oraConfigDataError 1`] = `
14+
<ErrorPage
15+
message="An unknown error occurred. Please try again."
16+
/>
17+
`;
18+
19+
exports[`<AppContainer /> render error pageDataError 1`] = `
20+
<ErrorPage
21+
message="An unknown error occurred. Please try again."
22+
/>
23+
`;
24+
25+
exports[`<AppContainer /> render loading isORAConfigLoaded 1`] = `
26+
<div
27+
className="w-100 h-100"
28+
>
29+
<Spinner
30+
animation="border"
31+
className="app-loading"
32+
screenReaderText="loading"
33+
/>
34+
</div>
35+
`;
36+
37+
exports[`<AppContainer /> render loading isPageDataLoaded 1`] = `
38+
<div
39+
className="w-100 h-100"
40+
>
41+
<Spinner
42+
animation="border"
43+
className="app-loading"
44+
screenReaderText="loading"
45+
/>
46+
</div>
47+
`;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { shallow } from '@edx/react-unit-test-utils';
2+
import {
3+
useIsPageDataLoaded,
4+
useIsORAConfigLoaded,
5+
usePageDataError,
6+
useORAConfigDataError,
7+
} from 'hooks/app';
8+
import AppContainer from '.';
9+
10+
jest.mock('hooks/app', () => ({
11+
useIsPageDataLoaded: jest.fn().mockReturnValue(true),
12+
useIsORAConfigLoaded: jest.fn().mockReturnValue(true),
13+
usePageDataError: jest.fn().mockReturnValue(null),
14+
useORAConfigDataError: jest.fn().mockReturnValue(null),
15+
}));
16+
17+
describe('<AppContainer />', () => {
18+
const props = {
19+
children: <div>children</div>,
20+
};
21+
22+
it('render default', () => {
23+
const wrapper = shallow(<AppContainer {...props} />);
24+
expect(wrapper.snapshot).toMatchSnapshot();
25+
expect(wrapper.instance.findByType('Spinner')).toHaveLength(0);
26+
});
27+
28+
describe('render error', () => {
29+
it('pageDataError', () => {
30+
usePageDataError.mockReturnValueOnce({ response: { data: { error: { errorCode: 'error' } } } });
31+
const wrapper = shallow(<AppContainer {...props} />);
32+
expect(wrapper.snapshot).toMatchSnapshot();
33+
expect(wrapper.instance.findByType('ErrorPage')).toHaveLength(1);
34+
});
35+
36+
it('oraConfigDataError', () => {
37+
useORAConfigDataError.mockReturnValueOnce({ response: { data: { error: { errorCode: 'error' } } } });
38+
const wrapper = shallow(<AppContainer {...props} />);
39+
expect(wrapper.snapshot).toMatchSnapshot();
40+
expect(wrapper.instance.findByType('ErrorPage')).toHaveLength(1);
41+
});
42+
});
43+
44+
describe('render loading', () => {
45+
it('isPageDataLoaded', () => {
46+
useIsPageDataLoaded.mockReturnValueOnce(false);
47+
const wrapper = shallow(<AppContainer {...props} />);
48+
expect(wrapper.snapshot).toMatchSnapshot();
49+
expect(wrapper.instance.findByType('Spinner')).toHaveLength(1);
50+
});
51+
52+
it('isORAConfigLoaded', () => {
53+
useIsORAConfigLoaded.mockReturnValueOnce(false);
54+
const wrapper = shallow(<AppContainer {...props} />);
55+
expect(wrapper.snapshot).toMatchSnapshot();
56+
expect(wrapper.instance.findByType('Spinner')).toHaveLength(1);
57+
});
58+
});
59+
});
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { shallow } from '@edx/react-unit-test-utils';
2+
3+
import { useExitWithoutSavingAction, useSubmitAssessmentAction } from 'hooks/actions';
4+
import AssessmentActions from './AssessmentActions';
5+
6+
jest.mock('hooks/actions', () => ({
7+
useExitWithoutSavingAction: jest.fn(),
8+
useSubmitAssessmentAction: jest.fn(),
9+
}));
10+
11+
jest.mock('components/ActionButton', () => 'ActionButton');
12+
jest.mock('components/ConfirmDialog', () => 'ConfirmDialog');
13+
14+
describe('<AssessmentActions />', () => {
15+
const mockExitWithoutSavingAction = {
16+
action: {
17+
onClick: jest.fn().mockName('useExitWithoutSavingAction.onClick'),
18+
},
19+
confirmProps: {
20+
onConfirm: jest.fn().mockName('useExitWithoutSavingAction.onConfirm'),
21+
},
22+
};
23+
const mockSubmitAssessmentAction = {
24+
action: {
25+
onClick: jest.fn().mockName('useSubmitAssessmentAction.onClick'),
26+
},
27+
confirmProps: {
28+
onConfirm: jest.fn().mockName('useSubmitAssessmentAction.onConfirm'),
29+
},
30+
};
31+
32+
beforeEach(() => {
33+
useExitWithoutSavingAction.mockReturnValue(mockExitWithoutSavingAction);
34+
useSubmitAssessmentAction.mockReturnValue(mockSubmitAssessmentAction);
35+
});
36+
37+
it('render default', () => {
38+
const wrapper = shallow(<AssessmentActions />);
39+
expect(wrapper.snapshot).toMatchSnapshot();
40+
41+
expect(wrapper.instance.findByType('ActionButton')).toHaveLength(2);
42+
expect(wrapper.instance.findByType('ConfirmDialog')).toHaveLength(2);
43+
});
44+
45+
it('render without submitConfirmDialog', () => {
46+
useSubmitAssessmentAction.mockReturnValueOnce({
47+
action: mockSubmitAssessmentAction.action,
48+
confirmProps: null,
49+
});
50+
const wrapper = shallow(<AssessmentActions />);
51+
expect(wrapper.snapshot).toMatchSnapshot();
52+
53+
expect(wrapper.instance.findByType('ActionButton')).toHaveLength(2);
54+
expect(wrapper.instance.findByType('ConfirmDialog')).toHaveLength(1);
55+
});
56+
57+
it('has correct mock value', () => {
58+
const wrapper = shallow(<AssessmentActions />);
59+
60+
const exitButton = wrapper.instance.findByType('ActionButton')[0];
61+
expect(exitButton.props).toMatchObject(mockExitWithoutSavingAction.action);
62+
63+
const exitConfirmDialog = wrapper.instance.findByType('ConfirmDialog')[0];
64+
expect(exitConfirmDialog.props).toMatchObject(mockExitWithoutSavingAction.confirmProps);
65+
66+
const submitButton = wrapper.instance.findByType('ActionButton')[1];
67+
expect(submitButton.props).toMatchObject(mockSubmitAssessmentAction.action);
68+
69+
const submitConfirmDialog = wrapper.instance.findByType('ConfirmDialog')[1];
70+
expect(submitConfirmDialog.props).toMatchObject(mockSubmitAssessmentAction.confirmProps);
71+
});
72+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`<OverallFeedback /> render default 1`] = `
4+
<Form.Group>
5+
<Form.Label
6+
className="criteria-label"
7+
>
8+
<span
9+
className="criteria-title"
10+
>
11+
Overall comments
12+
</span>
13+
<InfoPopover>
14+
<div
15+
data-testid="prompt-test-id"
16+
>
17+
useOverallFeedbackPrompt
18+
</div>
19+
</InfoPopover>
20+
</Form.Label>
21+
<Form.Control
22+
as="textarea"
23+
className="rubric-feedback feedback-input"
24+
floatingLabel="Add comments (Optional)"
25+
onChange={[MockFunction useOverallFeedbackFormFields.onChange]}
26+
value="useOverallFeedbackFormFields.value"
27+
/>
28+
</Form.Group>
29+
`;
30+
31+
exports[`<OverallFeedback /> render empty on studentTraining 1`] = `null`;

src/components/Assessment/EditableAssessment/OverallFeedback/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const OverallFeedback = () => {
3333
{formatMessage(messages.overallComments)}
3434
</span>
3535
<InfoPopover>
36-
<div>{prompt}</div>
36+
<div data-testid="prompt-test-id">{prompt}</div>
3737
</InfoPopover>
3838
</Form.Label>
3939
<Form.Control
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { shallow } from '@edx/react-unit-test-utils';
2+
3+
import { useOverallFeedbackPrompt, useOverallFeedbackFormFields } from 'hooks/assessment';
4+
import { useViewStep } from 'hooks/routing';
5+
import { stepNames } from 'constants/index';
6+
import OverallFeedback from '.';
7+
8+
jest.mock('hooks/assessment', () => ({
9+
useOverallFeedbackPrompt: jest.fn(),
10+
useOverallFeedbackFormFields: jest.fn(),
11+
}));
12+
13+
jest.mock('components/InfoPopover', () => 'InfoPopover');
14+
15+
jest.mock('hooks/routing', () => ({
16+
useViewStep: jest.fn().mockReturnValue('step'),
17+
}));
18+
19+
describe('<OverallFeedback />', () => {
20+
const mockOnChange = jest
21+
.fn()
22+
.mockName('useOverallFeedbackFormFields.onChange');
23+
const mockFeedbackValue = 'useOverallFeedbackFormFields.value';
24+
const mockPrompt = 'useOverallFeedbackPrompt';
25+
26+
beforeAll(() => {
27+
useOverallFeedbackPrompt.mockReturnValue(mockPrompt);
28+
useOverallFeedbackFormFields.mockReturnValue({
29+
value: mockFeedbackValue,
30+
onChange: mockOnChange,
31+
});
32+
});
33+
34+
it('render default', () => {
35+
const wrapper = shallow(<OverallFeedback />);
36+
expect(wrapper.snapshot).toMatchSnapshot();
37+
});
38+
39+
it('render empty on studentTraining', () => {
40+
useViewStep.mockReturnValueOnce(stepNames.studentTraining);
41+
const wrapper = shallow(<OverallFeedback />);
42+
expect(wrapper.snapshot).toMatchSnapshot();
43+
44+
expect(wrapper.isEmptyRender()).toBe(true);
45+
});
46+
47+
it('has correct mock value', () => {
48+
const wrapper = shallow(<OverallFeedback />);
49+
50+
expect(wrapper.instance.findByTestId('prompt-test-id')[0].children[0].el).toBe(
51+
mockPrompt,
52+
);
53+
54+
const { props } = wrapper.instance.findByType('Form.Control')[0];
55+
expect(props.value).toBe(mockFeedbackValue);
56+
expect(props.onChange).toBe(mockOnChange);
57+
});
58+
});
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`<AssessmentActions /> render default 1`] = `
4+
<div
5+
className="assessment-footer"
6+
>
7+
<ActionButton
8+
onClick={[MockFunction useExitWithoutSavingAction.onClick]}
9+
variant="outline-primary"
10+
/>
11+
<ConfirmDialog
12+
onConfirm={[MockFunction useExitWithoutSavingAction.onConfirm]}
13+
/>
14+
<ActionButton
15+
onClick={[MockFunction useSubmitAssessmentAction.onClick]}
16+
variant="primary"
17+
/>
18+
<ConfirmDialog
19+
onConfirm={[MockFunction useSubmitAssessmentAction.onConfirm]}
20+
/>
21+
</div>
22+
`;
23+
24+
exports[`<AssessmentActions /> render without submitConfirmDialog 1`] = `
25+
<div
26+
className="assessment-footer"
27+
>
28+
<ActionButton
29+
onClick={[MockFunction useExitWithoutSavingAction.onClick]}
30+
variant="outline-primary"
31+
/>
32+
<ConfirmDialog
33+
onConfirm={[MockFunction useExitWithoutSavingAction.onConfirm]}
34+
/>
35+
<ActionButton
36+
onClick={[MockFunction useSubmitAssessmentAction.onClick]}
37+
variant="primary"
38+
/>
39+
</div>
40+
`;

0 commit comments

Comments
 (0)