Skip to content

Commit bd269c2

Browse files
authored
test: deprecate react-unit-test-utils 3/14 (#339)
1 parent 7684efb commit bd269c2

File tree

9 files changed

+395
-416
lines changed

9 files changed

+395
-416
lines changed
Lines changed: 88 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import React from 'react';
2-
// import {cleanup, fireEvent, render} from '@testing-library/react';
3-
import { shallow } from '@edx/react-unit-test-utils';
1+
import { render } from '@testing-library/react';
2+
import '@testing-library/jest-dom';
43

54
import {
65
useGlobalState,
@@ -11,103 +10,153 @@ import { stepNames, stepStates } from 'constants/index';
1110

1211
import HotjarSurvey from './index';
1312

13+
jest.unmock('@openedx/paragon');
14+
jest.unmock('react');
15+
jest.unmock('@edx/frontend-platform/i18n');
16+
1417
jest.mock('hooks/app', () => ({
1518
useGlobalState: jest.fn(),
1619
useStepInfo: jest.fn(),
1720
useAssessmentStepConfig: jest.fn(),
1821
}));
1922

2023
describe('<HotjarSurvey />', () => {
21-
// * These tests opts to use shallow instead of render because I want to trigger the useEffect
22-
// * manually.
2324
beforeEach(() => {
2425
window.hj = jest.fn();
2526
});
27+
2628
afterEach(() => {
2729
delete window.hj;
2830
jest.clearAllMocks();
2931
});
3032

31-
it('show survey when self is require and step is not while peer is not require', () => {
32-
useAssessmentStepConfig.mockReturnValueOnce({
33+
it('renders survey container element', () => {
34+
useAssessmentStepConfig.mockReturnValue({
35+
settings: {
36+
self: { required: false },
37+
peer: { required: false },
38+
},
39+
});
40+
useGlobalState.mockReturnValue({
41+
activeStepState: stepStates.done,
42+
});
43+
useStepInfo.mockReturnValue({});
44+
45+
const { container } = render(<HotjarSurvey />);
46+
const surveyElement = container.querySelector('#openassessment_hotjar');
47+
expect(surveyElement).toBeInTheDocument();
48+
});
49+
50+
it('shows survey when self is required and step is done while peer is not required', () => {
51+
useAssessmentStepConfig.mockReturnValue({
3352
settings: {
3453
self: { required: true },
3554
peer: { required: false },
3655
},
3756
});
38-
useGlobalState.mockReturnValueOnce({
57+
useGlobalState.mockReturnValue({
3958
activeStepState: stepStates.done,
4059
});
60+
useStepInfo.mockReturnValue({});
4161

42-
expect(React.useEffect).not.toHaveBeenCalled();
43-
shallow(<HotjarSurvey />);
62+
render(<HotjarSurvey />);
4463

45-
const [[cb, [isShowSurvey]]] = React.useEffect.mock.calls;
46-
expect(isShowSurvey).toBe(true);
47-
cb();
4864
expect(window.hj).toHaveBeenCalledWith(
4965
'event',
5066
'lms_openassessment_survey_mfe',
5167
);
5268
});
5369

54-
it('show survey when peer is require iif completed the peer grading', () => {
55-
useAssessmentStepConfig.mockReturnValueOnce({
70+
it('does not show survey when self is required but step is not done', () => {
71+
useAssessmentStepConfig.mockReturnValue({
72+
settings: {
73+
self: { required: true },
74+
peer: { required: false },
75+
},
76+
});
77+
useGlobalState.mockReturnValue({
78+
activeStepState: stepStates.inProgress,
79+
});
80+
useStepInfo.mockReturnValue({});
81+
82+
render(<HotjarSurvey />);
83+
84+
expect(window.hj).not.toHaveBeenCalled();
85+
});
86+
87+
it('shows survey when peer is required and completed the required peer grading', () => {
88+
useAssessmentStepConfig.mockReturnValue({
5689
settings: {
5790
self: { required: false },
5891
peer: { required: true, minNumberToGrade: 2 },
5992
},
6093
});
61-
useStepInfo.mockReturnValueOnce({
94+
useStepInfo.mockReturnValue({
6295
[stepNames.peer]: { numberOfAssessmentsCompleted: 2 },
6396
});
64-
useGlobalState.mockReturnValueOnce({
65-
activeStepState: 'abitrairy',
97+
useGlobalState.mockReturnValue({
98+
activeStepState: 'arbitrary',
6699
});
67100

68-
expect(React.useEffect).not.toHaveBeenCalled();
69-
shallow(<HotjarSurvey />);
101+
render(<HotjarSurvey />);
70102

71-
const [[, [isShowSurvey]]] = React.useEffect.mock.calls;
72-
expect(isShowSurvey).toBe(true);
103+
expect(window.hj).toHaveBeenCalledWith(
104+
'event',
105+
'lms_openassessment_survey_mfe',
106+
);
73107
});
74108

75-
it('should not show survey when peer is require but not completed the peer grading', () => {
76-
useAssessmentStepConfig.mockReturnValueOnce({
109+
it('does not show survey when peer is required but not completed the peer grading', () => {
110+
useAssessmentStepConfig.mockReturnValue({
77111
settings: {
78112
self: { required: false },
79113
peer: { required: true, minNumberToGrade: 2 },
80114
},
81115
});
82-
useStepInfo.mockReturnValueOnce({
116+
useStepInfo.mockReturnValue({
83117
[stepNames.peer]: { numberOfAssessmentsCompleted: 1 },
84118
});
85-
useGlobalState.mockReturnValueOnce({
86-
activeStepState: 'abitrairy',
119+
useGlobalState.mockReturnValue({
120+
activeStepState: 'arbitrary',
87121
});
88122

89-
expect(React.useEffect).not.toHaveBeenCalled();
90-
shallow(<HotjarSurvey />);
123+
render(<HotjarSurvey />);
91124

92-
const [[, [isShowSurvey]]] = React.useEffect.mock.calls;
93-
expect(isShowSurvey).toBe(false);
125+
expect(window.hj).not.toHaveBeenCalled();
94126
});
95127

96-
it('should not show survey neither step is required', () => {
97-
useAssessmentStepConfig.mockReturnValueOnce({
128+
it('does not show survey when neither step is required', () => {
129+
useAssessmentStepConfig.mockReturnValue({
98130
settings: {
99131
[stepNames.self]: { required: false },
100132
[stepNames.peer]: { required: false },
101133
},
102134
});
103-
useGlobalState.mockReturnValueOnce({
104-
activeStepState: 'abitrairy',
135+
useGlobalState.mockReturnValue({
136+
activeStepState: 'arbitrary',
105137
});
138+
useStepInfo.mockReturnValue({});
139+
140+
render(<HotjarSurvey />);
141+
142+
expect(window.hj).not.toHaveBeenCalled();
143+
});
106144

107-
expect(React.useEffect).not.toHaveBeenCalled();
145+
it('does not show survey when window.hj is not available', () => {
146+
delete window.hj;
147+
148+
useAssessmentStepConfig.mockReturnValue({
149+
settings: {
150+
self: { required: true },
151+
peer: { required: false },
152+
},
153+
});
154+
useGlobalState.mockReturnValue({
155+
activeStepState: stepStates.done,
156+
});
157+
useStepInfo.mockReturnValue({});
108158

109-
shallow(<HotjarSurvey />);
110-
const [[, [isShowSurvey]]] = React.useEffect.mock.calls;
111-
expect(isShowSurvey).toBe(false);
159+
// Should not throw error when window.hj is undefined
160+
expect(() => render(<HotjarSurvey />)).not.toThrow();
112161
});
113162
});

src/components/InfoPopover/__snapshots__/index.test.jsx.snap

Lines changed: 0 additions & 34 deletions
This file was deleted.
Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,89 @@
1-
import { shallow } from '@edx/react-unit-test-utils';
1+
import { render, screen } from '@testing-library/react';
2+
import '@testing-library/jest-dom';
3+
import userEvent from '@testing-library/user-event';
4+
import { IntlProvider } from '@edx/frontend-platform/i18n';
25

36
import InfoPopover from './index';
47

8+
jest.unmock('@openedx/paragon');
9+
jest.unmock('react');
10+
jest.unmock('@edx/frontend-platform/i18n');
11+
512
describe('<InfoPopover />', () => {
613
const props = {
714
onClick: jest.fn().mockName('onClick'),
815
};
916

10-
const renderComponent = () => shallow(
11-
<InfoPopover {...props}>
12-
<div>Children</div>
13-
</InfoPopover>,
14-
);
17+
const renderWithIntl = (component) => render(<IntlProvider locale="en">{component}</IntlProvider>);
18+
19+
beforeEach(() => {
20+
jest.clearAllMocks();
21+
});
22+
23+
it('renders info icon button', () => {
24+
renderWithIntl(
25+
<InfoPopover {...props}>
26+
<div>Help content</div>
27+
</InfoPopover>,
28+
);
29+
30+
const iconButton = screen.getByRole('button');
31+
expect(iconButton).toBeInTheDocument();
32+
expect(iconButton).toHaveClass('esg-help-icon');
33+
expect(iconButton).toHaveClass('mb-2');
34+
expect(iconButton).toHaveClass('ml-2');
35+
});
36+
37+
it('calls onClick when icon button is clicked', async () => {
38+
const user = userEvent.setup();
39+
renderWithIntl(
40+
<InfoPopover {...props}>
41+
<div>Help content</div>
42+
</InfoPopover>,
43+
);
44+
45+
const iconButton = screen.getByRole('button');
46+
await user.click(iconButton);
47+
48+
expect(props.onClick).toHaveBeenCalledTimes(1);
49+
});
50+
51+
it('renders children content in popover when focused', async () => {
52+
const user = userEvent.setup();
53+
renderWithIntl(
54+
<InfoPopover {...props}>
55+
<div>Detailed help information</div>
56+
</InfoPopover>,
57+
);
58+
59+
const iconButton = screen.getByRole('button');
60+
61+
// Focus the button to trigger the popover
62+
await user.click(iconButton);
63+
64+
// Check if popover content appears
65+
expect(screen.getByText('Detailed help information')).toBeInTheDocument();
66+
});
67+
68+
it('renders with proper accessibility attributes', () => {
69+
renderWithIntl(
70+
<InfoPopover {...props}>
71+
<div>Help content</div>
72+
</InfoPopover>,
73+
);
74+
75+
const iconButton = screen.getByRole('button');
76+
expect(iconButton).toHaveAttribute('type', 'button');
77+
});
78+
79+
it('renders without onClick when not provided', () => {
80+
renderWithIntl(
81+
<InfoPopover>
82+
<div>Help content</div>
83+
</InfoPopover>,
84+
);
1585

16-
it('renders correctly', () => {
17-
const wrapper = renderComponent();
18-
expect(wrapper.snapshot).toMatchSnapshot();
86+
const iconButton = screen.getByRole('button');
87+
expect(iconButton).toBeInTheDocument();
1988
});
2089
});

src/components/Instructions/__snapshots__/index.test.jsx.snap

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)