@storybook/addon-vitest 0.0.0-pr-32795-sha-81cf1f23 → 0.0.0-pr-32717-sha-f340a68b
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/dist/_browser-chunks/chunk-JK72E6FR.js +6 -0
- package/dist/_browser-chunks/chunk-RPDOPHZX.js +77 -0
- package/dist/_node-chunks/chunk-724JPUHM.js +40 -0
- package/dist/_node-chunks/{chunk-KCHXXKAS.js → chunk-7ZCNTQXP.js} +24 -15
- package/dist/_node-chunks/chunk-A4VFZRVB.js +502 -0
- package/dist/_node-chunks/chunk-G6ASZ6US.js +69 -0
- package/dist/_node-chunks/{chunk-ML5LEYEM.js → chunk-K5BRNZW2.js} +19 -14
- package/dist/_node-chunks/chunk-KHNVQCL7.js +92 -0
- package/dist/_node-chunks/chunk-MLM43G3E.js +260 -0
- package/dist/_node-chunks/chunk-NGOGIT42.js +60 -0
- package/dist/_node-chunks/chunk-TXTKPPIA.js +247 -0
- package/dist/index.js +5 -1
- package/dist/manager.js +354 -163
- package/dist/node/coverage-reporter.js +864 -319
- package/dist/node/vitest.js +466 -190
- package/dist/postinstall.js +1276 -633
- package/dist/preset.js +354 -160
- package/dist/vitest-plugin/global-setup.js +105 -51
- package/dist/vitest-plugin/index.js +2381 -1161
- package/dist/vitest-plugin/setup-file.js +12 -6
- package/dist/vitest-plugin/test-utils.js +71 -31
- package/package.json +3 -7
- package/dist/_browser-chunks/chunk-ULSHVN74.js +0 -60
- package/dist/_node-chunks/chunk-43MIUCD6.js +0 -138
- package/dist/_node-chunks/chunk-NCYNCIBX.js +0 -1697
- package/dist/_node-chunks/chunk-NSF3UF7J.js +0 -339
- package/dist/_node-chunks/chunk-PYDFQUST.js +0 -35
- package/dist/_node-chunks/chunk-XTWQR354.js +0 -69
- package/dist/_node-chunks/chunk-ZI6UZG2P.js +0 -83
package/dist/node/vitest.js
CHANGED
|
@@ -1,36 +1,37 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import CJS_COMPAT_NODE_URL_xvr6gehai1p from 'node:url';
|
|
2
|
+
import CJS_COMPAT_NODE_PATH_xvr6gehai1p from 'node:path';
|
|
3
|
+
import CJS_COMPAT_NODE_MODULE_xvr6gehai1p from "node:module";
|
|
4
4
|
|
|
5
|
-
var __filename =
|
|
6
|
-
var __dirname =
|
|
7
|
-
var require =
|
|
5
|
+
var __filename = CJS_COMPAT_NODE_URL_xvr6gehai1p.fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = CJS_COMPAT_NODE_PATH_xvr6gehai1p.dirname(__filename);
|
|
7
|
+
var require = CJS_COMPAT_NODE_MODULE_xvr6gehai1p.createRequire(import.meta.url);
|
|
8
8
|
|
|
9
9
|
// ------------------------------------------------------------
|
|
10
10
|
// end of CJS compatibility banner, injected by Storybook's esbuild configuration
|
|
11
11
|
// ------------------------------------------------------------
|
|
12
12
|
import {
|
|
13
13
|
log
|
|
14
|
-
} from "../_node-chunks/chunk-
|
|
14
|
+
} from "../_node-chunks/chunk-724JPUHM.js";
|
|
15
15
|
import {
|
|
16
|
-
any
|
|
17
|
-
|
|
18
|
-
} from "../_node-chunks/chunk-XTWQR354.js";
|
|
16
|
+
any
|
|
17
|
+
} from "../_node-chunks/chunk-NGOGIT42.js";
|
|
19
18
|
import {
|
|
20
19
|
ADDON_ID,
|
|
21
20
|
COVERAGE_DIRECTORY,
|
|
22
21
|
STATUS_TYPE_ID_A11Y,
|
|
23
22
|
STATUS_TYPE_ID_COMPONENT_TEST,
|
|
24
23
|
storeOptions
|
|
25
|
-
} from "../_node-chunks/chunk-
|
|
26
|
-
import "../_node-chunks/chunk-
|
|
24
|
+
} from "../_node-chunks/chunk-KHNVQCL7.js";
|
|
25
|
+
import "../_node-chunks/chunk-7ZCNTQXP.js";
|
|
27
26
|
import {
|
|
28
27
|
dirname,
|
|
29
28
|
join,
|
|
30
29
|
normalize,
|
|
31
30
|
path
|
|
32
|
-
} from "../_node-chunks/chunk-
|
|
33
|
-
import
|
|
31
|
+
} from "../_node-chunks/chunk-TXTKPPIA.js";
|
|
32
|
+
import {
|
|
33
|
+
__name
|
|
34
|
+
} from "../_node-chunks/chunk-K5BRNZW2.js";
|
|
34
35
|
|
|
35
36
|
// src/node/vitest.ts
|
|
36
37
|
import process2 from "node:process";
|
|
@@ -43,41 +44,85 @@ import {
|
|
|
43
44
|
|
|
44
45
|
// ../../node_modules/es-toolkit/dist/function/debounce.mjs
|
|
45
46
|
function debounce(func, debounceMs, { signal, edges } = {}) {
|
|
46
|
-
let pendingThis
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
let pendingThis = void 0;
|
|
48
|
+
let pendingArgs = null;
|
|
49
|
+
const leading = edges != null && edges.includes("leading");
|
|
50
|
+
const trailing = edges == null || edges.includes("trailing");
|
|
51
|
+
const invoke = /* @__PURE__ */ __name(() => {
|
|
52
|
+
if (pendingArgs !== null) {
|
|
53
|
+
func.apply(pendingThis, pendingArgs);
|
|
54
|
+
pendingThis = void 0;
|
|
55
|
+
pendingArgs = null;
|
|
56
|
+
}
|
|
57
|
+
}, "invoke");
|
|
58
|
+
const onTimerEnd = /* @__PURE__ */ __name(() => {
|
|
59
|
+
if (trailing) {
|
|
60
|
+
invoke();
|
|
61
|
+
}
|
|
62
|
+
cancel();
|
|
63
|
+
}, "onTimerEnd");
|
|
64
|
+
let timeoutId = null;
|
|
65
|
+
const schedule = /* @__PURE__ */ __name(() => {
|
|
66
|
+
if (timeoutId != null) {
|
|
67
|
+
clearTimeout(timeoutId);
|
|
68
|
+
}
|
|
69
|
+
timeoutId = setTimeout(() => {
|
|
70
|
+
timeoutId = null;
|
|
71
|
+
onTimerEnd();
|
|
53
72
|
}, debounceMs);
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
73
|
+
}, "schedule");
|
|
74
|
+
const cancelTimer = /* @__PURE__ */ __name(() => {
|
|
75
|
+
if (timeoutId !== null) {
|
|
76
|
+
clearTimeout(timeoutId);
|
|
77
|
+
timeoutId = null;
|
|
78
|
+
}
|
|
79
|
+
}, "cancelTimer");
|
|
80
|
+
const cancel = /* @__PURE__ */ __name(() => {
|
|
81
|
+
cancelTimer();
|
|
82
|
+
pendingThis = void 0;
|
|
83
|
+
pendingArgs = null;
|
|
84
|
+
}, "cancel");
|
|
85
|
+
const flush = /* @__PURE__ */ __name(() => {
|
|
59
86
|
invoke();
|
|
60
|
-
},
|
|
61
|
-
|
|
87
|
+
}, "flush");
|
|
88
|
+
const debounced = /* @__PURE__ */ __name(function(...args) {
|
|
89
|
+
if (signal?.aborted) {
|
|
62
90
|
return;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
91
|
+
}
|
|
92
|
+
pendingThis = this;
|
|
93
|
+
pendingArgs = args;
|
|
94
|
+
const isFirstCall = timeoutId == null;
|
|
95
|
+
schedule();
|
|
96
|
+
if (leading && isFirstCall) {
|
|
97
|
+
invoke();
|
|
98
|
+
}
|
|
99
|
+
}, "debounced");
|
|
100
|
+
debounced.schedule = schedule;
|
|
101
|
+
debounced.cancel = cancel;
|
|
102
|
+
debounced.flush = flush;
|
|
103
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
104
|
+
return debounced;
|
|
68
105
|
}
|
|
106
|
+
__name(debounce, "debounce");
|
|
69
107
|
|
|
70
108
|
// ../../node_modules/es-toolkit/dist/function/partial.mjs
|
|
71
109
|
function partial(func, ...partialArgs) {
|
|
72
110
|
return partialImpl(func, placeholderSymbol, ...partialArgs);
|
|
73
111
|
}
|
|
112
|
+
__name(partial, "partial");
|
|
74
113
|
function partialImpl(func, placeholder, ...partialArgs) {
|
|
75
|
-
|
|
76
|
-
let providedArgsIndex = 0
|
|
114
|
+
const partialed = /* @__PURE__ */ __name(function(...providedArgs) {
|
|
115
|
+
let providedArgsIndex = 0;
|
|
116
|
+
const substitutedArgs = partialArgs.slice().map((arg) => arg === placeholder ? providedArgs[providedArgsIndex++] : arg);
|
|
117
|
+
const remainingArgs = providedArgs.slice(providedArgsIndex);
|
|
77
118
|
return func.apply(this, substitutedArgs.concat(remainingArgs));
|
|
78
|
-
};
|
|
79
|
-
|
|
119
|
+
}, "partialed");
|
|
120
|
+
if (func.prototype) {
|
|
121
|
+
partialed.prototype = Object.create(func.prototype);
|
|
122
|
+
}
|
|
123
|
+
return partialed;
|
|
80
124
|
}
|
|
125
|
+
__name(partialImpl, "partialImpl");
|
|
81
126
|
var placeholderSymbol = Symbol("partial.placeholder");
|
|
82
127
|
partial.placeholder = placeholderSymbol;
|
|
83
128
|
|
|
@@ -85,13 +130,22 @@ partial.placeholder = placeholderSymbol;
|
|
|
85
130
|
function partialRight(func, ...partialArgs) {
|
|
86
131
|
return partialRightImpl(func, placeholderSymbol2, ...partialArgs);
|
|
87
132
|
}
|
|
133
|
+
__name(partialRight, "partialRight");
|
|
88
134
|
function partialRightImpl(func, placeholder, ...partialArgs) {
|
|
89
|
-
|
|
90
|
-
|
|
135
|
+
const partialedRight = /* @__PURE__ */ __name(function(...providedArgs) {
|
|
136
|
+
const placeholderLength = partialArgs.filter((arg) => arg === placeholder).length;
|
|
137
|
+
const rangeLength = Math.max(providedArgs.length - placeholderLength, 0);
|
|
138
|
+
const remainingArgs = providedArgs.slice(0, rangeLength);
|
|
139
|
+
let providedArgsIndex = rangeLength;
|
|
140
|
+
const substitutedArgs = partialArgs.slice().map((arg) => arg === placeholder ? providedArgs[providedArgsIndex++] : arg);
|
|
91
141
|
return func.apply(this, remainingArgs.concat(substitutedArgs));
|
|
92
|
-
};
|
|
93
|
-
|
|
142
|
+
}, "partialedRight");
|
|
143
|
+
if (func.prototype) {
|
|
144
|
+
partialedRight.prototype = Object.create(func.prototype);
|
|
145
|
+
}
|
|
146
|
+
return partialedRight;
|
|
94
147
|
}
|
|
148
|
+
__name(partialRightImpl, "partialRightImpl");
|
|
95
149
|
var placeholderSymbol2 = Symbol("partialRight.placeholder");
|
|
96
150
|
partialRight.placeholder = placeholderSymbol2;
|
|
97
151
|
|
|
@@ -100,11 +154,36 @@ var DEFAULT_RETRIES = Number.POSITIVE_INFINITY;
|
|
|
100
154
|
|
|
101
155
|
// ../../node_modules/es-toolkit/dist/function/throttle.mjs
|
|
102
156
|
function throttle(func, throttleMs, { signal, edges = ["leading", "trailing"] } = {}) {
|
|
103
|
-
let pendingAt = null
|
|
104
|
-
|
|
157
|
+
let pendingAt = null;
|
|
158
|
+
const debounced = debounce(func, throttleMs, { signal, edges });
|
|
159
|
+
const throttled = /* @__PURE__ */ __name(function(...args) {
|
|
160
|
+
if (pendingAt == null) {
|
|
161
|
+
pendingAt = Date.now();
|
|
162
|
+
} else {
|
|
163
|
+
if (Date.now() - pendingAt >= throttleMs) {
|
|
164
|
+
pendingAt = Date.now();
|
|
165
|
+
debounced.cancel();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
debounced.apply(this, args);
|
|
169
|
+
}, "throttled");
|
|
170
|
+
throttled.cancel = debounced.cancel;
|
|
171
|
+
throttled.flush = debounced.flush;
|
|
172
|
+
return throttled;
|
|
173
|
+
}
|
|
174
|
+
__name(throttle, "throttle");
|
|
175
|
+
|
|
176
|
+
// src/utils.ts
|
|
177
|
+
function errorToErrorLike(error) {
|
|
178
|
+
return {
|
|
179
|
+
message: error.message,
|
|
180
|
+
name: error.name,
|
|
181
|
+
// avoid duplicating the error message in the stack trace
|
|
182
|
+
stack: error.stack?.replace(error.message, ""),
|
|
183
|
+
cause: error.cause && error.cause instanceof Error ? errorToErrorLike(error.cause) : void 0
|
|
105
184
|
};
|
|
106
|
-
return throttled.cancel = debounced.cancel, throttled.flush = debounced.flush, throttled;
|
|
107
185
|
}
|
|
186
|
+
__name(errorToErrorLike, "errorToErrorLike");
|
|
108
187
|
|
|
109
188
|
// src/node/vitest-manager.ts
|
|
110
189
|
import { existsSync } from "node:fs";
|
|
@@ -112,19 +191,28 @@ import { getProjectRoot, resolvePathInStorybookCache } from "storybook/internal/
|
|
|
112
191
|
|
|
113
192
|
// ../../node_modules/slash/index.js
|
|
114
193
|
function slash(path2) {
|
|
115
|
-
|
|
194
|
+
const isExtendedLengthPath = path2.startsWith("\\\\?\\");
|
|
195
|
+
if (isExtendedLengthPath) {
|
|
196
|
+
return path2;
|
|
197
|
+
}
|
|
198
|
+
return path2.replace(/\\/g, "/");
|
|
116
199
|
}
|
|
200
|
+
__name(slash, "slash");
|
|
117
201
|
|
|
118
202
|
// src/node/reporter.ts
|
|
119
203
|
var StorybookReporter = class {
|
|
120
204
|
constructor(testManager) {
|
|
121
205
|
this.testManager = testManager;
|
|
122
206
|
}
|
|
207
|
+
static {
|
|
208
|
+
__name(this, "StorybookReporter");
|
|
209
|
+
}
|
|
123
210
|
onInit(ctx) {
|
|
124
211
|
this.ctx = ctx;
|
|
125
212
|
}
|
|
126
213
|
onTestCaseResult(testCase) {
|
|
127
|
-
|
|
214
|
+
const { storyId, reports } = testCase.meta();
|
|
215
|
+
const testResult = testCase.result();
|
|
128
216
|
this.testManager.onTestCaseResult({
|
|
129
217
|
storyId,
|
|
130
218
|
testResult,
|
|
@@ -132,30 +220,42 @@ var StorybookReporter = class {
|
|
|
132
220
|
});
|
|
133
221
|
}
|
|
134
222
|
async onTestRunEnd(testModules, unhandledErrors) {
|
|
135
|
-
|
|
223
|
+
const totalTestCount = testModules.flatMap(
|
|
136
224
|
(t) => Array.from(t.children.allTests("passed")).concat(Array.from(t.children.allTests("failed")))
|
|
137
|
-
).length
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
225
|
+
).length;
|
|
226
|
+
const testModulesErrors = testModules.flatMap((t) => t.errors());
|
|
227
|
+
const serializedErrors = unhandledErrors.concat(testModulesErrors).map((e) => {
|
|
228
|
+
return {
|
|
229
|
+
...e,
|
|
230
|
+
name: e.name,
|
|
231
|
+
message: e.message,
|
|
232
|
+
stack: e.stack?.replace(e.message, ""),
|
|
233
|
+
cause: e.cause
|
|
234
|
+
};
|
|
235
|
+
});
|
|
144
236
|
this.testManager.onTestRunEnd({
|
|
145
237
|
totalTestCount,
|
|
146
238
|
unhandledErrors: serializedErrors
|
|
147
|
-
})
|
|
239
|
+
});
|
|
240
|
+
this.clearVitestState();
|
|
148
241
|
}
|
|
149
242
|
// TODO: Clearing the whole internal state of Vitest might be too aggressive
|
|
150
243
|
async clearVitestState() {
|
|
151
|
-
this.ctx.state.filesMap.clear()
|
|
244
|
+
this.ctx.state.filesMap.clear();
|
|
245
|
+
this.ctx.state.pathsSet.clear();
|
|
246
|
+
this.ctx.state.idMap.clear();
|
|
247
|
+
this.ctx.state.errorsSet.clear();
|
|
248
|
+
this.ctx.state.processTimeoutCauses?.clear();
|
|
152
249
|
}
|
|
153
250
|
};
|
|
154
251
|
|
|
155
252
|
// src/node/vitest-manager.ts
|
|
156
|
-
var VITEST_CONFIG_FILE_EXTENSIONS = ["mts", "mjs", "cts", "cjs", "ts", "tsx", "js", "jsx"]
|
|
253
|
+
var VITEST_CONFIG_FILE_EXTENSIONS = ["mts", "mjs", "cts", "cjs", "ts", "tsx", "js", "jsx"];
|
|
254
|
+
var VITEST_WORKSPACE_FILE_EXTENSION = ["ts", "js", "json"];
|
|
157
255
|
process.env.VITEST_STORYBOOK = "true";
|
|
158
|
-
var DOUBLE_SPACES = " "
|
|
256
|
+
var DOUBLE_SPACES = " ";
|
|
257
|
+
var getTestName = /* @__PURE__ */ __name((name) => `${name}${DOUBLE_SPACES}`, "getTestName");
|
|
258
|
+
var VitestManager = class {
|
|
159
259
|
constructor(testManager) {
|
|
160
260
|
this.testManager = testManager;
|
|
161
261
|
this.vitest = null;
|
|
@@ -163,32 +263,39 @@ var DOUBLE_SPACES = " ", getTestName = (name) => `${name}${DOUBLE_SPACES}`, Vit
|
|
|
163
263
|
this.vitestRestartPromise = null;
|
|
164
264
|
this.runningPromise = null;
|
|
165
265
|
}
|
|
266
|
+
static {
|
|
267
|
+
__name(this, "VitestManager");
|
|
268
|
+
}
|
|
166
269
|
async startVitest({ coverage }) {
|
|
167
|
-
|
|
270
|
+
const { createVitest } = await import("vitest/node");
|
|
271
|
+
const storybookCoverageReporter = [
|
|
168
272
|
"@storybook/addon-vitest/internal/coverage-reporter",
|
|
169
273
|
{
|
|
170
274
|
testManager: this.testManager,
|
|
171
275
|
coverageOptions: this.vitest?.config?.coverage
|
|
172
276
|
}
|
|
173
|
-
]
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
277
|
+
];
|
|
278
|
+
const coverageOptions = coverage ? {
|
|
279
|
+
enabled: true,
|
|
280
|
+
clean: true,
|
|
281
|
+
cleanOnRerun: true,
|
|
282
|
+
reportOnFailure: true,
|
|
178
283
|
reporter: [["html", {}], storybookCoverageReporter],
|
|
179
284
|
reportsDirectory: resolvePathInStorybookCache(COVERAGE_DIRECTORY)
|
|
180
|
-
} : { enabled:
|
|
285
|
+
} : { enabled: false };
|
|
286
|
+
const vitestWorkspaceConfig = any(
|
|
181
287
|
[
|
|
182
288
|
...VITEST_WORKSPACE_FILE_EXTENSION.map((ext) => `vitest.workspace.${ext}`),
|
|
183
289
|
...VITEST_CONFIG_FILE_EXTENSIONS.map((ext) => `vitest.config.${ext}`)
|
|
184
290
|
],
|
|
185
291
|
{ last: getProjectRoot() }
|
|
186
|
-
)
|
|
292
|
+
);
|
|
293
|
+
const projectName = "storybook:" + process.env.STORYBOOK_CONFIG_DIR;
|
|
187
294
|
try {
|
|
188
295
|
this.vitest = await createVitest("test", {
|
|
189
296
|
root: vitestWorkspaceConfig ? dirname(vitestWorkspaceConfig) : process.cwd(),
|
|
190
|
-
watch:
|
|
191
|
-
passWithNoTests:
|
|
297
|
+
watch: true,
|
|
298
|
+
passWithNoTests: false,
|
|
192
299
|
project: [projectName],
|
|
193
300
|
// TODO:
|
|
194
301
|
// Do we want to enable Vite's default reporter?
|
|
@@ -199,104 +306,176 @@ var DOUBLE_SPACES = " ", getTestName = (name) => `${name}${DOUBLE_SPACES}`, Vit
|
|
|
199
306
|
coverage: coverageOptions
|
|
200
307
|
});
|
|
201
308
|
} catch (err) {
|
|
202
|
-
|
|
309
|
+
const originalMessage = String(err.message);
|
|
203
310
|
if (originalMessage.includes("Found multiple projects")) {
|
|
204
|
-
|
|
311
|
+
const custom = [
|
|
205
312
|
"Storybook was unable to start the test run because you have multiple Vitest projects (or browsers) in headed mode.",
|
|
206
313
|
"Please set `headless: true` in your Storybook vitest config.\n\n"
|
|
207
|
-
].join(
|
|
208
|
-
|
|
209
|
-
|
|
314
|
+
].join("\n");
|
|
315
|
+
if (!originalMessage.startsWith(custom)) {
|
|
316
|
+
err.message = `${custom}${originalMessage}`;
|
|
317
|
+
}
|
|
210
318
|
}
|
|
211
319
|
throw err;
|
|
212
320
|
}
|
|
213
|
-
|
|
214
|
-
|
|
321
|
+
if (this.vitest) {
|
|
322
|
+
this.vitest.onCancel(() => {
|
|
323
|
+
});
|
|
324
|
+
}
|
|
215
325
|
try {
|
|
216
326
|
await this.vitest.init();
|
|
217
327
|
} catch (e) {
|
|
218
|
-
let message = "Failed to initialize Vitest"
|
|
219
|
-
|
|
220
|
-
|
|
328
|
+
let message = "Failed to initialize Vitest";
|
|
329
|
+
const isV8 = e.message?.includes("@vitest/coverage-v8");
|
|
330
|
+
const isIstanbul = e.message?.includes("@vitest/coverage-istanbul");
|
|
331
|
+
if (e.message?.includes("Failed to load url") && (isIstanbul || isV8) || // Vitest will sometimes not throw the correct missing-package-detection error, so we have to check for this as well
|
|
332
|
+
e instanceof TypeError && e?.message === "Cannot read properties of undefined (reading 'name')") {
|
|
333
|
+
const coveragePackage = isIstanbul ? "coverage-istanbul" : "coverage-v8";
|
|
334
|
+
message += `
|
|
221
335
|
|
|
222
|
-
Please install the @vitest/${
|
|
223
|
-
|
|
336
|
+
Please install the @vitest/${coveragePackage} package to collect coverage
|
|
337
|
+
`;
|
|
338
|
+
}
|
|
339
|
+
this.testManager.reportFatalError(message, e);
|
|
224
340
|
return;
|
|
225
341
|
}
|
|
226
342
|
await this.setupWatchers();
|
|
227
343
|
}
|
|
228
344
|
async restartVitest({ coverage }) {
|
|
229
|
-
|
|
345
|
+
await this.vitestRestartPromise;
|
|
346
|
+
this.vitestRestartPromise = new Promise(async (resolve, reject) => {
|
|
230
347
|
try {
|
|
231
|
-
await this.runningPromise
|
|
348
|
+
await this.runningPromise;
|
|
349
|
+
await this.vitest?.close();
|
|
350
|
+
await this.startVitest({ coverage });
|
|
351
|
+
resolve();
|
|
232
352
|
} catch (e) {
|
|
233
353
|
reject(e);
|
|
234
354
|
} finally {
|
|
235
355
|
this.vitestRestartPromise = null;
|
|
236
356
|
}
|
|
237
|
-
})
|
|
357
|
+
});
|
|
358
|
+
return this.vitestRestartPromise;
|
|
238
359
|
}
|
|
239
360
|
resetGlobalTestNamePattern() {
|
|
240
361
|
this.vitest?.setGlobalTestNamePattern("");
|
|
241
362
|
}
|
|
242
363
|
updateLastChanged(filepath) {
|
|
243
364
|
this.vitest.projects.forEach(({ browser, vite, server }) => {
|
|
244
|
-
|
|
365
|
+
if (server) {
|
|
366
|
+
const serverMods = server.moduleGraph.getModulesByFile(filepath);
|
|
367
|
+
serverMods?.forEach((mod) => server.moduleGraph.invalidateModule(mod));
|
|
368
|
+
}
|
|
369
|
+
if (vite) {
|
|
370
|
+
const serverMods = vite.moduleGraph.getModulesByFile(filepath);
|
|
371
|
+
serverMods?.forEach((mod) => vite.moduleGraph.invalidateModule(mod));
|
|
372
|
+
}
|
|
373
|
+
if (browser) {
|
|
374
|
+
const browserMods = browser.vite.moduleGraph.getModulesByFile(filepath);
|
|
375
|
+
browserMods?.forEach((mod) => browser.vite.moduleGraph.invalidateModule(mod));
|
|
376
|
+
}
|
|
245
377
|
});
|
|
246
378
|
}
|
|
247
379
|
async fetchStories(requestStoryIds) {
|
|
248
|
-
|
|
249
|
-
if (!indexUrl)
|
|
380
|
+
const indexUrl = this.testManager.store.getState().indexUrl;
|
|
381
|
+
if (!indexUrl) {
|
|
250
382
|
throw new Error(
|
|
251
383
|
"Tried to fetch stories to test, but the index URL was not set in the store yet."
|
|
252
384
|
);
|
|
385
|
+
}
|
|
253
386
|
try {
|
|
254
|
-
|
|
387
|
+
const index = await Promise.race([
|
|
255
388
|
fetch(indexUrl).then((res) => res.json()),
|
|
256
389
|
new Promise((_, reject) => setTimeout(reject, 3e3, new Error("Request took too long")))
|
|
257
390
|
]);
|
|
258
|
-
|
|
391
|
+
const storyIds = requestStoryIds || Object.keys(index.entries);
|
|
392
|
+
return storyIds.map((id) => index.entries[id]).filter((story) => story.type === "story");
|
|
259
393
|
} catch (e) {
|
|
260
|
-
|
|
394
|
+
log("Failed to fetch story index: " + e.message);
|
|
395
|
+
return [];
|
|
261
396
|
}
|
|
262
397
|
}
|
|
263
398
|
filterTestSpecifications(testSpecifications, stories) {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
399
|
+
const filteredTestSpecifications = [];
|
|
400
|
+
const filteredStoryIds = [];
|
|
401
|
+
const storiesByImportPath = {};
|
|
402
|
+
for (const story of stories) {
|
|
403
|
+
const absoluteImportPath = path.join(process.cwd(), story.importPath);
|
|
404
|
+
if (!storiesByImportPath[absoluteImportPath]) {
|
|
405
|
+
storiesByImportPath[absoluteImportPath] = [];
|
|
406
|
+
}
|
|
407
|
+
storiesByImportPath[absoluteImportPath].push(story);
|
|
268
408
|
}
|
|
269
|
-
for (
|
|
270
|
-
|
|
271
|
-
|
|
409
|
+
for (const testSpecification of testSpecifications) {
|
|
410
|
+
const { env = {} } = testSpecification.project.config;
|
|
411
|
+
const include = env.__VITEST_INCLUDE_TAGS__?.split(",").filter(Boolean) ?? ["test"];
|
|
412
|
+
const exclude = env.__VITEST_EXCLUDE_TAGS__?.split(",").filter(Boolean) ?? [];
|
|
413
|
+
const skip = env.__VITEST_SKIP_TAGS__?.split(",").filter(Boolean) ?? [];
|
|
414
|
+
const storiesInTestSpecification = storiesByImportPath[testSpecification.moduleId] ?? [];
|
|
415
|
+
const filteredStories = storiesInTestSpecification.filter((story) => {
|
|
416
|
+
if (include.length && !include.some((tag) => story.tags?.includes(tag))) {
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
if (exclude.some((tag) => story.tags?.includes(tag))) {
|
|
420
|
+
return false;
|
|
421
|
+
}
|
|
422
|
+
return true;
|
|
423
|
+
});
|
|
424
|
+
if (!filteredStories.length) {
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
if (!this.testManager.store.getState().watching) {
|
|
428
|
+
this.updateLastChanged(testSpecification.moduleId);
|
|
429
|
+
}
|
|
430
|
+
filteredTestSpecifications.push(testSpecification);
|
|
431
|
+
filteredStoryIds.push(
|
|
272
432
|
...filteredStories.filter((story) => !skip.some((tag) => story.tags?.includes(tag))).map((story) => story.id)
|
|
273
|
-
)
|
|
433
|
+
);
|
|
274
434
|
}
|
|
275
435
|
return { filteredTestSpecifications, filteredStoryIds };
|
|
276
436
|
}
|
|
277
437
|
async runTests(runPayload) {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (
|
|
282
|
-
|
|
283
|
-
|
|
438
|
+
const { watching, config } = this.testManager.store.getState();
|
|
439
|
+
const coverageShouldBeEnabled = config.coverage && !watching && (runPayload?.storyIds?.length ?? 0) === 0;
|
|
440
|
+
const currentCoverage = this.vitest?.config.coverage?.enabled;
|
|
441
|
+
if (!this.vitest) {
|
|
442
|
+
await this.startVitest({ coverage: coverageShouldBeEnabled });
|
|
443
|
+
} else if (currentCoverage !== coverageShouldBeEnabled) {
|
|
444
|
+
await this.restartVitest({ coverage: coverageShouldBeEnabled });
|
|
445
|
+
} else {
|
|
446
|
+
await this.vitestRestartPromise;
|
|
447
|
+
}
|
|
448
|
+
this.resetGlobalTestNamePattern();
|
|
449
|
+
await this.cancelCurrentRun();
|
|
450
|
+
const testSpecifications = await this.getStorybookTestSpecifications();
|
|
451
|
+
const allStories = await this.fetchStories();
|
|
452
|
+
const filteredStories = runPayload.storyIds ? allStories.filter((story) => runPayload.storyIds?.includes(story.id)) : allStories;
|
|
453
|
+
const isSingleStoryRun = runPayload.storyIds?.length === 1;
|
|
454
|
+
if (isSingleStoryRun) {
|
|
455
|
+
const selectedStory = filteredStories.find((story) => story.id === runPayload.storyIds?.[0]);
|
|
456
|
+
if (!selectedStory) {
|
|
284
457
|
throw new Error(`Story ${runPayload.storyIds?.[0]} not found`);
|
|
285
|
-
|
|
458
|
+
}
|
|
459
|
+
const storyName = selectedStory.name;
|
|
460
|
+
let regex;
|
|
461
|
+
const isParentStory = allStories.some((story) => selectedStory.id === story.parent);
|
|
462
|
+
const hasParentStory = allStories.some((story) => selectedStory.parent === story.id);
|
|
286
463
|
if (isParentStory) {
|
|
287
|
-
|
|
464
|
+
const parentName = getTestName(selectedStory.name);
|
|
288
465
|
regex = new RegExp(`^${parentName}`);
|
|
289
466
|
} else if (hasParentStory) {
|
|
290
|
-
|
|
291
|
-
if (!parentStory)
|
|
467
|
+
const parentStory = allStories.find((story) => story.id === selectedStory.parent);
|
|
468
|
+
if (!parentStory) {
|
|
292
469
|
throw new Error(`Parent story not found for story ${selectedStory.id}`);
|
|
293
|
-
|
|
470
|
+
}
|
|
471
|
+
const parentName = getTestName(parentStory.name);
|
|
294
472
|
regex = new RegExp(`^${parentName} ${storyName}$`);
|
|
295
|
-
} else
|
|
473
|
+
} else {
|
|
296
474
|
regex = new RegExp(`^${storyName}$`);
|
|
475
|
+
}
|
|
297
476
|
this.vitest.setGlobalTestNamePattern(regex);
|
|
298
477
|
}
|
|
299
|
-
|
|
478
|
+
const { filteredTestSpecifications, filteredStoryIds } = this.filterTestSpecifications(
|
|
300
479
|
testSpecifications,
|
|
301
480
|
filteredStories
|
|
302
481
|
);
|
|
@@ -306,92 +485,138 @@ Please install the @vitest/${isIstanbul ? "coverage-istanbul" : "coverage-v8"} p
|
|
|
306
485
|
...s.currentRun,
|
|
307
486
|
totalTestCount: filteredStoryIds.length
|
|
308
487
|
}
|
|
309
|
-
}))
|
|
488
|
+
}));
|
|
489
|
+
await this.vitest.runTestSpecifications(filteredTestSpecifications, true);
|
|
490
|
+
this.resetGlobalTestNamePattern();
|
|
310
491
|
}
|
|
311
492
|
async cancelCurrentRun() {
|
|
312
|
-
await this.vitest?.cancelCurrentRun("keyboard-input")
|
|
493
|
+
await this.vitest?.cancelCurrentRun("keyboard-input");
|
|
494
|
+
await this.runningPromise;
|
|
313
495
|
}
|
|
314
496
|
async getStorybookTestSpecifications() {
|
|
315
|
-
|
|
497
|
+
const globTestSpecifications = await this.vitest?.globTestSpecifications() ?? [];
|
|
498
|
+
return globTestSpecifications.filter(
|
|
316
499
|
(workspaceSpec) => this.isStorybookProject(workspaceSpec.project)
|
|
317
500
|
) ?? [];
|
|
318
501
|
}
|
|
319
502
|
async runAffectedTestsAfterChange(changedFilePath, event) {
|
|
320
|
-
|
|
321
|
-
|
|
503
|
+
const id = slash(changedFilePath);
|
|
504
|
+
this.vitest?.logger.clearHighlightCache(id);
|
|
505
|
+
this.updateLastChanged(id);
|
|
506
|
+
if (event === "add") {
|
|
507
|
+
const project = this.vitest?.projects.find(this.isStorybookProject.bind(this));
|
|
508
|
+
project?.matchesTestGlob(id);
|
|
509
|
+
}
|
|
510
|
+
if (!this.testManager.store.getState().watching) {
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
if (!this.vitest) {
|
|
322
514
|
return;
|
|
515
|
+
}
|
|
323
516
|
this.resetGlobalTestNamePattern();
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
517
|
+
const storybookProject = this.vitest.projects.find((p) => this.isStorybookProject(p));
|
|
518
|
+
const previewAnnotationSpecifications = this.testManager.store.getState().previewAnnotations.map((previewAnnotation) => {
|
|
519
|
+
return {
|
|
520
|
+
project: storybookProject ?? this.vitest.projects[0],
|
|
521
|
+
moduleId: typeof previewAnnotation === "string" ? previewAnnotation : previewAnnotation.absolute
|
|
522
|
+
};
|
|
523
|
+
});
|
|
524
|
+
const setupFilesSpecifications = this.vitest.projects.flatMap(
|
|
328
525
|
(project) => project.config.setupFiles.map((setupFile) => ({
|
|
329
526
|
project,
|
|
330
527
|
moduleId: setupFile
|
|
331
528
|
}))
|
|
332
|
-
)
|
|
529
|
+
);
|
|
530
|
+
const syntheticGlobalTestSpecifications = previewAnnotationSpecifications.concat(setupFilesSpecifications);
|
|
531
|
+
const testSpecifications = await this.getStorybookTestSpecifications();
|
|
532
|
+
const allStories = await this.fetchStories();
|
|
533
|
+
let affectsGlobalFiles = false;
|
|
534
|
+
const affectedTestSpecifications = (await Promise.all(
|
|
333
535
|
syntheticGlobalTestSpecifications.concat(testSpecifications).map(async (testSpecification) => {
|
|
334
|
-
|
|
335
|
-
if (changedFilePath === testSpecification.moduleId || dependencies.has(changedFilePath))
|
|
336
|
-
|
|
536
|
+
const dependencies = await this.getTestDependencies(testSpecification);
|
|
537
|
+
if (changedFilePath === testSpecification.moduleId || dependencies.has(changedFilePath)) {
|
|
538
|
+
if (syntheticGlobalTestSpecifications.includes(testSpecification)) {
|
|
539
|
+
affectsGlobalFiles = true;
|
|
540
|
+
}
|
|
541
|
+
return testSpecification;
|
|
542
|
+
}
|
|
337
543
|
})
|
|
338
|
-
)).filter(Boolean)
|
|
339
|
-
|
|
544
|
+
)).filter(Boolean);
|
|
545
|
+
const testSpecificationsToRun = affectsGlobalFiles ? testSpecifications : affectedTestSpecifications;
|
|
546
|
+
if (!testSpecificationsToRun.length) {
|
|
340
547
|
return;
|
|
341
|
-
|
|
548
|
+
}
|
|
549
|
+
const { filteredTestSpecifications, filteredStoryIds } = this.filterTestSpecifications(
|
|
342
550
|
testSpecificationsToRun,
|
|
343
551
|
allStories
|
|
344
552
|
);
|
|
345
553
|
await this.testManager.runTestsWithState({
|
|
346
554
|
storyIds: filteredStoryIds,
|
|
347
555
|
triggeredBy: "watch",
|
|
348
|
-
callback: async () => {
|
|
556
|
+
callback: /* @__PURE__ */ __name(async () => {
|
|
349
557
|
this.testManager.store.setState((s) => ({
|
|
350
558
|
...s,
|
|
351
559
|
currentRun: {
|
|
352
560
|
...s.currentRun,
|
|
353
561
|
totalTestCount: filteredStoryIds.length
|
|
354
562
|
}
|
|
355
|
-
}))
|
|
356
|
-
|
|
563
|
+
}));
|
|
564
|
+
await this.vitest.cancelCurrentRun("keyboard-input");
|
|
565
|
+
await this.runningPromise;
|
|
566
|
+
await this.vitest.runTestSpecifications(filteredTestSpecifications, false);
|
|
567
|
+
}, "callback")
|
|
357
568
|
});
|
|
358
569
|
}
|
|
359
570
|
// This is an adaptation of Vitest's own implementation
|
|
360
571
|
// see https://github.com/vitest-dev/vitest/blob/14409088166152c920ce7fa4ad4c0ba57149b869/packages/vitest/src/node/specifications.ts#L171-L198
|
|
361
572
|
async getTestDependencies(spec) {
|
|
362
|
-
|
|
363
|
-
|
|
573
|
+
const deps = /* @__PURE__ */ new Set();
|
|
574
|
+
const addImports = /* @__PURE__ */ __name(async (project, filepath) => {
|
|
575
|
+
if (deps.has(filepath)) {
|
|
364
576
|
return;
|
|
577
|
+
}
|
|
365
578
|
deps.add(filepath);
|
|
366
|
-
|
|
367
|
-
|
|
579
|
+
const mod = project.vite.moduleGraph.getModuleById(filepath);
|
|
580
|
+
const transformed = mod?.ssrTransformResult || await project.vite.transformRequest(filepath, { ssr: true });
|
|
581
|
+
if (!transformed) {
|
|
368
582
|
return;
|
|
369
|
-
|
|
583
|
+
}
|
|
584
|
+
const dependencies = [...transformed.deps ?? [], ...transformed.dynamicDeps ?? []];
|
|
370
585
|
await Promise.all(
|
|
371
586
|
dependencies.map(async (dep) => {
|
|
372
|
-
|
|
373
|
-
!fsPath.includes("node_modules") && !deps.has(fsPath) && existsSync(fsPath)
|
|
587
|
+
const fsPath = dep.startsWith("/@fs/") ? dep.slice(process.platform === "win32" ? 5 : 4) : join(project.config.root, dep);
|
|
588
|
+
if (!fsPath.includes("node_modules") && !deps.has(fsPath) && existsSync(fsPath)) {
|
|
589
|
+
await addImports(project, fsPath);
|
|
590
|
+
}
|
|
374
591
|
})
|
|
375
592
|
);
|
|
376
|
-
};
|
|
377
|
-
|
|
593
|
+
}, "addImports");
|
|
594
|
+
await addImports(spec.project, spec.moduleId);
|
|
595
|
+
deps.delete(spec.moduleId);
|
|
596
|
+
return deps;
|
|
378
597
|
}
|
|
379
598
|
async registerVitestConfigListener() {
|
|
380
599
|
this.vitest.vite.watcher.on("change", async (file) => {
|
|
381
|
-
|
|
600
|
+
const isConfig = normalize(file) === this.vitest?.vite?.config.configFile;
|
|
601
|
+
if (isConfig) {
|
|
382
602
|
log("Restarting Vitest due to config change");
|
|
383
|
-
|
|
603
|
+
const { watching, config } = this.testManager.store.getState();
|
|
384
604
|
await this.restartVitest({ coverage: config.coverage && !watching });
|
|
385
605
|
}
|
|
386
606
|
});
|
|
387
607
|
}
|
|
388
608
|
async setupWatchers() {
|
|
389
|
-
this.resetGlobalTestNamePattern()
|
|
609
|
+
this.resetGlobalTestNamePattern();
|
|
610
|
+
this.vitest.vite.watcher.removeAllListeners("change");
|
|
611
|
+
this.vitest.vite.watcher.removeAllListeners("add");
|
|
612
|
+
this.vitest.vite.watcher.on(
|
|
390
613
|
"change",
|
|
391
614
|
(file) => this.runAffectedTestsAfterChange(file, "change")
|
|
392
|
-
)
|
|
615
|
+
);
|
|
616
|
+
this.vitest.vite.watcher.on("add", (file) => {
|
|
393
617
|
this.runAffectedTestsAfterChange(file, "add");
|
|
394
|
-
})
|
|
618
|
+
});
|
|
619
|
+
this.registerVitestConfigListener();
|
|
395
620
|
}
|
|
396
621
|
isStorybookProject(project) {
|
|
397
622
|
return !!project.config.env?.__STORYBOOK_URL__;
|
|
@@ -405,7 +630,8 @@ var testStateToStatusValueMap = {
|
|
|
405
630
|
warning: "status-value:warning",
|
|
406
631
|
failed: "status-value:error",
|
|
407
632
|
skipped: "status-value:unknown"
|
|
408
|
-
}
|
|
633
|
+
};
|
|
634
|
+
var TestManager = class _TestManager {
|
|
409
635
|
constructor(options) {
|
|
410
636
|
this.batchedTestCaseResults = [];
|
|
411
637
|
/**
|
|
@@ -423,15 +649,28 @@ var testStateToStatusValueMap = {
|
|
|
423
649
|
* eventually causing the manager and dev server to lose connection.
|
|
424
650
|
*/
|
|
425
651
|
this.throttledFlushTestCaseResults = throttle(() => {
|
|
426
|
-
|
|
427
|
-
this.batchedTestCaseResults = []
|
|
428
|
-
|
|
652
|
+
const testCaseResultsToFlush = this.batchedTestCaseResults;
|
|
653
|
+
this.batchedTestCaseResults = [];
|
|
654
|
+
this.store.setState((s) => {
|
|
655
|
+
let { success: ctSuccess, error: ctError } = s.currentRun.componentTestCount;
|
|
656
|
+
let { success: a11ySuccess, warning: a11yWarning, error: a11yError } = s.currentRun.a11yCount;
|
|
429
657
|
testCaseResultsToFlush.forEach(({ testResult, reports }) => {
|
|
430
|
-
testResult.state === "passed"
|
|
431
|
-
|
|
658
|
+
if (testResult.state === "passed") {
|
|
659
|
+
ctSuccess++;
|
|
660
|
+
} else if (testResult.state === "failed") {
|
|
661
|
+
ctError++;
|
|
662
|
+
}
|
|
663
|
+
reports?.filter((r) => r.type === "a11y").forEach((report) => {
|
|
664
|
+
if (report.status === "passed") {
|
|
665
|
+
a11ySuccess++;
|
|
666
|
+
} else if (report.status === "warning") {
|
|
667
|
+
a11yWarning++;
|
|
668
|
+
} else if (report.status === "failed") {
|
|
669
|
+
a11yError++;
|
|
670
|
+
}
|
|
432
671
|
});
|
|
433
672
|
});
|
|
434
|
-
|
|
673
|
+
const finishedTestCount = ctSuccess + ctError;
|
|
435
674
|
return {
|
|
436
675
|
...s,
|
|
437
676
|
currentRun: {
|
|
@@ -445,57 +684,75 @@ var testStateToStatusValueMap = {
|
|
|
445
684
|
}
|
|
446
685
|
};
|
|
447
686
|
});
|
|
448
|
-
|
|
687
|
+
const componentTestStatuses = testCaseResultsToFlush.map(({ storyId, testResult }) => ({
|
|
449
688
|
storyId,
|
|
450
689
|
typeId: STATUS_TYPE_ID_COMPONENT_TEST,
|
|
451
690
|
value: testStateToStatusValueMap[testResult.state],
|
|
452
691
|
title: "Component tests",
|
|
453
|
-
description: testResult.errors?.map((error) => error.stack || error.message).join(
|
|
454
|
-
|
|
455
|
-
sidebarContextMenu: !1
|
|
692
|
+
description: testResult.errors?.map((error) => error.stack || error.message).join("\n") ?? "",
|
|
693
|
+
sidebarContextMenu: false
|
|
456
694
|
}));
|
|
457
695
|
this.componentTestStatusStore.set(componentTestStatuses);
|
|
458
|
-
|
|
696
|
+
const a11yStatuses = testCaseResultsToFlush.flatMap(
|
|
459
697
|
({ storyId, reports }) => reports?.filter((r) => r.type === "a11y").map((a11yReport) => ({
|
|
460
698
|
storyId,
|
|
461
699
|
typeId: STATUS_TYPE_ID_A11Y,
|
|
462
700
|
value: testStateToStatusValueMap[a11yReport.status],
|
|
463
701
|
title: "Accessibility tests",
|
|
464
702
|
description: "",
|
|
465
|
-
sidebarContextMenu:
|
|
703
|
+
sidebarContextMenu: false
|
|
466
704
|
}))
|
|
467
705
|
).filter((a11yStatus) => a11yStatus !== void 0);
|
|
468
|
-
a11yStatuses.length > 0
|
|
706
|
+
if (a11yStatuses.length > 0) {
|
|
707
|
+
this.a11yStatusStore.set(a11yStatuses);
|
|
708
|
+
}
|
|
469
709
|
}, 500);
|
|
470
|
-
this.store = options.store
|
|
710
|
+
this.store = options.store;
|
|
711
|
+
this.componentTestStatusStore = options.componentTestStatusStore;
|
|
712
|
+
this.a11yStatusStore = options.a11yStatusStore;
|
|
713
|
+
this.testProviderStore = options.testProviderStore;
|
|
714
|
+
this.onReady = options.onReady;
|
|
715
|
+
this.storybookOptions = options.storybookOptions;
|
|
716
|
+
this.vitestManager = new VitestManager(this);
|
|
717
|
+
this.store.subscribe("TRIGGER_RUN", this.handleTriggerRunEvent.bind(this));
|
|
718
|
+
this.store.subscribe("CANCEL_RUN", this.handleCancelEvent.bind(this));
|
|
719
|
+
this.store.untilReady().then(() => {
|
|
720
|
+
return this.vitestManager.startVitest({ coverage: this.store.getState().config.coverage });
|
|
721
|
+
}).then(() => this.onReady?.()).catch((e) => {
|
|
471
722
|
this.reportFatalError("Failed to start Vitest", e);
|
|
472
723
|
});
|
|
473
724
|
}
|
|
725
|
+
static {
|
|
726
|
+
__name(this, "TestManager");
|
|
727
|
+
}
|
|
474
728
|
async handleTriggerRunEvent(event) {
|
|
475
729
|
await this.runTestsWithState({
|
|
476
730
|
storyIds: event.payload.storyIds,
|
|
477
731
|
triggeredBy: event.payload.triggeredBy,
|
|
478
|
-
callback: async () => {
|
|
732
|
+
callback: /* @__PURE__ */ __name(async () => {
|
|
479
733
|
try {
|
|
480
|
-
await this.vitestManager.vitestRestartPromise
|
|
734
|
+
await this.vitestManager.vitestRestartPromise;
|
|
735
|
+
await this.vitestManager.runTests(event.payload);
|
|
481
736
|
} catch (err) {
|
|
482
|
-
|
|
737
|
+
this.reportFatalError("Failed to run tests", err);
|
|
738
|
+
throw err;
|
|
483
739
|
}
|
|
484
|
-
}
|
|
740
|
+
}, "callback")
|
|
485
741
|
});
|
|
486
742
|
}
|
|
487
743
|
async handleCancelEvent() {
|
|
488
744
|
try {
|
|
489
745
|
this.store.setState((s) => ({
|
|
490
746
|
...s,
|
|
491
|
-
cancelling:
|
|
492
|
-
}))
|
|
747
|
+
cancelling: true
|
|
748
|
+
}));
|
|
749
|
+
await this.vitestManager.cancelCurrentRun();
|
|
493
750
|
} catch (err) {
|
|
494
751
|
this.reportFatalError("Failed to cancel tests", err);
|
|
495
752
|
} finally {
|
|
496
753
|
this.store.setState((s) => ({
|
|
497
754
|
...s,
|
|
498
|
-
cancelling:
|
|
755
|
+
cancelling: false
|
|
499
756
|
}));
|
|
500
757
|
}
|
|
501
758
|
}
|
|
@@ -504,7 +761,9 @@ var testStateToStatusValueMap = {
|
|
|
504
761
|
triggeredBy,
|
|
505
762
|
callback
|
|
506
763
|
}) {
|
|
507
|
-
this.componentTestStatusStore.unset(storyIds)
|
|
764
|
+
this.componentTestStatusStore.unset(storyIds);
|
|
765
|
+
this.a11yStatusStore.unset(storyIds);
|
|
766
|
+
this.store.setState((s) => ({
|
|
508
767
|
...s,
|
|
509
768
|
currentRun: {
|
|
510
769
|
...storeOptions.initialState.currentRun,
|
|
@@ -513,12 +772,17 @@ var testStateToStatusValueMap = {
|
|
|
513
772
|
storyIds,
|
|
514
773
|
config: s.config
|
|
515
774
|
}
|
|
516
|
-
}))
|
|
517
|
-
|
|
775
|
+
}));
|
|
776
|
+
process.env.VITEST_STORYBOOK_CONFIG = JSON.stringify(this.store.getState().config);
|
|
777
|
+
await this.testProviderStore.runWithState(async () => {
|
|
778
|
+
await callback();
|
|
779
|
+
this.store.send({
|
|
518
780
|
type: "TEST_RUN_COMPLETED",
|
|
519
781
|
payload: this.store.getState().currentRun
|
|
520
|
-
})
|
|
782
|
+
});
|
|
783
|
+
if (this.store.getState().currentRun.unhandledErrors.length > 0) {
|
|
521
784
|
throw new Error("Tests completed but there are unhandled errors");
|
|
785
|
+
}
|
|
522
786
|
});
|
|
523
787
|
}
|
|
524
788
|
onTestModuleCollected(collectedTestCount) {
|
|
@@ -531,11 +795,16 @@ var testStateToStatusValueMap = {
|
|
|
531
795
|
}));
|
|
532
796
|
}
|
|
533
797
|
onTestCaseResult(result) {
|
|
534
|
-
|
|
535
|
-
|
|
798
|
+
const { storyId, testResult, reports } = result;
|
|
799
|
+
if (!storyId) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
this.batchedTestCaseResults.push({ storyId, testResult, reports });
|
|
803
|
+
this.throttledFlushTestCaseResults();
|
|
536
804
|
}
|
|
537
805
|
onTestRunEnd(endResult) {
|
|
538
|
-
this.throttledFlushTestCaseResults.flush()
|
|
806
|
+
this.throttledFlushTestCaseResults.flush();
|
|
807
|
+
this.store.setState((s) => ({
|
|
539
808
|
...s,
|
|
540
809
|
currentRun: {
|
|
541
810
|
...s.currentRun,
|
|
@@ -555,7 +824,8 @@ var testStateToStatusValueMap = {
|
|
|
555
824
|
}));
|
|
556
825
|
}
|
|
557
826
|
async reportFatalError(message, error) {
|
|
558
|
-
await this.store.untilReady()
|
|
827
|
+
await this.store.untilReady();
|
|
828
|
+
this.store.send({
|
|
559
829
|
type: "FATAL_ERROR",
|
|
560
830
|
payload: {
|
|
561
831
|
message,
|
|
@@ -565,26 +835,30 @@ var testStateToStatusValueMap = {
|
|
|
565
835
|
}
|
|
566
836
|
static async start(options) {
|
|
567
837
|
return new Promise((resolve) => {
|
|
568
|
-
|
|
838
|
+
const testManager = new _TestManager({
|
|
569
839
|
...options,
|
|
570
|
-
onReady: () => {
|
|
571
|
-
resolve(testManager)
|
|
572
|
-
|
|
840
|
+
onReady: /* @__PURE__ */ __name(() => {
|
|
841
|
+
resolve(testManager);
|
|
842
|
+
options.onReady?.();
|
|
843
|
+
}, "onReady")
|
|
573
844
|
});
|
|
574
845
|
});
|
|
575
846
|
}
|
|
576
847
|
};
|
|
577
848
|
|
|
578
849
|
// src/node/vitest.ts
|
|
579
|
-
var UniversalStore = experimental_UniversalStore
|
|
580
|
-
|
|
850
|
+
var UniversalStore = experimental_UniversalStore;
|
|
851
|
+
var getStatusStore = experimental_getStatusStore;
|
|
852
|
+
var getTestProviderStore = experimental_getTestProviderStore;
|
|
853
|
+
var channel = new Channel({
|
|
854
|
+
async: true,
|
|
581
855
|
transport: {
|
|
582
|
-
send: (event) => {
|
|
856
|
+
send: /* @__PURE__ */ __name((event) => {
|
|
583
857
|
process2.send?.(event);
|
|
584
|
-
},
|
|
585
|
-
setHandler: (handler) => {
|
|
858
|
+
}, "send"),
|
|
859
|
+
setHandler: /* @__PURE__ */ __name((handler) => {
|
|
586
860
|
process2.on("message", handler);
|
|
587
|
-
}
|
|
861
|
+
}, "setHandler")
|
|
588
862
|
}
|
|
589
863
|
});
|
|
590
864
|
UniversalStore.__prepare(channel, UniversalStore.Environment.SERVER);
|
|
@@ -594,18 +868,20 @@ new TestManager({
|
|
|
594
868
|
componentTestStatusStore: getStatusStore(STATUS_TYPE_ID_COMPONENT_TEST),
|
|
595
869
|
a11yStatusStore: getStatusStore(STATUS_TYPE_ID_A11Y),
|
|
596
870
|
testProviderStore: getTestProviderStore(ADDON_ID),
|
|
597
|
-
onReady: () => {
|
|
871
|
+
onReady: /* @__PURE__ */ __name(() => {
|
|
598
872
|
process2.send?.({ type: "ready" });
|
|
599
|
-
},
|
|
873
|
+
}, "onReady"),
|
|
600
874
|
storybookOptions: {
|
|
601
875
|
configDir: process2.env.STORYBOOK_CONFIG_DIR || ""
|
|
602
876
|
}
|
|
603
877
|
});
|
|
604
|
-
var exit = (code = 0) => {
|
|
605
|
-
channel?.removeAllListeners()
|
|
606
|
-
|
|
878
|
+
var exit = /* @__PURE__ */ __name((code = 0) => {
|
|
879
|
+
channel?.removeAllListeners();
|
|
880
|
+
process2.exit(code);
|
|
881
|
+
}, "exit");
|
|
882
|
+
var createUnhandledErrorHandler = /* @__PURE__ */ __name((message) => async (error) => {
|
|
607
883
|
try {
|
|
608
|
-
|
|
884
|
+
const payload = {
|
|
609
885
|
message,
|
|
610
886
|
error: {
|
|
611
887
|
message: error.message,
|
|
@@ -621,7 +897,7 @@ var exit = (code = 0) => {
|
|
|
621
897
|
} finally {
|
|
622
898
|
exit(1);
|
|
623
899
|
}
|
|
624
|
-
};
|
|
900
|
+
}, "createUnhandledErrorHandler");
|
|
625
901
|
process2.on(
|
|
626
902
|
"uncaughtException",
|
|
627
903
|
createUnhandledErrorHandler("Uncaught exception in the test runner process")
|