Skip to content

Commit 423611b

Browse files
authored
chore: Add initial jest tests + code coverage (#13)
- Adds initial infra for running front-end tests (`jest`, `ts-jest`, `jest.config.js`, etc) - Adds codecov integration front-end code
1 parent afc2fa3 commit 423611b

File tree

20 files changed

+2512
-170
lines changed

20 files changed

+2512
-170
lines changed

.github/workflows/coder.yaml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ jobs:
136136
with:
137137
token: ${{ secrets.CODECOV_TOKEN }}
138138
files: ./gotests.coverage
139-
flags: ${{ matrix.os }}
139+
flags: unittest-go-${{ matrix.os }}
140140
fail_ci_if_error: true
141141

142142
test-js:
@@ -161,3 +161,12 @@ jobs:
161161
- run: yarn install
162162

163163
- run: yarn build
164+
165+
- run: yarn test:coverage
166+
167+
- uses: codecov/codecov-action@v2
168+
with:
169+
token: ${{ secrets.CODECOV_TOKEN }}
170+
files: ./coverage/lcov.info
171+
flags: unittest-js
172+
fail_ci_if_error: true

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ yarn-error.log
1616

1717
# Front-end ignore
1818
.next/
19-
site/.next/
19+
site/.next/
20+
coverage/

.prettierignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ yarn-error.log
1212

1313
# Front-end ignore
1414
.next/
15-
site/.next/
15+
site/.next/
16+
coverage/

jest.config.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module.exports = {
2+
projects: [
3+
{
4+
coverageReporters: ["text", "lcov"],
5+
displayName: "test",
6+
preset: "ts-jest",
7+
roots: ["<rootDir>/site"],
8+
transform: {
9+
"^.+\\.tsx?$": "ts-jest",
10+
},
11+
testEnvironment: "jsdom",
12+
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
13+
testPathIgnorePatterns: ["/node_modules/", "/__tests__/fakes"],
14+
moduleDirectories: ["node_modules", "<rootDir>"],
15+
},
16+
],
17+
collectCoverageFrom: [
18+
"<rootDir>/site/**/*.js",
19+
"<rootDir>/site/**/*.ts",
20+
"<rootDir>/site/**/*.tsx",
21+
"!<rootDir>/site/**/*.stories.tsx",
22+
"!<rootDir>/site/.next/**/*.*",
23+
"!<rootDir>/site/next-env.d.ts",
24+
"!<rootDir>/site/next.config.js",
25+
],
26+
}

package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,26 @@
88
"build:dev": "next build site",
99
"dev": "next dev site",
1010
"format:check": "prettier --check '**/*.{css,html,js,json,jsx,md,ts,tsx,yaml,yml}'",
11-
"format:write": "prettier --write '**/*.{css,html,js,json,jsx,md,ts,tsx,yaml,yml}'"
11+
"format:write": "prettier --write '**/*.{css,html,js,json,jsx,md,ts,tsx,yaml,yml}'",
12+
"test": "jest --selectProjects test",
13+
"test:coverage": "jest --selectProjects test --collectCoverage"
1214
},
1315
"devDependencies": {
1416
"@material-ui/core": "4.9.4",
1517
"@material-ui/icons": "4.5.1",
1618
"@material-ui/lab": "4.0.0-alpha.42",
19+
"@testing-library/react": "12.1.2",
20+
"@types/jest": "27.4.0",
1721
"@types/node": "14.18.4",
1822
"@types/react": "17.0.38",
1923
"@types/react-dom": "17.0.11",
2024
"@types/superagent": "4.1.14",
25+
"jest": "27.4.7",
2126
"next": "12.0.7",
2227
"prettier": "2.5.1",
2328
"react": "17.0.2",
2429
"react-dom": "17.0.2",
30+
"ts-jest": "27.1.2",
2531
"ts-loader": "9.2.6",
2632
"typescript": "4.5.4"
2733
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { fireEvent, render, screen } from "@testing-library/react"
2+
import React from "react"
3+
import { SplitButton, SplitButtonProps } from "./SplitButton"
4+
5+
namespace Helpers {
6+
export type SplitButtonOptions = "a" | "b" | "c"
7+
8+
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
9+
export const callback = (selectedOption: SplitButtonOptions): void => {}
10+
11+
export const options: SplitButtonProps<SplitButtonOptions>["options"] = [
12+
{
13+
label: "test a",
14+
value: "a",
15+
},
16+
{
17+
label: "test b",
18+
value: "b",
19+
},
20+
{
21+
label: "test c",
22+
value: "c",
23+
},
24+
]
25+
}
26+
27+
describe("SplitButton", () => {
28+
describe("onClick", () => {
29+
it("is called when primary action is clicked", () => {
30+
// Given
31+
const mockedAndSpyedCallback = jest.fn(Helpers.callback)
32+
33+
// When
34+
render(<SplitButton onClick={mockedAndSpyedCallback} options={Helpers.options} />)
35+
fireEvent.click(screen.getByText("test a"))
36+
37+
// Then
38+
expect(mockedAndSpyedCallback.mock.calls.length).toBe(1)
39+
expect(mockedAndSpyedCallback.mock.calls[0][0]).toBe("a")
40+
})
41+
42+
it("is called when clicking option in pop-up", () => {
43+
// Given
44+
const mockedAndSpyedCallback = jest.fn(Helpers.callback)
45+
46+
// When
47+
render(<SplitButton onClick={mockedAndSpyedCallback} options={Helpers.options} />)
48+
const buttons = screen.getAllByRole("button")
49+
const dropdownButton = buttons[1]
50+
fireEvent.click(dropdownButton)
51+
fireEvent.click(screen.getByText("test c"))
52+
53+
// Then
54+
expect(mockedAndSpyedCallback.mock.calls.length).toBe(1)
55+
expect(mockedAndSpyedCallback.mock.calls[0][0]).toBe("c")
56+
})
57+
})
58+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { screen } from "@testing-library/react"
2+
import { render } from "../../test_helpers"
3+
import React from "react"
4+
import { EmptyState, EmptyStateProps } from "./index"
5+
6+
describe("EmptyState", () => {
7+
it("renders (smoke test)", async () => {
8+
// When
9+
render(<EmptyState message="Hello, world" />)
10+
11+
// Then
12+
await screen.findByText("Hello, world")
13+
})
14+
})

site/components/Icons/index.test.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from "react"
2+
import { SvgIcon } from "@material-ui/core"
3+
import { render } from "./../../test_helpers"
4+
5+
import * as Icons from "./index"
6+
7+
const getAllIcons = (): [string, typeof SvgIcon][] => {
8+
let k: keyof typeof Icons
9+
let ret: [string, typeof SvgIcon][] = []
10+
for (k in Icons) {
11+
ret.push([k, Icons[k]])
12+
}
13+
return ret
14+
}
15+
16+
describe("Icons", () => {
17+
const allIcons = getAllIcons()
18+
19+
it.each(allIcons)(`rendering icon %p`, (_name, Icon) => {
20+
render(<Icon />)
21+
})
22+
})

site/components/Navbar/NavMenuEntry.tsx

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

site/components/Navbar/index.test.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from "react"
2+
import { screen } from "@testing-library/react"
3+
4+
import { render } from "../../test_helpers"
5+
import { Navbar } from "./index"
6+
7+
describe("Navbar", () => {
8+
it("renders content", async () => {
9+
// When
10+
render(<Navbar />)
11+
12+
// Then
13+
await screen.findAllByText("Coder", { exact: false })
14+
})
15+
})

0 commit comments

Comments
 (0)