Skip to content

Commit

Permalink
Lk/unit test (#185)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
leangseu-edx authored Feb 14, 2024
1 parent ecca975 commit f745954
Show file tree
Hide file tree
Showing 169 changed files with 8,232 additions and 92 deletions.
2 changes: 2 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const config = createConfig('jest', {
'src/hooks/testHooks', // don't check coverage for jest mocking tools
// 'src/data/services/lms/fakeData', // don't check coverage for mock data
'src/test', // don't check coverage for test integration test utils
'messages.js', // don't check coverage for i18n messages
'src/data/services/lms/fakeData', // don't check coverage for fake data
],
testTimeout: 120000,
});
Expand Down
28 changes: 28 additions & 0 deletions src/components/ActionButton.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { shallow } from '@edx/react-unit-test-utils';

import ActionButton from './ActionButton';

describe('<ActionButton />', () => {
const props = {
state: 'arbitraryState',
};

it('render empty when no onClick or href', () => {
const wrapper = shallow(<ActionButton {...props} />);
expect(wrapper.isEmptyRender()).toBe(true);
});

it('render StatefulButton when state is provided', () => {
const wrapper = shallow(<ActionButton href="some-href" state="loading" />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.findByType('StatefulButton')).toHaveLength(1);
expect(wrapper.instance.findByType('Button')).toHaveLength(0);
});

it('render Button when state is not provided', () => {
const wrapper = shallow(<ActionButton onClick={jest.fn().mockName('onClick')} />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.findByType('StatefulButton')).toHaveLength(0);
expect(wrapper.instance.findByType('Button')).toHaveLength(1);
});
});
47 changes: 47 additions & 0 deletions src/components/AppContainer/__snapshots__/index.test.jsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<AppContainer /> render default 1`] = `
<div
className="w-100 h-100"
>
<div>
children
</div>
</div>
`;

exports[`<AppContainer /> render error oraConfigDataError 1`] = `
<ErrorPage
message="An unknown error occurred. Please try again."
/>
`;

exports[`<AppContainer /> render error pageDataError 1`] = `
<ErrorPage
message="An unknown error occurred. Please try again."
/>
`;

exports[`<AppContainer /> render loading isORAConfigLoaded 1`] = `
<div
className="w-100 h-100"
>
<Spinner
animation="border"
className="app-loading"
screenReaderText="loading"
/>
</div>
`;

exports[`<AppContainer /> render loading isPageDataLoaded 1`] = `
<div
className="w-100 h-100"
>
<Spinner
animation="border"
className="app-loading"
screenReaderText="loading"
/>
</div>
`;
59 changes: 59 additions & 0 deletions src/components/AppContainer/index.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { shallow } from '@edx/react-unit-test-utils';
import {
useIsPageDataLoaded,
useIsORAConfigLoaded,
usePageDataError,
useORAConfigDataError,
} from 'hooks/app';
import AppContainer from '.';

jest.mock('hooks/app', () => ({
useIsPageDataLoaded: jest.fn().mockReturnValue(true),
useIsORAConfigLoaded: jest.fn().mockReturnValue(true),
usePageDataError: jest.fn().mockReturnValue(null),
useORAConfigDataError: jest.fn().mockReturnValue(null),
}));

describe('<AppContainer />', () => {
const props = {
children: <div>children</div>,
};

it('render default', () => {
const wrapper = shallow(<AppContainer {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.findByType('Spinner')).toHaveLength(0);
});

describe('render error', () => {
it('pageDataError', () => {
usePageDataError.mockReturnValueOnce({ response: { data: { error: { errorCode: 'error' } } } });
const wrapper = shallow(<AppContainer {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.findByType('ErrorPage')).toHaveLength(1);
});

it('oraConfigDataError', () => {
useORAConfigDataError.mockReturnValueOnce({ response: { data: { error: { errorCode: 'error' } } } });
const wrapper = shallow(<AppContainer {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.findByType('ErrorPage')).toHaveLength(1);
});
});

describe('render loading', () => {
it('isPageDataLoaded', () => {
useIsPageDataLoaded.mockReturnValueOnce(false);
const wrapper = shallow(<AppContainer {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.findByType('Spinner')).toHaveLength(1);
});

it('isORAConfigLoaded', () => {
useIsORAConfigLoaded.mockReturnValueOnce(false);
const wrapper = shallow(<AppContainer {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.findByType('Spinner')).toHaveLength(1);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { shallow } from '@edx/react-unit-test-utils';

import { useExitWithoutSavingAction, useSubmitAssessmentAction } from 'hooks/actions';
import AssessmentActions from './AssessmentActions';

jest.mock('hooks/actions', () => ({
useExitWithoutSavingAction: jest.fn(),
useSubmitAssessmentAction: jest.fn(),
}));

jest.mock('components/ActionButton', () => 'ActionButton');
jest.mock('components/ConfirmDialog', () => 'ConfirmDialog');

describe('<AssessmentActions />', () => {
const mockExitWithoutSavingAction = {
action: {
onClick: jest.fn().mockName('useExitWithoutSavingAction.onClick'),
},
confirmProps: {
onConfirm: jest.fn().mockName('useExitWithoutSavingAction.onConfirm'),
},
};
const mockSubmitAssessmentAction = {
action: {
onClick: jest.fn().mockName('useSubmitAssessmentAction.onClick'),
},
confirmProps: {
onConfirm: jest.fn().mockName('useSubmitAssessmentAction.onConfirm'),
},
};

beforeEach(() => {
useExitWithoutSavingAction.mockReturnValue(mockExitWithoutSavingAction);
useSubmitAssessmentAction.mockReturnValue(mockSubmitAssessmentAction);
});

it('render default', () => {
const wrapper = shallow(<AssessmentActions />);
expect(wrapper.snapshot).toMatchSnapshot();

expect(wrapper.instance.findByType('ActionButton')).toHaveLength(2);
expect(wrapper.instance.findByType('ConfirmDialog')).toHaveLength(2);
});

it('render without submitConfirmDialog', () => {
useSubmitAssessmentAction.mockReturnValueOnce({
action: mockSubmitAssessmentAction.action,
confirmProps: null,
});
const wrapper = shallow(<AssessmentActions />);
expect(wrapper.snapshot).toMatchSnapshot();

expect(wrapper.instance.findByType('ActionButton')).toHaveLength(2);
expect(wrapper.instance.findByType('ConfirmDialog')).toHaveLength(1);
});

it('has correct mock value', () => {
const wrapper = shallow(<AssessmentActions />);

const exitButton = wrapper.instance.findByType('ActionButton')[0];
expect(exitButton.props).toMatchObject(mockExitWithoutSavingAction.action);

const exitConfirmDialog = wrapper.instance.findByType('ConfirmDialog')[0];
expect(exitConfirmDialog.props).toMatchObject(mockExitWithoutSavingAction.confirmProps);

const submitButton = wrapper.instance.findByType('ActionButton')[1];
expect(submitButton.props).toMatchObject(mockSubmitAssessmentAction.action);

const submitConfirmDialog = wrapper.instance.findByType('ConfirmDialog')[1];
expect(submitConfirmDialog.props).toMatchObject(mockSubmitAssessmentAction.confirmProps);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<OverallFeedback /> render default 1`] = `
<Form.Group>
<Form.Label
className="criteria-label"
>
<span
className="criteria-title"
>
Overall comments
</span>
<InfoPopover>
<div
data-testid="prompt-test-id"
>
useOverallFeedbackPrompt
</div>
</InfoPopover>
</Form.Label>
<Form.Control
as="textarea"
className="rubric-feedback feedback-input"
floatingLabel="Add comments (Optional)"
onChange={[MockFunction useOverallFeedbackFormFields.onChange]}
value="useOverallFeedbackFormFields.value"
/>
</Form.Group>
`;

