Skip to content

Commit ce976eb

Browse files
committed
[dashboard] added tests for Dashboard and ScanList
1 parent 291d249 commit ce976eb

File tree

6 files changed

+178
-13
lines changed

6 files changed

+178
-13
lines changed

dashboard/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@
3333
"last 1 firefox version",
3434
"last 1 safari version"
3535
]
36-
}
36+
},
37+
"devDependencies": {}
3738
}

dashboard/src/App.test.js

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,33 @@
11
import React from 'react';
2-
import { render } from '@testing-library/react';
2+
import { render, unmountComponentAtNode } from 'react-dom';
33
import App from './App';
4+
import axiosMock from 'axios';
5+
import { act } from 'react-dom/test-utils';
6+
jest.mock('axios');
47

5-
test('renders learn react link', () => {
6-
const { getByText } = render(<App />);
7-
const linkElement = getByText(/learn react/i);
8-
expect(linkElement).toBeInTheDocument();
8+
describe('App', () => {
9+
let container = null;
10+
11+
beforeEach(() => {
12+
container = document.createElement('div');
13+
document.body.appendChild(container);
14+
});
15+
16+
afterEach(() => {
17+
unmountComponentAtNode(container);
18+
container.remove();
19+
container = null;
20+
});
21+
22+
it('renders without error', async () => {
23+
axiosMock.get.mockResolvedValueOnce({
24+
status: 200,
25+
data: [],
26+
});
27+
28+
await act(async () => {
29+
render(<App />, container);
30+
});
31+
expect(container.childNodes.length).toBe(2);
32+
});
933
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react';
2+
import { render, unmountComponentAtNode } from 'react-dom';
3+
import Dashboard from './Dashboard';
4+
import axiosMock from 'axios';
5+
import { act } from 'react-dom/test-utils';
6+
7+
jest.mock('axios');
8+
9+
describe('Dashboard', () => {
10+
let container = null;
11+
beforeEach(() => {
12+
container = document.createElement('div');
13+
document.body.appendChild(container);
14+
});
15+
16+
afterEach(() => {
17+
// en sortie de test
18+
unmountComponentAtNode(container);
19+
container.remove();
20+
container = null;
21+
});
22+
23+
it('fetches the scans once at render', async () => {
24+
axiosMock.get.mockResolvedValueOnce({
25+
status: 200,
26+
data: [],
27+
});
28+
29+
await act(async () => {
30+
render(<Dashboard />, container);
31+
});
32+
33+
expect(axiosMock.get).toHaveBeenCalledTimes(1);
34+
});
35+
});

dashboard/src/components/ScanList.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,19 @@ const ScanList = ({ list }) => {
2727
</Card.Header>
2828
</Card>
2929
{list.map((scan, index) => (
30-
<Card key={index}>
30+
<Card key={index} className="scan_item">
3131
<Accordion.Toggle style={{ cursor: 'pointer' }} as={Card.Header} eventKey={index}>
3232
<Row>
33-
<Col sm={3}>{scan.repositoryName}</Col>
34-
<Col sm={3}>{scan.status}</Col>
35-
<Col sm={5}>{displayCorrectTimestamp(scan)}</Col>
36-
<Col sm={1}>
33+
<Col className="repoName" sm={3}>
34+
{scan.repositoryName}
35+
</Col>
36+
<Col className="status" sm={3}>
37+
{scan.status}
38+
</Col>
39+
<Col className="timestamp" sm={5}>
40+
{displayCorrectTimestamp(scan)}
41+
</Col>
42+
<Col className="findings" sm={1}>
3743
{scan.findings.length > 0 ? (
3844
<Badge pill variant="warning">
3945
{scan.findings.length}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import React from 'react';
2+
import { render, unmountComponentAtNode } from 'react-dom';
3+
import ScanList from './ScanList';
4+
import { act } from 'react-dom/test-utils';
5+
6+
describe('ScanList', () => {
7+
let container = null;
8+
beforeEach(() => {
9+
container = document.createElement('div');
10+
document.body.appendChild(container);
11+
});
12+
13+
afterEach(() => {
14+
unmountComponentAtNode(container);
15+
container.remove();
16+
container = null;
17+
});
18+
19+
it('displays all the element of the list', () => {
20+
const mockScans = [
21+
{ repositoryName: 'One', status: 'pending', queuedAt: '01/01/2020', findings: [] },
22+
{ repositoryName: 'Two', status: 'pending', queuedAt: '01/01/2020', findings: [] },
23+
{ repositoryName: 'Three', status: 'pending', queuedAt: '01/01/2020', findings: [] },
24+
];
25+
26+
act(() => {
27+
render(<ScanList list={mockScans} />, container);
28+
});
29+
30+
expect(container.querySelectorAll('.scan_item').length).toEqual(3);
31+
});
32+
33+
it('displays the correct timestamp depending on status', () => {
34+
const queuedAt = '01/01/2020';
35+
const scanningAt = '02/01/2020';
36+
const finishedAt = '03/01/2020';
37+
const mockScans = [
38+
{ repositoryName: 'One', status: 'Pending', queuedAt, scanningAt, finishedAt, findings: [] },
39+
{ repositoryName: 'Two', status: 'In Progress', queuedAt, scanningAt, finishedAt, findings: [] },
40+
{ repositoryName: 'Three', status: 'Failure', queuedAt, scanningAt, finishedAt, findings: [] },
41+
{ repositoryName: 'Four', status: 'Success', queuedAt, scanningAt, finishedAt, findings: [] },
42+
];
43+
44+
act(() => {
45+
render(<ScanList list={mockScans} />, container);
46+
});
47+
48+
const [pending, scanning, failure, success] = container.querySelectorAll('.scan_item');
49+
expect(pending.querySelector('.timestamp').textContent).toEqual(queuedAt);
50+
expect(scanning.querySelector('.timestamp').textContent).toEqual(scanningAt);
51+
expect(failure.querySelector('.timestamp').textContent).toEqual(finishedAt);
52+
expect(success.querySelector('.timestamp').textContent).toEqual(finishedAt);
53+
});
54+
55+
it('displays the Badges with a number of findings', () => {
56+
const mockFinding = {
57+
ruleId: 1,
58+
metadata: { description: 'description', severity: 'HIGH' },
59+
location: { path: '/somwhere', positions: { begin: { line: 666 } } },
60+
};
61+
62+
const finishedAt = '03/01/2020';
63+
const mockScans = [
64+
{ repositoryName: 'one', status: 'Success', finishedAt, findings: [mockFinding] },
65+
{ repositoryName: 'two', status: 'Success', finishedAt, findings: [mockFinding, mockFinding] },
66+
{
67+
repositoryName: 'three',
68+
status: 'Success',
69+
finishedAt,
70+
findings: [mockFinding, mockFinding, mockFinding],
71+
},
72+
];
73+
74+
act(() => {
75+
render(<ScanList list={mockScans} />, container);
76+
});
77+
78+
const [one, two, three] = container.querySelectorAll('.scan_item');
79+
expect(one.querySelector('.findings').childNodes[0].textContent).toEqual('1');
80+
expect(two.querySelector('.findings').childNodes[0].textContent).toEqual('2');
81+
expect(three.querySelector('.findings').childNodes[0].textContent).toEqual('3');
82+
});
83+
84+
it('does not display the Badge when there is no findings', () => {
85+
const mockScans = [{ repositoryName: 'One', status: 'pending', queuedAt: '01/01/2020', findings: [] }];
86+
87+
act(() => {
88+
render(<ScanList list={mockScans} />, container);
89+
});
90+
91+
const scan = container.querySelector('.scan_item');
92+
expect(scan.querySelector('.findings').childNodes.length).toEqual(0);
93+
expect(scan.querySelector('.findings').textContent).toEqual('');
94+
});
95+
});

dashboard/src/components/useScan.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@ const useScan = () => {
1818

1919
useEffect(() => {
2020
(async () => {
21-
const response = await axios.get(url);
22-
setScans(response.data);
21+
try {
22+
const response = await axios.get(url);
23+
setScans(response.data);
24+
} catch (e) {
25+
throw new Error('could not fetch scan, there is likely a problem with the server');
26+
}
2327
})();
2428
}, []);
2529

0 commit comments

Comments
 (0)