Skip to content
This repository was archived by the owner on Jun 26, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
00ba779
chore(deps): replace Jest 29 + ts-jest with Vitest (D-08, D-09)
kneth May 20, 2026
e9b3e0f
chore(config): add vitest.config.ts (D-01 D-02 D-03 D-04 D-14)
kneth May 20, 2026
df84c9d
chore(tsconfig): add vitest/globals types via reference file (D-03)
kneth May 20, 2026
ab0a167
chore(scripts): update yarn test to invoke Vitest (D-02 D-05)
kneth May 20, 2026
c15664c
fix(test): migrate test/setup.ts from Jest to Vitest (D-06 D-07 D-11 …
kneth May 20, 2026
1781884
fix(test): migrate zustand mock to Vitest async factory (D-12)
kneth May 20, 2026
aa409a7
fix(test): migrate react-router-dom mock from jest.fn to vi.fn (D-13)
kneth May 20, 2026
5f0e830
fix(test): migrate testUtils and MSW spy helpers to Vitest
kneth May 20, 2026
b4d2fe9
fix(test): migrate jest → vi across all src/ test files
kneth May 20, 2026
e9cae89
fix(test): migrate remaining tests to Vitest — 468/470 passing
kneth May 20, 2026
a9f328a
fix(test): fix all 5 remaining flaky tests — 470/470 passing
kneth May 20, 2026
d624f9f
fix(test): silence JSDOM "Not implemented" console warnings in test s…
kneth May 20, 2026
43dd8bf
fix(test): eliminate remaining Vite plugin stderr warnings during tes…
kneth May 20, 2026
ddb4756
fix(test): suppress React act() warnings from antd message leave anim…
kneth May 20, 2026
8194f25
fix issue with active tabs
kneth May 22, 2026
7e3512d
update lock file
kneth May 22, 2026
a5ec39d
fix builds
kneth May 22, 2026
4f1cfde
fix(test): use findAllByText to handle antd message portal DOM leak i…
kneth May 22, 2026
556309c
Only use fake timers when Ant needs them (claude-assisted)
joncombe Jun 2, 2026
882ace5
Tidy msw usage, remove duplicate code, remove jest artifacts, misc ti…
joncombe Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,13 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Restore Vitest cache
uses: actions/cache@v4
with:
path: node_modules/.vite
key: vitest-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('vitest.config.ts', 'vite.config.base.ts') }}
restore-keys: |
vitest-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-

- name: Run component tests
run: pnpm test
11 changes: 6 additions & 5 deletions __mocks__/react-router-dom.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { PropsWithChildren } from 'react';
import type { Mock } from 'vitest';

export const navigateMock = jest.fn();
export const navigateMock: Mock = vi.fn();

export const useLocation = jest.fn();
export const useRouteMatch = jest.fn();
export const useNavigate = () => navigateMock;
export const useParams = jest.fn();
export const useLocation: Mock = vi.fn();
export const useRouteMatch: Mock = vi.fn();
export const useNavigate = (): Mock => navigateMock;
export const useParams: Mock = vi.fn();
export const withRouter = (children: React.ReactNode) => children;
export const Route = ({
path = 'index',
Expand Down
57 changes: 26 additions & 31 deletions __mocks__/zustand.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// __mocks__/zustand.ts
import { act } from '@testing-library/react';
import * as zustand from 'zustand';
import type * as Zustand from 'zustand';

const { create: actualCreate, createStore: actualCreateStore } =
jest.requireActual<typeof zustand>('zustand');

// a variable to hold reset functions for all stores declared in the app
// Holds reset functions for all stores created in the app
export const storeResetFns = new Set<() => void>();

const createUncurried = <T>(stateCreator: zustand.StateCreator<T>) => {
const createUncurried = <T>(
stateCreator: Zustand.StateCreator<T>,
actualCreate: typeof Zustand.create,
) => {
const store = actualCreate(stateCreator);
const initialState = store.getInitialState();
storeResetFns.add(() => {
Expand All @@ -17,15 +16,10 @@ const createUncurried = <T>(stateCreator: zustand.StateCreator<T>) => {
return store;
};

// when creating a store, we get its initial state, create a reset function and add it in the set
export const create = (<T>(stateCreator: zustand.StateCreator<T>) => {
// to support curried version of create
return typeof stateCreator === 'function'
? createUncurried(stateCreator)
: createUncurried;
}) as typeof zustand.create;

const createStoreUncurried = <T>(stateCreator: zustand.StateCreator<T>) => {
const createStoreUncurried = <T>(
stateCreator: Zustand.StateCreator<T>,
actualCreateStore: typeof Zustand.createStore,
) => {
const store = actualCreateStore(stateCreator);
const initialState = store.getInitialState();
storeResetFns.add(() => {
Expand All @@ -34,19 +28,20 @@ const createStoreUncurried = <T>(stateCreator: zustand.StateCreator<T>) => {
return store;
};

// when creating a store, we get its initial state, create a reset function and add it in the set
export const createStore = (<T>(stateCreator: zustand.StateCreator<T>) => {
// to support curried version of createStore
return typeof stateCreator === 'function'
? createStoreUncurried(stateCreator)
: createStoreUncurried;
}) as typeof zustand.createStore;
// Async factory — invoked by vi.mock('zustand', async () => { ... }) in test/setup.ts.
// vi.importActual returns a Promise (unlike the old sync API).
export default async () => {
const actual = await vi.importActual<typeof Zustand>('zustand');

// reset all stores after each test run
afterEach(() => {
act(() => {
storeResetFns.forEach(resetFn => {
resetFn();
});
});
});
const create = (<T>(stateCreator: Zustand.StateCreator<T>) =>
typeof stateCreator === 'function'
? createUncurried(stateCreator, actual.create)
: createUncurried) as typeof Zustand.create;

const createStore = (<T>(stateCreator: Zustand.StateCreator<T>) =>
typeof stateCreator === 'function'
? createStoreUncurried(stateCreator, actual.createStore)
: createStoreUncurried) as typeof Zustand.createStore;

return { ...actual, create, createStore };
};
3 changes: 1 addition & 2 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ export default [
globals: {
...globals.browser,
...globals.node,
...globals.jest,
expect: true,
...globals.vitest,
__DEV__: true,
},

Expand Down
53 changes: 0 additions & 53 deletions jest.config.js

This file was deleted.

28 changes: 12 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,24 +82,21 @@
},
"scripts": {
"start": "vite",
"build": "tsc && vite build",
"build-lib": "tsc && vite build --config vite.config.lib.ts && pnpm run build-lib-css-entries",
"build": "tsc -p tsconfig.build.json && vite build",
"build-lib": "tsc -p tsconfig.build.json && vite build --config vite.config.lib.ts && pnpm run build-lib-css-entries",
"build-lib-css-entries": "mkdir -p dist/styles && tailwindcss -i ./src/styles/components.css -o ./dist/styles/components.css --minify && pnpm run sync-theme-css",
"sync-theme-css": "cp ./src/styles/theme.css ./dist/styles/theme.css && printf \"@import './styles/components.css';\\n@import './styles/theme.css';\\n\" > ./dist/style.css",
"build-lib-css-components-watch": "mkdir -p dist/styles && tailwindcss -i ./src/styles/components.css -o ./dist/styles/components.css --watch --minify",
"build-lib-theme-watch": "chokidar \"src/styles/theme.css\" -c \"pnpm run sync-theme-css\"",
"build-lib-watch": "pnpm run sync-theme-css && concurrently -k -n vite,css,theme \"vite build --config vite.config.lib.ts --watch\" \"pnpm run build-lib-css-components-watch\" \"pnpm run build-lib-theme-watch\"",
"check-types": "tsc --noemit",
"prepack": "pnpm run build-lib",
"test": "jest",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"test:ui": "vitest --ui",
"lint": "eslint --cache --ext=.ts --ext=.tsx src/"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
Expand All @@ -120,7 +117,6 @@
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/jest": "^29.5.14",
"@types/lodash": "^4.17.24",
"@types/node": "^24.12.4",
"@types/papaparse": "^5.5.2",
Expand All @@ -129,7 +125,9 @@
"@types/react-syntax-highlighter": "^15.5.13",
"@typescript-eslint/eslint-plugin": "^8.60.0",
"@typescript-eslint/parser": "^8.60.0",
"@vitejs/plugin-react-swc": "^3.11.0",
"@vitejs/plugin-react-swc": "^4.3.1",
"@vitest/coverage-istanbul": "^4.1.7",
"@vitest/ui": "^4.1.7",
"autoprefixer": "^10.5.0",
"chokidar-cli": "^3.0.0",
"concurrently": "^9.2.1",
Expand All @@ -140,9 +138,7 @@
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0",
"globals": "^17.6.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-fixed-jsdom": "^0.0.11",
"jsdom": "^29.1.1",
"msw": "^2.12.7",
"postcss": "^8.5.15",
"prettier": "^3.8.3",
Expand All @@ -152,12 +148,12 @@
"react-dom": "^19.2.6",
"react-router-dom": "^7.15.1",
"tailwindcss": "^3.4.19",
"ts-jest": "^29.4.11",
"typescript": "^5.9.3",
"vite": "^6.4.2",
"vite": "^8.0.13",
"vite-plugin-dts": "^4.5.4",
"vite-plugin-eslint": "^1.8.1",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^4.1.7",
"whatwg-fetch": "^3.6.20"
},
"peerDependencies": {
Expand Down
Loading
Loading