Target branch: 1.x (currently v1.8.0, maintenance line).
The equivalent change for main is tracked separately — the two branches have
identical eslint.config.mjs, jest.config.ts and test layouts, so the work is
the same modulo the one difference noted under "Branch-specific notes".
Motivation
Kaoto (KaotoIO/kaoto) migrated packages/ui from Jest to Vitest in commit
769cc74 ("jest to vitest migration", 341 files changed). @kaoto/forms is still
on Jest, which leaves the two repositories on different runners, different setup
files and different mocking APIs — a constant source of friction when moving code
or contributors between them.
Vitest also removes the SWC/Babel double-transform this repo currently carries:
tests would run through the same Vite pipeline already used by yarn start and
yarn build:site.
Current state on 1.x
-
Runner: Jest 29 + @swc/jest, config in jest.config.ts, setup in jest-setup.ts
-
51 test files under src/, 14 snapshot files
-
30 files reference the jest global:
| API |
occurrences |
jest.fn |
148 |
jest.spyOn |
22 |
jest.clearAllMocks |
7 |
jest.restoreAllMocks |
5 |
jest.Mock (type) |
5 |
jest.mock |
4 |
jest.useFakeTimers / useRealTimers |
2 / 2 |
jest.requireMock |
2 |
jest.requireActual, jest.runAllTimers, jest.advanceTimersByTime, jest.MockedFunction |
1 each |
Branch-specific notes
1.x's jest-setup.ts contains a ResizeObserver mock that main does not have.
Port it to vitest-setup.ts as well — Kaoto's vitest-setup.ts implements it as a
class (ResizeObserverMock with observe/unobserve/disconnect as vi.fn()),
which avoids the arrow-function-as-constructor problem.
1.x also uses jest.requireMock in two places; main does not.
Scope
- Config — replace
jest.config.ts with vitest.config.mts modelled on
packages/ui/vitest.config.mts in Kaoto: globals: true, environment: 'jsdom',
include: ['**/?(*.)+(test).[tj]s?(x)'], testTimeout: 10_000, clearMocks: true,
and server.deps.inline for @patternfly/* (replaces the current
transformIgnorePatterns). Vite's own CSS/asset handling replaces the
moduleNameMapper entries pointing at src/__mocks__/styleMock.ts and fileMock.ts.
- Setup — port
jest-setup.ts to vitest-setup.ts: @testing-library/jest-dom/vitest,
vi in place of jest, and vitest-fetch-mock for the window.fetch mock. The SVG
mocks (getScreenCTM, getBBox, getComputedTextLength, createSVGMatrix),
matchMedia, crypto, ResizeObserver and scrollIntoView mocks carry over.
- Test files —
jest.* → vi.*; jest.Mock / jest.MockedFunction → Mock /
MockedFunction imported from vitest; jest.requireActual → await vi.importActual(...);
jest.requireMock → await vi.importMock(...). Note vi.mock() is hoisted with
stricter rules than jest.mock() — factories cannot close over outer variables.
- Published
./testing entrypoint — src/form/testing/FieldTestProvider.tsx and
src/form/testing/FormWrapper.tsx use jest.fn() as default prop values. This is
shipped to consumers via @kaoto/forms/testing, so it must not depend on any runner
global. Replace with plain no-op functions (() => {}) rather than swapping in vi.fn().
- Coverage — swap
coverageProvider: 'babel' for @vitest/coverage-v8, preserving
the current collectCoverageFrom include/exclude list.
- Snapshots — expect churn; Vitest's serializer differs slightly from Jest's
(the Kaoto migration touched every .snap file).
- Cleanup — drop
jest, jest-environment-jsdom, @swc/jest, babel-jest,
@types/jest, @babel/*, babel.config.cjs, and src/__mocks__/ if unused.
- Scripts —
"test": "vitest run --config vitest.config.mts" plus a
"test:watch" counterpart, matching Kaoto.
Acceptance criteria
Reference
- Kaoto migration commit:
KaotoIO/kaoto@769cc74
- Kaoto config:
packages/ui/vitest.config.mts, packages/ui/vitest-setup.ts,
packages/ui/vitest-mocks-setup.ts
Motivation
Kaoto (
KaotoIO/kaoto) migratedpackages/uifrom Jest to Vitest in commit769cc74("jest to vitest migration", 341 files changed).@kaoto/formsis stillon Jest, which leaves the two repositories on different runners, different setup
files and different mocking APIs — a constant source of friction when moving code
or contributors between them.
Vitest also removes the SWC/Babel double-transform this repo currently carries:
tests would run through the same Vite pipeline already used by
yarn startandyarn build:site.Current state on
1.xRunner: Jest 29 +
@swc/jest, config injest.config.ts, setup injest-setup.ts51 test files under
src/, 14 snapshot files30 files reference the
jestglobal:jest.fnjest.spyOnjest.clearAllMocksjest.restoreAllMocksjest.Mock(type)jest.mockjest.useFakeTimers/useRealTimersjest.requireMockjest.requireActual,jest.runAllTimers,jest.advanceTimersByTime,jest.MockedFunctionBranch-specific notes
1.x'sjest-setup.tscontains aResizeObservermock thatmaindoes not have.Port it to
vitest-setup.tsas well — Kaoto'svitest-setup.tsimplements it as aclass (
ResizeObserverMockwithobserve/unobserve/disconnectasvi.fn()),which avoids the arrow-function-as-constructor problem.
1.xalso usesjest.requireMockin two places;maindoes not.Scope
jest.config.tswithvitest.config.mtsmodelled onpackages/ui/vitest.config.mtsin Kaoto:globals: true,environment: 'jsdom',include: ['**/?(*.)+(test).[tj]s?(x)'],testTimeout: 10_000,clearMocks: true,and
server.deps.inlinefor@patternfly/*(replaces the currenttransformIgnorePatterns). Vite's own CSS/asset handling replaces themoduleNameMapperentries pointing atsrc/__mocks__/styleMock.tsandfileMock.ts.jest-setup.tstovitest-setup.ts:@testing-library/jest-dom/vitest,viin place ofjest, andvitest-fetch-mockfor thewindow.fetchmock. The SVGmocks (
getScreenCTM,getBBox,getComputedTextLength,createSVGMatrix),matchMedia,crypto,ResizeObserverandscrollIntoViewmocks carry over.jest.*→vi.*;jest.Mock/jest.MockedFunction→Mock/MockedFunctionimported fromvitest;jest.requireActual→await vi.importActual(...);jest.requireMock→await vi.importMock(...). Notevi.mock()is hoisted withstricter rules than
jest.mock()— factories cannot close over outer variables../testingentrypoint —src/form/testing/FieldTestProvider.tsxandsrc/form/testing/FormWrapper.tsxusejest.fn()as default prop values. This isshipped to consumers via
@kaoto/forms/testing, so it must not depend on any runnerglobal. Replace with plain no-op functions (
() => {}) rather than swapping invi.fn().coverageProvider: 'babel'for@vitest/coverage-v8, preservingthe current
collectCoverageFrominclude/exclude list.(the Kaoto migration touched every
.snapfile).jest,jest-environment-jsdom,@swc/jest,babel-jest,@types/jest,@babel/*,babel.config.cjs, andsrc/__mocks__/if unused."test": "vitest run --config vitest.config.mts"plus a"test:watch"counterpart, matching Kaoto.Acceptance criteria
yarn testruns the full suite on Vitest with no Jest dependency left inpackage.jsonjestglobal referenced anywhere undersrc/, especially insrc/form/testing/@kaoto/forms/testingstill build (KaotoFormPageObjectis imported by Kaoto'spackages/ui)Reference
KaotoIO/kaoto@769cc74packages/ui/vitest.config.mts,packages/ui/vitest-setup.ts,packages/ui/vitest-mocks-setup.ts