Uh oh!
There was an error while loading. Please reload this page.
Replace Pleasantest with Vitest browser mode - #2421
Merged
Merged
Conversation
Pleasantest has not shipped since v5.0.0 in July 2024. It does not declare support for the Node version we run, and its Puppeteer 22 pin is why the CI test job was held back on ubuntu-22.04. It also couples us to Jest, which sits in front of the remaining #2391 work. Vitest is the natural fit because it transforms through Vite, which we are already on. That turns out to matter more than the runner choice: the Twig plugin Storybook uses works unchanged in tests, so `import template from './alert.twig'` replaces the filesystem Twing environment the tests built for themselves in test-utils.ts, and component scripts are imported directly instead of being passed to Pleasantest as source strings for `utils.runJS`. Both files are gone, and so are Jest and its Babel transform. Tests are split across two Vitest projects. Seven of the twenty-five assert only what a template rendered, so they run in Node against jsdom in milliseconds; the other eighteen assert accessibility trees, computed layout or real focus, none of which jsdom provides, and run in Chromium via Playwright. The split is by filename, `*.browser.test.ts` against `*.test.ts`. The suite goes from 9.4s to 8.5s, and the remainder is almost entirely the two deliberate multi-second waits in the Subscribe lifecycle test, which are unchanged. The twenty inline accessibility tree snapshots become fourteen ARIA snapshots plus explicit assertions covering the rest. Three of those assertions exist because ARIA snapshots record no focus state or accessible description, which Pleasantest's tree did: the reply textbox's description and the focus assertions in Comment and Sky Nav were read out of snapshots before and are asserted directly now. Card and Overview change more than their serialisation, so they move to the node project and assert markup. Both templates downgrade a header/footer to a div unless the wrapper is a sectioning element, precisely to avoid spurious banner and contentinfo landmarks, and the old snapshots could show that because the Chromium of the day exposed a scoped header as a banner anyway. Current engines follow the ARIA spec, where a header inside an article is not a landmark at all -- so Overview's two variants serialised to an identical three lines and the tests could no longer fail independently. Card had a second problem: its demo footer renders `'now'|date(...)`, so a snapshot that includes text captures the day it was written. What the templates document is which element they emit, and that is now what is asserted. Alert's `hidden` test is a query rather than a snapshot for a related reason. Vitest reads an empty inline snapshot as one it has still to write, so the empty snapshot this test used to carry would have passed whatever the alert rendered. Notes on the rest: - moduleResolution moves from "node" to "bundler". The legacy mode cannot read package exports subpaths, so it could not resolve `vitest/browser`. - Root-level .ts files have never satisfied the type-aware ESLint rules, because tsconfig covers `src` and test-utils.ts sat outside it. The Vitest config and setup files are read through an inferred project instead. - The browser project sets an 800x600 viewport, which is what Puppeteer defaulted to and therefore what these tests were written against. Browser mode's own default is a phone-sized 414x896, which would put every component on the small-screen side of the 40em breakpoint. - Vite's forwarding of browser window errors is switched off, because Vitest reports unhandled errors itself, under a heading that fails the run and names the test. Console forwarding stays on. Elastic Textarea resizes a textarea from inside a ResizeObserver watching that same textarea, which is the point of the component, and Chromium reports the pass it cannot deliver as a window error -- in real browsers as much as here. Dropping the duplicate halves the noise; Vite cannot filter it by message. No changeset: nothing published changes. The bundles are the same size, and Rollup's entry glob already skips `.test.` files.
|
✅ Deploy Preview for cloudfour-patterns ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
The build job failed on this branch: rollup-plugin-dts could not resolve "./src/components/comment/comment" from the entry `gulp buildTypes` generates. TypeScript infers the declaration output layout from the common directory of everything in the program. Emitting to `ts-dist/src/...`, which that entry expects, therefore depended on some file outside `src` being part of the compilation -- and one was, by accident: every test imported `../../../test-utils.js`, which dragged a project-root file in and pushed the common directory up to the root. Deleting test-utils.ts left `src` as the common directory, so declarations moved to `ts-dist/components/...` and the entry pointed at nothing. `rootDir` is now set explicitly, so the layout no longer moves when the set of files changes. This did not fail locally because `clean` only removed `dist`. A `ts-dist` from an earlier build still had the old `src` tree in it alongside the new output, so the entry resolved against stale files. `clean` now removes both, which is what let the real failure show up in a fresh checkout first.
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 21, 2026
Closed
spaceninja added a commit
that referenced
this pull request
Aug 24, 2026
Three unrelated leftovers from #2391: - Button Swap's browser test was named 'Swap UI state when clicked' but never clicks -- this package ships the markup, not the swap script. Name it for what it asserts, and assert the half the name claimed but did not cover: that the swapped state is present and hidden. - Root-level TypeScript belonged to no tsconfig project, so the type-aware lint rules could not see it. #2421 worked around that with a hand-maintained allowDefaultProject list, which is what let test-utils.ts go unlinted. Add root-level globs to tsconfig instead, so the next file is covered automatically and gets our real strictness rather than an inferred project's defaults. This pulled twing/vite-plugin-twig.mjs into the program under checkJs, hence the annotations there. - src/index-with-dependencies.scss was the last @import in the repo. Dart Sass 3 removes @import. Fixes#2431
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Pleasantest has not shipped a release since v5.0.0 in July 2024. Nothing is broken today, but it constrains everything around it: it does not declare support for the Node version we run, and its Puppeteer 22 pin is the reason the CI test job was held back on
ubuntu-22.04. It is also a Jest integration, which puts it directly in front of the remaining #2391 work. This moves the suite to Vitest browser mode and drops Jest, Pleasantest and Puppeteer.Vitest was the natural fit because it transforms through Vite, which we are already on — and that turned out to matter more than the runner itself. The Twig plugin Storybook uses works unchanged in tests, so templates are now imported directly rather than rendered through a filesystem Twing environment the tests built for themselves, and component scripts are imported as modules rather than handed to Pleasantest as source strings. Both of those support files are gone. Tests are split across two projects: the seven that only assert what a template rendered run in Node against jsdom, and the eighteen that need a real accessibility tree, computed layout or genuine focus run in Chromium. Same twenty-five tests, and the suite drops from 9.4s to 8.5s.
Two things are worth a reviewer's attention, both recorded in code comments and the commit message. Card and Overview no longer snapshot the accessibility tree. Both templates deliberately downgrade a
header/footerto adivunless the wrapper is a sectioning element, to avoid spurious banner and contentinfo landmarks, and the old snapshots could show that only because the Chromium of the day exposed a scopedheaderas a banner anyway. Current engines follow the ARIA spec, where aheaderinside anarticleis not a landmark at all — so Overview's two variants serialised to an identical three lines and its two tests could no longer fail independently. They now assert which element the template emits, which is the behaviour the templates actually document. Alert'shiddentest is a query rather than a snapshot, because Vitest reads an empty inline snapshot as one it has still to write, so the empty snapshot it used to carry would have passed whatever the alert rendered.One known wart is left in place: four lines of
ResizeObserver loop completed with undelivered notificationsper run. Elastic Textarea resizes a textarea from inside a ResizeObserver watching that textarea, which is the point of the component, and Chromium reports it in real browsers too. I halved it by dropping Vite's duplicate window-error forwarding, but silencing the rest would mean also swallowing real console errors from tests, which is a worse trade.Also worth flagging as follow-ups rather than fixing here: Button Swap's test is still named "Swap UI state when clicked" but never clicks, because this package ships that component's markup and not its script — the original test asserted the same snapshot twice as before/after. And Pleasantest's minimum click target-size check has no equivalent in Vitest, so that one guard is gone.
Screenshots
Testing
Chromium is not part of
npm install— Playwright downloads browsers separately.npx playwright install chromium. It should download a browser, or tell you it is already there.npm run build, thennpm test. All 25 tests should pass in roughly 8–9 seconds, and the output should label each test with eithernodeorbrowser (chromium).src/components/alert/alert.twig, change the<p>wrapping the message to a<span>and runnpm testagain. The Alert tests should fail, and the failure should show that a paragraph was expected where plain text was found. Undo the change.src/components/card/card.twig, change the first line so the tag defaults to'div'instead of'article'.npm testshould fail on "should use header/footer with article", reporting adivwhere anarticlewas expected. Undo the change.npm run test:watch, save a change to any test file, and confirm only that file re-runs. Pressqto quit.npm startand spot-check a few component pages in Storybook — Alert, Card, Sky Nav, Subscribe. They should render as before, and the Twig source preview under each example should still show the template snippet. This shares the Twig plugin with the tests now, and the Babel and TypeScript settings both changed.testjob runs onubuntu-latestand that the Playwright install step succeeds.