@storybook/addon-vitest 10.3.0-alpha.7 → 10.3.0-alpha.8

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.
@@ -1,37 +1,37 @@
1
- import CJS_COMPAT_NODE_URL_g0psqpo75ib from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_g0psqpo75ib from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_g0psqpo75ib from "node:module";
1
+ import CJS_COMPAT_NODE_URL_kcvris1e0og from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_kcvris1e0og from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_kcvris1e0og from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_g0psqpo75ib.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_g0psqpo75ib.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_g0psqpo75ib.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_kcvris1e0og.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_kcvris1e0og.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_kcvris1e0og.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-BJDGFRVW.js";
14
+ } from "../_node-chunks/chunk-AXU25N75.js";
15
15
  import {
16
16
  any,
17
17
  up
18
- } from "../_node-chunks/chunk-PBLJAZW7.js";
18
+ } from "../_node-chunks/chunk-ZYZKWOO3.js";
19
19
  import {
20
- ADDON_ID,
20
+ ADDON_ID2 as ADDON_ID,
21
21
  COVERAGE_DIRECTORY,
22
22
  STATUS_TYPE_ID_A11Y,
23
23
  STATUS_TYPE_ID_COMPONENT_TEST,
24
24
  storeOptions
25
- } from "../_node-chunks/chunk-YY2HJHG6.js";
26
- import "../_node-chunks/chunk-MVGTYBTG.js";
25
+ } from "../_node-chunks/chunk-PPDGQAGO.js";
26
+ import "../_node-chunks/chunk-XMFVMTKT.js";
27
27
  import {
28
28
  dirname,
29
29
  join,
30
30
  normalize,
31
31
  path,
32
32
  resolve
33
- } from "../_node-chunks/chunk-CEAAKDGT.js";
34
- import "../_node-chunks/chunk-V75YOJAB.js";
33
+ } from "../_node-chunks/chunk-4X3EFM32.js";
34
+ import "../_node-chunks/chunk-CMEPFTWL.js";
35
35
 
36
36
  // src/node/vitest.ts
37
37
  import process2 from "node:process";
@@ -129,6 +129,14 @@ import { existsSync, readFileSync } from "node:fs";
129
129
  import { getProjectRoot, resolvePathInStorybookCache } from "storybook/internal/common";
130
130
  import { Tag } from "storybook/internal/core-server";
131
131
 
132
+ // ../../../node_modules/es-toolkit/dist/string/words.mjs
133
+ var CASE_SPLIT_PATTERN = new RegExp("\\p{Lu}?\\p{Ll}+|[0-9]+|\\p{Lu}+(?!\\p{Ll})|\\p{Emoji_Presentation}|\\p{Extended_Pictographic}|\\p{L}+", "gu");
134
+
135
+ // ../../../node_modules/es-toolkit/dist/string/escapeRegExp.mjs
136
+ function escapeRegExp(str) {
137
+ return str.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
138
+ }
139
+
132
140
  // ../../../node_modules/slash/index.js
133
141
  function slash(path2) {
134
142
  return path2.startsWith("\\\\?\\") ? path2 : path2.replace(/\\/g, "/");
@@ -209,7 +217,7 @@ var DOUBLE_SPACES = " ", getTestName = (name) => `${name}${DOUBLE_SPACES}`, Vit
209
217
  for (let file of configFiles) {
210
218
  let maybe = any([file], { cwd: location, last: getProjectRoot() });
211
219
  if (maybe && existsSync(maybe)) {
212
- firstVitestConfig ??= maybe;
220
+ firstVitestConfig ??= dirname(maybe);
213
221
  let content = readFileSync(maybe, "utf8");
214
222
  if (content.includes("storybookTest") || content.includes("@storybook/addon-vitest")) {
215
223
  vitestWorkspaceConfig = dirname(maybe);
@@ -281,21 +289,52 @@ Please install the @vitest/${isIstanbul ? "coverage-istanbul" : "coverage-v8"} p
281
289
  server && server.moduleGraph.getModulesByFile(filepath)?.forEach((mod) => server.moduleGraph.invalidateModule(mod)), vite && vite.moduleGraph.getModulesByFile(filepath)?.forEach((mod) => vite.moduleGraph.invalidateModule(mod)), browser && browser.vite.moduleGraph.getModulesByFile(filepath)?.forEach((mod) => browser.vite.moduleGraph.invalidateModule(mod));
282
290
  });
283
291
  }
284
- async fetchStories(requestStoryIds) {
285
- let indexUrl = this.testManager.store.getState().indexUrl;
286
- if (!indexUrl)
287
- throw new Error(
288
- "Tried to fetch stories to test, but the index URL was not set in the store yet."
289
- );
290
- try {
291
- let index = await Promise.race([
292
- fetch(indexUrl).then((res) => res.json()),
293
- new Promise((_, reject) => setTimeout(reject, 3e3, new Error("Request took too long")))
294
- ]);
295
- return (requestStoryIds || Object.keys(index.entries)).map((id) => index.entries[id]).filter((story) => story.type === "story");
296
- } catch (e) {
297
- return log("Failed to fetch story index: " + e.message), [];
292
+ getStories(requestStoryIds) {
293
+ let index = this.testManager.store.getState().index;
294
+ if (requestStoryIds) {
295
+ let stories = [];
296
+ for (let id of requestStoryIds) {
297
+ let entry = index.entries[id];
298
+ entry?.type === "story" && stories.push(entry);
299
+ }
300
+ return stories;
301
+ }
302
+ return Object.values(index.entries).filter((entry) => entry.type === "story");
303
+ }
304
+ /**
305
+ * Builds the exact Vitest name-pattern fragment for one selected Storybook entry.
306
+ *
307
+ * The pattern differs by entry type:
308
+ *
309
+ * - Component entry (has child stories/tests): match the whole describe block prefix
310
+ * - Story-test entry (has parent): match "parent describe + test name" exactly
311
+ * - Regular story entry: match the story name exactly
312
+ */
313
+ buildStoryTestNamePattern(story, allStories, storiesById) {
314
+ if (allStories.some((candidate) => story.id === candidate.parent))
315
+ return `^${escapeRegExp(getTestName(story.name))}`;
316
+ if (story.parent) {
317
+ let parentStory = storiesById[story.parent];
318
+ if (!parentStory)
319
+ throw new Error(`Parent story not found for story ${story.id}`);
320
+ return `^${escapeRegExp(getTestName(parentStory.name))} ${escapeRegExp(story.name)}$`;
298
321
  }
322
+ return `^${escapeRegExp(story.name)}$`;
323
+ }
324
+ /**
325
+ * Combines multiple per-story patterns into one global regex so Vitest can run an exact subset of
326
+ * tests across one or more files in a single invocation.
327
+ */
328
+ buildTestNamePatternForStories(selectedStories, allStories) {
329
+ let storiesById = Object.fromEntries(allStories.map((story) => [story.id, story])), storyPatterns = [
330
+ ...new Set(
331
+ selectedStories.map(
332
+ (story) => this.buildStoryTestNamePattern(story, allStories, storiesById)
333
+ )
334
+ )
335
+ ];
336
+ if (storyPatterns.length)
337
+ return storyPatterns.length === 1 ? new RegExp(storyPatterns[0]) : new RegExp(`(?:${storyPatterns.map((pattern) => `(?:${pattern})`).join("|")})`);
299
338
  }
300
339
  filterTestSpecifications(testSpecifications, stories) {
301
340
  let filteredTestSpecifications = [], filteredStoryIds = [], storiesByImportPath = {};
@@ -314,24 +353,10 @@ Please install the @vitest/${isIstanbul ? "coverage-istanbul" : "coverage-v8"} p
314
353
  async runTests(runPayload) {
315
354
  let { watching, config } = this.testManager.store.getState(), coverageShouldBeEnabled = config.coverage && !watching && (runPayload?.storyIds?.length ?? 0) === 0, currentCoverage = this.vitest?.config.coverage?.enabled;
316
355
  this.vitest ? currentCoverage !== coverageShouldBeEnabled ? await this.restartVitest({ coverage: coverageShouldBeEnabled }) : await this.vitestRestartPromise : await this.startVitest({ coverage: coverageShouldBeEnabled }), this.resetGlobalTestNamePattern(), await this.cancelCurrentRun();
317
- let testSpecifications = await this.getStorybookTestSpecifications(), allStories = await this.fetchStories(), filteredStories = runPayload.storyIds ? allStories.filter((story) => runPayload.storyIds?.includes(story.id)) : allStories;
318
- if (runPayload.storyIds?.length === 1) {
319
- let selectedStory = filteredStories.find((story) => story.id === runPayload.storyIds?.[0]);
320
- if (!selectedStory)
321
- throw new Error(`Story ${runPayload.storyIds?.[0]} not found`);
322
- let storyName = selectedStory.name, regex, isParentStory = allStories.some((story) => selectedStory.id === story.parent), hasParentStory = allStories.some((story) => selectedStory.parent === story.id);
323
- if (isParentStory) {
324
- let parentName = getTestName(selectedStory.name);
325
- regex = new RegExp(`^${parentName}`);
326
- } else if (hasParentStory) {
327
- let parentStory = allStories.find((story) => story.id === selectedStory.parent);
328
- if (!parentStory)
329
- throw new Error(`Parent story not found for story ${selectedStory.id}`);
330
- let parentName = getTestName(parentStory.name);
331
- regex = new RegExp(`^${parentName} ${storyName}$`);
332
- } else
333
- regex = new RegExp(`^${storyName}$`);
334
- this.vitest.setGlobalTestNamePattern(regex);
356
+ let testSpecifications = await this.getStorybookTestSpecifications(), allStories = this.getStories(), filteredStories = runPayload.storyIds ? allStories.filter((story) => runPayload.storyIds?.includes(story.id)) : allStories;
357
+ if (runPayload.storyIds?.length) {
358
+ let regex = this.buildTestNamePatternForStories(filteredStories, allStories);
359
+ regex && this.vitest.setGlobalTestNamePattern(regex);
335
360
  }
336
361
  let { filteredTestSpecifications, filteredStoryIds } = this.filterTestSpecifications(
337
362
  testSpecifications,
@@ -366,7 +391,7 @@ Please install the @vitest/${isIstanbul ? "coverage-istanbul" : "coverage-v8"} p
366
391
  project,
367
392
  moduleId: setupFile
368
393
  }))
369
- ), syntheticGlobalTestSpecifications = previewAnnotationSpecifications.concat(setupFilesSpecifications), testSpecifications = await this.getStorybookTestSpecifications(), allStories = await this.fetchStories(), affectsGlobalFiles = !1, affectedTestSpecifications = (await Promise.all(
394
+ ), syntheticGlobalTestSpecifications = previewAnnotationSpecifications.concat(setupFilesSpecifications), testSpecifications = await this.getStorybookTestSpecifications(), allStories = this.getStories(), affectsGlobalFiles = !1, affectedTestSpecifications = (await Promise.all(
370
395
  syntheticGlobalTestSpecifications.concat(testSpecifications).map(async (testSpecification) => {
371
396
  let dependencies = await this.getTestDependencies(testSpecification);
372
397
  if (changedFilePath === testSpecification.moduleId || dependencies.has(changedFilePath))
@@ -461,7 +486,34 @@ var testStateToStatusValueMap = {
461
486
  */
462
487
  this.throttledFlushTestCaseResults = throttle(() => {
463
488
  let testCaseResultsToFlush = this.batchedTestCaseResults;
464
- this.batchedTestCaseResults = [], this.store.setState((s) => {
489
+ this.batchedTestCaseResults = [];
490
+ let componentTestStatuses = testCaseResultsToFlush.map(({ storyId, testResult }) => ({
491
+ storyId,
492
+ typeId: STATUS_TYPE_ID_COMPONENT_TEST,
493
+ value: testStateToStatusValueMap[testResult.state],
494
+ title: "Component tests",
495
+ description: testResult.errors?.map((error) => error.stack || error.message).join(`
496
+ `) ?? "",
497
+ sidebarContextMenu: !1
498
+ }));
499
+ this.componentTestStatusStore.set(componentTestStatuses);
500
+ let a11yReportsByStoryId = {}, a11yStatuses = [];
501
+ for (let { storyId, reports } of testCaseResultsToFlush) {
502
+ let storyA11yReports = reports?.filter((r) => r.type === "a11y");
503
+ if (storyA11yReports?.length) {
504
+ a11yReportsByStoryId[storyId] = storyA11yReports.map((r) => r.result);
505
+ for (let a11yReport of storyA11yReports)
506
+ a11yStatuses.push({
507
+ storyId,
508
+ typeId: STATUS_TYPE_ID_A11Y,
509
+ value: testStateToStatusValueMap[a11yReport.status],
510
+ title: "Accessibility tests",
511
+ description: "",
512
+ sidebarContextMenu: !1
513
+ });
514
+ }
515
+ }
516
+ a11yStatuses.length > 0 && this.a11yStatusStore.set(a11yStatuses), this.store.setState((s) => {
465
517
  let { success: ctSuccess, error: ctError } = s.currentRun.componentTestCount, { success: a11ySuccess, warning: a11yWarning, error: a11yError } = s.currentRun.a11yCount;
466
518
  testCaseResultsToFlush.forEach(({ testResult, reports }) => {
467
519
  testResult.state === "passed" ? ctSuccess++ : testResult.state === "failed" && ctError++, reports?.filter((r) => r.type === "a11y").forEach((report) => {
@@ -475,6 +527,12 @@ var testStateToStatusValueMap = {
475
527
  ...s.currentRun,
476
528
  componentTestCount: { success: ctSuccess, error: ctError },
477
529
  a11yCount: { success: a11ySuccess, warning: a11yWarning, error: a11yError },
530
+ componentTestStatuses: s.currentRun.componentTestStatuses.concat(componentTestStatuses),
531
+ a11yStatuses: s.currentRun.a11yStatuses.concat(a11yStatuses),
532
+ a11yReports: {
533
+ ...s.currentRun.a11yReports,
534
+ ...a11yReportsByStoryId
535
+ },
478
536
  // in some cases successes and errors can exceed the anticipated totalTestCount
479
537
  // e.g. when testing more tests than the stories we know about upfront
480
538
  // in those cases, we set the totalTestCount to the sum of successes and errors
@@ -482,27 +540,6 @@ var testStateToStatusValueMap = {
482
540
  }
483
541
  };
484
542
  });
485
- let componentTestStatuses = testCaseResultsToFlush.map(({ storyId, testResult }) => ({
486
- storyId,
487
- typeId: STATUS_TYPE_ID_COMPONENT_TEST,
488
- value: testStateToStatusValueMap[testResult.state],
489
- title: "Component tests",
490
- description: testResult.errors?.map((error) => error.stack || error.message).join(`
491
- `) ?? "",
492
- sidebarContextMenu: !1
493
- }));
494
- this.componentTestStatusStore.set(componentTestStatuses);
495
- let a11yStatuses = testCaseResultsToFlush.flatMap(
496
- ({ storyId, reports }) => reports?.filter((r) => r.type === "a11y").map((a11yReport) => ({
497
- storyId,
498
- typeId: STATUS_TYPE_ID_A11Y,
499
- value: testStateToStatusValueMap[a11yReport.status],
500
- title: "Accessibility tests",
501
- description: "",
502
- sidebarContextMenu: !1
503
- }))
504
- ).filter((a11yStatus) => a11yStatus !== void 0);
505
- a11yStatuses.length > 0 && this.a11yStatusStore.set(a11yStatuses);
506
543
  }, 500);
507
544
  this.store = options.store, this.componentTestStatusStore = options.componentTestStatusStore, this.a11yStatusStore = options.a11yStatusStore, this.testProviderStore = options.testProviderStore, this.onReady = options.onReady, this.storybookOptions = options.storybookOptions, this.vitestManager = new VitestManager(this), this.store.subscribe("TRIGGER_RUN", this.handleTriggerRunEvent.bind(this)), this.store.subscribe("CANCEL_RUN", this.handleCancelEvent.bind(this)), this.store.untilReady().then(() => this.vitestManager.startVitest({ coverage: this.store.getState().config.coverage })).then(() => this.onReady?.()).catch((e) => {
508
545
  this.reportFatalError("Failed to start Vitest", e);
@@ -512,6 +549,7 @@ var testStateToStatusValueMap = {
512
549
  await this.runTestsWithState({
513
550
  storyIds: event.payload.storyIds,
514
551
  triggeredBy: event.payload.triggeredBy,
552
+ configOverride: event.payload.configOverride,
515
553
  callback: async () => {
516
554
  try {
517
555
  await this.vitestManager.vitestRestartPromise, await this.vitestManager.runTests(event.payload);
@@ -539,18 +577,21 @@ var testStateToStatusValueMap = {
539
577
  async runTestsWithState({
540
578
  storyIds,
541
579
  triggeredBy,
580
+ configOverride,
542
581
  callback
543
582
  }) {
544
- this.componentTestStatusStore.unset(storyIds), this.a11yStatusStore.unset(storyIds), this.store.setState((s) => ({
583
+ this.componentTestStatusStore.unset(storyIds), this.a11yStatusStore.unset(storyIds);
584
+ let runConfig = configOverride ?? this.store.getState().config;
585
+ this.store.setState((s) => ({
545
586
  ...s,
546
587
  currentRun: {
547
588
  ...storeOptions.initialState.currentRun,
548
589
  triggeredBy,
549
590
  startedAt: Date.now(),
550
591
  storyIds,
551
- config: s.config
592
+ config: runConfig
552
593
  }
553
- })), process.env.VITEST_STORYBOOK_CONFIG = JSON.stringify(this.store.getState().config), await this.testProviderStore.runWithState(async () => {
594
+ })), process.env.VITEST_STORYBOOK_CONFIG = JSON.stringify(runConfig), await this.testProviderStore.runWithState(async () => {
554
595
  if (await callback(), this.store.send({
555
596
  type: "TEST_RUN_COMPLETED",
556
597
  payload: this.store.getState().currentRun
@@ -569,21 +610,32 @@ var testStateToStatusValueMap = {
569
610
  }
570
611
  onTestCaseResult(result) {
571
612
  let { storyId, testResult, reports } = result;
572
- storyId && (this.batchedTestCaseResults.push({ storyId, testResult, reports }), this.throttledFlushTestCaseResults());
613
+ if (!storyId)
614
+ return;
615
+ let requestedStoryIds = this.store.getState().currentRun.storyIds;
616
+ requestedStoryIds && !this.isRequestedStoryOrChild(storyId, requestedStoryIds) || (this.batchedTestCaseResults.push({ storyId, testResult, reports }), this.throttledFlushTestCaseResults());
617
+ }
618
+ isRequestedStoryOrChild(storyId, requestedStoryIds) {
619
+ if (requestedStoryIds.includes(storyId))
620
+ return !0;
621
+ let entry = this.store.getState().index.entries[storyId];
622
+ return entry?.type === "story" && !!entry.parent && requestedStoryIds.includes(entry.parent);
573
623
  }
574
624
  onTestRunEnd(endResult) {
575
- this.throttledFlushTestCaseResults.flush(), this.store.setState((s) => ({
576
- ...s,
577
- currentRun: {
578
- ...s.currentRun,
579
- // when the test run is finished, we can set the totalTestCount to the actual number of tests run
580
- // this number can be lower than the total number of tests we anticipated upfront
581
- // e.g. when some tests where skipped without us knowing about it upfront
582
- totalTestCount: endResult.totalTestCount,
583
- unhandledErrors: endResult.unhandledErrors,
584
- finishedAt: Date.now()
585
- }
586
- }));
625
+ this.throttledFlushTestCaseResults.flush(), this.store.setState((s) => {
626
+ let focusedRunTotal = s.currentRun.componentTestCount.success + s.currentRun.componentTestCount.error;
627
+ return {
628
+ ...s,
629
+ currentRun: {
630
+ ...s.currentRun,
631
+ // For focused runs, keep totals aligned with filtered case results.
632
+ // For full runs, use Vitest's reported total.
633
+ totalTestCount: s.currentRun.storyIds ? focusedRunTotal : endResult.totalTestCount,
634
+ unhandledErrors: endResult.unhandledErrors,
635
+ finishedAt: Date.now()
636
+ }
637
+ };
638
+ });
587
639
  }
588
640
  onCoverageCollected(coverageSummary) {
589
641
  this.store.setState((s) => ({
@@ -1,29 +1,29 @@
1
- import CJS_COMPAT_NODE_URL_g0psqpo75ib from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_g0psqpo75ib from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_g0psqpo75ib from "node:module";
1
+ import CJS_COMPAT_NODE_URL_kcvris1e0og from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_kcvris1e0og from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_kcvris1e0og from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_g0psqpo75ib.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_g0psqpo75ib.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_g0psqpo75ib.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_kcvris1e0og.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_kcvris1e0og.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_kcvris1e0og.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
  any
14
- } from "./_node-chunks/chunk-PBLJAZW7.js";
14
+ } from "./_node-chunks/chunk-ZYZKWOO3.js";
15
15
  import {
16
16
  DOCUMENTATION_LINK
17
- } from "./_node-chunks/chunk-YY2HJHG6.js";
17
+ } from "./_node-chunks/chunk-PPDGQAGO.js";
18
18
  import {
19
19
  require_dist
20
- } from "./_node-chunks/chunk-X2V34NMS.js";
20
+ } from "./_node-chunks/chunk-CH65VRNB.js";
21
21
  import {
22
22
  dirname,
23
23
  normalize,
24
24
  relative,
25
25
  resolve
26
- } from "./_node-chunks/chunk-CEAAKDGT.js";
26
+ } from "./_node-chunks/chunk-4X3EFM32.js";
27
27
  import {
28
28
  require_compare,
29
29
  require_constants,
@@ -33,11 +33,11 @@ import {
33
33
  require_parse_options,
34
34
  require_re,
35
35
  require_semver
36
- } from "./_node-chunks/chunk-YED2XXJM.js";
36
+ } from "./_node-chunks/chunk-AAOBFW7E.js";
37
37
  import {
38
38
  __commonJS,
39
39
  __toESM
40
- } from "./_node-chunks/chunk-V75YOJAB.js";
40
+ } from "./_node-chunks/chunk-CMEPFTWL.js";
41
41
 
42
42
  // ../../../node_modules/semver/functions/parse.js
43
43
  var require_parse = __commonJS({
@@ -895,13 +895,13 @@ var import_semver = __toESM(require_semver2(), 1), import_ts_dedent = __toESM(re
895
895
  async function getTemplatePath(name) {
896
896
  switch (name) {
897
897
  case "vitest.config.template":
898
- return import("./_node-chunks/vitest.config-DWELCQGH.js");
898
+ return import("./_node-chunks/vitest.config-HZ76KW4E.js");
899
899
  case "vitest.config.4.template":
900
- return import("./_node-chunks/vitest.config.4-3JCB7DY2.js");
900
+ return import("./_node-chunks/vitest.config.4-ZLHYFA4U.js");
901
901
  case "vitest.config.3.2.template":
902
- return import("./_node-chunks/vitest.config.3.2-FVRHETO4.js");
902
+ return import("./_node-chunks/vitest.config.3.2-DZXGDNUB.js");
903
903
  case "vitest.workspace.template":
904
- return import("./_node-chunks/vitest.workspace-EHG6SZIY.js");
904
+ return import("./_node-chunks/vitest.workspace-GDTAHSX6.js");
905
905
  default:
906
906
  throw new Error(`Unknown template: ${name}`);
907
907
  }
package/dist/preset.js CHANGED
@@ -1,10 +1,10 @@
1
- import CJS_COMPAT_NODE_URL_g0psqpo75ib from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_g0psqpo75ib from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_g0psqpo75ib from "node:module";
1
+ import CJS_COMPAT_NODE_URL_kcvris1e0og from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_kcvris1e0og from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_kcvris1e0og from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_g0psqpo75ib.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_g0psqpo75ib.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_g0psqpo75ib.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_kcvris1e0og.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_kcvris1e0og.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_kcvris1e0og.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
@@ -12,28 +12,30 @@ var require = CJS_COMPAT_NODE_MODULE_g0psqpo75ib.createRequire(import.meta.url);
12
12
  import {
13
13
  log,
14
14
  noop
15
- } from "./_node-chunks/chunk-BJDGFRVW.js";
15
+ } from "./_node-chunks/chunk-AXU25N75.js";
16
16
  import {
17
- ADDON_ID,
17
+ ADDON_ID2 as ADDON_ID,
18
18
  COVERAGE_DIRECTORY,
19
19
  STATUS_STORE_CHANNEL_EVENT_NAME,
20
20
  STORE_CHANNEL_EVENT_NAME,
21
21
  STORYBOOK_ADDON_TEST_CHANNEL,
22
22
  TEST_PROVIDER_STORE_CHANNEL_EVENT_NAME,
23
+ TRIGGER_TEST_RUN_REQUEST,
24
+ TRIGGER_TEST_RUN_RESPONSE,
23
25
  storeOptions
24
- } from "./_node-chunks/chunk-YY2HJHG6.js";
26
+ } from "./_node-chunks/chunk-PPDGQAGO.js";
25
27
  import {
26
28
  require_picocolors
27
- } from "./_node-chunks/chunk-MVGTYBTG.js";
29
+ } from "./_node-chunks/chunk-XMFVMTKT.js";
28
30
  import {
29
31
  require_dist
30
- } from "./_node-chunks/chunk-X2V34NMS.js";
32
+ } from "./_node-chunks/chunk-CH65VRNB.js";
31
33
  import {
32
34
  normalize
33
- } from "./_node-chunks/chunk-CEAAKDGT.js";
35
+ } from "./_node-chunks/chunk-4X3EFM32.js";
34
36
  import {
35
37
  __toESM
36
- } from "./_node-chunks/chunk-V75YOJAB.js";
38
+ } from "./_node-chunks/chunk-CMEPFTWL.js";
37
39
 
38
40
  // src/preset.ts
39
41
  import { mkdir } from "node:fs/promises";
@@ -47,6 +49,7 @@ import {
47
49
  experimental_UniversalStore,
48
50
  experimental_getTestProviderStore
49
51
  } from "storybook/internal/core-server";
52
+ import { logger } from "storybook/internal/node-logger";
50
53
  import { cleanPaths, oneWayHash, sanitizeError, telemetry } from "storybook/internal/telemetry";
51
54
 
52
55
  // ../../../node_modules/es-toolkit/dist/predicate/isPlainObject.mjs
@@ -444,7 +447,7 @@ var experimental_serverChannel = async (channel, options) => {
444
447
 
445
448
  Refer to the following documentation for more information: ${import_picocolors.default.yellow("https://storybook.js.org/docs/get-started/frameworks/nextjs-vite?ref=upgrade#choose-between-vite-and-webpack")}\n
446
449
  `), channel;
447
- let fsCache = createFileSystemCache({
450
+ let storyIndexGenerator = await options.presets.apply("storyIndexGenerator"), fsCache = createFileSystemCache({
448
451
  basePath: resolvePathInStorybookCache(ADDON_ID.replace("/", "-")),
449
452
  ns: "storybook",
450
453
  ttl: 336 * 60 * 60 * 1e3
@@ -458,6 +461,7 @@ var experimental_serverChannel = async (channel, options) => {
458
461
  initialState: {
459
462
  ...storeOptions.initialState,
460
463
  previewAnnotations: (previewAnnotations ?? []).concat(previewPath ?? []),
464
+ index: await storyIndexGenerator.getIndex(),
461
465
  ...selectCachedState(cachedState)
462
466
  },
463
467
  leader: !0
@@ -466,7 +470,14 @@ var experimental_serverChannel = async (channel, options) => {
466
470
  isEqual(selectCachedState(state), selectCachedState(previousState)) || fsCache.set("state", selectCachedState(state));
467
471
  });
468
472
  let testProviderStore = experimental_getTestProviderStore(ADDON_ID);
469
- if (store.subscribe("TRIGGER_RUN", (event, eventInfo) => {
473
+ if (storyIndexGenerator.onInvalidated(async () => {
474
+ try {
475
+ let index = await storyIndexGenerator.getIndex();
476
+ store.setState((s) => ({ ...s, index }));
477
+ } catch (error) {
478
+ logger.debug("Failed to update story index after invalidation, Error:"), logger.debug(error);
479
+ }
480
+ }), store.subscribe("TRIGGER_RUN", (event, eventInfo) => {
470
481
  testProviderStore.setState("test-provider-state:running"), store.setState((s) => ({
471
482
  ...s,
472
483
  fatalError: void 0
@@ -513,6 +524,48 @@ var experimental_serverChannel = async (channel, options) => {
513
524
  ...s,
514
525
  currentRun: { ...s.currentRun, coverageSummary: void 0, unhandledErrors: [] }
515
526
  }));
527
+ }), channel.on(TRIGGER_TEST_RUN_REQUEST, async (payload) => {
528
+ let { requestId, actor, storyIds, config: configOverride } = payload, sendResponse = (response) => {
529
+ channel.emit(TRIGGER_TEST_RUN_RESPONSE, { requestId, ...response });
530
+ };
531
+ await store.untilReady();
532
+ let {
533
+ currentRun: { startedAt, finishedAt },
534
+ config
535
+ } = store.getState();
536
+ if (startedAt && !finishedAt) {
537
+ sendResponse({
538
+ status: "error",
539
+ error: { message: "Tests are already running" }
540
+ });
541
+ return;
542
+ }
543
+ store.send({
544
+ type: "TRIGGER_RUN",
545
+ payload: {
546
+ storyIds,
547
+ triggeredBy: `external:${actor}`,
548
+ ...configOverride && {
549
+ configOverride: { ...config, ...configOverride }
550
+ }
551
+ }
552
+ });
553
+ let unsubscribe = store.subscribe((event) => {
554
+ switch (event.type) {
555
+ case "TEST_RUN_COMPLETED": {
556
+ unsubscribe(), sendResponse({ status: "completed", result: event.payload });
557
+ return;
558
+ }
559
+ case "FATAL_ERROR": {
560
+ unsubscribe(), sendResponse({ status: "error", error: event.payload });
561
+ return;
562
+ }
563
+ case "CANCEL_RUN": {
564
+ unsubscribe(), sendResponse({ status: "cancelled" });
565
+ return;
566
+ }
567
+ }
568
+ });
516
569
  }), !core.disableTelemetry) {
517
570
  let enableCrashReports = core.enableCrashReports || options.enableCrashReports;
518
571
  channel.on(STORYBOOK_ADDON_TEST_CHANNEL, (event) => {
@@ -1,10 +1,10 @@
1
- import CJS_COMPAT_NODE_URL_g0psqpo75ib from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_g0psqpo75ib from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_g0psqpo75ib from "node:module";
1
+ import CJS_COMPAT_NODE_URL_kcvris1e0og from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_kcvris1e0og from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_kcvris1e0og from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_g0psqpo75ib.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_g0psqpo75ib.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_g0psqpo75ib.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_kcvris1e0og.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_kcvris1e0og.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_kcvris1e0og.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
@@ -13,7 +13,7 @@ import {
13
13
  __commonJS,
14
14
  __require,
15
15
  __toESM
16
- } from "../_node-chunks/chunk-V75YOJAB.js";
16
+ } from "../_node-chunks/chunk-CMEPFTWL.js";
17
17
 
18
18
  // ../../../node_modules/tree-kill/index.js
19
19
  var require_tree_kill = __commonJS({