Skip to content

Test: Add public Vitest packages - #82765

Closed
ciampo wants to merge 4 commits into
trunkfrom
codex/vitest-public-packages
Closed

ciampo wants to merge 4 commits into
trunkfrom
codex/vitest-public-packages

Conversation

@ciampo

@ciampo ciampo commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Part of #80855. Follows #82761 and uses the build guard merged in #82154.

What?

Add @wordpress/vitest-console and @wordpress/vitest-preset-default for Vitest 5, with public exports, matcher types, package registration, changelogs and migration guidance. Prepare their additive release.

Why?

The replacement packages must ship and pass consumer verification before released tooling adopts them. Existing Jest packages, Jest lint defaults and wp-scripts test-unit-js remain available.

How?

The preset uses Node by default, filename-selected jsdom and Chromium projects, explicit imports and isolated tests. Node/jsdom use CSS proxies; Browser Mode loads real styles and preserves native browser APIs. Consumer setup runs after preset setup. Plain React JSX works without Emotion installed. Consumers install and configure the Emotion transform explicitly on Vite 7 and 8.

Add isolated packed-consumer checks and a separate public Node/Vite CI matrix. The existing repository test matrix is unchanged.

Testing Instructions

  1. Build packages, then run npm run --workspace @wordpress/unit-tests test:unit:vitest:packages.
  2. Set VITEST_CONSUMER_VITE=7.3.6 to check Vite 7. Set VITEST_CONSUMER_JEST=1 on Node 24 to include the unchanged packed Jest tooling.
  3. Follow the new preset README in a consumer. Ordinary tests should use Node, *.jsdom.test.* should use jsdom, and *.browser.test.* should use Chromium with real styles.
Verification and release notes
  • Packed consumers passed on Node 22.12.0, 24.20.0 and 26.8.2 with Vite 7.3.6 and 8.2.2.
  • Coverage includes plain JSX without Emotion installed, consumer-configured Emotion, synchronous and asynchronous matcher types, setup inheritance, failure output, native browser values, CSS proxies, and both rebuilt CSS-module and regular-CSS output, including token fallbacks and deduplication.
  • Package tests passed 39 tests. Existing Jest package checks passed 34 tests; the packed Jest command and public Jest lint defaults also passed.
  • Full build, typecheck, relevant lint, package contents, dependency checks, routing and conventions passed.
  • The isolated new-package install has zero security advisories. The repository audit remains at 47, unchanged from base 351883676c6: 5 low, 27 moderate and 15 high.
  • Vitest 5.0.0's vitest/config declaration entry references the undeclared @vitest/expect package. The documented .mjs config works; this preset's public types use vite and vitest/node and compile without that retired package.
  • Rebased once onto Test: Remove obsolete internal test setup and transforms #82761 at 351883676c606bdefc0a8b4fd140833511ec03c1.

Testing Instructions for Keyboard

Not applicable; this changes test tooling.

Follow-ups

Publish and verify @wordpress/vitest-console, then @wordpress/vitest-preset-default, before adopting them in released public tooling. The packages use the repository's 1.0.0-prerelease convention until release processing.

Published @wordpress/build@0.23.0 contains the required guard. Rebuild affected generated CSS with that version or later. No additional build-fix PR is planned. Publishing these packages does not require switching wp-scripts or removing Jest.

Use of AI Tools

Codex implemented the changes, ran verification and performed an independent review.

@github-actions

github-actions Bot commented Sep 11, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

📦 Bundle size

Size Change: 0 B

Total Size: 8.08 MB

3c85f6a Run

⚡ Performance

Show the results

Client side metrics exclude the server response time.

front-end-block-theme

Metric 4aa9c12 trunk % Change
timeToFirstByte 56 ms +10.45% -1.25% 56 ms +10.27% -2.05% 0%
largestContentfulPaint 92 ms +13.04% -2.17% 96 ms +4.17% -8.33% -4.17%
lcpMinusTtfb 35.5 ms +11.83% -7.04% 34.9 ms +14.61% -4.58% 1.72%
wpBeforeTemplate 27.88 ms +20.66% -1.22% 27.88 ms +12.27% -1.18% 0%
wpTemplate 24.44 ms +4.01% -3.4% 24.08 ms +5.36% -1.2% 1.5%
wpTotal 52.32 ms +11.03% -0.99% 52.34 ms +10.41% -1.93% -0.04%
wpMemoryUsage 7.52 MB +0% -0% 7.49 MB +0% -0% 0.46%
wpDbQueries 17 +0% -0% 17 +0% -0% 0%

