describe(me) docs
early v0.12.1 browser mode · jsdom Live · Foundations
Examples npm GitHub

Viewer and CLI

describe-me dev serves the viewer, repaints it after every test run and can mount a test in Live. describe-me build writes the recorded frames as a static site, with Live under --live. This page covers both commands and everything the viewer does.

The CLI #

The describe-me package installs one binary. It always needs a command:

describe-me dev   [--data .describe-me] [--port 6006] [--no-live] [--root <dir>]
describe-me build [--data .describe-me] [--out describe-me-dist] [--no-vendor-fonts]
                  [--live] [--root <dir>]
Command or flag Default What it does
describe-me dev — Starts a Vite dev server for the viewer and serves the data directory under /__data. When the reporter rewrites manifest.json, the server tells the page, and the viewer loads the manifest again. Vite prints the URL. Then it starts the live preview and prints its address after Live preview:. It never downloads fonts.
describe-me build — Writes the viewer as a static site to --out and copies the data directory into it as __data/. With --live it builds the live preview into __live/ and writes __live.json next to the viewer. Then it downloads web fonts into the copy of the data (fonts in the static site). The data directory itself never changes.
describe-me --help — Prints the usage. So does describe-me without a command, also when it has flags.
--data .describe-me dev and build. The directory the reporter wrote, relative to the current directory. When you set the plugin's outDir, pass the same directory here.
--out describe-me-dist build only. Where the static site goes. The directory is emptied first, so never point it at a folder that holds other files.
--port 6006 dev only. The port of the dev server. When it is busy, Vite moves on to the next free port. Read the URL it prints.
--help, -h — Any command. Prints the usage instead of running it.
--live on in dev,
off in build
build builds the live preview into the site, so the static site shows Live (Live in the static site). dev has it on anyway. The site then holds the compiled code of your components, the test files and the setup files with their test data, readable because it is not minified, and your project's public/. Publish it only where that code may be seen. A failed live build stops the command with exit code 1 (why it stops).
--no-live on in dev,
off in build
dev starts the viewer alone, without the live preview. The Live toggle is then hidden. On build it is the default: the site has no Live.
--root from the manifest dev and build --live. The project of the live preview, relative to the current directory. Without it, the preview uses the root and configFile of the manifest. With it, the preview uses that directory and the config file Vitest picks there, the first vitest.config.*, then vite.config.*. Use it before the first test run, when the manifest comes from another machine, or on the __data/ of a built site, whose manifest names the project by an id.
--no-vendor-fonts fonts are downloaded build only. Leaves web fonts on their hosts, so the build makes no network requests. Use it in CI without network access or under privacy rules.
describe-me: Unknown option '--prot'. To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- "--prot"

Finding your way #

The Counter increments test in the browser-mode example has three frames. Step through them with ← and →.

Groups

With sidebar.groups, the files sit in named groups, which can nest. A group's row shows an arrow and the name. A click anywhere on it opens or closes the group. Groups come in the config's order, a group's subgroups before its files, and files without a group come after every group.

A group without subgroups whose one file has a single describe of the group's name, in any case, shows as that file alone, so a Button group does not repeat its Button file. It has no row to close. The file's own arrow still collapses the file. A manifest without groups shows the files in path order. The sidebars of the browser-mode and the shadcn/ui examples show groups.

Hiding the panels

The first row of a test, an overview and Foundations starts and ends with a toggle. The one on the left hides or shows the sidebar, the one on the right the inspector, and the center takes the space. [ and ] do the same. A toggle looks pressed while its panel shows. / and a click on a tag in the inspector show a hidden sidebar, since both need it.

Until you toggle a panel, the window's width decides: below 1100 px the inspector starts hidden, below 800 px the sidebar too, and a window that grows past those widths shows them again. A panel you toggled stays as you left it. The browser keeps that per project, like the sidebar's width. It is not part of the link. Without storage it lasts until you reload.

Theme

The three buttons at the right end of the header set the viewer's own colors. system, the default, follows your system. light and dark override it. The choice is the same for every project. The browser keeps it in localStorage, and it is not part of the link. Without storage the switch still works until you reload.

Under auto, the default of the background switch, the theme picks the canvas and the frame's color scheme for a page that declares no scheme and paints no dark background. The dark theme gives the dark canvas, with the frame's dark variant, and system follows your system. Under light, dark and transparent the theme changes nothing on the stage. The specimens of Foundations never follow it. So a link without bg can look different in another theme, and bg=light or bg=dark fixes the canvas.

The field at the top of the sidebar filters the tests. Every word you type must occur, case-insensitive, in the test's full name with its suites, in its file path, in its component's name, in its tags or in the names of its file's groups. Different words may match different fields, so counter.test reset finds the Counter test that resets, by its file and its name. A search shows matches inside collapsed groups and suites too, and leaves out groups without a match. The search is not part of the link and is not stored.

A test's Vitest tags, its own and those of its describe blocks and file, show next to its name and in the inspector. A click on a tag in the inspector narrows the sidebar to the tests with that tag, and a second click shows every test again, as does the × next to the tag above the tree. The tag is part of the link, and ↑ ↓ follow it like the search. docs and no-docs do not show, because they only pick which tests become stories.

The arrow in front of a file or describe row collapses it, and a click on a group's row opens or closes the group. The browser keeps the collapsed rows in localStorage, per project, so several projects on localhost:6006 do not mix. Without storage, as in a private window that blocks it, collapsing still works until you reload. Opening a test expands the rows around it and opens its groups too.

Keyboard #

Key Where What it does
← → a test The previous or next frame. In Live, they leave Live and show the frame that was selected before, frame 0 for a test that opened in Live.
↑ ↓ a test The previous or next test the sidebar shows, so they follow the search and skip collapsed groups and suites. From a test hidden in a collapsed group or suite, they go to the nearest row the sidebar shows. From a test the search does not match, ↓ goes to the first match and ↑ to the last.
↑ ↓ an overview ↓ opens its first test, ↑ its last.
L a test Turns Live off or on, once the live preview is ready. A test opens in Live. The key works in either case, and not with Ctrl, Meta or Alt held.
/ anywhere Focuses the search and selects its text. In Foundations, it focuses the token filter instead when the page has one. Not with Ctrl, Meta or Alt held, which leaves the key to the browser.
[ ] anywhere Hides or shows the sidebar and the inspector, as the panel toggles do. Not with Ctrl or Meta held, except as part of AltGr, which some keyboard layouts need for a bracket.
Esc the search field Clears the search and leaves the field.
Enter ↓ the search field Opens the first match and leaves the field, so the arrow keys work again.
← → the sidebar's edge Narrows or widens the sidebar by 16 px. Tab reaches the edge after the sidebar's rows.

Shortcuts are off while you type in an input, a textarea, a select or an editable element, and until the manifest has loaded. They are also off while the sidebar's edge has focus. While the frame of a test in Live has focus, keys go to the component, as Live explains. In Foundations, only /, [ and ] work, and / focuses the token filter when the page has one.

Viewport size and background #

The toolbar above the stage sets the size of the replayed page in CSS pixels, and what the frame stands on. The presets are 100%, 768px and 375px. The W and H fields take any width and height.

Background

Frames have no card. A frame shows only what its page's CSS paints, on the stage's canvas. The swatches after the presets pick the canvas:

Neither React example paints its page, so their components stand right on the canvas. Both have dark tokens under prefers-color-scheme: dark, which the dark canvas turns on, as in this Disclosure test of the jsdom example. The shadcn/ui and Material UI examples paint their page with their design system's background, and the canvas takes it, so no band shows. Under dark, both paint their dark one, as in this Button test of the shadcn/ui example and this PlanCard test of the Material UI example.

Live #

Live mounts the selected test for real, in a frame of the live preview, in place of its recorded frame. When the live preview is ready, a test opens in Live. The component starts as the test's arrange phase set it up: everything before the test's first render runs, and nothing after it. So Live is a fresh start: it does not replay the test's interactions to reach a later frame. Writing stories explains which part of a test runs.

Turning it off and on

Try it on the Menu test of the browser-mode example: open Actions and pick Rename.

While it mounts

What is real

The inspector

While Live shows, a Live section takes the place of the frame section:

The component section shows the props the test rendered with. Once the live preview is ready, the keyboard hint at the bottom adds L live.

Size and focus

Moving around

When the toggle is hidden or greyed out

The viewer never waits for the live preview, so the recorded frames show while it starts. Once the preview is ready the test switches to Live. It does not if you stepped through frames meanwhile, or if the link has live=0 or frame.

Where it runs

The live preview is a second Vite dev server, on your project's own Vite and config. It loads the project and config of the manifest, or of --root. describe-me dev starts it on a free port on localhost and serves it through its own port, under /__describe-me/, so one address reaches the viewer and Live, also through a forwarded port in a container or a web IDE such as Codespaces or StackBlitz. It prints the address, such as http://localhost:6006/__describe-me/. The viewer learns the preview's state from /__live.json on its own dev server: starting, ready with the preview's base, __describe-me/, off, or error with the reason. On a static site built with --live, the page is a static build under __live/, and __live.json next to the viewer says ready with that base (Live in the static site).

The address holds the view, so you can copy it to share a frame at a size:

#test=a7f4d7422f6a&frame=1&w=375

That link opens the second frame of a Disclosure test in the jsdom example, 375 pixels wide.

Component overview #

A click on a file or describe row in the sidebar opens its overview. It shows the props of each component its tests render, which values the tests cover, and the last frame of every test as a thumbnail. Try the Button overview in the browser-mode example. Writing stories explains how coverage is counted. A long props table folds as in the inspector and stays unfolded for that component until you reload the page.

Issues and the version banner #

The header opens with the sygnet and the name of the project, the name of the nearest package.json at or above the Vitest root, else the root directory's name. The tab's title carries it too, as <project> · describe-me, so two viewers tell apart.

The issues chip in the header counts what this run could not document: setup problems, anonymous components, components without props docs, missing assets, fonts that nothing loads and remote stylesheet hosts. It opens a list with links to the tests, with setup warnings first, in a section of their own. When there is nothing to report, the chip is not there. Troubleshooting explains each entry.

The manifest names the describe-me release that wrote it. When its major.minor differs from the viewer's own, a banner under the header says so, for example:

Written by @describe-me/vitest 0.6.0. This viewer is describe-me 0.5.2, so frames may not show correctly. Install every describe-me package at the same version.

The versions in it are those of your packages. Data from 0.5.0 and older names no writer and never shows the banner. Upgrade describe-me and @describe-me/vitest together, run the tests again and reload (one version for all packages). How it works explains which versions read which data.

Hosting the static site #

describe-me build writes plain files: the viewer, its assets and __data/. Any static file server or host can serve them.

python3 -m http.server 8080 --directory describe-me-dist

Then open http://localhost:8080/. An open page checks the manifest every 60 seconds and repaints only when a new run has been deployed.

Build the docs in CI has a GitHub Actions workflow that runs the tests, builds the site and publishes it to GitHub Pages.

Live in the static site

describe-me build --live puts the live preview next to the viewer, as __live/ and __live.json. Live then works as it does under describe-me dev: