Skip to content

Commit 2f58666

Browse files
feat: refactor tests
1 parent 76ca3cf commit 2f58666

File tree

2 files changed

+156
-6
lines changed

2 files changed

+156
-6
lines changed
+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import React from 'react';
2+
import { render } from '@testing-library/react';
3+
import { useSelector } from 'react-redux';
4+
import LiveTab from './LiveTab';
5+
6+
jest.mock('react-redux', () => ({
7+
useSelector: jest.fn(),
8+
}));
9+
10+
describe('LiveTab', () => {
11+
afterEach(() => {
12+
jest.clearAllMocks();
13+
document.body.innerHTML = '';
14+
});
15+
16+
it('renders iframe from liveModel using dangerouslySetInnerHTML', () => {
17+
useSelector.mockImplementation((selector) => selector({
18+
courseHome: { courseId: 'course-v1:test+id+2024' },
19+
models: {
20+
live: {
21+
'course-v1:test+id+2024': {
22+
iframe: '<iframe id="lti-tab-embed" src="about:blank"></iframe>',
23+
},
24+
},
25+
},
26+
}));
27+
28+
render(<LiveTab />);
29+
30+
const iframe = document.getElementById('lti-tab-embed');
31+
expect(iframe).toBeInTheDocument();
32+
expect(iframe.src).toBe('about:blank');
33+
});
34+
35+
it('adds classes to iframe after mount', () => {
36+
document.body.innerHTML = `
37+
<div id="live_tab">
38+
<iframe id="lti-tab-embed" class=""></iframe>
39+
</div>
40+
`;
41+
42+
useSelector.mockImplementation((selector) => selector({
43+
courseHome: { courseId: 'course-v1:test+id+2024' },
44+
models: {
45+
live: {
46+
'course-v1:test+id+2024': {
47+
iframe: '<iframe id="lti-tab-embed"></iframe>',
48+
},
49+
},
50+
},
51+
}));
52+
53+
render(<LiveTab />);
54+
55+
const iframe = document.getElementById('lti-tab-embed');
56+
expect(iframe.className).toContain('vh-100');
57+
expect(iframe.className).toContain('w-100');
58+
expect(iframe.className).toContain('border-0');
59+
});
60+
61+
it('does not throw if iframe is not found in DOM', () => {
62+
useSelector.mockImplementation((selector) => selector({
63+
courseHome: { courseId: 'course-v1:test+id+2024' },
64+
models: {
65+
live: {
66+
'course-v1:test+id+2024': {
67+
iframe: '<div>No iframe here</div>',
68+
},
69+
},
70+
},
71+
}));
72+
73+
expect(() => render(<LiveTab />)).not.toThrow();
74+
const iframe = document.getElementById('lti-tab-embed');
75+
expect(iframe).toBeNull();
76+
});
77+
});

src/course-home/progress-tab/grades/grade-summary/GradeSummaryHeader.test.jsx

+79-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import React from 'react';
2-
import {
3-
render, screen, waitFor,
4-
} from '@testing-library/react';
2+
import { render, screen, waitFor } from '@testing-library/react';
53
import userEvent from '@testing-library/user-event';
64
import { useSelector } from 'react-redux';
75
import { IntlProvider } from 'react-intl';
86

7+
import { fireEvent } from '@testing-library/dom';
98
import GradeSummaryHeader from './GradeSummaryHeader';
109
import { useModel } from '../../../../generic/model-store';
1110
import messages from '../messages';
@@ -18,6 +17,10 @@ jest.mock('../../../../generic/model-store', () => ({
1817
useModel: jest.fn(),
1918
}));
2019

20+
jest.mock('../../../../data/hooks', () => ({
21+
useContextId: () => 'test-course-id',
22+
}));
23+
2124
describe('GradeSummaryHeader', () => {
2225
beforeEach(() => {
2326
useSelector.mockImplementation((selector) => selector({
@@ -30,25 +33,95 @@ describe('GradeSummaryHeader', () => {
3033
render(
3134
<IntlProvider locale="en" messages={messages}>
3235
<GradeSummaryHeader
33-
intl={{ formatMessage: jest.fn((msg) => msg.defaultMessage) }}
3436
allOfSomeAssignmentTypeIsLocked={false}
3537
{...props}
3638
/>
3739
</IntlProvider>,
3840
);
3941
};
4042

41-
it('visible the tooltip when Escape is pressed', async () => {
43+
it('shows tooltip on icon button click', async () => {
44+
renderComponent();
45+
46+
const iconButton = screen.getByRole('button', {
47+
name: messages.gradeSummaryTooltipAlt.defaultMessage,
48+
});
49+
50+
await userEvent.click(iconButton);
51+
52+
await waitFor(() => {
53+
expect(screen.getByText(messages.gradeSummaryTooltipBody.defaultMessage)).toBeInTheDocument();
54+
});
55+
});
56+
57+
it('hides tooltip on mouse out', async () => {
4258
renderComponent();
4359

4460
const iconButton = screen.getByRole('button', {
4561
name: messages.gradeSummaryTooltipAlt.defaultMessage,
4662
});
4763

48-
userEvent.click(iconButton);
64+
fireEvent.mouseOver(iconButton);
4965

5066
await waitFor(() => {
5167
expect(screen.getByText(messages.gradeSummaryTooltipBody.defaultMessage)).toBeVisible();
5268
});
69+
70+
fireEvent.mouseOut(iconButton);
71+
72+
await waitFor(() => {
73+
expect(screen.queryByText(messages.gradeSummaryTooltipBody.defaultMessage)).toBeNull();
74+
});
75+
});
76+
77+
it('hides tooltip on blur', async () => {
78+
renderComponent();
79+
80+
const iconButton = screen.getByRole('button', {
81+
name: messages.gradeSummaryTooltipAlt.defaultMessage,
82+
});
83+
84+
await userEvent.hover(iconButton);
85+
await userEvent.click(iconButton);
86+
87+
await waitFor(() => {
88+
expect(screen.getByText(messages.gradeSummaryTooltipBody.defaultMessage)).toBeInTheDocument();
89+
});
90+
91+
const blurTarget = document.createElement('button');
92+
blurTarget.textContent = 'Outside';
93+
document.body.appendChild(blurTarget);
94+
blurTarget.focus();
95+
96+
await userEvent.unhover(iconButton);
97+
98+
await waitFor(() => {
99+
expect(screen.queryByText(messages.gradeSummaryTooltipBody.defaultMessage)).not.toBeInTheDocument();
100+
});
101+
102+
document.body.removeChild(blurTarget);
103+
});
104+
105+
it('hides tooltip when Escape is pressed (covers handleKeyDown)', async () => {
106+
renderComponent();
107+
108+
const iconButton = screen.getByRole('button', {
109+
name: messages.gradeSummaryTooltipAlt.defaultMessage,
110+
});
111+
112+
await userEvent.hover(iconButton);
113+
await userEvent.click(iconButton);
114+
115+
await waitFor(() => {
116+
expect(screen.getByText(messages.gradeSummaryTooltipBody.defaultMessage)).toBeInTheDocument();
117+
});
118+
119+
fireEvent.keyDown(iconButton, { key: 'Escape', code: 'Escape' });
120+
121+
await userEvent.unhover(iconButton);
122+
123+
await waitFor(() => {
124+
expect(screen.queryByText(messages.gradeSummaryTooltipBody.defaultMessage)).not.toBeInTheDocument();
125+
});
53126
});
54127
});

0 commit comments

Comments
 (0)