front-end-classic-theme

Metric 4aa9c12 trunk % Change
timeToFirstByte 43.55 ms +4.59% -1.72% 47.15 ms +7.74% -1.27% -7.64%
largestContentfulPaint 92 ms +4.35% -0% 100 ms +4% -0% -8%
lcpMinusTtfb 49.05 ms +2.85% -1.22% 53.35 ms +1.12% -0.75% -8.06%
wpBeforeTemplate 26.58 ms +6.55% -1.73% 26.09 ms +8.43% -2.41% 1.88%
wpTemplate 13.76 ms +2.69% -2.76% 17.92 ms +2.29% -1.4% -23.21%
wpTotal 40.7 ms +4.69% -2.63% 44 ms +8.07% -0.91% -7.5%
wpMemoryUsage 6.00 MB +0% -0% 6.10 MB +0% -0% -1.67%
wpDbQueries 10 +0% -0% 14 +0% -0% -28.57%

media-processing

Metric 4aa9c12 trunk % Change
mediaProcessingJpeg 399.73 ms +0.52% -1.01% 394.75 ms +1.74% -0.52% 1.26%
mediaProcessingAvif 6105.41 ms +0.15% -0.26% 6046.25 ms +0.33% -0.15% 0.98%
mediaProcessingJpegToAvif 4214.93 ms +0.14% -0.1% 4177.71 ms +0.19% -0.09% 0.89%

media-upload

Metric 4aa9c12 trunk % Change
jpegUploadProcessing 1463.83 ms +32.49% -2.32% 1418.6 ms +2% -0.92% 3.19%
pngUploadProcessing 202.31 ms +5.89% -3.08% 213.84 ms +14.61% -2.85% -5.39%
largeJpegUploadProcessing 1416.89 ms +0.67% -0.97% 1417.46 ms +0.32% -0.5% -0.04%
multipleImageUploadProcessing 1550.21 ms +1.81% -0.54% 1547.92 ms +1.79% -0.11% 0.15%

post-editor

Metric 4aa9c12 trunk % Change
serverResponse 524.51 ms +4.57% -3.78% 502.16 ms +2.24% -3.48% 4.45%
firstPaint 235.94 ms +57.06% -2.1% 236.21 ms +8.76% -3.54% -0.11%
domContentLoaded 1076.81 ms +3.81% -2.5% 1063.29 ms +2.74% -1.44% 1.27%
loaded 1078.08 ms +3.8% -2.5% 1064.52 ms +2.75% -1.41% 1.27%
firstContentfulPaint 449.06 ms +4.44% -3.48% 431.78 ms +3.21% -3.01% 4%
firstBlock 3323.93 ms +0.71% -0.51% 3319.72 ms +0.18% -0.67% 0.13%
type 15.89 ms +1.51% -8.56% 16.06 ms +3.74% -11.89% -1.06%
typeWithoutInspector 15.01 ms +3.13% -8.26% 15.08 ms +6.56% -2.19% -0.46%
typeWithTopToolbar 19.14 ms +6.48% -8.88% 19.89 ms +3.37% -5.38% -3.77%
typeContainer 9.29 ms +10.23% -5.06% 10.88 ms +3.49% -20.77% -14.61%
focus 78.25 ms +4.22% -7.69% 86.97 ms +8.2% -3.3% -10.03%
firstFocus 171.08 ms +0% -0% 187.57 ms +0% -0% -8.79%
selectAll 627.94 ms +5.27% -2.71% 658.13 ms +1.54% -4.8% -4.59%
listViewOpen 75.26 ms +4.46% -3.68% 74.81 ms +4.28% -4.53% 0.6%
inserterOpen 24.21 ms +4.09% -12.89% 23.8 ms +12.69% -5.71% 1.72%
inserterHover 3.43 ms +14.87% -7.29% 4.18 ms +18.66% -4.55% -17.94%
inserterSearch 8.36 ms +2.75% -3.83% 8.68 ms +11.87% -17.17% -3.69%
loadPatterns 614.31 ms +1.86% -0.95% 672.36 ms +2.78% -1.85% -8.63%
wpTotal 514.56 ms +4.64% -3.94% 491.95 ms +2.37% -3.43% 4.6%
wpMemoryUsage 13.05 MB +0% -0% 13.02 MB +0% -0% 0.25%
wpDbQueries 54 +0% -1.85% 54 +0% -0% 0%

