Skip to content

feat(FR-2748): fully migrate test files from jest.* to vi.* and align TS globals#7083

Merged
graphite-app[bot] merged 1 commit intomainfrom
04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals
Apr 30, 2026
Merged

feat(FR-2748): fully migrate test files from jest.* to vi.* and align TS globals#7083
graphite-app[bot] merged 1 commit intomainfrom
04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals

Conversation

@nowgnuesLee
Copy link
Copy Markdown
Contributor

@nowgnuesLee nowgnuesLee commented Apr 27, 2026

Resolves #7081(FR-2748)

Summary

Finishes the Jest → Vitest migration started in FR-2609. The earlier PRs left two compat shims as migration aids (vitest.jest-compat.ts setting globalThis.jest = vi, and jest-globals-shim.ts aliasing @jest/globals). Useful at the time but they obscured what was actually a vitest test, and left a TypeScript gap exposed by the audit (vi not typed; project globals from the deleted react/src/react-app-env.d.ts lost). This PR completes the rename so the shims become unnecessary.

Mechanical jest.* → vi.* migration (15 test files)

  • Single-line: jest.fn, jest.spyOn, jest.mocked, jest.clearAllMocks, jest.resetAllMocks, jest.restoreAllMocks, jest.useFakeTimers, jest.useRealTimers, jest.runAllTimers, jest.advanceTimersByTime, jest.runOnlyPendingTimers.
  • Multi-line patterns (const x = jest\n.fn()) handled via perl -0777.
  • Type positions: jest.MockedFunction<T> / jest.MockedClass<T> / jest.SpyInstance / jest.SpiedFunction rewritten to use vi.mocked(...) (value) or MockInstance / ReturnType<typeof vi.spyOn> (type) imported from 'vitest'.
  • matchMedia.mock.js (used by both react/ and BUI) also moved off jest.fn().

Drop the runtime compat shims

  • Removed __test__/vitest.jest-compat.ts from root, react/, and BUI.
  • Removed packages/backend.ai-ui/__test__/jest-globals-shim.ts.
  • Dropped the @jest/globals alias from BUI's vitest.config.ts.
  • Dropped the second setupFiles entry in all three vitest configs.

Restore the project's ambient TypeScript types

FR-2611 deleted react/src/react-app-env.d.ts (CRA-shaped name) along with CRA itself, but the file held real custom types: DeepPartial, SelectivePartial, OptionalFieldsOnly, NonNullableItem, NonNullableNodeOnEdges, BackendAIOptions, BackendAIClient, globalThis.{isElectron, packageVersion, electronInitialHref, …}, Window.switchLanguage, and the backend.ai-client-esm module shim. Those all return, now living in react/src/ambient.d.ts with the CRA reference removed.

Wire vitest globals into TypeScript

Used /// <reference types="vitest/globals" /> in ambient .d.ts files instead of touching the tsconfig.json "types" arrays:

  • react/src/ambient.d.ts
  • packages/backend.ai-ui/svg.d.ts

Why not "types": ["vitest/globals"] in tsconfig: that would exclude @types/jest from auto-loading, which then breaks @testing-library/jest-dom's default matcher augmentation (expect(el).toBeInTheDocument() etc). The reference directive pulls in vitest globals additively without changing the tsconfig "types" contract.

Keep one globalThis.jest = vi line in setupTests

@testing-library/dom's waitFor checks globalThis.jest to detect Jest-style fake timers; if present, it switches to its timer-aware polling loop. Without that detection, tests that combine vi.useFakeTimers() with await waitFor(…) hang — the polling setTimeout never fires under faked timers.

The line is no longer a compat shim for project test code (all test code uses vi.* now); it's purely a @testing-library/dom integration hook. Comment in both react/src/setupTests.ts and packages/backend.ai-ui/setupTests.ts explains the new purpose.

Verification

  • bash scripts/verify.sh → ALL PASS (lint + format + TypeScript).
  • pnpm --prefix ./react run vitest856 / 856 pass.
  • pnpm --prefix ./packages/backend.ai-ui run vitest319 / 320 (1 pre-existing FR-1731 skip).
  • pnpm exec vitest run (root) → 91 / 91.
  • pnpm run build (root) and make dep (Electron) succeed; built index.html references only manifest.json (no manifest.webmanifest); Electron build emits es6://assets/index-* URLs.

