Skip to content

Commit 0454456

Browse files
authored
Move JS tests from Jest to Vitest (#5362)
* chore: migrated all tests to Vitest * fix: mock imports properly * fix: improve vitest performance * fix: enable coverage report * fix: use experimental AST remapping for coverage stats * fix: tests linting * chore: remove jest and jest linting rules * fix: errors in some tests * fix: use jsdom for vitest environment * fix: linting * fix: increase test timeout (just to be safe)
1 parent e21fb94 commit 0454456

87 files changed

Lines changed: 978 additions & 1540 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

eslint.config.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import jest from "eslint-plugin-jest";
1+
import vitest from '@vitest/eslint-plugin'
22
import react from "eslint-plugin-react";
33
import prettier from "eslint-plugin-prettier";
44
import jsxA11Y from "eslint-plugin-jsx-a11y";
@@ -38,7 +38,7 @@ export default [
3838
),
3939
{
4040
plugins: {
41-
jest,
41+
vitest,
4242
react,
4343
prettier,
4444
"jsx-a11y": jsxA11Y,
@@ -48,7 +48,7 @@ export default [
4848
Object.entries({
4949
...globals.browser,
5050
...globals.node,
51-
...jest.environments.globals.globals,
51+
...vitest.environments.env.globals
5252
}).map(([key, value]) => [key.trim(), value]),
5353
),
5454
parser: babelParser,

jest.config.js

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

jest.setup.js

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

package.json

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"lint-python": "flake8 webapp tests && black --diff --check --line-length 79 webapp tests",
77
"test": "yarn run test-python && yarn run test-js-all && yarn run lint-scss",
88
"test-e2e": "cypress run --quiet",
9-
"test-js": "jest",
9+
"test-js": "vitest run",
1010
"test-js-all": "yarn run lint-js && yarn run test-js",
1111
"test-python": "yarn run lint-python && FLASK_DEBUG=0 python3 -m unittest discover tests",
1212
"test-python-job": "SECRET_KEY=insecure_secret_key coverage run --source=. -m unittest discover tests",
@@ -39,13 +39,13 @@
3939
"@testing-library/jest-dom": "6.6.3",
4040
"@testing-library/react": "16.2.0",
4141
"@testing-library/user-event": "14.5.2",
42-
"@types/jest": "29.5.14",
4342
"@types/randomstring": "1.3.0",
4443
"@types/react": "19.1.8",
4544
"@types/react-dom": "19.1.6",
4645
"@types/react-redux": "7.1.34",
4746
"@types/topojson-client": "3.1.5",
4847
"@vitejs/plugin-react-swc": "4.0.0",
48+
"@vitest/eslint-plugin": "^1.3.9",
4949
"autoprefixer": "10.4.20",
5050
"d3": "7.9.0",
5151
"d3-array": "3.2.4",
@@ -95,35 +95,29 @@
9595
"@percy/cli": "1.30.6",
9696
"@types/cypress": "1.1.6",
9797
"@types/d3": "7.4.3",
98-
"@types/markdown-it": "14.1.2",
9998
"@types/uuid": "10.0.0",
10099
"@typescript-eslint/eslint-plugin": "^8.19.1",
101100
"@typescript-eslint/parser": "^8.19.1",
102-
"babel-jest": "29.7.0",
101+
"@vitest/coverage-v8": "3.2.4",
102+
"@vitest/ui": "3.2.4",
103103
"concurrently": "9.1.2",
104104
"cypress": "14.5.4",
105105
"eslint": "9.17.0",
106106
"eslint-config-prettier": "9.1.0",
107-
"eslint-plugin-jest": "28.10.0",
108107
"eslint-plugin-jsx-a11y": "^6.9.0",
109108
"eslint-plugin-prettier": "5.2.1",
110109
"eslint-plugin-react": "7.37.3",
111-
"identity-obj-proxy": "3.0.0",
112-
"jest": "29.7.0",
113-
"jest-environment-jsdom": "29.7.0",
114-
"jest-fixed-jsdom": "0.0.9",
115110
"msw": "2.7.0",
116-
"sass-loader": "16.0.4",
117111
"stylelint": "16.12.0",
118112
"stylelint-config-standard-scss": "14.0.0",
119113
"stylelint-order": "6.0.4",
120-
"ts-jest": "29.2.5"
114+
"vitest": "^3.2.4"
121115
},
122116
"resolutions": {
123117
"lodash": "4.17.21",
124118
"eslint/**/minimatch": "3.1.2",
125119
"eslint-*/minimatch": "3.1.2",
126120
"@typescript-eslint/**/minimatch": "9.0.5",
127-
"ts-jest/ejs/jake/filelist/minimatch": "5.1.6"
121+
"@vitest/coverage-v8/**/minimatch": "9.0.5"
128122
}
129123
}

static/js/libs/__tests__/debounce.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import debounce from "../debounce";
2+
import type { Mock } from "vitest";
23

3-
jest.useFakeTimers();
4-
const fn: jest.Mock = jest.fn();
4+
vi.useFakeTimers();
5+
const fn: Mock = vi.fn();
56

67
describe("debounce", () => {
78
test("function is only called once", () => {
@@ -11,7 +12,7 @@ describe("debounce", () => {
1112
debouncedFn();
1213
}
1314

14-
jest.runAllTimers();
15+
vi.runAllTimers();
1516

1617
expect(fn).toHaveBeenCalledTimes(1);
1718
});
@@ -23,7 +24,7 @@ describe("debounce", () => {
2324
debouncedFn();
2425
}
2526

26-
jest.runAllTimers();
27+
vi.runAllTimers();
2728

2829
expect(fn).toHaveBeenCalledTimes(2);
2930
});

static/js/libs/__tests__/events.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ button.classList.add("test-button");
88

99
describe("Events", () => {
1010
test("adds an event listener", () => {
11-
const testEvent = jest.fn();
11+
const testEvent = vi.fn();
1212
events.addEvent("click", button, testEvent);
1313
button.click();
1414
expect(testEvent).toHaveBeenCalled();
1515
});
1616

1717
test("adds events by type", () => {
18-
const testEvent = jest.fn();
18+
const testEvent = vi.fn();
1919
events.addEvents({
2020
click: {
2121
"[class=test-button]": (event: { preventDefault: () => void }) => {

static/js/libs/__tests__/iframeSize.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import "@testing-library/jest-dom";
22
import iframeSize from "../iframeSize";
3+
import type { Mock } from "vitest";
34

45
describe("iframeSize", () => {
56
test("sizes iframe to container width and maintain ratio", () => {
@@ -14,7 +15,7 @@ describe("iframeSize", () => {
1415

1516
document.body.appendChild(frameWrapper);
1617

17-
frameWrapper.getBoundingClientRect = jest.fn(
18+
frameWrapper.getBoundingClientRect = vi.fn(
1819
(): DOMRect => ({
1920
x: 0,
2021
y: 0,
@@ -26,7 +27,7 @@ describe("iframeSize", () => {
2627
height: 500,
2728
toJSON: () => ({}),
2829
}),
29-
) as jest.Mock;
30+
) as Mock;
3031

3132
iframeSize(".frame-wrapper");
3233

static/js/libs/__tests__/mouse.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import mouse from "../mouse";
33

44
describe("mouse", () => {
55
test("calls the updatePosition method on mousemove", () => {
6-
const spy = jest.spyOn(mouse, "updatePosition");
7-
8-
window.dispatchEvent(new Event("mousemove"));
6+
window.dispatchEvent(
7+
new MouseEvent("mousemove", { clientX: 1, clientY: 1 }),
8+
);
99

1010
// Take out of the event loop so runs after event is triggered
1111
setTimeout(() => {
12-
expect(spy).toHaveBeenCalled();
12+
expect(mouse.position).toMatchObject({ x: 1, y: 1 });
1313
}, 0);
1414
});
1515
});

static/js/libs/__tests__/throttle.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import throttle from "../throttle";
22

33
describe("throttle", () => {
44
test("calls function", () => {
5-
const fn = jest.fn();
5+
const fn = vi.fn();
66
const throttledFunction: () => void = throttle(fn, -1);
77
throttledFunction();
88
expect(fn).toHaveBeenCalled();
99
});
1010

1111
test("doesn't call function", () => {
12-
const fn = jest.fn();
12+
const fn = vi.fn();
1313
const throttledFunction: () => void = throttle(fn, 1);
1414
throttledFunction();
1515
expect(fn).not.toHaveBeenCalled();

static/js/public/first-snap-flow.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ describe("initChooseName", () => {
5959

6060
it("should set cookie on submit", () => {
6161
delete window.location;
62-
window.location = { reload: jest.fn() };
62+
window.location = { reload: vi.fn() };
6363

6464
nameInput.click();
6565
nameInput.value = "valid-name";

0 commit comments

Comments
 (0)