site-editor

Metric 4aa9c12 trunk % Change
serverResponse 489.31 ms +9.18% -2.54% 497.71 ms +3.42% -7.21% -1.69%
firstPaint 258.96 ms +70.64% -2.87% 257.11 ms +18.07% -8.85% 0.72%
domContentLoaded 1137.49 ms +1.94% -2.28% 1138.27 ms +0.53% -2.39% -0.07%
loaded 1138.7 ms +1.96% -2.28% 1139.58 ms +0.52% -2.38% -0.08%
firstContentfulPaint 445.3 ms +2.15% -2.39% 443.93 ms +3.13% -1.84% 0.31%
firstBlock 4236.02 ms +2.11% -0.39% 4242.32 ms +1.46% -0.82% -0.15%
type 15.97 ms +3.26% -5.82% 15.02 ms +20.57% -2.4% 6.32%
navigate 119.25 ms +8.33% -10.29% 99.57 ms +15.55% -1.07% 19.76%
loadPatterns 1551.09 ms +9.9% -11.31% 1538.61 ms +6.08% -12.35% 0.81%
loadPages 1073.88 ms +0.92% -1.77% 1082.62 ms +0.84% -0.29% -0.81%
wpTotal 479.63 ms +9.28% -2.67% 487.89 ms +3.46% -7.28% -1.69%
wpMemoryUsage 12.01 MB +0% -0% 11.97 MB +0% -0% 0.3%
wpDbQueries 43 +2.33% -0% 43 +2.33% -0% 0%

3c85f6a Run

@ciampo ciampo self-assigned this Sep 11, 2026
@ciampo ciampo added the [Type] Feature New feature to highlight in changelogs. label Sep 11, 2026
@ciampo

ciampo commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor Author

@WordPress/gutenberg-components @tyxla @manzoorwanijk @Mamaduka @t-hamano @sirreal @desrosj

As I started working on a vitest replacement for existing @wordpress/jest-console and @wordpress/jest-preset-default packages, I'm not sure sure about needing / wanting to publish new replacement pacakges.

Compared to Jest, most features are already available in Vitest. The useful additions could start as tested configuration examples and a small internal console helper. Existing Jest packages do not require one-for-one Vitest replacements.

The main tradeoff is consistent configuration and centrally distributed fixes versus additional maintenance. Shared packages could help WordPress projects, but upstream Vitest/Vite changes can require updates to configuration, matcher types, supported versions and consumer tests, followed by new releases. We already needed different Vite 7/8 optimizer settings and Vitest 5 matcher types. Copied configurations shift that maintenance to consumers; they do not eliminate it.

Preset: which features are worth keeping?

“Supported” does not always mean “enabled by default.” Several useful policies only need native configuration options.

Feature Assessment
Node by default, explicit imports, isolated test files Already Vitest defaults. Keep them without custom implementation.
TypeScript and JSX compilation Vite provides the transformation machinery. Consumers still need the appropriate runtime/settings and separate type checking.
Filename-selected Node/jsdom/browser projects Useful convention, expressible through native projects and file patterns. A documented config may be enough.
Real browser CSS, layout and native browser APIs Valuable to keep. Provided by Browser Mode with a separately installed provider/browser.
Suite-owned browser mocks Valuable to keep. Consumers can provide only the mocks their suites need; no shared blanket mocks are required.
CSS-module proxies in Node/jsdom Already supported. Our exact proxy class names are mainly legacy snapshot/assertion compatibility.
Real styles from @wordpress/build output Valuable to verify, but depends on the build fix and rebuilding generated CSS, not on a test preset.
Mock call-history clearing Already enabled by default in Vitest 5.
Resetting implementations, restoring spies and stubbed globals/environment variables Useful native options, but stronger than the defaults. Choose them deliberately rather than copying Jest policy wholesale.
Timer cleanup and setup order Native hooks/options can handle these. Prefer cleanup owned by the suite or fixture that creates the resource.
Jest-style hook order Migration compatibility. Prefer Vitest's reverse teardown order for new suites.
Snapshot formatting and failure diagnostics Our snapshot settings already match Vitest defaults; diagnostics use native reporters/options.
Jest-style discovery and vendor/ exclusions Small configuration choices. Prefer native .test/.spec discovery for new projects.
WordPress globals SCRIPT_DEBUG can be useful for targeted tests. Legacy TinyMCE/user globals should be supplied only where needed.
React/SWC, Emotion, jsdom, Playwright and Sass choices Consumer-specific dependencies. Avoid making every project carry every environment/compiler. Emotion is now consumer-configured in this PR.
Public exports and types Import convenience, but also more APIs to support. Exporting a plain config locally needs no new middleware layer.