Out of scope

  • Removing the globalThis.jest = vi line entirely (would require reconfiguring @testing-library/dom to use vitest's fake-timer integration manually — larger change).
  • Switching to @testing-library/jest-dom/vitest entry (kept the default entry to avoid the BAIFlex snapshot client conflict observed during exploration).
  • The pre-existing BAIDomainSelect.test.tsx describe.skip (FR-1731 issue, unrelated to this migration).

Stack

Top of the Vite migration stack (now 14 PRs). Builds on PR #7071 (feat(FR-2746) re-enable skipped tests).

Copy link
Copy Markdown
Contributor Author

nowgnuesLee commented Apr 27, 2026


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • flow:merge-queue - adds this PR to the back of the merge queue
  • flow:hotfix - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has required the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 27, 2026

Coverage Report for backend-ai-ui-coverage (./packages/backend.ai-ui)

Status Category Percentage Covered / Total
🔵 Lines 7.91% 322 / 4066
🔵 Statements 7.2% 368 / 5106
🔵 Functions 8.72% 88 / 1009
🔵 Branches 6.39% 321 / 5020
File CoverageNo changed files found.
Generated in workflow #112 for commit 9fa887b by the Vitest Coverage Report Action

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 27, 2026

Coverage Report for root-coverage

Status Category Percentage Covered / Total
🔵 Lines 3.76% 85 / 2258
🔵 Statements 3.97% 92 / 2312
🔵 Functions 3.85% 14 / 363
🔵 Branches 5.11% 68 / 1329
File CoverageNo changed files found.
Generated in workflow #112 for commit 9fa887b by the Vitest Coverage Report Action

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 27, 2026

Coverage Report for react-coverage (./react)

Status Category Percentage Covered / Total
🔵 Lines 7.24% 1646 / 22722
🔵 Statements 6.04% 1777 / 29374
🔵 Functions 5.69% 285 / 5007
🔵 Branches 4.38% 1169 / 26682
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
react/src/ambient.d.ts 100% 100% 100% 100%
Generated in workflow #9 for commit 660e96a by the Vitest Coverage Report Action

@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch 2 times, most recently from 660e96a to 0ef6b62 Compare April 27, 2026 13:57
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2746_re-enable_5_tests_skipped_during_vitest_migration branch from 388ded7 to 06b0e97 Compare April 27, 2026 13:57
@nowgnuesLee nowgnuesLee marked this pull request as ready for review April 28, 2026 04:25
Copilot AI review requested due to automatic review settings April 28, 2026 04:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Completes the Jest → Vitest migration by converting remaining jest.* usages in tests to vi.*, removing temporary compatibility shims, and restoring missing ambient TypeScript globals/types.

Changes:

  • Migrated remaining test helpers/types from jest.* to vi.* across React, root, and backend.ai-ui tests; removed @jest/globals shim usage.
  • Removed Vitest↔Jest runtime/alias shims from Vitest configs and deleted the shim files.
  • Restored/added ambient TypeScript declarations (including Vitest globals references) and updated test setup to expose globalThis.jest for @testing-library/dom fake-timer detection.

Reviewed changes

Copilot reviewed 29 out of 31 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
vitest.config.ts Removes repo-root Jest-compat setup file from Vitest config.
scripts/i18n-merge-driver.test.ts Replaces jest.clearAllMocks() with vi.clearAllMocks().
react/vitest.config.ts Removes React Jest-compat setup file from Vitest config.
react/vite.config.ts Adds dev-server allowedHosts parsing and changes default port.
react/src/setupTests.ts Adds globalThis.jest = vi hook for Testing Library fake-timer detection.
react/src/hooks/useLoginOrchestration.test.ts Replaces Jest mocked types/usage with vi.mocked/vi.fn.
react/src/hooks/tests/useMultiStepNotification.test.tsx Migrates mocked function typing and fn() usage to vi.*.
react/src/helper/customThemeConfig.test.ts Migrates spy typing from Jest to Vitest (MockInstance).
react/src/helper/big-number.test.ts Adjusts custom matcher typing augmentation to align with current global matcher typing strategy.
react/src/ambient.d.ts Reintroduces project ambient types + adds Vitest globals reference for TS.
react/test/vitest.jest-compat.ts Deletes React Jest-compat shim file.
react/test/matchMedia.mock.js Moves matchMedia mock off jest.fn() to vi.fn().
packages/backend.ai-ui/vitest.config.ts Removes @jest/globals alias and Jest-compat setup file from Vitest config.
packages/backend.ai-ui/svg.d.ts Adds Vitest globals reference for TS.
packages/backend.ai-ui/src/hooks/useIntervalValue.test.tsx Migrates timer mocking from Jest fake timers to Vitest fake timers.
packages/backend.ai-ui/src/helper/useDebouncedDeferredValue.test.ts Migrates timer mocking utilities from Jest to Vitest.
packages/backend.ai-ui/src/helper/index.test.ts Removes @jest/globals import (uses globals instead).
packages/backend.ai-ui/src/components/BAIUnmountAfterClose.test.tsx Migrates mock/spies from jest.fn() to vi.fn().
packages/backend.ai-ui/src/components/BAITag.test.tsx Migrates mock/spies from jest.fn() to vi.fn().
packages/backend.ai-ui/src/components/BAIPropertyFilter.test.tsx Migrates callback mocks from jest.fn() to vi.fn().
packages/backend.ai-ui/src/components/BAILink.test.tsx Migrates callback mocks from jest.fn() to vi.fn().
packages/backend.ai-ui/src/components/BAIFlex.test.tsx Removes @jest/globals import (uses globals instead).
packages/backend.ai-ui/src/components/BAICard.test.tsx Migrates mocks from jest.fn() to vi.fn().
packages/backend.ai-ui/src/components/BAIButton.test.tsx Migrates mocks from jest.fn() to vi.fn() (including async action tests).
packages/backend.ai-ui/src/components/BAIBulkEditFormItem.test.tsx Migrates callback mock from jest.fn() to vi.fn().
packages/backend.ai-ui/src/test/matchMedia.mock.js Moves matchMedia mock off jest.fn() to vi.fn().
packages/backend.ai-ui/src/test/matchMedia.mock.cjs Updates comment wording around mock strategy (still references Jest in header).
packages/backend.ai-ui/setupTests.ts Adds globalThis.jest = vi hook for Testing Library fake-timer detection.
packages/backend.ai-ui/test/vitest.jest-compat.ts Deletes BUI Jest-compat shim file.
packages/backend.ai-ui/test/jest-globals-shim.ts Deletes @jest/globals re-export shim file.
test/vitest.jest-compat.ts Deletes repo-root Jest-compat shim file.

Comment thread react/src/setupTests.ts
Comment thread packages/backend.ai-ui/src/__test__/matchMedia.mock.cjs
Comment thread react/vite.config.ts
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch from 0ef6b62 to 8981c28 Compare April 28, 2026 05:02
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2746_re-enable_5_tests_skipped_during_vitest_migration branch from 06b0e97 to a00cbcb Compare April 28, 2026 05:02
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch from 8981c28 to a55f50b Compare April 28, 2026 05:15
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2746_re-enable_5_tests_skipped_during_vitest_migration branch 2 times, most recently from 4c7f5bb to a579c9b Compare April 28, 2026 05:19
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch from a55f50b to 1acb275 Compare April 28, 2026 05:19
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2746_re-enable_5_tests_skipped_during_vitest_migration branch from a579c9b to 866800d Compare April 28, 2026 05:25
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch from 1acb275 to 7437b6e Compare April 28, 2026 05:25
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2746_re-enable_5_tests_skipped_during_vitest_migration branch from 866800d to cfea1f5 Compare April 28, 2026 05:28
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch from 7437b6e to 0353467 Compare April 28, 2026 05:28
@yomybaby yomybaby force-pushed the 04-27-feat_fr-2746_re-enable_5_tests_skipped_during_vitest_migration branch from cfea1f5 to 1034319 Compare April 30, 2026 12:08
@yomybaby yomybaby force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch from 0353467 to 5f30412 Compare April 30, 2026 12:08
@graphite-app
Copy link
Copy Markdown

graphite-app Bot commented Apr 30, 2026

Merge activity

… TS globals (#7083)

Resolves #7081(FR-2748)

## Summary

Finishes the Jest → Vitest migration started in FR-2609. The earlier PRs left two compat shims as migration aids (`vitest.jest-compat.ts` setting `globalThis.jest = vi`, and `jest-globals-shim.ts` aliasing `@jest/globals`). Useful at the time but they obscured what was actually a vitest test, and left a TypeScript gap exposed by the audit (`vi` not typed; project globals from the deleted `react/src/react-app-env.d.ts` lost). This PR completes the rename so the shims become unnecessary.

### Mechanical jest.* → vi.* migration (15 test files)

- Single-line: `jest.fn`, `jest.spyOn`, `jest.mocked`, `jest.clearAllMocks`, `jest.resetAllMocks`, `jest.restoreAllMocks`, `jest.useFakeTimers`, `jest.useRealTimers`, `jest.runAllTimers`, `jest.advanceTimersByTime`, `jest.runOnlyPendingTimers`.
- Multi-line patterns (`const x = jest\n.fn()`) handled via `perl -0777`.
- Type positions: `jest.MockedFunction<T>` / `jest.MockedClass<T>` / `jest.SpyInstance` / `jest.SpiedFunction` rewritten to use `vi.mocked(...)` (value) or `MockInstance` / `ReturnType<typeof vi.spyOn>` (type) imported from `'vitest'`.
- `matchMedia.mock.js` (used by both react/ and BUI) also moved off `jest.fn()`.

### Drop the runtime compat shims

- Removed `__test__/vitest.jest-compat.ts` from root, react/, and BUI.
- Removed `packages/backend.ai-ui/__test__/jest-globals-shim.ts`.
- Dropped the `@jest/globals` alias from BUI's `vitest.config.ts`.
- Dropped the second `setupFiles` entry in all three vitest configs.

### Restore the project's ambient TypeScript types

FR-2611 deleted `react/src/react-app-env.d.ts` (CRA-shaped name) along with CRA itself, but the file held real custom types: `DeepPartial`, `SelectivePartial`, `OptionalFieldsOnly`, `NonNullableItem`, `NonNullableNodeOnEdges`, `BackendAIOptions`, `BackendAIClient`, `globalThis.{isElectron, packageVersion, electronInitialHref, …}`, `Window.switchLanguage`, and the `backend.ai-client-esm` module shim. Those all return, now living in `react/src/ambient.d.ts` with the CRA reference removed.

### Wire vitest globals into TypeScript

Used `/// <reference types="vitest/globals" />` in ambient `.d.ts` files instead of touching the `tsconfig.json` `"types"` arrays:
- `react/src/ambient.d.ts`
- `packages/backend.ai-ui/svg.d.ts`

**Why not `"types": ["vitest/globals"]` in tsconfig**: that would exclude `@types/jest` from auto-loading, which then breaks `@testing-library/jest-dom`'s default matcher augmentation (`expect(el).toBeInTheDocument()` etc). The reference directive pulls in vitest globals additively without changing the tsconfig `"types"` contract.

### Keep one `globalThis.jest = vi` line in setupTests

`@testing-library/dom`'s `waitFor` checks `globalThis.jest` to detect Jest-style fake timers; if present, it switches to its timer-aware polling loop. Without that detection, tests that combine `vi.useFakeTimers()` with `await waitFor(…)` hang — the polling `setTimeout` never fires under faked timers.

The line is **no longer a compat shim for project test code** (all test code uses `vi.*` now); it's purely a `@testing-library/dom` integration hook. Comment in both `react/src/setupTests.ts` and `packages/backend.ai-ui/setupTests.ts` explains the new purpose.

## Verification

- `bash scripts/verify.sh` → ALL PASS (lint + format + TypeScript).
- `pnpm --prefix ./react run vitest` → **856 / 856** pass.
- `pnpm --prefix ./packages/backend.ai-ui run vitest` → **319 / 320** (1 pre-existing FR-1731 skip).
- `pnpm exec vitest run` (root) → **91 / 91**.
- `pnpm run build` (root) and `make dep` (Electron) succeed; built `index.html` references only `manifest.json` (no `manifest.webmanifest`); Electron build emits `es6://assets/index-*` URLs.

## Out of scope

- Removing the `globalThis.jest = vi` line entirely (would require reconfiguring `@testing-library/dom` to use vitest's fake-timer integration manually — larger change).
- Switching to `@testing-library/jest-dom/vitest` entry (kept the default entry to avoid the BAIFlex snapshot client conflict observed during exploration).
- The pre-existing `BAIDomainSelect.test.tsx` `describe.skip` (FR-1731 issue, unrelated to this migration).

## Stack

Top of the Vite migration stack (now 14 PRs). Builds on PR #7071 (`feat(FR-2746)` re-enable skipped tests).
@graphite-app graphite-app Bot force-pushed the 04-27-feat_fr-2746_re-enable_5_tests_skipped_during_vitest_migration branch from 1034319 to cc748d3 Compare April 30, 2026 12:19
@graphite-app graphite-app Bot force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch from 5f30412 to 9fa887b Compare April 30, 2026 12:20
graphite-app Bot pushed a commit that referenced this pull request Apr 30, 2026
Resolves #6809(FR-2606)

## Summary

Dev-server regression noticed after the Vite cutover: pages that mount a Monaco editor break at mount time because the `/resources/monaco/vs/*` URL prefix no longer resolves on the dev server.

`@monaco-editor/react` loads the Monaco AMD runtime at runtime via:

```ts
loader.config({ paths: { vs: '/resources/monaco/vs' } });
```

(see `react/src/helper/monacoEditor.ts`). The self-hosted prefix exists so the editor works in offline / air-gapped deployments where jsDelivr is unreachable.

Pre-Vite, the dev-server side of this contract was the `static` directory list in `react/craco.config.cjs` (lines 44–60 of the now-deleted file): it served `react/node_modules/monaco-editor/min/vs/*` at the `/resources/monaco/vs` URL prefix. Production builds copy the same tree to `build/web/resources/monaco/vs/` via the root `copymonaco` script (`package.json:32`).

After #6876 (FR-2611) dropped `craco.config.cjs`, the production `copymonaco` step was preserved but the dev-server-side mapping was not ported to `vite.config.ts`. As a result, in `pnpm run dev`, requests to `/resources/monaco/vs/loader.js` 404 and any page that mounts a Monaco editor breaks.

**Fix**: add `monacoStaticPlugin()` to `react/vite.config.ts` mirroring the deleted craco `static` entry.

- Serves `/resources/monaco/vs/*` from `react/node_modules/monaco-editor/min/vs/*`.
- `apply: 'serve'` — dev-only; production is unchanged because `copymonaco` already populates `build/web/resources/monaco/vs/`.
- Path-traversal guard via `filePath.startsWith(monacoRoot)` after `join` normalization.
- Registered in the `plugins` array before `projectRootStaticPlugin()` so the narrower Monaco prefix is matched first.

## Verification

- [x] `bash scripts/verify.sh` — Relay / Lint / Format / TypeScript all PASS
- [ ] `pnpm run dev`, navigate to a Monaco-mounting page (manifest editor on Environments page) — editor renders without console errors, no `cdn.jsdelivr.net` fetches
- [ ] DevTools → Network: `/resources/monaco/vs/loader.js`, `/resources/monaco/vs/editor/editor.main.js` return 200 from the dev server

## Stack

Top of the Vite migration follow-up stack. Sits on top of #7083 (FR-2748).
Base automatically changed from 04-27-feat_fr-2746_re-enable_5_tests_skipped_during_vitest_migration to main April 30, 2026 12:36
@graphite-app graphite-app Bot merged commit 9fa887b into main Apr 30, 2026
7 of 8 checks passed
@graphite-app graphite-app Bot deleted the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch April 30, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100~500 LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fully migrate test files from jest.* to vi.* and align TypeScript globals

2 participants