Limitations
describe-me is early. This page lists every known limit, where it applies, the workaround and whether a fix is planned.
At a glance #
open has no fix announced. planned is on the roadmap. by design follows from how describe-me or the environment works. fixed in 0.5.2 names the release with the fix.
| Limitation | Applies to | Workaround | Status |
|---|---|---|---|
fireEvent inside your own act() records before React
flushes, so its frame shows the DOM from before the update. See
Limitations in jsdom.
|
jsdom |
Drop your own act(), because Testing Library already wraps
fireEvent in one. Where the act() has to stay, put the
block in a step().
|
open |
| Concurrent tests are never recorded, because they would share one recorder. See Environments. | both | Make the tests you want in the docs sequential. | by design |
stories: 'tagged' and no-docs need test tags, which
arrived in Vitest 4.1. On 4.0 stories: 'tagged' throws before any
test runs, and a test tagged no-docs still becomes a story, because
4.0 ignores tags. See
Which tests become stories.
|
both |
Upgrade to Vitest 4.1, or keep stories: 'all' and pick files with
include.
|
by design |
Frames record hover and focus, but not :active, and not a hover your
own code fakes, for example with dispatchEvent(). The rules of a
stylesheet from another origin keep their real pseudo-classes in the replay, and
so does a state after a pseudo-element, such as
::part(label):focus-visible. A rule with a hover after a
pseudo-element, such as ::-webkit-scrollbar-thumb:hover, is missing
from the replay, as before 0.12. rrweb's own copy of it is invalid, so the browser
drops the whole rule. States inside a shadow tree are not recorded. See
Environments.
|
both | A state shows when the component puts it into the DOM, for example as a class or an attribute. | by design |
A wrapper that ignores children never mounts your
element, so the test gets no component name. See
Naming.
|
both |
Call recorder.setComponent() with name and
file after render.
|
planned |
| The reporter reads props with the compiler API of TypeScript 5 and 6. TypeScript 7 has none it can use, so a project on it gets no props tables. The run records as usual and warns once. See Props. | both | Install typescript 6 for the props tables. |
open |
With test.projects entries that set their own root,
include and exclude match different paths in the test
run and in the reporter. See
Which tests record.
|
both |
Use globs that start with **/, or leave include and
exclude out.
|
open |
In Vitest 5, inline test.projects entries share the root's Vite
server and did not get describe-me's setup file. Their tests recorded nothing and
left every component mounted for the next test. See
Monorepos and projects.
|
both |
On 0.6.0, set test.sharedViteServer: false in the root config, or
upgrade all packages.
|
fixed in 0.6.1 |
A project without describe-me, with extends: false or a config file
of its own, ran with Testing Library's auto-cleanup switched off, because the
plugin set RTL_SKIP_AUTO_CLEANUP in the root's test.env,
which Vitest hands to every project. Its components stayed mounted for the next
test. See Monorepos and projects.
|
jsdom |
Before 0.6.1, set test.env: { RTL_SKIP_AUTO_CLEANUP: '' } in that
project, or upgrade all packages.
|
fixed in 0.6.1 |
| A test file that two projects run is one module in the manifest, so the project that finishes last decides its stories. See Monorepos and projects. | both | Give each project its own test files. | open |
describeMe() in the plugins of a project, and not in the
root config, writes no manifest, because Vitest runs only the root config's
reporters. See Monorepos and projects.
|
both | Add describeMe() to the root config. |
open |
A test skipped in a filtered run (-t, .only,
.skip) keeps what the last run recorded for it. See
Tests that are left out.
|
both | Run the whole suite before you publish the docs. | by design |
| Recording adds time to every recorded test and to the end of the run. See Performance. | both | Record fewer files, or record in a docs run of its own. | open |
All four describe-me packages must be on one version. Mixed copies of
@describe-me/core fail every test file. See
One version for all packages.
|
both | Upgrade them together, and group them in your update bot. | by design |
| Recording added React act warnings in jsdom. See Troubleshooting. | jsdom | On 0.5.1, upgrade all packages. | fixed in 0.5.2 |
A wait of the recorder can move a React act warning in either direction. It waits
for a held-back render frame at the end of a test, before the closing frame, after
a step() and after a user-event call without
@testing-library/react. See
jsdom.
|
jsdom |
Await findBy… or waitFor for async updates instead of a
bare sleep.
|
by design |
The plugin replaced Vitest's default reporters, such as minimal for
AI agents and github-actions. See
Reporters.
|
both | On 0.5.1, name your reporters in the config. | fixed in 0.5.2 |
include: [] recorded every test file. See
Which tests record.
|
both | On 0.5.1, use exclude: '**' to record none. |
fixed in 0.5.2 |
| Tooltips, menus and dropdowns placed by a positioning library show up in the top-left corner. See Limitations in jsdom. | jsdom |
Record such tests in browser mode, or leave their files out with
exclude.
|
by design |
| What the test measures, scrolls or observes behaves differently, because jsdom has no layout. See Limitations in jsdom. | jsdom | Record such tests in browser mode. | by design |
| Web fonts never load during the test, and a link that a font loader adds sets a timer in every capture. See Limitations in jsdom. | jsdom |
Load fonts in previewHead, and do not call font loaders in tests.
|
by design |
Snapshots hold no canvas pixels, so a <canvas> is blank in the
viewer. See Limitations in jsdom.
|
both | None. | by design |
adoptedStyleSheets on a shadow root are not captured. See
Styling techniques.
|
browser mode jsdom | None yet. | planned |
jsdom has no constructable stylesheets, so
document.adoptedStyleSheets cannot be captured. See
Styling techniques.
|
jsdom | Record such components in browser mode. | by design |
Rules go through jsdom's CSS parser, which drops what it does not understand.
Nesting, @layer and @container are not verified. See
Styling techniques.
|
jsdom | Record such styles in browser mode. | open |
CSS linked from previewHead is copied as it is on disk, without
PostCSS, Tailwind or any other Vite transform. See
Fonts.
|
viewer build | Link plain CSS. | open |
| The font check knows Google Fonts, Bunny Fonts and Fontsource on jsDelivr. A stylesheet from any other host turns it off, and a family installed only on your machine counts as missing. See The font check. | build | Load fonts from one of those hosts or with @font-face. |
open |
describe-me build needs the network to download web fonts into the
site. See Vendoring.
|
build |
After one online build the font cache lets later builds run offline.
--no-vendor-fonts keeps the build off the network.
|
by design |
| The viewer only replayed recorded snapshots and could not mount a component live. See Live. | viewer | On 0.5, write a test for each state you want to show. | fixed in 0.6.0 |
| Live runs only the arrange phase of a test, so it is a fresh start, not frame N of the timeline. See What Live runs. | viewer | Click and type in the frame to reach a later state, or open the recorded frame. | by design |
Arrange code that needs Node, such as node:fs or
msw/node, does not load in the browser, so Live cannot mount the
test. On a static site a file that imports a Node module fails as a whole, even
when its arrange phase never calls it. See
What Live runs.
|
viewer |
Keep the arrange phase free of Node-only code. For a setup file, list a browser
version of it in
live.setupFiles, and alias a module of it that tests import, as
MSW in Live does.
|
by design |
Live loads the root config, so a test.projects entry with a config of
its own runs with the plugins and aliases of the root config. See
The live preview.
|
viewer | Put the plugins and aliases the components need in the root config. | open |
vi.mock and vi.doMock have no effect in Live, so the
component uses the real module. The inspector shows a notice for each call. See
What Live runs.
|
viewer |
Pass the mocked behaviour as props, or answer the requests in a setup file, such
as MSW's setupWorker in live.setupFiles (MSW in Live).
|
open |
A static site has no dev server, so a plugin whose apply is
'serve' runs in a build without one. What it does through the server
(middleware, HMR, a websocket) or adds to the page in
transformIndexHtml is missing. One that needs the server in a
transform stops describe-me build --live. See
The static live preview.
|
build |
Leave the plugin out while
DESCRIBE_ME_LIVE
is set, as in
...(process.env.DESCRIBE_ME_LIVE ? [] : [devTool()]). Live under
describe-me dev then runs without it too.
|
by design |
| A built site opened from disk does not load, because the viewer fetches its data. See Hosting. | build | Serve the folder over HTTP. | open |
| A 0.4 viewer cannot read 0.5 data. Its frames show without their stylesheets. See Upgrading. | viewer |
Upgrade describe-me together with @describe-me/vitest.
|
by design |
| Renaming a test or moving it to another suite or file changes its id, so links to it stop opening it. See Links. | viewer | Update the links after a rename. | by design |
The Tailwind 4 theme comes from __unstable__loadDesignSystem of
@tailwindcss/node, an unstable API. When it fails,
foundationsErrors says so, and Foundations keeps the recorded custom
properties. See Foundations.
|
both | None. | open |
Foundations does not read the tailwind.config.js of Tailwind 3. See
Foundations.
|
both | Declare the tokens as custom properties in a stylesheet the tests load. | planned |
| Chakra UI, Mantine and Radix Themes have no preset of their own in Foundations. They show in generic blocks by name prefix. Chakra UI and Mantine presets are on the roadmap, and Radix Themes has none announced. See Design systems. | viewer | None. | planned |
| Only CSS that the tests load counts for Foundations, so a token stylesheet that only the app entry imports is missing. See Foundations. | both |
Import the token stylesheet in a test setup file or in the custom
render wrapper (global styles).
|
by design |
| Only React has an adapter. See Frameworks and tools. | both | None yet. | planned |
| describe-me records Vitest tests only. See Frameworks and tools. | both | None. | by design |
Recording #
A frame is the DOM at one moment, with its hover and focus. What else is not in the DOM is
not in the frame:
:active and a faked hover, and a
fireEvent that React has not flushed yet. Concurrent tests and tests a
filtered run skips record nothing new. A
wrapper that ignores children needs you
to name the test, props tables need TypeScript 5 or 6,
and projects with their own root need
**/ globs. Recording costs time, see
Performance, and needs
one version of every package. 0.5.2 fixed
act warnings,
the default reporters and
an empty include. Writing stories explains which tests are
left out.
Environments #
jsdom has no layout engine and loads nothing, so what differs is what happens inside the test: popovers, layout and observers and fonts. The frames are the same kind of thing in both environments, laid out by a real browser in the viewer. No snapshot holds canvas pixels. Environments has the details, and when to pick browser mode.
Styles and fonts #
A snapshot is DOM plus stylesheets, so styles that live elsewhere are missing: stylesheets adopted by a shadow root, and in jsdom every adopted stylesheet and rules its parser drops. The preview head skips Vite transforms, the font check knows three hosts, and font vendoring needs the network. Styles and fonts has the details.
Viewer and static site #
The viewer replays recorded snapshots, and up to 0.5 it could not
run your components.
Live in describe-me dev, and in a site built
with describe-me build --live, mounts one test for real, but it runs
only the arrange phase,
no code that needs Node,
no module mocks,
only the root config and, on a static site,
no dev server for plugins. A built site
needs HTTP. A
0.4 viewer cannot read 0.5 data, and links to a test
break when it is renamed. Foundations reads
only the CSS that the tests load, the Tailwind
4 theme through an unstable API and
not the config of Tailwind 3, and shows
Chakra UI, Mantine and Radix Themes in generic
blocks by name prefix. Viewer and CLI and
Foundations have the details.
Frameworks and tools #
describe-me is early. It works with React only: the core has no React in it, but React is the only adapter. It records Vitest tests only, in browser mode or jsdom. Vue and Svelte adapters are on the roadmap. No other test runner is announced.
What comes next #
Live shipped in 0.6.0 and Foundations in 0.9.0. These are announced, without dates:
- Controls. Turn the props table into inputs that re-render the live component at once with the changed props.
-
adoptedStyleSheetsin shadow roots. Capture them as the document's are. See the limit. -
Vue and Svelte adapters. A
renderwrapper each. See the limit. -
Names from wrappers that ignore
children. Today you name such a test withrecorder.setComponent(). See the limit. -
Token export. Write the tokens of Foundations as a DTCG
tokens.json. - Chakra UI and Mantine presets. Blocks shaped like each design system, as Material UI has. See the limit.
-
Tailwind 3. Read the theme from
tailwind.config.js. See the limit.