Removing a dependency from Gutenberg later would not automatically remove the obligation to support external consumers who rely on it through a public preset.

Console: useful enforcement, but reconsider the inherited API

Failing tests on unexpected warnings/errors is worth keeping. Vitest's normal spies can assert expected calls, but do not automatically enforce that policy across a suite. Custom names such as toHaveWarnedWith are mostly migration convenience.

The current helper also has a weakness: once a test acknowledges one warning, an additional unexpected warning can pass. A replacement should consider checking the complete expected call list. We should also decide whether info/log should fail tests at all.

We compared the following on Vitest 5 in Node, jsdom and Chromium:

Approach Result
Native spies/assertions Good for individual logging tests. Automatic enforcement still needs setup.
Current WordPress helper Catches unasserted output and test teardown output, but misses extra calls after acknowledgement.
vitest-fail-on-console@0.10.1 Closest existing alternative. Runtime checks worked, but teardown detection depends on hook order. Strict NodeNext types failed; Bundler resolution passed. Not a drop-in replacement.
vitest-console@0.2.1 Provides matchers, not automatic enforcement. Its types reference removed Vitest APIs and incorrectly type async assertions; cleanup also failed after explicit spy restoration.
Small local helper using native hooks/assertions Detected extra calls and teardown output, but still needs work around explicit spy restoration and suite-level output. A prototype, not a finished replacement.

Global console spies also remain unsafe for concurrent tests within one file. File isolation alone does not solve that problem.

Verification and a possible next step

A small configuration using neither proposed package passed representative Node, jsdom and Chromium tests on Vite 7 and 8, including JSX and both generated CSS output forms. This was not a full Gutenberg migration or a finished replacement configuration.

The current packages also passed all six supported Node/Vite consumer combinations. That establishes that they work, but does not establish that publishing them is necessary.

I'd start with tested config examples, keep Gutenberg's shared setup internal, and refine console enforcement separately. If external projects need the same maintained conventions, we could then consider a small public config export or helper with a clear scope. Neither package is currently required by Gutenberg's internal migration. Existing public Jest tooling and wp-scripts test-unit-js can remain available independently.

Let me know what y'all think ✌️

@manzoorwanijk

Copy link
Copy Markdown
Member

IMHO, it's fine to deprecate them and announce the move to Vitest.

@ciampo

ciampo commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Cool, I'm going to close this PR and skip this step in the migration. Thank you all

Comment thread .github/labeler.yml
Comment on lines +365 to +372
'[Tool] Vitest console':
- changed-files:
- any-glob-to-any-file: 'packages/vitest-console/**'

'[Tool] Vitest preset':
- changed-files:
- any-glob-to-any-file: 'packages/vitest-preset-default/**'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Observation: My validation changes in #76263 were effective in making sure that new packages are added to the mapping here, though I suppose it doesn't actually validate that the label actually exists, which might be a good follow-on enhancement.

It looks like @sirreal 's improvements in #81614 might help this.

@aduth

aduth commented Sep 14, 2026

Copy link
Copy Markdown
Member

Compared to Jest, most features are already available in Vitest.

This is pretty valuable testimony in itself to a benefit of adopting Vitest 🙌

@manzoorwanijk
manzoorwanijk deleted the codex/vitest-public-packages branch September 14, 2026 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Feature New feature to highlight in changelogs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants