Skip to content

chore(test): migrate component-library from jest to vitest#72475

Open
stephenliang wants to merge 3 commits intostephen/dep-dedupe-catalogfrom
stephen/cl-vitest
Open

chore(test): migrate component-library from jest to vitest#72475
stephenliang wants to merge 3 commits intostephen/dep-dedupe-catalogfrom
stephen/cl-vitest

Conversation

@stephenliang
Copy link
Copy Markdown
Member

@stephenliang stephenliang commented May 2, 2026

Why

The direction for frontend/: all unit and integ tests runs on Vitest; only the legacy apps/ webpack bundle stays on Jest. Aligning on Vitest also unifies the workspace's browser integration testing — apps/design-system-storybook already runs storybook tests through @vitest/browser-playwright, so a single Vitest core means unit, browser, and storybook test paths share one runner instead of fragmenting across Jest + Vitest.

packages/component-library was the lone holdout still on Jest + @swc/jest + jest-environment-jsdom + identity-obj-proxy — duplicating the transform toolchain alongside the Vite/SWC pipeline already used for the build, dragging extra deps into node_modules, and contradicting the workspace direction. After this change, Jest only remains in the repo-root apps/ legacy bundle, and every packages/* runs on a single test runner.

graph LR
  subgraph Before
    A1[apps/<br/>legacy webpack] -->|Jest| J1[Jest<br/>+ @swc/jest<br/>+ jsdom@20<br/>+ identity-obj-proxy]
    P1[packages/core] -->|Vitest| V1[Vitest]
    M1[packages/labs/music] -->|Vitest| V1
    C1[packages/component-library<br/>★ outlier] -->|Jest| J1
    B1[apps/design-system-storybook<br/>browser integ tests] -->|Vitest browser-playwright| V1
  end
Loading
graph LR
  subgraph After
    A2[apps/<br/>legacy webpack] -->|Jest| J2[Jest]
    P2[packages/core] -->|Vitest| V2[Vitest 4.1.5]
    M2[packages/labs/music] -->|Vitest| V2
    C2[packages/component-library] -->|Vitest| V2
    B2[apps/design-system-storybook<br/>browser integ tests] -->|Vitest browser-playwright| V2
  end
Loading

node_modules impact

Measured du -sb frontend/node_modules immediately after a fresh yarn install on each branch:

Metric Before (stephen/dep-dedupe-catalog) After (this branch) Delta
size 1,155.84 MB 1,119.85 MB −35.99 MB
file count 78,835 74,169 −4,666 files
yarn.lock lines 20,355 19,746 −609 lines

Removed deps: @swc/jest, @swc/core, @types/jest, @types/identity-obj-proxy, eslint-plugin-jest, identity-obj-proxy, jest, jest-environment-jsdom.

Features

1. component-library: Jest → Vitest

  • jest.config.mjs deleted; vitest.config.ts added (extends shared preset, declares setupFiles, declares @/* alias, sets transitional css.modules.classNameStrategy: 'non-scoped' for two DSCO test files asserting on un-hashed CSS-module class names).
  • 41 test files rewritten: jest.{fn,mock,spyOn}vi.*; jest.Mock type → Mock from vitest; WithPopover.test.tsx partial mock uses async importOriginal callback.
  • setupTests.tsimport '@testing-library/jest-dom/vitest'; (extends vitest's expect with jest-dom matchers).
  • package.json script: "test": "jest""test": "vitest --run" (matching packages/core and packages/labs/music).
  • eslint.config.mjs drops the deleted cdoJestConfig, picks up the new cdoVitestConfig.

2. Shared lint-config presets (new infrastructure)

  • New lint-config/vitest/react.mjs — shared Vitest base for React + jsdom packages. Adopted by component-library, music-lab, and the lab generator template (turbo/generators/templates/lab/vitest.config.ts.hbs now re-exports the preset). Mirrors the existing eslint/{node,react}.mjs and typescript/tsconfig.*.json patterns.
  • New lint-config/eslint/vitest.mjs — overlay applying @vitest/eslint-plugin's recommended to **/*.test.{ts,tsx}. Symmetric replacement for the deleted eslint/jest.mjs. Adopted by component-library and music-lab.
  • Deleted lint-config/eslint/jest.mjs. Vestigial cdoJestConfig import dropped from packages/fonts/eslint.config.mjs (fonts has no tests).
  • lint-config/README.md and docs/conventions/packages.md updated to document the new presets.

