You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(FR-2609): Vitest migration for react/ (100% pass, 856/856 tests) (#6874)
Resolves#6812(FR-2609)
## Summary
Migrates `react/`'s test suite from Jest to Vitest. **856/856 tests passing** under Vitest.
(Commit title still reads `96.9% pass rate, 822/848 tests` — that was the baseline before the last-mile fixes landed in-tree via `gt modify`. Current state is 100%; see test-plan counts below.)
### New files
- `react/vitest.config.ts` — reuses `@vitejs/plugin-react` + `babel-plugin-react-compiler` + `babel-plugin-relay` so tests and the running app exercise identical transformed code.
- `react/__test__/vitest.jest-compat.ts` — exposes `vi` as `jest` globally, so existing `jest.fn()` / `jest.spyOn()` calls in test files continue to work without a sweeping rename.
### Vitest 4 pitfalls fixed inline
- **`process.env.NODE_ENV` is non-configurable** in Node 20+. Replaced `Object.defineProperty(process.env, 'NODE_ENV', ...)` with `vi.stubEnv('NODE_ENV', ...)` + `vi.unstubAllEnvs()` in `customThemeConfig.test.ts`.
- **Default-export mock shape**: `vi.mock(path, () => Component)` must return `{ default: Component }` for files imported via `import X from ...`. Fixed in `MyResourceWithinResourceGroup.test.tsx`.
- **Arrow-function `mockImplementation` called with `new`**: `new TabCount()` throws because arrow functions aren't constructors. Swapped all `MockedTabCount.mockImplementation(() => ({...}))` to `function(this: any) {...}` in `useLoginOrchestration.test.ts`.
- **Factory-created vi.fn() mock history** isn't cleared by `vi.restoreAllMocks()` (that only touches `spyOn` spies). Added `vi.clearAllMocks()` in `afterEach` to prevent call-count leakage across tests.
## Test plan
- [x] `pnpm --prefix ./react run vitest` → 856/856 pass
- [x] Same React Compiler / Relay transforms as prod build (`'use memo'` optimisations active in tests)
- [x] `scripts/verify.sh` passes for Lint + Format + Relay checks
## Stack
Builds on FR-2608. The broader Jest → Vitest cutover continues in the next PR (BUI + root `/src`).
`pnpm --prefix ./react run vitest` now passes **856/856 tests** across the migrated suite. The Vitest-semantic differences from Jest noted below have been resolved as part of this PR, so this note no longer implies outstanding failures.
85
+
86
+
### What was added
87
+
88
+
-`react/vitest.config.ts` — dedicated Vitest config, separate from `vite.config.ts`. Shares the transform pipeline (`@vitejs/plugin-react` + babel-plugin-relay with per-directory `artifactDirectory` + babel-plugin-react-compiler) so tests exercise the same transforms as dev/prod.
89
+
-`react/__test__/vitest.jest-compat.ts` — a setup file that aliases `globalThis.jest = vi` so legacy `jest.fn()` / `jest.clearAllMocks()` call sites continue to work. Migration aid only; new tests should use `vi.*` directly.
90
+
-`vitest` / `vitest:watch` scripts in `react/package.json`.
91
+
92
+
### Bulk migrations applied
93
+
94
+
Mechanical `jest.` → `vi.` rewrites across 39 test files (perl one-liner in the commit message):
Without this, Vitest's `vi.mock` hoisting does NOT apply to `jest.mock(...)` calls (Vitest only recognises literal `vi.mock` for hoisting). The rewrites restore mock correctness across 14+ files.
101
+
102
+
### Module resolution
103
+
104
+
-`src/` baseUrl via regex alias `{ find: /^src\//, replacement: reactSrc + '/' }`.
105
+
-`backend.ai-ui/*`, `backend.ai-client-esm` mapped to same mocks Jest used.
-`.css` / `.css?raw` → `__test__/rawCss.mock.js` (regex anchored with `^.+` so the entire specifier is replaced; array-form aliases replace the matched portion).
108
+
109
+
### Vitest-semantic differences from Jest (resolved in this PR)
110
+
111
+
-`react/src/helper/customThemeConfig.test.ts` — was using `Object.defineProperty(process.env, 'NODE_ENV', ...)` to toggle dev/prod; Vitest's `process.env.NODE_ENV` has an immutable descriptor. Migrated to `vi.stubEnv('NODE_ENV', ...)` + `vi.unstubAllEnvs()` in `afterEach`, plus `vi.restoreAllMocks()` between nested describes to avoid event-dispatcher accumulation.
112
+
-`react/src/components/MyResourceWithinResourceGroup.test.tsx` and `react/src/hooks/useResourceLimitAndRemaining.test.ts` — bare `vi.mock(path)` without a factory does not produce a `default` export for ESM under Vitest. Fixed by passing an explicit `() => ({ default: vi.fn() })` factory.
113
+
114
+
### Performance
115
+
116
+
- Vitest run: ~20s wall clock for 848 tests (transform 71s, tests 6s — tests themselves are very fast; the time is transform + import cost, paid only once per file).
117
+
- Jest equivalent on the same tree has not been measured in this session; prior expectation was 60-120s. Confidence level: "materially faster" but exact multiplier needs a controlled benchmark.
118
+
119
+
### Still open
120
+
121
+
- BUI (`packages/backend.ai-ui`) Jest → Vitest migration
122
+
- Root `/src` Jest → Vitest migration
123
+
-`transformIgnorePatterns` regex in existing `react/jest.config.cjs` can be deleted once the Jest pipeline is fully retired.
124
+
83
125
## Production `vite build` + Workbox PWA — landed (FR-2608)
84
126
85
127
`pnpm --prefix ./react run vite:build` now produces a working web build with a generated service worker. Output goes to `react/build/`, same directory the craco pipeline uses.
0 commit comments