Skip to content

Commit d88d14c

Browse files
test: enhance test suite for coverage
1 parent f363481 commit d88d14c

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { render, screen, fireEvent } from '@testing-library/react';
2+
import { IntlProvider } from '@edx/frontend-platform/i18n';
3+
import PreviousRunLinkTable from './PreviousRunLinkTable';
4+
5+
const intlWrapper = (ui: React.ReactElement) => render(
6+
<IntlProvider locale="en" messages={{}}>
7+
{ui}
8+
</IntlProvider>,
9+
);
10+
11+
describe('PreviousRunLinkTable', () => {
12+
const mockUnitWithLinks = {
13+
id: 'unit-2',
14+
displayName: 'Unit with previous run links',
15+
blocks: [
16+
{
17+
id: 'block-1',
18+
displayName: 'Block with links',
19+
url: 'http://example.com',
20+
brokenLinks: [],
21+
lockedLinks: [],
22+
externalForbiddenLinks: [],
23+
previousRunLinks: ['https://prev-link.com/1'],
24+
},
25+
],
26+
};
27+
28+
const mockUnitNoLinks = {
29+
id: 'unit-1',
30+
displayName: 'Unit without links',
31+
blocks: [
32+
{
33+
id: 'block-1',
34+
displayName: 'Block without links',
35+
url: 'http://example.com',
36+
brokenLinks: [],
37+
lockedLinks: [],
38+
externalForbiddenLinks: [],
39+
previousRunLinks: [],
40+
},
41+
],
42+
};
43+
44+
it('renders table with previous run links', () => {
45+
intlWrapper(<PreviousRunLinkTable unit={mockUnitWithLinks} />);
46+
expect(screen.getByText('Unit with previous run links')).toBeInTheDocument();
47+
48+
mockUnitWithLinks.blocks[0].previousRunLinks.forEach(link => {
49+
expect(screen.getByText(link)).toBeInTheDocument();
50+
});
51+
});
52+
53+
it('renders nothing if no previous run links', () => {
54+
const { container } = intlWrapper(<PreviousRunLinkTable unit={mockUnitNoLinks} />);
55+
expect(container.firstChild).toBeNull();
56+
});
57+
58+
it('opens previous run link in new tab on click', () => {
59+
const originalOpen = window.open;
60+
window.open = jest.fn();
61+
intlWrapper(<PreviousRunLinkTable unit={mockUnitWithLinks} />);
62+
fireEvent.click(screen.getByText('https://prev-link.com/1'));
63+
expect(window.open).toHaveBeenCalledWith('https://prev-link.com/1', '_blank');
64+
window.open = originalOpen;
65+
});
66+
67+
it('handles missing displayName gracefully', () => {
68+
const unit = {
69+
id: 'unit-3',
70+
displayName: 'Unit with test links',
71+
blocks: [
72+
{
73+
id: 'block-3',
74+
displayName: '',
75+
url: 'http://example.com/block3',
76+
brokenLinks: [],
77+
lockedLinks: [],
78+
externalForbiddenLinks: [],
79+
previousRunLinks: ['https://prev-link.com/1'],
80+
},
81+
],
82+
};
83+
intlWrapper(<PreviousRunLinkTable unit={unit} />);
84+
expect(screen.getByText('Go to block')).toBeInTheDocument();
85+
expect(screen.getByText('https://prev-link.com/1')).toBeInTheDocument();
86+
});
87+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { render, screen, fireEvent } from '@testing-library/react';
2+
import React from 'react';
3+
import PreviousRunSectionCollapsible from './PreviousRunSectionCollapsible';
4+
5+
describe('PreviousRunSectionCollapsible', () => {
6+
const defaultProps = {
7+
index: 1,
8+
handleToggle: jest.fn(),
9+
isOpen: false,
10+
hasPrevAndIsOpen: false,
11+
hasNextAndIsOpen: false,
12+
title: 'Section Title',
13+
children: <div>Section Content</div>,
14+
previousRunLinksCount: 3,
15+
className: 'test-class',
16+
};
17+
18+
it('renders with closed state and correct title/count', () => {
19+
render(<PreviousRunSectionCollapsible {...defaultProps} />);
20+
expect(screen.getByText('Section Title')).toBeInTheDocument();
21+
expect(screen.getByText('3')).toBeInTheDocument();
22+
});
23+
24+
it('renders with open state and shows children', () => {
25+
render(<PreviousRunSectionCollapsible {...defaultProps} isOpen />);
26+
expect(screen.getByText('Section Content')).toBeInTheDocument();
27+
});
28+
29+
it('shows dash when previousRunLinksCount is 0', () => {
30+
render(<PreviousRunSectionCollapsible {...defaultProps} previousRunLinksCount={0} />);
31+
expect(screen.getByText('-')).toBeInTheDocument();
32+
});
33+
34+
it('calls handleToggle with index when header is clicked', () => {
35+
const handleToggle = jest.fn();
36+
render(<PreviousRunSectionCollapsible {...defaultProps} handleToggle={handleToggle} />);
37+
// Click the header icon (which is inside the header div)
38+
const header = screen.getByText('Section Title').closest('.section-collapsible-header-item');
39+
if (header) {
40+
fireEvent.click(header);
41+
} else {
42+
// fallback: click the whole header area
43+
fireEvent.click(screen.getByText('Section Title'));
44+
}
45+
expect(handleToggle).toHaveBeenCalledWith(1);
46+
});
47+
48+
it('applies custom className', () => {
49+
render(<PreviousRunSectionCollapsible {...defaultProps} className="my-custom-class" />);
50+
expect(screen.getByText('Section Title').parentElement?.parentElement).toHaveClass('my-custom-class');
51+
});
52+
});

0 commit comments

Comments
 (0)