3. Yarn catalog: vitest sibling version-lock

vitest, @vitest/browser-playwright, and @vitest/coverage-v8 are version-locked siblings from the vitest monorepo — version drift between them produces install-time peer warnings. Promoted all three to the catalog at ^4.1.5 with a heading comment explaining why they bump together. apps/design-system-storybook was previously off-version on 4.0.15; now realigned via catalog:.

4. Test hygiene caught by the new vitest eslint overlay

vitest/no-commented-out-tests flagged 5 commented-out it(...) blocks (pre-existing scaffolding from prior contributors). Converted to it.todo(...) so they surface as todos in the test report. Bodies that referenced unimplemented props (steps on Slider) were dropped along with their bodies — git history preserves them.

5. Code-review fix folded in

FontAwesomeV6IconTest.tsx was being silently skipped post-migration: Jest's default discovery picked up *Test.tsx (capital T, no dot), but Vitest's default include is **/*.{test,spec}.?(c|m)[jt]s?(x). Renamed to FontAwesomeV6Icon.test.tsx to match the convention every other test file follows. Also dropped a per-file jest-dom import the bulk sed missed (didn't match the *.test.tsx glob). Recovered 2 tests (236 → 238).

Links

  • Jira:

Testing story

Verified end-to-end:

  • yarn turbo run test --filter=@code-dot-org/component-library42 test files, 238 tests pass + 5 todos (was 236 in 41 files; the FontAwesome rename recovered 2 tests).
  • yarn turbo run test --filter=@code-dot-org/music-lab — passes via the new shared preset.
  • yarn turbo run typecheck --filter=@code-dot-org/component-library — passes (confirms @types/jest removal didn't strand any reference).
  • yarn turbo run lint --filter=@code-dot-org/component-library — passes (one unrelated pre-existing import-x/no-named-as-default-member warning on the storybook import).
  • yarn release:dryrun from frontend/ — full guard (build + lint + typecheck + test across 31 turbo tasks) green.
  • Codegen smoke test: yarn turbo gen package codegen-test-pkg and yarn turbo gen lab codegen-test both run the post-generation release:dryrun (36 and 41 turbo tasks respectively) successfully — the new shared preset path resolves correctly from a freshly-scaffolded lab on first install. Generated artifacts removed and studio integration reverted.

Deployment notes

Standard merge-and-deploy. No runtime changes in the published @code-dot-org/component-library package — the Vitest swap only affects how tests run, not what ships. The package's dist/ output is byte-identical with respect to test-runner choice.

Privacy and security

None. Test infrastructure only. No new PII, auth changes, or API surface changes.

stephenliang and others added 2 commits May 2, 2026 12:49
Last packages/* still on jest. Aligns with frontend/AGENTS.md ("packages/*
use Vitest. apps/ uses Jest"), drops a parallel transform toolchain
(@swc/jest, @types/jest, jest-environment-jsdom, identity-obj-proxy), and
shrinks node_modules + lockfile (yarn.lock -1238 lines).

component-library:
- replace jest.config.mjs with vitest.config.ts (extends shared preset,
  adds setupFiles + alias + transitional css.modules.classNameStrategy
  'non-scoped' for 2 DSCO test files asserting on raw module classes)
- rewrite 41 test files: jest.{fn,mock,spyOn} -> vi.*; jest.Mock type ->
  Mock from 'vitest'; partial mock in WithPopover uses async importOriginal
- setupTests.ts -> '@testing-library/jest-dom/vitest'
- fix SimpleList.test.tsx: jsdom 26 normalizes css colors to rgb(...)
  (jsdom 20 inside jest-environment-jsdom did not)
- convert pre-existing commented-out tests to it.todo() (rule:
  vitest/no-commented-out-tests caught 5 sites)

shared:
- new lint-config/vitest/react.mjs preset (react()+jsdom+globals);
  adopted by music-lab and component-library; lab generator template
  re-exports it
- new lint-config/eslint/vitest.mjs overlay (@vitest/eslint-plugin
  recommended on *.test.{ts,tsx}); adopted by component-library and
  music-lab (symmetric to the deleted jest overlay)
- delete lint-config/eslint/jest.mjs; drop vestigial cdoJestConfig from
  fonts/eslint.config.mjs
- promote vitest sibling trio to catalog (vitest, @vitest/browser-playwright,
  @vitest/coverage-v8) at ^4.1.5 to prevent version drift; align
  design-system-storybook off pinned 4.0.15
- update lint-config/README.md and docs/conventions/packages.md

Verified: 236/236 tests pass; full yarn release:dryrun (31 turbo tasks)
green; codegen smoke-tested via yarn turbo gen package + lab end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The file was being silently skipped after the jest→vitest migration.
Jest's default discovery picked up *Test.tsx; vitest's default include
(**/*.{test,spec}.?(c|m)[jt]s?(x)) does not. Every other test file in the
package follows <Name>.test.tsx, so rename to match rather than expanding
the include pattern. Also drop the per-file '@testing-library/jest-dom'
import (covered by setupFiles) — the bulk sed missed this file because it
didn't match the *.test.tsx glob.