exports[`<OverallFeedback /> render empty on studentTraining 1`] = `null`;
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const OverallFeedback = () => {
{formatMessage(messages.overallComments)}
</span>
<InfoPopover>
<div>{prompt}</div>
<div data-testid="prompt-test-id">{prompt}</div>
</InfoPopover>
</Form.Label>
<Form.Control
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { shallow } from '@edx/react-unit-test-utils';

import { useOverallFeedbackPrompt, useOverallFeedbackFormFields } from 'hooks/assessment';
import { useViewStep } from 'hooks/routing';
import { stepNames } from 'constants/index';
import OverallFeedback from '.';

jest.mock('hooks/assessment', () => ({
useOverallFeedbackPrompt: jest.fn(),
useOverallFeedbackFormFields: jest.fn(),
}));

jest.mock('components/InfoPopover', () => 'InfoPopover');

jest.mock('hooks/routing', () => ({
useViewStep: jest.fn().mockReturnValue('step'),
}));

describe('<OverallFeedback />', () => {
const mockOnChange = jest
.fn()
.mockName('useOverallFeedbackFormFields.onChange');
const mockFeedbackValue = 'useOverallFeedbackFormFields.value';
const mockPrompt = 'useOverallFeedbackPrompt';

beforeAll(() => {
useOverallFeedbackPrompt.mockReturnValue(mockPrompt);
useOverallFeedbackFormFields.mockReturnValue({
value: mockFeedbackValue,
onChange: mockOnChange,
});
});

it('render default', () => {
const wrapper = shallow(<OverallFeedback />);
expect(wrapper.snapshot).toMatchSnapshot();
});

it('render empty on studentTraining', () => {
useViewStep.mockReturnValueOnce(stepNames.studentTraining);
const wrapper = shallow(<OverallFeedback />);
expect(wrapper.snapshot).toMatchSnapshot();

expect(wrapper.isEmptyRender()).toBe(true);
});

it('has correct mock value', () => {
const wrapper = shallow(<OverallFeedback />);

expect(wrapper.instance.findByTestId('prompt-test-id')[0].children[0].el).toBe(
mockPrompt,
);

const { props } = wrapper.instance.findByType('Form.Control')[0];
expect(props.value).toBe(mockFeedbackValue);
expect(props.onChange).toBe(mockOnChange);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<AssessmentActions /> render default 1`] = `
<div
className="assessment-footer"
>
<ActionButton
onClick={[MockFunction useExitWithoutSavingAction.onClick]}
variant="outline-primary"
/>
<ConfirmDialog
onConfirm={[MockFunction useExitWithoutSavingAction.onConfirm]}
/>
<ActionButton
onClick={[MockFunction useSubmitAssessmentAction.onClick]}
variant="primary"
/>
<ConfirmDialog
onConfirm={[MockFunction useSubmitAssessmentAction.onConfirm]}
/>
</div>
`;

exports[`<AssessmentActions /> render without submitConfirmDialog 1`] = `
<div
className="assessment-footer"
>
<ActionButton
onClick={[MockFunction useExitWithoutSavingAction.onClick]}
variant="outline-primary"
/>
<ConfirmDialog
onConfirm={[MockFunction useExitWithoutSavingAction.onConfirm]}
/>
<ActionButton
onClick={[MockFunction useSubmitAssessmentAction.onClick]}
variant="primary"
/>
</div>
`;
Loading

0 comments on commit f745954

Please sign in to comment.