@describe-me/vitest 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -88
- package/dist/patch-testing-library-user-event.d.ts +3 -2
- package/dist/patch-testing-library-user-event.js +9 -3
- package/dist/record-action.d.ts +6 -2
- package/dist/record-action.js +6 -3
- package/dist/testing-library-wraps-in-act.d.ts +6 -0
- package/dist/testing-library-wraps-in-act.js +11 -0
- package/package.json +8 -5
package/README.md
CHANGED
|
@@ -1,106 +1,75 @@
|
|
|
1
1
|
# @describe-me/vitest
|
|
2
2
|
|
|
3
|
-
The Vitest
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
**Your tests are your stories.** The Vitest plugin, setup files and reporter of
|
|
4
|
+
describe-me: living component documentation generated from the Vitest tests
|
|
5
|
+
you already have.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**[Read the docs](https://grzehub.github.io/describe-me/)** · open the viewer
|
|
8
|
+
of the [browser-mode example](https://grzehub.github.io/describe-me/examples/react-browser/)
|
|
9
|
+
or the [jsdom example](https://grzehub.github.io/describe-me/examples/react-jsdom/)
|
|
10
|
+
· [Limitations](https://grzehub.github.io/describe-me/limitations.html)
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
describe-me captures the DOM after each step of a test and shows the result as
|
|
13
|
+
a browsable catalog. `describe` blocks become the sidebar, each `it` is a
|
|
14
|
+
story, and each step is a frame you can scrub through. Stories cannot rot,
|
|
15
|
+
because they are tests. If one drifts from the component, CI goes red.
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
Status: prototype. React 18 and 19, Vitest 4 and 5 in browser mode or jsdom,
|
|
18
|
+
static snapshots.
|
|
15
19
|
|
|
16
|
-
##
|
|
20
|
+
## Which package do I need
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
| Package | What it is | Install it |
|
|
23
|
+
| --------------------- | -------------------------------------------------- | ----------------------- |
|
|
24
|
+
| `describe-me` | the viewer and the `describe-me` CLI | yes |
|
|
25
|
+
| `@describe-me/vitest` | the Vitest plugin, setup files and reporter (this) | yes |
|
|
26
|
+
| `@describe-me/react` | `render` functions that record frames | yes |
|
|
27
|
+
| `@describe-me/core` | the recorder and the manifest types | no, the others bring it |
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
records a frame after every `Locator` action and keyboard-level `userEvent`.
|
|
24
|
-
- **DOM environments** such as jsdom (anything else): redirects
|
|
25
|
-
`@testing-library/react`, records a frame after every `fireEvent` and every
|
|
26
|
-
`@testing-library/user-event` call, turns on `test.css` so imported
|
|
27
|
-
stylesheets reach the snapshots, and sets `RTL_SKIP_AUTO_CLEANUP` so the
|
|
28
|
-
component is unmounted only after the closing frame. The setup file sets
|
|
29
|
-
React's `IS_REACT_ACT_ENVIRONMENT` where Testing Library would and turns it
|
|
30
|
-
off while the recorder waits, so act warnings match a run without
|
|
31
|
-
describe-me. It also works without user-event installed.
|
|
29
|
+
## Quick start
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
```sh
|
|
32
|
+
pnpm add -D describe-me @describe-me/vitest @describe-me/react
|
|
33
|
+
```
|
|
36
34
|
|
|
37
35
|
```ts
|
|
36
|
+
// vitest.config.ts
|
|
38
37
|
import { describeMe } from '@describe-me/vitest/plugin'
|
|
39
38
|
|
|
40
|
-
// browser mode
|
|
41
|
-
export default defineConfig({
|
|
42
|
-
plugins: [react(), describeMe()],
|
|
43
|
-
test: {
|
|
44
|
-
browser: { enabled: true, provider: playwright(), instances: [{ browser: 'chromium' }] },
|
|
45
|
-
},
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
// jsdom
|
|
49
39
|
export default defineConfig({
|
|
50
40
|
plugins: [react(), describeMe()],
|
|
51
|
-
test: { environment: 'jsdom' },
|
|
41
|
+
test: { environment: 'jsdom' }, // or your browser-mode settings
|
|
52
42
|
})
|
|
53
43
|
```
|
|
54
44
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
`describeMe(
|
|
74
|
-
`
|
|
75
|
-
|
|
76
|
-
[
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
```ts
|
|
87
|
-
import DescribeMeReporter from '@describe-me/vitest/reporter'
|
|
88
|
-
|
|
89
|
-
export default defineConfig({
|
|
90
|
-
test: {
|
|
91
|
-
// browser mode: '@describe-me/vitest/setup'
|
|
92
|
-
setupFiles: ['@describe-me/vitest/setup-dom'],
|
|
93
|
-
reporters: ['default', new DescribeMeReporter()],
|
|
94
|
-
// jsdom only: keep imported CSS and leave unmounting to describe-me
|
|
95
|
-
css: true,
|
|
96
|
-
env: { RTL_SKIP_AUTO_CLEANUP: 'true' },
|
|
97
|
-
},
|
|
98
|
-
})
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
`typescript` is an optional peer: without it the docs are still generated, only
|
|
102
|
-
the props tables are left out. `@testing-library/user-event` is an optional
|
|
103
|
-
peer too, needed only in DOM environments.
|
|
104
|
-
|
|
105
|
-
See the [root README](https://github.com/grzehub/describe-me#readme) for the
|
|
106
|
-
full picture.
|
|
45
|
+
Run your tests, then `describe-me dev` opens the viewer.
|
|
46
|
+
[Getting started](https://grzehub.github.io/describe-me/getting-started.html)
|
|
47
|
+
walks through both environments. Keep all describe-me packages on one version
|
|
48
|
+
([why](https://grzehub.github.io/describe-me/installation.html#lockstep)).
|
|
49
|
+
|
|
50
|
+
## This package
|
|
51
|
+
|
|
52
|
+
The plugin is the whole integration. It detects browser mode or a DOM
|
|
53
|
+
environment, registers the setup file and the reporter, and redirects your
|
|
54
|
+
test library's `render` to the recording one, so existing tests record frames
|
|
55
|
+
unchanged.
|
|
56
|
+
[What the plugin changes](https://grzehub.github.io/describe-me/configuration.html#plugin)
|
|
57
|
+
lists every change it makes to your config, and
|
|
58
|
+
[Options](https://grzehub.github.io/describe-me/configuration.html#options)
|
|
59
|
+
every option it takes.
|
|
60
|
+
|
|
61
|
+
| Entry point | What it holds |
|
|
62
|
+
| ------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `@describe-me/vitest/plugin` | [`describeMe()`](https://grzehub.github.io/describe-me/api.html#entry-vitest-plugin) |
|
|
64
|
+
| `@describe-me/vitest` | [`step()` and `recorder`](https://grzehub.github.io/describe-me/api.html#entry-vitest) |
|
|
65
|
+
| `@describe-me/vitest/setup` | [the browser-mode setup file](https://grzehub.github.io/describe-me/api.html#entry-vitest-setup) |
|
|
66
|
+
| `@describe-me/vitest/setup-dom` | [the jsdom setup file](https://grzehub.github.io/describe-me/api.html#entry-vitest-setup-dom) |
|
|
67
|
+
| `@describe-me/vitest/reporter` | [the reporter, to wire by hand](https://grzehub.github.io/describe-me/api.html#entry-vitest-reporter) |
|
|
68
|
+
|
|
69
|
+
`typescript` and `@testing-library/user-event` are optional peers. Without
|
|
70
|
+
TypeScript the docs have no props tables. user-event is needed only when your
|
|
71
|
+
jsdom tests use it.
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
MIT
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* It comes in two shapes, the direct API (`userEvent.click(el)`) and an
|
|
4
4
|
* instance from `userEvent.setup()`, and the first delegates to the second,
|
|
5
5
|
* so both are patched and `recordAction`'s depth guard keeps one gesture to
|
|
6
|
-
* one frame.
|
|
7
|
-
*
|
|
6
|
+
* one frame. Under @testing-library/react a frame is taken as soon as the
|
|
7
|
+
* call resolves, otherwise after one settle. When the optional peer is not
|
|
8
|
+
* installed, there is nothing to patch. Safe to call more than once.
|
|
8
9
|
*/
|
|
9
10
|
export declare function patchTestingLibraryUserEvent(): Promise<void>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { elementLabel } from '@describe-me/core';
|
|
2
2
|
import { describeArg } from './describe-arg.js';
|
|
3
3
|
import { recordAction } from './record-action.js';
|
|
4
|
+
import { testingLibraryWrapsInAct } from './testing-library-wraps-in-act.js';
|
|
4
5
|
/** Every interaction of user-event 14 that can change what the page shows. */
|
|
5
6
|
const METHODS = [
|
|
6
7
|
'click',
|
|
@@ -31,7 +32,11 @@ function patchMethods(target) {
|
|
|
31
32
|
if (typeof original !== 'function' || original[PATCHED]) {
|
|
32
33
|
continue;
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
// Testing Library's wrappers commit the DOM before the call resolves. A settle
|
|
36
|
+
// would only move React updates into a wait with the act flag off.
|
|
37
|
+
const wrapped = (...args) => recordAction(labelFor(method, args), async () => original.apply(target, args), {
|
|
38
|
+
settle: !testingLibraryWrapsInAct(),
|
|
39
|
+
});
|
|
35
40
|
wrapped[PATCHED] = true;
|
|
36
41
|
target[method] = wrapped;
|
|
37
42
|
}
|
|
@@ -41,8 +46,9 @@ function patchMethods(target) {
|
|
|
41
46
|
* It comes in two shapes, the direct API (`userEvent.click(el)`) and an
|
|
42
47
|
* instance from `userEvent.setup()`, and the first delegates to the second,
|
|
43
48
|
* so both are patched and `recordAction`'s depth guard keeps one gesture to
|
|
44
|
-
* one frame.
|
|
45
|
-
*
|
|
49
|
+
* one frame. Under @testing-library/react a frame is taken as soon as the
|
|
50
|
+
* call resolves, otherwise after one settle. When the optional peer is not
|
|
51
|
+
* installed, there is nothing to patch. Safe to call more than once.
|
|
46
52
|
*/
|
|
47
53
|
export async function patchTestingLibraryUserEvent() {
|
|
48
54
|
let userEvent;
|
package/dist/record-action.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { CaptureOptions } from '@describe-me/core';
|
|
2
|
+
/**
|
|
3
|
+
* Run one user interaction and record a frame for it, but only for the outermost call.
|
|
4
|
+
* `settle: false` takes the frame as soon as the interaction resolves, without a wait.
|
|
5
|
+
*/
|
|
6
|
+
export declare function recordAction<T>(label: string, run: () => Promise<T>, options?: Pick<CaptureOptions, 'settle'>): Promise<T>;
|
package/dist/record-action.js
CHANGED
|
@@ -7,8 +7,11 @@ import { recorder } from '@describe-me/core';
|
|
|
7
7
|
* test left running cannot swallow the next test's frame.
|
|
8
8
|
*/
|
|
9
9
|
const nesting = { generation: -1, depth: 0 };
|
|
10
|
-
/**
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Run one user interaction and record a frame for it, but only for the outermost call.
|
|
12
|
+
* `settle: false` takes the frame as soon as the interaction resolves, without a wait.
|
|
13
|
+
*/
|
|
14
|
+
export async function recordAction(label, run, options = {}) {
|
|
12
15
|
const generation = recorder.generation;
|
|
13
16
|
if (generation !== nesting.generation) {
|
|
14
17
|
nesting.generation = generation;
|
|
@@ -26,7 +29,7 @@ export async function recordAction(label, run) {
|
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
31
|
if (generation === nesting.generation && nesting.depth === 0) {
|
|
29
|
-
await recorder.capture('action', label, undefined, { generation });
|
|
32
|
+
await recorder.capture('action', label, undefined, { generation, settle: options.settle });
|
|
30
33
|
}
|
|
31
34
|
return result;
|
|
32
35
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether @testing-library/dom still runs user-event calls through the
|
|
3
|
+
* `asyncWrapper` that @testing-library/react installed, so the DOM is committed
|
|
4
|
+
* when a call resolves. False when @describe-me/react/testing-library never loaded.
|
|
5
|
+
*/
|
|
6
|
+
export declare function testingLibraryWrapsInAct(): boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// `publish-testing-library-act.ts` in @describe-me/react writes this key.
|
|
2
|
+
const ACT_CHECK = Symbol.for('describe-me.testing-library-act');
|
|
3
|
+
/**
|
|
4
|
+
* Whether @testing-library/dom still runs user-event calls through the
|
|
5
|
+
* `asyncWrapper` that @testing-library/react installed, so the DOM is committed
|
|
6
|
+
* when a call resolves. False when @describe-me/react/testing-library never loaded.
|
|
7
|
+
*/
|
|
8
|
+
export function testingLibraryWrapsInAct() {
|
|
9
|
+
const check = globalThis[ACT_CHECK];
|
|
10
|
+
return typeof check === 'function' && check() === true;
|
|
11
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@describe-me/vitest",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.5.4",
|
|
4
|
+
"description": "Living component documentation from your Vitest tests: the Vitest plugin, setup files and reporter of describe-me",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vitest",
|
|
7
|
+
"react",
|
|
7
8
|
"storybook",
|
|
9
|
+
"storybook alternative",
|
|
8
10
|
"component documentation",
|
|
9
|
-
"
|
|
11
|
+
"living documentation",
|
|
12
|
+
"jsdom",
|
|
10
13
|
"testing"
|
|
11
14
|
],
|
|
12
15
|
"license": "MIT",
|
|
@@ -60,13 +63,13 @@
|
|
|
60
63
|
"dependencies": {
|
|
61
64
|
"picomatch": "^4.0.3",
|
|
62
65
|
"std-env": "^4.0.0",
|
|
63
|
-
"@describe-me/core": "^0.5.
|
|
66
|
+
"@describe-me/core": "^0.5.4"
|
|
64
67
|
},
|
|
65
68
|
"peerDependencies": {
|
|
66
69
|
"vitest": "^4.0.0 || ^5.0.0",
|
|
67
70
|
"typescript": "^5.0.0 || ^6.0.0",
|
|
68
71
|
"@testing-library/user-event": "^14.0.0",
|
|
69
|
-
"describe-me": "^0.5.
|
|
72
|
+
"describe-me": "^0.5.4"
|
|
70
73
|
},
|
|
71
74
|
"peerDependenciesMeta": {
|
|
72
75
|
"typescript": {
|