@describe-me/vitest 0.5.1 → 0.5.3
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 +18 -10
- package/dist/act-neutral-wait.d.ts +7 -0
- package/dist/act-neutral-wait.js +30 -0
- package/dist/collect-component-docs-safely.js +7 -1
- package/dist/compile-include.d.ts +3 -0
- package/dist/compile-include.js +8 -0
- package/dist/default-reporters.d.ts +5 -0
- package/dist/default-reporters.js +35 -0
- package/dist/file-filter.d.ts +2 -1
- package/dist/file-filter.js +4 -3
- package/dist/patch-testing-library-user-event.d.ts +3 -2
- package/dist/patch-testing-library-user-event.js +9 -3
- package/dist/plugin.d.ts +2 -1
- package/dist/plugin.js +7 -4
- package/dist/read-runtime-options.js +1 -1
- package/dist/record-action.d.ts +6 -2
- package/dist/record-action.js +6 -3
- package/dist/register-recording-hooks.d.ts +2 -1
- package/dist/register-recording-hooks.js +2 -2
- package/dist/reporter.d.ts +3 -1
- package/dist/reporter.js +10 -4
- package/dist/runtime-options.d.ts +5 -2
- package/dist/setup-dom.js +4 -2
- package/dist/testing-library-wraps-in-act.d.ts +6 -0
- package/dist/testing-library-wraps-in-act.js +11 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ pnpm add -D @describe-me/vitest @describe-me/react describe-me
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
All describe-me packages must be on the same version
|
|
14
|
-
([
|
|
14
|
+
([One version for all packages](https://grzehub.github.io/describe-me/installation.html#lockstep)).
|
|
15
15
|
|
|
16
16
|
## Usage
|
|
17
17
|
|
|
@@ -26,13 +26,16 @@ plugin detects where the tests run:
|
|
|
26
26
|
`@testing-library/user-event` call, turns on `test.css` so imported
|
|
27
27
|
stylesheets reach the snapshots, and sets `RTL_SKIP_AUTO_CLEANUP` so the
|
|
28
28
|
component is unmounted only after the closing frame. The setup file sets
|
|
29
|
-
React's `IS_REACT_ACT_ENVIRONMENT` where Testing Library would
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
React's `IS_REACT_ACT_ENVIRONMENT` where Testing Library would. With
|
|
30
|
+
`@testing-library/react`, it takes user-event frames without a wait. The
|
|
31
|
+
flag is off for the few waits that remain, which can still move an act
|
|
32
|
+
warning
|
|
33
|
+
([jsdom](https://grzehub.github.io/describe-me/environments.html#jsdom)). It
|
|
34
|
+
also works without user-event installed.
|
|
32
35
|
|
|
33
36
|
jsdom has no layout, so positioned popovers show in the top-left corner and
|
|
34
37
|
canvas stays blank
|
|
35
|
-
([Limitations in jsdom](https://github.
|
|
38
|
+
([Limitations in jsdom](https://grzehub.github.io/describe-me/environments.html#jsdom-limits)).
|
|
36
39
|
|
|
37
40
|
```ts
|
|
38
41
|
import { describeMe } from '@describe-me/vitest/plugin'
|
|
@@ -58,7 +61,9 @@ A test that records no frame before the closing one (no recording `render`,
|
|
|
58
61
|
no interaction, no `step()`) costs no snapshot and is left out of the
|
|
59
62
|
manifest. `describeMe({ include, exclude })` chooses which test files are
|
|
60
63
|
recorded, with picomatch globs relative to the Vitest root. `exclude` wins.
|
|
61
|
-
Tests in other files still run, but record nothing.
|
|
64
|
+
Tests in other files still run, but record nothing. Leaving `include` out
|
|
65
|
+
records every test file. `include: []` records none and warns, while
|
|
66
|
+
`exclude: '**'` records none without a warning. The reporter takes the
|
|
62
67
|
same two options, but on its own it only filters the manifest: without the
|
|
63
68
|
plugin the setup file does not know them.
|
|
64
69
|
|
|
@@ -66,12 +71,16 @@ plugin the setup file does not know them.
|
|
|
66
71
|
every frame's `<head>`, like Storybook's `preview-head.html`: typically the
|
|
67
72
|
font links that the app shell loads and tests never do. It never reaches the
|
|
68
73
|
test page, and the local files it links are copied into the output directory
|
|
69
|
-
([Fonts](https://github.
|
|
74
|
+
([Fonts](https://grzehub.github.io/describe-me/styles-and-fonts.html#fonts) in the docs).
|
|
70
75
|
|
|
71
76
|
`describeMe({ renderFrame })` chooses when the render frame is taken:
|
|
72
77
|
`'eager'` (default) right after mount, `'lazy'` right before the next
|
|
73
78
|
interaction, or `{ pending: '<selector>' }` once a loader is gone. See
|
|
74
|
-
[Render frame timing](https://github.
|
|
79
|
+
[Render frame timing](https://grzehub.github.io/describe-me/configuration.html#render-frame).
|
|
80
|
+
|
|
81
|
+
The plugin adds its reporter to the ones your config names. If it names
|
|
82
|
+
none, the reporter joins the ones Vitest picks on its own, such as `minimal`
|
|
83
|
+
for AI agents and `github-actions` in GitHub Actions.
|
|
75
84
|
|
|
76
85
|
The pieces can also be wired by hand. Tests then import from the adapter
|
|
77
86
|
themselves: `render` from `@describe-me/react` in browser mode, and `render`,
|
|
@@ -96,5 +105,4 @@ export default defineConfig({
|
|
|
96
105
|
the props tables are left out. `@testing-library/user-event` is an optional
|
|
97
106
|
peer too, needed only in DOM environments.
|
|
98
107
|
|
|
99
|
-
See the [
|
|
100
|
-
full picture.
|
|
108
|
+
See the [docs](https://grzehub.github.io/describe-me/) for the full picture.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run a recorder wait with React's `IS_REACT_ACT_ENVIRONMENT` flag off, as
|
|
3
|
+
* Testing Library's `asyncWrapper` does for `waitFor` and user-event. Otherwise
|
|
4
|
+
* an update that lands in the wait logs an act warning that a run without
|
|
5
|
+
* describe-me never shows.
|
|
6
|
+
*/
|
|
7
|
+
export declare function actNeutralWait(wait: () => Promise<void>): Promise<void>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Waits can overlap, for example an un-awaited interaction or `flush()` with
|
|
3
|
+
* captures in flight. The flag from before the first one comes back when the
|
|
4
|
+
* last one ends.
|
|
5
|
+
*/
|
|
6
|
+
let depth = 0;
|
|
7
|
+
let previous;
|
|
8
|
+
/**
|
|
9
|
+
* Run a recorder wait with React's `IS_REACT_ACT_ENVIRONMENT` flag off, as
|
|
10
|
+
* Testing Library's `asyncWrapper` does for `waitFor` and user-event. Otherwise
|
|
11
|
+
* an update that lands in the wait logs an act warning that a run without
|
|
12
|
+
* describe-me never shows.
|
|
13
|
+
*/
|
|
14
|
+
export async function actNeutralWait(wait) {
|
|
15
|
+
const host = globalThis;
|
|
16
|
+
if (depth === 0) {
|
|
17
|
+
previous = host.IS_REACT_ACT_ENVIRONMENT;
|
|
18
|
+
host.IS_REACT_ACT_ENVIRONMENT = false;
|
|
19
|
+
}
|
|
20
|
+
depth++;
|
|
21
|
+
try {
|
|
22
|
+
await wait();
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
depth--;
|
|
26
|
+
if (depth === 0) {
|
|
27
|
+
host.IS_REACT_ACT_ENVIRONMENT = previous;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -13,6 +13,12 @@ function warnAboutMissingTypeScript() {
|
|
|
13
13
|
* props tables instead of a crashing reporter.
|
|
14
14
|
*/
|
|
15
15
|
export async function collectComponentDocsSafely(root, entries) {
|
|
16
|
+
const rendered = Array.from(entries);
|
|
17
|
+
// Importing TypeScript takes a few hundred milliseconds, wasted on a run
|
|
18
|
+
// that recorded no component.
|
|
19
|
+
if (rendered.length === 0) {
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
16
22
|
try {
|
|
17
23
|
await import('typescript');
|
|
18
24
|
}
|
|
@@ -21,5 +27,5 @@ export async function collectComponentDocsSafely(root, entries) {
|
|
|
21
27
|
return {};
|
|
22
28
|
}
|
|
23
29
|
const { collectComponentDocs } = await import('./collect-component-docs.js');
|
|
24
|
-
return collectComponentDocs(root,
|
|
30
|
+
return collectComponentDocs(root, rendered);
|
|
25
31
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { compileGlobs } from './compile-globs.js';
|
|
2
|
+
/** Keeps an omitted `include` (`null`, every test file) apart from an empty list (no test file). */
|
|
3
|
+
export function compileInclude(patterns) {
|
|
4
|
+
if (patterns === undefined) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
return compileGlobs(patterns);
|
|
8
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { isAgent } from 'std-env';
|
|
4
|
+
import { configDefaults } from 'vitest/config';
|
|
5
|
+
/**
|
|
6
|
+
* Vitest 4.0 has no `agent` reporter and loads the name as a reporter module,
|
|
7
|
+
* which fails the run. An unreadable version counts as 4.0.
|
|
8
|
+
*/
|
|
9
|
+
function hasAgentReporter() {
|
|
10
|
+
try {
|
|
11
|
+
const manifest = createRequire(import.meta.url).resolve('vitest/package.json');
|
|
12
|
+
const { version } = JSON.parse(readFileSync(manifest, 'utf8'));
|
|
13
|
+
const [major, minor] = version.split('.').map(Number);
|
|
14
|
+
return major > 4 || (major === 4 && minor >= 1);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The reporters the installed Vitest uses when the config names none, such as
|
|
22
|
+
* `minimal` for AI agents and `github-actions` in GitHub Actions.
|
|
23
|
+
*/
|
|
24
|
+
export function defaultReporters() {
|
|
25
|
+
// Vitest 5 exports the list. Vitest 4 exports none and fills it while
|
|
26
|
+
// resolving the config, only when it is still empty, so its rule is rebuilt here.
|
|
27
|
+
if (configDefaults.reporters.length > 0) {
|
|
28
|
+
return [...configDefaults.reporters];
|
|
29
|
+
}
|
|
30
|
+
const reporters = [isAgent && hasAgentReporter() ? 'agent' : 'default'];
|
|
31
|
+
if (process.env.GITHUB_ACTIONS === 'true') {
|
|
32
|
+
reporters.push('github-actions');
|
|
33
|
+
}
|
|
34
|
+
return reporters;
|
|
35
|
+
}
|
package/dist/file-filter.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { RuntimeOptions } from './runtime-options.js';
|
|
2
2
|
/**
|
|
3
|
-
* Takes a path relative to the root, with posix separators.
|
|
3
|
+
* Takes a path relative to the root, with posix separators. An `include` of
|
|
4
|
+
* `null` selects every file, an empty list selects none. Build it once and
|
|
4
5
|
* reuse the returned function, which memoizes per file name. The test runtime
|
|
5
6
|
* imports this file, so no Node imports.
|
|
6
7
|
*/
|
package/dist/file-filter.js
CHANGED
|
@@ -2,12 +2,13 @@ function toRegExps(globs) {
|
|
|
2
2
|
return globs.map((glob) => new RegExp(glob.source, glob.flags));
|
|
3
3
|
}
|
|
4
4
|
/**
|
|
5
|
-
* Takes a path relative to the root, with posix separators.
|
|
5
|
+
* Takes a path relative to the root, with posix separators. An `include` of
|
|
6
|
+
* `null` selects every file, an empty list selects none. Build it once and
|
|
6
7
|
* reuse the returned function, which memoizes per file name. The test runtime
|
|
7
8
|
* imports this file, so no Node imports.
|
|
8
9
|
*/
|
|
9
10
|
export function fileFilter(options) {
|
|
10
|
-
const include = toRegExps(options.include);
|
|
11
|
+
const include = options.include === null ? null : toRegExps(options.include);
|
|
11
12
|
const exclude = toRegExps(options.exclude);
|
|
12
13
|
const answers = new Map();
|
|
13
14
|
return (fileName) => {
|
|
@@ -15,7 +16,7 @@ export function fileFilter(options) {
|
|
|
15
16
|
if (known !== undefined) {
|
|
16
17
|
return known;
|
|
17
18
|
}
|
|
18
|
-
const included = include
|
|
19
|
+
const included = include === null || include.some((glob) => glob.test(fileName));
|
|
19
20
|
const answer = included && !exclude.some((glob) => glob.test(fileName));
|
|
20
21
|
answers.set(fileName, answer);
|
|
21
22
|
return answer;
|
|
@@ -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/plugin.d.ts
CHANGED
|
@@ -33,7 +33,8 @@ export interface DescribeMeOptions {
|
|
|
33
33
|
/**
|
|
34
34
|
* Test files to record, as globs relative to the Vitest root, matched with
|
|
35
35
|
* picomatch, dotfiles included. Tests in other files still run, but record
|
|
36
|
-
* nothing and leave the manifest.
|
|
36
|
+
* nothing and leave the manifest. An empty list records no test file and
|
|
37
|
+
* warns. Default: every test file.
|
|
37
38
|
*/
|
|
38
39
|
include?: string | string[];
|
|
39
40
|
/** Test files never to record, as globs like `include`. Wins over `include`. Default: none. */
|
package/dist/plugin.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { adapterPackageRoot } from './adapter-package-root.js';
|
|
2
2
|
import { compileGlobs } from './compile-globs.js';
|
|
3
|
+
import { compileInclude } from './compile-include.js';
|
|
4
|
+
import { defaultReporters } from './default-reporters.js';
|
|
3
5
|
import { projectModulePath } from './project-module-path.js';
|
|
4
6
|
import { registerExports } from './register-exports.js';
|
|
5
7
|
import DescribeMeReporter from './reporter.js';
|
|
@@ -110,7 +112,7 @@ export function describeMe(options = {}) {
|
|
|
110
112
|
// Checked here, so invalid options fail before any test runs. Vite
|
|
111
113
|
// deep-merges `provide`, so the user's own keys survive.
|
|
112
114
|
const runtimeOptions = {
|
|
113
|
-
include:
|
|
115
|
+
include: compileInclude(options.include),
|
|
114
116
|
exclude: compileGlobs(options.exclude),
|
|
115
117
|
renderFrame: validateRenderFrame(options.renderFrame),
|
|
116
118
|
};
|
|
@@ -124,9 +126,10 @@ export function describeMe(options = {}) {
|
|
|
124
126
|
previewHead: options.previewHead,
|
|
125
127
|
setupWarnings,
|
|
126
128
|
});
|
|
127
|
-
// Vite concatenates
|
|
128
|
-
//
|
|
129
|
-
|
|
129
|
+
// Vite concatenates our list with the user's. Any list replaces the
|
|
130
|
+
// reporters Vitest picks on its own, so without one of the user's, ours
|
|
131
|
+
// joins Vitest's defaults.
|
|
132
|
+
const reporters = userConfig.test?.reporters ? [reporter] : [...defaultReporters(), reporter];
|
|
130
133
|
const config = environment === 'browser'
|
|
131
134
|
? browserConfig(renderModule)
|
|
132
135
|
: domConfig(userConfig, styledComponents);
|
|
@@ -3,7 +3,7 @@ import { RUNTIME_OPTIONS_KEY } from './runtime-options.js';
|
|
|
3
3
|
/** Without the plugin nothing is provided, so a hand-wired setup keeps recording every test. */
|
|
4
4
|
export function readRuntimeOptions() {
|
|
5
5
|
return (inject(RUNTIME_OPTIONS_KEY) ?? {
|
|
6
|
-
include:
|
|
6
|
+
include: null,
|
|
7
7
|
exclude: [],
|
|
8
8
|
renderFrame: 'eager',
|
|
9
9
|
});
|
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
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AroundWait } from '@describe-me/core';
|
|
1
2
|
import type { RuntimeOptions } from './runtime-options.js';
|
|
2
3
|
/**
|
|
3
4
|
* The per-test lifecycle shared by every environment: begin a recording, take
|
|
@@ -7,4 +8,4 @@ import type { RuntimeOptions } from './runtime-options.js';
|
|
|
7
8
|
* jsdom. Concurrent tests would share the one recorder, so they are not
|
|
8
9
|
* recorded.
|
|
9
10
|
*/
|
|
10
|
-
export declare function registerRecordingHooks(options: RuntimeOptions): void;
|
|
11
|
+
export declare function registerRecordingHooks(options: RuntimeOptions, aroundWait?: AroundWait): void;
|
|
@@ -9,10 +9,10 @@ import { fileFilter } from './file-filter.js';
|
|
|
9
9
|
* jsdom. Concurrent tests would share the one recorder, so they are not
|
|
10
10
|
* recorded.
|
|
11
11
|
*/
|
|
12
|
-
export function registerRecordingHooks(options) {
|
|
12
|
+
export function registerRecordingHooks(options, aroundWait) {
|
|
13
13
|
const isRecordedFile = fileFilter(options);
|
|
14
14
|
let warnedConcurrent = false;
|
|
15
|
-
recorder.configure({ renderFrame: options.renderFrame });
|
|
15
|
+
recorder.configure({ renderFrame: options.renderFrame, aroundWait });
|
|
16
16
|
beforeEach((context) => {
|
|
17
17
|
if (context.task.concurrent) {
|
|
18
18
|
if (!warnedConcurrent) {
|
package/dist/reporter.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ export interface DescribeMeReporterOptions {
|
|
|
4
4
|
outDir?: string;
|
|
5
5
|
/**
|
|
6
6
|
* Which test files appear in the manifest: globs relative to the Vitest
|
|
7
|
-
* root, matched with picomatch, dotfiles included.
|
|
7
|
+
* root, matched with picomatch, dotfiles included. An empty list leaves every
|
|
8
|
+
* file out of the manifest and warns. Default: every test file.
|
|
8
9
|
*/
|
|
9
10
|
include?: string | string[];
|
|
10
11
|
/**
|
|
@@ -24,6 +25,7 @@ export interface DescribeMeReporterOptions {
|
|
|
24
25
|
export default class DescribeMeReporter implements Reporter {
|
|
25
26
|
private readonly outDirOption;
|
|
26
27
|
private readonly isRecordedFile;
|
|
28
|
+
private readonly emptyInclude;
|
|
27
29
|
private readonly previewHead;
|
|
28
30
|
private readonly generator;
|
|
29
31
|
private readonly setupWarnings;
|
package/dist/reporter.js
CHANGED
|
@@ -8,6 +8,7 @@ import { META_KEY, } from '@describe-me/core/types';
|
|
|
8
8
|
import { AssetStore } from './asset-store.js';
|
|
9
9
|
import { collectComponentDocsSafely } from './collect-component-docs-safely.js';
|
|
10
10
|
import { compileGlobs } from './compile-globs.js';
|
|
11
|
+
import { compileInclude } from './compile-include.js';
|
|
11
12
|
import { componentEntries } from './component-entries.js';
|
|
12
13
|
import { fileFilter } from './file-filter.js';
|
|
13
14
|
import { FontAudit } from './font-audit.js';
|
|
@@ -27,6 +28,7 @@ function recordOf(tc) {
|
|
|
27
28
|
export default class DescribeMeReporter {
|
|
28
29
|
outDirOption;
|
|
29
30
|
isRecordedFile;
|
|
31
|
+
emptyInclude;
|
|
30
32
|
previewHead;
|
|
31
33
|
generator;
|
|
32
34
|
setupWarnings;
|
|
@@ -39,10 +41,9 @@ export default class DescribeMeReporter {
|
|
|
39
41
|
modules = new Map();
|
|
40
42
|
constructor(options = {}) {
|
|
41
43
|
this.outDirOption = options.outDir ?? '.describe-me';
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
});
|
|
44
|
+
const include = compileInclude(options.include);
|
|
45
|
+
this.isRecordedFile = fileFilter({ include, exclude: compileGlobs(options.exclude) });
|
|
46
|
+
this.emptyInclude = include !== null && include.length === 0;
|
|
46
47
|
// A blank head, such as an empty preview-head.html, is the same as none.
|
|
47
48
|
this.previewHead = options.previewHead?.trim() ? options.previewHead : undefined;
|
|
48
49
|
this.generator = readGenerator();
|
|
@@ -59,6 +60,11 @@ export default class DescribeMeReporter {
|
|
|
59
60
|
if (this.previewHead !== undefined && /<script\b/i.test(this.previewHead)) {
|
|
60
61
|
console.warn('describe-me: previewHead contains a <script>, which the viewer never runs.');
|
|
61
62
|
}
|
|
63
|
+
// Here and not in the constructor: the plugin builds the reporter in
|
|
64
|
+
// `config()`, which also runs for a `vite build` that shares the config.
|
|
65
|
+
if (this.emptyInclude) {
|
|
66
|
+
console.warn("describe-me: include is an empty list, so no test file is recorded. Leave include out to record every test file, or set exclude: '**' to record none without this warning.");
|
|
67
|
+
}
|
|
62
68
|
}
|
|
63
69
|
onTestRunStart() {
|
|
64
70
|
this.assets.startRun();
|
|
@@ -10,8 +10,11 @@ export interface CompiledGlob {
|
|
|
10
10
|
flags: string;
|
|
11
11
|
}
|
|
12
12
|
export interface RuntimeOptions {
|
|
13
|
-
/**
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* `null` means every test file, an empty list means none. `null` survives
|
|
15
|
+
* `provide` / `inject` and Vite's config merge, `undefined` would not.
|
|
16
|
+
*/
|
|
17
|
+
include: CompiledGlob[] | null;
|
|
15
18
|
/** Wins over `include`. */
|
|
16
19
|
exclude: CompiledGlob[];
|
|
17
20
|
renderFrame: RenderFrameMode;
|
package/dist/setup-dom.js
CHANGED
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
* `setupFiles: ['@describe-me/vitest/setup-dom']`. Patches Testing Library's
|
|
4
4
|
* userEvent, when it is installed, so every interaction records a frame, sets
|
|
5
5
|
* React's act flag where Testing Library would, and registers the recording
|
|
6
|
-
* hooks.
|
|
6
|
+
* hooks. The act flag is off while the recorder waits, as in Testing Library's
|
|
7
|
+
* own waits. Which test files are recorded (`include` / `exclude`) and when the
|
|
7
8
|
* render frame is taken (`renderFrame`) come from the plugin. Never imports
|
|
8
9
|
* `vitest/browser`, which only exists in browser mode.
|
|
9
10
|
*/
|
|
11
|
+
import { actNeutralWait } from './act-neutral-wait.js';
|
|
10
12
|
import { mirrorReactActEnvironment } from './mirror-react-act-environment.js';
|
|
11
13
|
import { patchTestingLibraryUserEvent } from './patch-testing-library-user-event.js';
|
|
12
14
|
import { readRuntimeOptions } from './read-runtime-options.js';
|
|
13
15
|
import { registerRecordingHooks } from './register-recording-hooks.js';
|
|
14
16
|
await patchTestingLibraryUserEvent();
|
|
15
17
|
mirrorReactActEnvironment();
|
|
16
|
-
registerRecordingHooks(readRuntimeOptions());
|
|
18
|
+
registerRecordingHooks(readRuntimeOptions(), actNeutralWait);
|
|
@@ -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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@describe-me/vitest",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Vitest integration for describe-me: plugin, setup file and reporter",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vitest",
|
|
@@ -59,13 +59,14 @@
|
|
|
59
59
|
],
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"picomatch": "^4.0.3",
|
|
62
|
-
"
|
|
62
|
+
"std-env": "^4.0.0",
|
|
63
|
+
"@describe-me/core": "^0.5.3"
|
|
63
64
|
},
|
|
64
65
|
"peerDependencies": {
|
|
65
66
|
"vitest": "^4.0.0 || ^5.0.0",
|
|
66
67
|
"typescript": "^5.0.0 || ^6.0.0",
|
|
67
68
|
"@testing-library/user-event": "^14.0.0",
|
|
68
|
-
"describe-me": "^0.5.
|
|
69
|
+
"describe-me": "^0.5.3"
|
|
69
70
|
},
|
|
70
71
|
"peerDependenciesMeta": {
|
|
71
72
|
"typescript": {
|