Restores 2 tests (236 → 238 passing).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@stephenliang stephenliang marked this pull request as ready for review May 2, 2026 20:13
@stephenliang stephenliang requested a review from a team as a code owner May 2, 2026 20:13
@stephenliang stephenliang requested a review from Copilot May 2, 2026 20:34
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

Migrates frontend/packages/component-library test runner and related tooling from Jest to Vitest, aligning packages/* on a single unit/integration test runner and introducing shared Vitest + ESLint presets in @code-dot-org/lint-config.

Changes:

  • Replace Jest config/scripts in component-library with Vitest configuration and update tests from jest.* to vi.*.
  • Add shared lint-config presets for Vitest (Vitest+React+jsdom config + ESLint overlay) and adopt them in packages and generators.
  • Update workspace dependency catalog/lockfile to version-lock Vitest sibling packages and remove Jest/SWC/JSDOM@20-era dependencies from component-library.

Reviewed changes

Copilot reviewed 56 out of 57 changed files in this pull request and generated no comments.

Show a summary per file
File Description
frontend/yarn.lock Removes Jest-related deps for component-library; updates Vitest + related packages; lockfile churn from dependency realignment.
frontend/.yarnrc.yml Updates catalog entries to version-lock vitest and sibling @vitest/* packages together.
frontend/turbo/generators/templates/lab/vitest.config.ts.hbs Simplifies generated lab Vitest config to re-export shared preset.
frontend/packages/lint-config/vitest/react.mjs New shared Vitest config preset for React + jsdom packages.
frontend/packages/lint-config/eslint/vitest.mjs New ESLint overlay applying @vitest/eslint-plugin recommended rules to test files.
frontend/packages/lint-config/eslint/jest.mjs Removes Jest ESLint overlay preset.
frontend/packages/lint-config/package.json Adds devDeps needed to support new Vitest + ESLint presets.
frontend/packages/lint-config/README.md Documents new Vitest presets and ESLint overlay usage.
frontend/packages/labs/music/vitest.config.ts Switches to shared Vitest preset re-export.
frontend/packages/labs/music/eslint.config.mjs Adds Vitest ESLint overlay.
frontend/packages/fonts/eslint.config.mjs Drops unused Jest ESLint overlay import/spread.
frontend/packages/component-library/vitest.config.ts Adds Vitest config (extends shared preset) with alias + setup + CSS modules compatibility option.
frontend/packages/component-library/src/setupTests.ts Switches jest-dom setup to the Vitest integration entrypoint.
frontend/packages/component-library/package.json Changes test script to Vitest and replaces Jest-related devDeps with Vitest/Vite/jsdom equivalents.
frontend/packages/component-library/jest.config.mjs Removes Jest configuration.
frontend/packages/component-library/eslint.config.mjs Replaces Jest ESLint overlay with Vitest overlay.
frontend/packages/component-library/src/video/tests/YoutubeVideo.test.tsx Migrates mocks/spies from Jest to Vitest.
frontend/packages/component-library/src/video/tests/Video.test.tsx Migrates mocks/types from Jest to Vitest.
frontend/packages/component-library/src/video/tests/PlayButton.test.tsx Migrates jest.fn() to vi.fn().
frontend/packages/component-library/src/video/tests/FacadeBackground.test.tsx Migrates jest.fn() to vi.fn().
frontend/packages/component-library/src/video/tests/Facade.test.tsx Migrates jest.fn() to vi.fn().
frontend/packages/component-library/src/tooltip/tests/Tooltip.test.tsx Removes per-file jest-dom import now covered by setup file.
frontend/packages/component-library/src/toggle/tests/Toggle.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/textField/tests/TextField.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/tags/tests/Tags.test.tsx Removes per-file jest-dom import; migrates mock typing/creation to Vitest.
frontend/packages/component-library/src/tabs/tests/Tabs.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/slider/tests/Slider.test.tsx Removes per-file jest-dom import; migrates spies to vi; converts commented tests to it.todo.
frontend/packages/component-library/src/segmentedButtons/tests/SegmentedButtons.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/radioButton/tests/RadioButtonsGroup.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/radioButton/tests/RadioButton.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/popover/tests/WithPopover.test.tsx Migrates partial module mock to Vitest’s async importOriginal pattern; updates spies to vi.
frontend/packages/component-library/src/popover/tests/Popover.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/notification-banner/tests/NotificationBanner.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/modal/tests/Modal.test.tsx Removes per-file jest-dom import; migrates callbacks to vi.fn().
frontend/packages/component-library/src/list/simpleList/tests/SimpleList.test.tsx Updates color assertion to match newer jsdom normalization and adjusts inline style injection.
frontend/packages/component-library/src/link/tests/Link.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/image/tests/Image.test.tsx Migrates callback mocks to vi.fn().
frontend/packages/component-library/src/heroBanner/tests/HeroBanner.test.tsx Migrates module mock to vi.mock.
frontend/packages/component-library/src/formFieldWrapper/tests/FormFieldWrapper.test.tsx Removes per-file jest-dom import now covered by setup file.
frontend/packages/component-library/src/fontAwesomeV6Icon/tests/FontAwesomeV6Icon.test.tsx Removes per-file jest-dom import now covered by setup file.
frontend/packages/component-library/src/dropdown/simpleDropdown/tests/SimpleDropdown.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/dropdown/iconDropdown/tests/IconDropdown.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/dropdown/checkboxDropdown/tests/CheckboxDropdown.test.tsx Removes per-file jest-dom import now covered by setup file.
frontend/packages/component-library/src/dropdown/actionDropdown/tests/ActionDropdown.test.tsx Migrates mocks/types from Jest to Vitest.
frontend/packages/component-library/src/dropdown/tests/CustomDropdown.test.tsx Removes per-file jest-dom import now covered by setup file.
frontend/packages/component-library/src/dialog/tests/Dialog.test.tsx Removes per-file jest-dom import; migrates callbacks to vi.fn().
frontend/packages/component-library/src/dialog/tests/CustomDialog.test.tsx Migrates console.warn spy to vi; converts commented tests to it.todo.
frontend/packages/component-library/src/closeButton/tests/CloseButton.test.tsx Removes per-file jest-dom import; migrates handler mock to vi.fn().
frontend/packages/component-library/src/chips/tests/Chips.test.tsx Removes per-file jest-dom import now covered by setup file.
frontend/packages/component-library/src/checkbox/tests/Checkbox.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/button/tests/_BaseButton.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/breadcrumbs/tests/Breadcrumbs.test.tsx Removes per-file jest-dom import now covered by setup file.
frontend/packages/component-library/src/alert/tests/Alert.test.tsx Removes per-file jest-dom import; migrates spies to vi.
frontend/packages/component-library/src/actionBlock/fullWidthActionBlock/tests/FullWidthActionBlock.test.tsx Removes per-file jest-dom import; migrates module mocks to vi.
frontend/packages/component-library/src/actionBlock/tests/ActionBlock.test.tsx Removes per-file jest-dom import; migrates module mocks to vi.
frontend/docs/conventions/packages.md Updates conventions to reference Vitest ESLint overlay and shared Vitest preset.
frontend/apps/design-system-storybook/package.json Aligns @vitest/browser-playwright and @vitest/coverage-v8 to catalog-managed versions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants