@storybook/addon-vitest 0.0.0-pr-32717-sha-be0e21bb → 0.0.0-pr-32882-sha-d65d0e7f

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,29 +1,33 @@
1
- import CJS_COMPAT_NODE_URL_xzhl7pzrhxc from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_xzhl7pzrhxc from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_xzhl7pzrhxc from "node:module";
1
+ import CJS_COMPAT_NODE_URL_2v687h26vhe from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_2v687h26vhe from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_2v687h26vhe from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_xzhl7pzrhxc.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_xzhl7pzrhxc.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_xzhl7pzrhxc.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_2v687h26vhe.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_2v687h26vhe.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_2v687h26vhe.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
+ execa,
13
14
  resolvePackageDir
14
- } from "./_node-chunks/chunk-TXAYOS7Q.js";
15
+ } from "./_node-chunks/chunk-POD5FBDR.js";
15
16
  import {
16
- any
17
- } from "./_node-chunks/chunk-LRZSVFFB.js";
17
+ any,
18
+ getAddonNames,
19
+ up
20
+ } from "./_node-chunks/chunk-PWT7VWXJ.js";
18
21
  import {
19
- DOCUMENTATION_LINK
20
- } from "./_node-chunks/chunk-EM5CDNWG.js";
22
+ DOCUMENTATION_LINK,
23
+ SUPPORTED_FRAMEWORKS
24
+ } from "./_node-chunks/chunk-VETR5WKO.js";
21
25
  import {
22
26
  dirname,
23
27
  join,
24
28
  relative,
25
29
  resolve
26
- } from "./_node-chunks/chunk-THU64LL5.js";
30
+ } from "./_node-chunks/chunk-RFFTF3P3.js";
27
31
  import {
28
32
  require_compare,
29
33
  require_constants,
@@ -33,12 +37,12 @@ import {
33
37
  require_parse_options,
34
38
  require_re,
35
39
  require_semver
36
- } from "./_node-chunks/chunk-D3P7SNRB.js";
40
+ } from "./_node-chunks/chunk-A7VETTJF.js";
37
41
  import {
38
42
  __commonJS,
39
43
  __name,
40
44
  __toESM
41
- } from "./_node-chunks/chunk-NDZSUWTL.js";
45
+ } from "./_node-chunks/chunk-ZGPYNFM4.js";
42
46
 
43
47
  // ../../node_modules/semver/functions/parse.js
44
48
  var require_parse = __commonJS({
@@ -360,7 +364,7 @@ var require_coerce = __commonJS({
360
364
  var SemVer = require_semver();
361
365
  var parse = require_parse();
362
366
  var { safeRe: re, t } = require_re();
363
- var coerce = /* @__PURE__ */ __name((version, options) => {
367
+ var coerce2 = /* @__PURE__ */ __name((version, options) => {
364
368
  if (version instanceof SemVer) {
365
369
  return version;
366
370
  }
@@ -395,7 +399,7 @@ var require_coerce = __commonJS({
395
399
  const build = options.includePrerelease && match[6] ? `+${match[6]}` : "";
396
400
  return parse(`${major}.${minor}.${patch}${prerelease}${build}`, options);
397
401
  }, "coerce");
398
- module.exports = coerce;
402
+ module.exports = coerce2;
399
403
  }
400
404
  });
401
405
 
@@ -968,7 +972,7 @@ var require_max_satisfying = __commonJS({
968
972
  "use strict";
969
973
  var SemVer = require_semver();
970
974
  var Range = require_range();
971
- var maxSatisfying = /* @__PURE__ */ __name((versions2, range, options) => {
975
+ var maxSatisfying = /* @__PURE__ */ __name((versions, range, options) => {
972
976
  let max = null;
973
977
  let maxSV = null;
974
978
  let rangeObj = null;
@@ -977,7 +981,7 @@ var require_max_satisfying = __commonJS({
977
981
  } catch (er) {
978
982
  return null;
979
983
  }
980
- versions2.forEach((v) => {
984
+ versions.forEach((v) => {
981
985
  if (rangeObj.test(v)) {
982
986
  if (!max || maxSV.compare(v) === -1) {
983
987
  max = v;
@@ -997,7 +1001,7 @@ var require_min_satisfying = __commonJS({
997
1001
  "use strict";
998
1002
  var SemVer = require_semver();
999
1003
  var Range = require_range();
1000
- var minSatisfying = /* @__PURE__ */ __name((versions2, range, options) => {
1004
+ var minSatisfying = /* @__PURE__ */ __name((versions, range, options) => {
1001
1005
  let min = null;
1002
1006
  let minSV = null;
1003
1007
  let rangeObj = null;
@@ -1006,7 +1010,7 @@ var require_min_satisfying = __commonJS({
1006
1010
  } catch (er) {
1007
1011
  return null;
1008
1012
  }
1009
- versions2.forEach((v) => {
1013
+ versions.forEach((v) => {
1010
1014
  if (rangeObj.test(v)) {
1011
1015
  if (!min || minSV.compare(v) === 1) {
1012
1016
  min = v;
@@ -1204,11 +1208,11 @@ var require_simplify = __commonJS({
1204
1208
  "use strict";
1205
1209
  var satisfies2 = require_satisfies();
1206
1210
  var compare = require_compare();
1207
- module.exports = (versions2, range, options) => {
1211
+ module.exports = (versions, range, options) => {
1208
1212
  const set = [];
1209
1213
  let first = null;
1210
1214
  let prev = null;
1211
- const v = versions2.sort((a, b) => compare(a, b, options));
1215
+ const v = versions.sort((a, b) => compare(a, b, options));
1212
1216
  for (const version of v) {
1213
1217
  const included = satisfies2(version, range, options);
1214
1218
  if (included) {
@@ -1440,7 +1444,7 @@ var require_semver2 = __commonJS({
1440
1444
  var gte = require_gte();
1441
1445
  var lte = require_lte();
1442
1446
  var cmp = require_cmp();
1443
- var coerce = require_coerce();
1447
+ var coerce2 = require_coerce();
1444
1448
  var Comparator = require_comparator();
1445
1449
  var Range = require_range();
1446
1450
  var satisfies2 = require_satisfies();
@@ -1478,7 +1482,7 @@ var require_semver2 = __commonJS({
1478
1482
  gte,
1479
1483
  lte,
1480
1484
  cmp,
1481
- coerce,
1485
+ coerce: coerce2,
1482
1486
  Comparator,
1483
1487
  Range,
1484
1488
  satisfies: satisfies2,
@@ -1509,24 +1513,56 @@ var require_semver2 = __commonJS({
1509
1513
  import { existsSync } from "node:fs";
1510
1514
  import * as fs2 from "node:fs/promises";
1511
1515
  import { writeFile } from "node:fs/promises";
1512
- import { babelParse, generate } from "storybook/internal/babel";
1513
- import { AddonVitestService } from "storybook/internal/cli";
1516
+ import { isAbsolute, posix, sep } from "node:path";
1517
+ import { fileURLToPath, pathToFileURL } from "node:url";
1518
+ import { babelParse, generate, traverse } from "storybook/internal/babel";
1514
1519
  import {
1515
1520
  JsPackageManagerFactory,
1516
1521
  formatFileContent,
1522
+ getInterpretedFile,
1517
1523
  getProjectRoot,
1518
- getStorybookInfo,
1519
- versions
1524
+ isCI as isCI2,
1525
+ loadMainConfig,
1526
+ scanAndTransformFiles,
1527
+ transformImportFiles
1520
1528
  } from "storybook/internal/common";
1521
- import { CLI_COLORS } from "storybook/internal/node-logger";
1522
- import {
1523
- AddonVitestPostinstallError,
1524
- AddonVitestPostinstallPrerequisiteCheckError
1525
- } from "storybook/internal/server-errors";
1526
- import { SupportedFramework } from "storybook/internal/types";
1529
+ import { experimental_loadStorybook } from "storybook/internal/core-server";
1530
+ import { readConfig, writeConfig } from "storybook/internal/csf-tools";
1531
+ import { logger as logger2 } from "storybook/internal/node-logger";
1532
+
1533
+ // ../../node_modules/empathic/package.mjs
1534
+ function up2(options) {
1535
+ return up("package.json", options);
1536
+ }
1537
+ __name(up2, "up");
1538
+
1539
+ // src/postinstall.ts
1527
1540
  var import_semver = __toESM(require_semver2(), 1);
1541
+ import prompts from "prompts";
1528
1542
  import { dedent } from "ts-dedent";
1529
1543
 
1544
+ // src/postinstall-logger.ts
1545
+ import { isCI } from "storybook/internal/common";
1546
+ import { colors, logger } from "storybook/internal/node-logger";
1547
+ var fancy = process.platform !== "win32" || isCI() || process.env.TERM === "xterm-256color";
1548
+ var step = colors.gray("\u203A");
1549
+ var info = colors.blue(fancy ? "\u2139" : "i");
1550
+ var success = colors.green(fancy ? "\u2714" : "\u221A");
1551
+ var warning = colors.orange(fancy ? "\u26A0" : "\u203C");
1552
+ var error = colors.red(fancy ? "\u2716" : "\xD7");
1553
+ var baseOptions = {
1554
+ borderStyle: "round",
1555
+ padding: 1
1556
+ };
1557
+ var print = /* @__PURE__ */ __name((message, options) => {
1558
+ logger.line(1);
1559
+ logger.logBox(message, { ...baseOptions, ...options });
1560
+ }, "print");
1561
+ var printInfo = /* @__PURE__ */ __name((title, message, options) => print(message, { borderColor: "blue", title, ...options }), "printInfo");
1562
+ var printWarning = /* @__PURE__ */ __name((title, message, options) => print(message, { borderColor: "yellow", title, ...options }), "printWarning");
1563
+ var printError = /* @__PURE__ */ __name((title, message, options) => print(message, { borderColor: "red", title, ...options }), "printError");
1564
+ var printSuccess = /* @__PURE__ */ __name((title, message, options) => print(message, { borderColor: "green", title, ...options }), "printSuccess");
1565
+
1530
1566
  // src/updateVitestFile.ts
1531
1567
  import * as fs from "node:fs/promises";
1532
1568
  var loadTemplate = /* @__PURE__ */ __name(async (name, replacements) => {
@@ -1580,7 +1616,10 @@ var updateConfigFile = /* @__PURE__ */ __name((source, target) => {
1580
1616
  } else if (targetExportDefault.declaration.type === "CallExpression" && targetExportDefault.declaration.callee.type === "Identifier" && targetExportDefault.declaration.callee.name === "defineConfig" && targetExportDefault.declaration.arguments[0]?.type === "ObjectExpression") {
1581
1617
  canHandleConfig = true;
1582
1618
  } else if (targetExportDefault.declaration.type === "CallExpression" && targetExportDefault.declaration.callee.type === "Identifier" && targetExportDefault.declaration.callee.name === "mergeConfig" && targetExportDefault.declaration.arguments.length >= 2) {
1583
- canHandleConfig = true;
1619
+ const defineConfigNodes = targetExportDefault.declaration.arguments.filter(
1620
+ (arg) => arg?.type === "CallExpression" && arg.callee.type === "Identifier" && arg.callee.name === "defineConfig" && arg.arguments[0]?.type === "ObjectExpression"
1621
+ );
1622
+ canHandleConfig = defineConfigNodes.length > 0;
1584
1623
  }
1585
1624
  if (!canHandleConfig) {
1586
1625
  return false;
@@ -1613,24 +1652,20 @@ var updateConfigFile = /* @__PURE__ */ __name((source, target) => {
1613
1652
  mergeProperties(properties, exportDefault.declaration.arguments[0].properties);
1614
1653
  updated = true;
1615
1654
  } else if (exportDefault.declaration.type === "CallExpression" && exportDefault.declaration.callee.type === "Identifier" && exportDefault.declaration.callee.name === "mergeConfig" && exportDefault.declaration.arguments.length >= 2) {
1616
- const configObjectNodes = [];
1617
- for (const arg of exportDefault.declaration.arguments) {
1618
- if (arg?.type === "CallExpression" && arg.callee.type === "Identifier" && arg.callee.name === "defineConfig" && arg.arguments[0]?.type === "ObjectExpression") {
1619
- configObjectNodes.push(arg.arguments[0]);
1620
- } else if (arg?.type === "ObjectExpression") {
1621
- configObjectNodes.push(arg);
1622
- }
1623
- }
1624
- const configObjectWithTest = configObjectNodes.find(
1625
- (obj) => obj.properties.some(
1655
+ const defineConfigNodes = exportDefault.declaration.arguments.filter(
1656
+ (arg) => arg?.type === "CallExpression" && arg.callee.type === "Identifier" && arg.callee.name === "defineConfig" && arg.arguments[0]?.type === "ObjectExpression"
1657
+ );
1658
+ const defineConfigNodeWithTest = defineConfigNodes.find(
1659
+ (node) => node.arguments[0].type === "ObjectExpression" && node.arguments[0].properties.some(
1626
1660
  (p) => p.type === "ObjectProperty" && p.key.type === "Identifier" && p.key.name === "test"
1627
1661
  )
1628
1662
  );
1629
- const targetConfigObject = configObjectWithTest || configObjectNodes[0];
1630
- if (!targetConfigObject) {
1663
+ const defineConfigNode = defineConfigNodeWithTest || defineConfigNodes[0];
1664
+ if (!defineConfigNode) {
1631
1665
  return false;
1632
1666
  }
1633
- const existingTestProp = targetConfigObject.properties.find(
1667
+ const defineConfigProps = defineConfigNode.arguments[0];
1668
+ const existingTestProp = defineConfigProps.properties.find(
1634
1669
  (p) => p.type === "ObjectProperty" && p.key.type === "Identifier" && p.key.name === "test"
1635
1670
  );
1636
1671
  if (existingTestProp && existingTestProp.value.type === "ObjectExpression") {
@@ -1642,16 +1677,6 @@ var updateConfigFile = /* @__PURE__ */ __name((source, target) => {
1642
1677
  (p) => p.type === "ObjectProperty" && p.key.type === "Identifier" && (p.key.name === "workspace" || p.key.name === "projects")
1643
1678
  );
1644
1679
  if (workspaceOrProjectsProp && workspaceOrProjectsProp.value.type === "ArrayExpression") {
1645
- const coverageProp = existingTestProp.value.properties.find(
1646
- (p) => p.type === "ObjectProperty" && p.key.type === "Identifier" && p.key.name === "coverage"
1647
- );
1648
- const testPropsWithoutCoverage = existingTestProp.value.properties.filter(
1649
- (p) => p !== coverageProp
1650
- );
1651
- const testConfigForProject = {
1652
- type: "ObjectExpression",
1653
- properties: testPropsWithoutCoverage
1654
- };
1655
1680
  const existingTestProject = {
1656
1681
  type: "ObjectExpression",
1657
1682
  properties: [
@@ -1665,28 +1690,25 @@ var updateConfigFile = /* @__PURE__ */ __name((source, target) => {
1665
1690
  {
1666
1691
  type: "ObjectProperty",
1667
1692
  key: { type: "Identifier", name: "test" },
1668
- value: testConfigForProject,
1693
+ value: existingTestProp.value,
1669
1694
  computed: false,
1670
1695
  shorthand: false
1671
1696
  }
1672
1697
  ]
1673
1698
  };
1674
1699
  workspaceOrProjectsProp.value.elements.unshift(existingTestProject);
1675
- targetConfigObject.properties = targetConfigObject.properties.filter(
1700
+ defineConfigProps.properties = defineConfigProps.properties.filter(
1676
1701
  (p) => p !== existingTestProp
1677
1702
  );
1678
- if (coverageProp && templateTestProp.value.type === "ObjectExpression") {
1679
- templateTestProp.value.properties.unshift(coverageProp);
1680
- }
1681
- mergeProperties(properties, targetConfigObject.properties);
1703
+ mergeProperties(properties, defineConfigProps.properties);
1682
1704
  } else {
1683
- mergeProperties(properties, targetConfigObject.properties);
1705
+ mergeProperties(properties, defineConfigProps.properties);
1684
1706
  }
1685
1707
  } else {
1686
- mergeProperties(properties, targetConfigObject.properties);
1708
+ mergeProperties(properties, defineConfigProps.properties);
1687
1709
  }
1688
1710
  } else {
1689
- mergeProperties(properties, targetConfigObject.properties);
1711
+ mergeProperties(properties, defineConfigProps.properties);
1690
1712
  }
1691
1713
  updated = true;
1692
1714
  }
@@ -1735,133 +1757,274 @@ var updateWorkspaceFile = /* @__PURE__ */ __name((source, target) => {
1735
1757
  var ADDON_NAME = "@storybook/addon-vitest";
1736
1758
  var EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".cts", ".mts", ".cjs", ".mjs"];
1737
1759
  var addonA11yName = "@storybook/addon-a11y";
1760
+ var hasErrors = false;
1761
+ function nameMatches(name, pattern) {
1762
+ if (name === pattern) {
1763
+ return true;
1764
+ }
1765
+ if (name.includes(`${pattern}${sep}`)) {
1766
+ return true;
1767
+ }
1768
+ if (name.includes(`${pattern}${posix.sep}`)) {
1769
+ return true;
1770
+ }
1771
+ return false;
1772
+ }
1773
+ __name(nameMatches, "nameMatches");
1774
+ var logErrors = /* @__PURE__ */ __name((...args) => {
1775
+ hasErrors = true;
1776
+ printError(...args);
1777
+ }, "logErrors");
1778
+ var findFile = /* @__PURE__ */ __name((basename, extensions = EXTENSIONS) => any(
1779
+ extensions.map((ext) => basename + ext),
1780
+ { last: getProjectRoot() }
1781
+ ), "findFile");
1738
1782
  async function postInstall(options) {
1739
- const errors = [];
1740
- const { logger, prompt } = options;
1783
+ printSuccess(
1784
+ "\u{1F44B} Howdy!",
1785
+ dedent`
1786
+ I'm the installation helper for ${ADDON_NAME}
1787
+
1788
+ Hold on for a moment while I look at your project and get it set up...
1789
+ `
1790
+ );
1741
1791
  const packageManager = JsPackageManagerFactory.getPackageManager({
1742
1792
  force: options.packageManager
1743
1793
  });
1744
- const findFile = /* @__PURE__ */ __name((basename, extensions = EXTENSIONS) => any(
1745
- extensions.map((ext) => basename + ext),
1746
- { last: getProjectRoot(), cwd: options.configDir }
1747
- ), "findFile");
1748
1794
  const vitestVersionSpecifier = await packageManager.getInstalledVersion("vitest");
1795
+ const coercedVitestVersion = vitestVersionSpecifier ? (0, import_semver.coerce)(vitestVersionSpecifier) : null;
1749
1796
  const isVitest3_2To4 = vitestVersionSpecifier ? (0, import_semver.satisfies)(vitestVersionSpecifier, ">=3.2.0 <4.0.0") : false;
1750
1797
  const isVitest4OrNewer = vitestVersionSpecifier ? (0, import_semver.satisfies)(vitestVersionSpecifier, ">=4.0.0") : true;
1751
- const info = await getStorybookInfo(options.configDir);
1798
+ const info2 = await getStorybookInfo(options);
1752
1799
  const allDeps = packageManager.getAllDependencies();
1753
- const addonVitestService = new AddonVitestService();
1754
- const compatibilityResult = await addonVitestService.validateCompatibility({
1755
- packageManager,
1756
- framework: info.framework,
1757
- builder: info.builder
1758
- });
1759
- let result = null;
1760
- if (!compatibilityResult.compatible && compatibilityResult.reasons) {
1761
- const reasons = compatibilityResult.reasons.map((r) => `\u2022 ${CLI_COLORS.error(r)}`);
1762
- reasons.unshift(dedent`
1763
- Automated setup failed
1764
- We have found incompatibilities due to the following package incompatibilities:
1765
- `);
1766
- reasons.push(
1767
- dedent`
1768
- You can fix these issues and rerun the command to reinstall. If you wish to roll back the installation, remove ${ADDON_NAME} from the "addons" array
1769
- in your main Storybook config file and remove the dependency from your package.json file.
1800
+ const dependencies = [
1801
+ "vitest",
1802
+ "playwright",
1803
+ isVitest4OrNewer ? "@vitest/browser-playwright" : "@vitest/browser"
1804
+ ];
1805
+ const uniqueDependencies = dependencies.filter((p) => !allDeps[p]);
1806
+ const mainJsPath = getInterpretedFile(resolve(options.configDir, "main"));
1807
+ const config = await readConfig(mainJsPath);
1808
+ const hasCustomWebpackConfig = !!config.getFieldNode(["webpackFinal"]);
1809
+ const isInteractive = process.stdout.isTTY && !isCI2();
1810
+ if (nameMatches(info2.frameworkPackageName, "@storybook/nextjs") && !hasCustomWebpackConfig) {
1811
+ const out = options.yes || !isInteractive ? { migrateToNextjsVite: !!options.yes } : await prompts({
1812
+ type: "confirm",
1813
+ name: "migrateToNextjsVite",
1814
+ message: dedent`
1815
+ The addon requires the use of @storybook/nextjs-vite to work with Next.js.
1816
+ https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#install-and-set-up
1770
1817
 
1771
- Please check the documentation for more information about its requirements and installation:
1772
- https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}
1773
- `
1774
- );
1775
- result = reasons.map((r) => r.trim()).join("\n\n");
1776
- }
1777
- if (result) {
1778
- logger.error(result);
1779
- throw new AddonVitestPostinstallPrerequisiteCheckError({
1780
- reasons: compatibilityResult.reasons
1818
+ Do you want to migrate?
1819
+ `,
1820
+ initial: true
1781
1821
  });
1822
+ if (out.migrateToNextjsVite) {
1823
+ await packageManager.addDependencies({ type: "devDependencies", skipInstall: true }, [
1824
+ "@storybook/nextjs-vite"
1825
+ ]);
1826
+ await packageManager.removeDependencies(["@storybook/nextjs"]);
1827
+ traverse(config._ast, {
1828
+ StringLiteral(path) {
1829
+ if (path.node.value === "@storybook/nextjs") {
1830
+ path.node.value = "@storybook/nextjs-vite";
1831
+ }
1832
+ }
1833
+ });
1834
+ await writeConfig(config, mainJsPath);
1835
+ info2.frameworkPackageName = "@storybook/nextjs-vite";
1836
+ info2.builderPackageName = "@storybook/builder-vite";
1837
+ await scanAndTransformFiles({
1838
+ promptMessage: "Enter a glob to scan for all @storybook/nextjs imports to substitute with @storybook/nextjs-vite:",
1839
+ force: options.yes,
1840
+ dryRun: false,
1841
+ transformFn: /* @__PURE__ */ __name((files, options2, dryRun) => transformImportFiles(files, options2, dryRun), "transformFn"),
1842
+ transformOptions: {
1843
+ "@storybook/nextjs": "@storybook/nextjs-vite"
1844
+ }
1845
+ });
1846
+ }
1782
1847
  }
1783
- if (!options.skipDependencyManagement) {
1784
- const versionedDependencies = await addonVitestService.collectDependencies(packageManager);
1785
- if (info.framework === SupportedFramework.NEXTJS) {
1786
- const allDeps2 = packageManager.getAllDependencies();
1787
- if (!allDeps2["@storybook/nextjs-vite"]) {
1848
+ const annotationsImport = SUPPORTED_FRAMEWORKS.find(
1849
+ (f) => nameMatches(info2.frameworkPackageName, f)
1850
+ ) ? info2.frameworkPackageName === "@storybook/nextjs" ? "@storybook/nextjs-vite" : info2.frameworkPackageName : null;
1851
+ const isRendererSupported = !!annotationsImport;
1852
+ const prerequisiteCheck = /* @__PURE__ */ __name(async () => {
1853
+ const reasons = [];
1854
+ if (hasCustomWebpackConfig) {
1855
+ reasons.push("\u2022 The addon can not be used with a custom Webpack configuration.");
1856
+ }
1857
+ if (!nameMatches(info2.frameworkPackageName, "@storybook/nextjs") && !nameMatches(info2.builderPackageName, "@storybook/builder-vite")) {
1858
+ reasons.push(
1859
+ "\u2022 The addon can only be used with a Vite-based Storybook framework or Next.js."
1860
+ );
1861
+ }
1862
+ if (!isRendererSupported) {
1863
+ reasons.push(dedent`
1864
+ • The addon cannot yet be used with ${info2.frameworkPackageName}
1865
+ `);
1866
+ }
1867
+ if (coercedVitestVersion && !(0, import_semver.satisfies)(coercedVitestVersion, ">=3.0.0")) {
1868
+ reasons.push(dedent`
1869
+ • The addon requires Vitest 3.0.0 or higher. You are currently using ${vitestVersionSpecifier}.
1870
+ Please update all of your Vitest dependencies and try again.
1871
+ `);
1872
+ }
1873
+ const mswVersionSpecifier = await packageManager.getInstalledVersion("msw");
1874
+ const coercedMswVersion = mswVersionSpecifier ? (0, import_semver.coerce)(mswVersionSpecifier) : null;
1875
+ if (coercedMswVersion && !(0, import_semver.satisfies)(coercedMswVersion, ">=2.0.0")) {
1876
+ reasons.push(dedent`
1877
+ • The addon uses Vitest behind the scenes, which supports only version 2 and above of MSW. However, we have detected version ${coercedMswVersion.version} in this project.
1878
+ Please update the 'msw' package and try again.
1879
+ `);
1880
+ }
1881
+ if (nameMatches(info2.frameworkPackageName, "@storybook/nextjs")) {
1882
+ const nextVersion = await packageManager.getInstalledVersion("next");
1883
+ if (!nextVersion) {
1884
+ reasons.push(dedent`
1885
+ • You are using @storybook/nextjs without having "next" installed.
1886
+ Please install "next" or use a different Storybook framework integration and try again.
1887
+ `);
1788
1888
  }
1789
1889
  }
1790
- const v8Version = await packageManager.getInstalledVersion("@vitest/coverage-v8");
1791
- const istanbulVersion = await packageManager.getInstalledVersion("@vitest/coverage-istanbul");
1792
- if (!v8Version && !istanbulVersion) {
1793
- logger.step(
1890
+ if (reasons.length > 0) {
1891
+ reasons.unshift(
1892
+ `@storybook/addon-vitest's automated setup failed due to the following package incompatibilities:`
1893
+ );
1894
+ reasons.push("--------------------------------");
1895
+ reasons.push(
1794
1896
  dedent`
1795
- You don't seem to have a coverage reporter installed. Vitest needs either V8 or Istanbul to generate coverage reports.
1796
-
1797
- Adding "@vitest/coverage-v8" to enable coverage reporting.
1798
- Read more about Vitest coverage providers at https://vitest.dev/guide/coverage.html#coverage-providers
1897
+ You can fix these issues and rerun the command to reinstall. If you wish to roll back the installation, remove ${ADDON_NAME} from the "addons" array
1898
+ in your main Storybook config file and remove the dependency from your package.json file.
1799
1899
  `
1800
1900
  );
1901
+ if (!isRendererSupported) {
1902
+ reasons.push(
1903
+ dedent`
1904
+ Please check the documentation for more information about its requirements and installation:
1905
+ https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}
1906
+ `
1907
+ );
1908
+ } else {
1909
+ reasons.push(
1910
+ dedent`
1911
+ Fear not, however, you can follow the manual installation process instead at:
1912
+ https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#manual-setup
1913
+ `
1914
+ );
1915
+ }
1916
+ return reasons.map((r) => r.trim()).join("\n\n");
1801
1917
  }
1802
- if (versionedDependencies.length > 0) {
1803
- logger.step("Adding dependencies to your package.json");
1804
- logger.log(" " + versionedDependencies.join(", "));
1805
- await packageManager.addDependencies(
1806
- { type: "devDependencies", skipInstall: true },
1807
- versionedDependencies
1808
- );
1918
+ return null;
1919
+ }, "prerequisiteCheck");
1920
+ const result = await prerequisiteCheck();
1921
+ if (result) {
1922
+ logErrors("\u26D4\uFE0F Sorry!", result);
1923
+ logger2.line(1);
1924
+ return;
1925
+ }
1926
+ if (info2.frameworkPackageName === "@storybook/nextjs") {
1927
+ printInfo(
1928
+ "\u{1F37F} Just so you know...",
1929
+ dedent`
1930
+ It looks like you're using Next.js.
1931
+
1932
+ Adding "@storybook/nextjs-vite/vite-plugin" so you can use it with Vitest.
1933
+
1934
+ More info about the plugin at https://github.com/storybookjs/vite-plugin-storybook-nextjs
1935
+ `
1936
+ );
1937
+ try {
1938
+ const storybookVersion = await packageManager.getInstalledVersion("storybook");
1939
+ uniqueDependencies.push(`@storybook/nextjs-vite@^${storybookVersion}`);
1940
+ } catch (e) {
1941
+ console.error("Failed to install @storybook/nextjs-vite. Please install it manually");
1809
1942
  }
1810
- if (!options.skipInstall) {
1811
- await packageManager.installDependencies();
1943
+ }
1944
+ const v8Version = await packageManager.getInstalledVersion("@vitest/coverage-v8");
1945
+ const istanbulVersion = await packageManager.getInstalledVersion("@vitest/coverage-istanbul");
1946
+ if (!v8Version && !istanbulVersion) {
1947
+ printInfo(
1948
+ "\u{1F648} Let me cover this for you",
1949
+ dedent`
1950
+ You don't seem to have a coverage reporter installed. Vitest needs either V8 or Istanbul to generate coverage reports.
1951
+
1952
+ Adding "@vitest/coverage-v8" to enable coverage reporting.
1953
+ Read more about Vitest coverage providers at https://vitest.dev/guide/coverage.html#coverage-providers
1954
+ `
1955
+ );
1956
+ uniqueDependencies.push(`@vitest/coverage-v8`);
1957
+ }
1958
+ const versionedDependencies = uniqueDependencies.map((p) => {
1959
+ if (p.includes("vitest")) {
1960
+ return vitestVersionSpecifier ? `${p}@${vitestVersionSpecifier}` : p;
1812
1961
  }
1962
+ return p;
1963
+ });
1964
+ if (versionedDependencies.length > 0) {
1965
+ await packageManager.addDependencies(
1966
+ { type: "devDependencies", skipInstall: true },
1967
+ versionedDependencies
1968
+ );
1969
+ logger2.line(1);
1970
+ logger2.plain(`${step} Installing dependencies:`);
1971
+ logger2.plain(" " + versionedDependencies.join(", "));
1813
1972
  }
1814
- if (!options.skipDependencyManagement) {
1815
- if (!options.skipInstall) {
1816
- const playwrightErrors = await addonVitestService.installPlaywright(packageManager, {
1817
- yes: options.yes
1973
+ await packageManager.installDependencies();
1974
+ logger2.line(1);
1975
+ if (options.skipInstall) {
1976
+ logger2.plain("Skipping Playwright installation, please run this command manually:");
1977
+ logger2.plain(" npx playwright install chromium --with-deps");
1978
+ } else {
1979
+ logger2.plain(`${step} Configuring Playwright with Chromium (this might take some time):`);
1980
+ logger2.plain(" npx playwright install chromium --with-deps");
1981
+ try {
1982
+ await packageManager.executeCommand({
1983
+ command: "npx",
1984
+ args: ["playwright", "install", "chromium", "--with-deps"]
1818
1985
  });
1819
- errors.push(...playwrightErrors);
1820
- } else {
1821
- logger.warn(dedent`
1822
- Playwright browser binaries installation skipped. Please run the following command manually later:
1823
- ${CLI_COLORS.cta("npx playwright install chromium --with-deps")}
1824
- `);
1986
+ } catch (e) {
1987
+ console.error("Failed to install Playwright. Please install it manually");
1825
1988
  }
1826
1989
  }
1827
1990
  const fileExtension = allDeps.typescript || findFile("tsconfig", [...EXTENSIONS, ".json"]) ? "ts" : "js";
1828
1991
  const vitestSetupFile = resolve(options.configDir, `vitest.setup.${fileExtension}`);
1829
1992
  if (existsSync(vitestSetupFile)) {
1830
- const errorMessage = dedent`
1831
- Found an existing Vitest setup file:
1832
- ${vitestSetupFile}
1833
- Please refer to the documentation to complete the setup manually:
1834
- https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#manual-setup
1835
- `;
1836
- logger.line();
1837
- logger.error(`${errorMessage}
1838
- `);
1839
- errors.push("Found existing Vitest setup file");
1840
- } else {
1841
- logger.step(`Creating a Vitest setup file for Storybook:`);
1842
- logger.log(`${vitestSetupFile}
1843
- `);
1844
- const previewExists = EXTENSIONS.map((ext) => resolve(options.configDir, `preview${ext}`)).some(
1845
- existsSync
1846
- );
1847
- const annotationsImport = info.frameworkPackage;
1848
- const imports = [`import { setProjectAnnotations } from '${annotationsImport}';`];
1849
- const projectAnnotations = [];
1850
- if (previewExists) {
1851
- imports.push(`import * as projectAnnotations from './preview';`);
1852
- projectAnnotations.push("projectAnnotations");
1853
- }
1854
- await writeFile(
1855
- vitestSetupFile,
1993
+ logErrors(
1994
+ "\u{1F6A8} Oh no!",
1856
1995
  dedent`
1996
+ Found an existing Vitest setup file:
1997
+ ${vitestSetupFile}
1998
+
1999
+ Please refer to the documentation to complete the setup manually:
2000
+ https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#manual-setup
2001
+ `
2002
+ );
2003
+ logger2.line(1);
2004
+ return;
2005
+ }
2006
+ logger2.line(1);
2007
+ logger2.plain(`${step} Creating a Vitest setup file for Storybook:`);
2008
+ logger2.plain(` ${vitestSetupFile}`);
2009
+ const previewExists = EXTENSIONS.map((ext) => resolve(options.configDir, `preview${ext}`)).some(
2010
+ existsSync
2011
+ );
2012
+ const imports = [`import { setProjectAnnotations } from '${annotationsImport}';`];
2013
+ const projectAnnotations = [];
2014
+ if (previewExists) {
2015
+ imports.push(`import * as projectAnnotations from './preview';`);
2016
+ projectAnnotations.push("projectAnnotations");
2017
+ }
2018
+ await writeFile(
2019
+ vitestSetupFile,
2020
+ dedent`
1857
2021
  ${imports.join("\n")}
1858
2022
 
1859
2023
  // This is an important step to apply the right configuration when testing your stories.
1860
2024
  // More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
1861
2025
  setProjectAnnotations([${projectAnnotations.join(", ")}]);
1862
2026
  `
1863
- );
1864
- }
2027
+ );
1865
2028
  const vitestWorkspaceFile = findFile("vitest.workspace", [".ts", ".js", ".json"]);
1866
2029
  const viteConfigFile = findFile("vite.config");
1867
2030
  const vitestConfigFile = findFile("vitest.config");
@@ -1893,12 +2056,14 @@ async function postInstall(options) {
1893
2056
  const target = babelParse(workspaceFile);
1894
2057
  const updated = updateWorkspaceFile(source, target);
1895
2058
  if (updated) {
1896
- logger.step(`Updating your Vitest workspace file...`);
1897
- logger.log(`${vitestWorkspaceFile}`);
2059
+ logger2.line(1);
2060
+ logger2.plain(`${step} Updating your Vitest workspace file:`);
2061
+ logger2.plain(` ${vitestWorkspaceFile}`);
1898
2062
  const formattedContent = await formatFileContent(vitestWorkspaceFile, generate(target).code);
1899
2063
  await writeFile(vitestWorkspaceFile, formattedContent);
1900
2064
  } else {
1901
- logger.error(
2065
+ logErrors(
2066
+ "\u{1F6A8} Oh no!",
1902
2067
  dedent`
1903
2068
  Could not update existing Vitest workspace file:
1904
2069
  ${vitestWorkspaceFile}
@@ -1910,7 +2075,8 @@ async function postInstall(options) {
1910
2075
  https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#manual-setup
1911
2076
  `
1912
2077
  );
1913
- errors.push("Unable to update existing Vitest workspace file");
2078
+ logger2.line(1);
2079
+ return;
1914
2080
  }
1915
2081
  } else if (rootConfig) {
1916
2082
  let target, updated;
@@ -1929,101 +2095,148 @@ async function postInstall(options) {
1929
2095
  updated = updateConfigFile(source, target);
1930
2096
  }
1931
2097
  if (target && updated) {
1932
- logger.step(`Updating your ${vitestConfigFile ? "Vitest" : "Vite"} config file:`);
1933
- logger.log(` ${rootConfig}`);
2098
+ logger2.line(1);
2099
+ logger2.plain(`${step} Updating your ${vitestConfigFile ? "Vitest" : "Vite"} config file:`);
2100
+ logger2.plain(` ${rootConfig}`);
1934
2101
  const formattedContent = await formatFileContent(rootConfig, generate(target).code);
1935
- const shouldAddReference = !configFileHasTypeReference && !vitestConfigFile;
1936
2102
  await writeFile(
1937
2103
  rootConfig,
1938
- shouldAddReference ? '/// <reference types="vitest/config" />\n' + formattedContent : formattedContent
2104
+ configFileHasTypeReference ? formattedContent : '/// <reference types="vitest/config" />\n' + formattedContent
1939
2105
  );
1940
2106
  } else {
1941
- logger.error(dedent`
2107
+ logErrors(
2108
+ "\u{1F6A8} Oh no!",
2109
+ dedent`
1942
2110
  We were unable to update your existing ${vitestConfigFile ? "Vitest" : "Vite"} config file.
1943
2111
 
1944
2112
  Please refer to the documentation to complete the setup manually:
1945
2113
  https://storybook.js.org/docs/writing-tests/integrations/vitest-addon#manual-setup
1946
- `);
1947
- errors.push("Unable to update existing Vitest config file");
2114
+ `
2115
+ );
1948
2116
  }
1949
2117
  } else {
1950
- const parentDir = dirname(options.configDir);
1951
- const newConfigFile = resolve(parentDir, `vitest.config.${fileExtension}`);
2118
+ const newConfigFile = resolve(`vitest.config.${fileExtension}`);
1952
2119
  const configTemplate = await loadTemplate(getTemplateName(), {
1953
2120
  CONFIG_DIR: options.configDir,
1954
2121
  SETUP_FILE: relative(dirname(newConfigFile), vitestSetupFile)
1955
2122
  });
1956
- logger.step(`Creating a Vitest config file:`);
1957
- logger.log(`${newConfigFile}`);
2123
+ logger2.line(1);
2124
+ logger2.plain(`${step} Creating a Vitest config file:`);
2125
+ logger2.plain(` ${newConfigFile}`);
1958
2126
  const formattedContent = await formatFileContent(newConfigFile, configTemplate);
1959
2127
  await writeFile(newConfigFile, formattedContent);
1960
2128
  }
1961
- const a11yAddon = info.addons.find((addon) => addon.includes(addonA11yName));
2129
+ const a11yAddon = info2.addons.find((addon) => addon.includes(addonA11yName));
1962
2130
  if (a11yAddon) {
1963
2131
  try {
1964
- const command = ["automigrate", "addon-a11y-addon-test"];
1965
- command.push("--loglevel", "silent");
1966
- command.push("--yes", "--skip-doctor");
1967
- if (options.packageManager) {
1968
- command.push("--package-manager", options.packageManager);
1969
- }
1970
- if (options.skipInstall) {
1971
- command.push("--skip-install");
1972
- }
1973
- if (options.configDir !== ".storybook") {
1974
- command.push("--config-dir", `"${options.configDir}"`);
1975
- }
1976
- const remoteCommand = packageManager.getRemoteRunCommand(
2132
+ logger2.plain(`${step} Setting up ${addonA11yName} for @storybook/addon-vitest:`);
2133
+ await execa(
1977
2134
  "storybook",
1978
- command,
1979
- versions.storybook
2135
+ [
2136
+ "automigrate",
2137
+ "addon-a11y-addon-test",
2138
+ "--loglevel",
2139
+ "silent",
2140
+ "--yes",
2141
+ "--skip-doctor",
2142
+ ...options.packageManager ? ["--package-manager", options.packageManager] : [],
2143
+ ...options.skipInstall ? ["--skip-install"] : [],
2144
+ ...options.configDir !== ".storybook" ? ["--config-dir", `"${options.configDir}"`] : []
2145
+ ],
2146
+ {
2147
+ stdio: "inherit"
2148
+ }
1980
2149
  );
1981
- const [cmd, ...args] = remoteCommand.split(" ");
1982
- await prompt.executeTask(() => packageManager.executeCommand({ command: cmd, args }), {
1983
- id: "a11y-addon-setup",
1984
- intro: "Setting up a11y addon for @storybook/addon-vitest",
1985
- error: "Failed to setup a11y addon for @storybook/addon-vitest",
1986
- success: "a11y addon setup successfully"
1987
- });
1988
2150
  } catch (e) {
1989
- console.log(e);
1990
- logger.line();
1991
- logger.error(dedent`
1992
- Could not automatically set up ${addonA11yName} for @storybook/addon-vitest.
2151
+ logErrors(
2152
+ "\u{1F6A8} Oh no!",
2153
+ dedent`
2154
+ We have detected that you have ${addonA11yName} installed but could not automatically set it up for @storybook/addon-vitest:
2155
+
2156
+ ${e instanceof Error ? e.message : String(e)}
2157
+
1993
2158
  Please refer to the documentation to complete the setup manually:
1994
2159
  https://storybook.js.org/docs/writing-tests/accessibility-testing#test-addon-integration
1995
- `);
1996
- errors.push(
1997
- "The @storybook/addon-a11y couldn't be set up for the Vitest addon" + (e instanceof Error ? e.stack : String(e))
2160
+ `
1998
2161
  );
1999
2162
  }
2000
2163
  }
2001
2164
  const runCommand = rootConfig ? `npx vitest --project=storybook` : `npx vitest`;
2002
- logger.line();
2003
- if (errors.length === 0) {
2004
- logger.step(CLI_COLORS.success("All done!"));
2005
- logger.log(dedent`
2165
+ if (!hasErrors) {
2166
+ printSuccess(
2167
+ "\u{1F389} All done!",
2168
+ dedent`
2006
2169
  @storybook/addon-vitest is now configured and you're ready to run your tests!
2170
+
2007
2171
  Here are a couple of tips to get you started:
2008
-
2009
- You can run tests with "${CLI_COLORS.cta(runCommand)}"
2010
- • Vitest IDE extension shows all stories as tests in your editor!
2011
-
2172
+ • You can run tests with "${runCommand}"
2173
+ When using the Vitest extension in your editor, all of your stories will be shown as tests!
2174
+
2012
2175
  Check the documentation for more information about its features and options at:
2013
2176
  https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}
2014
- `);
2177
+ `
2178
+ );
2015
2179
  } else {
2016
- logger.warn(
2180
+ printWarning(
2181
+ "\u26A0\uFE0F Done, but with errors!",
2017
2182
  dedent`
2018
- Done, but with errors!
2019
- @storybook/addon-vitest was installed successfully, but there were some errors during the setup process. Please refer to the documentation to complete the setup manually and check the errors above:
2183
+ @storybook/addon-vitest was installed successfully, but there were some errors during the setup process.
2184
+
2185
+ Please refer to the documentation to complete the setup manually and check the errors above:
2020
2186
  https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#manual-setup
2021
2187
  `
2022
2188
  );
2023
- throw new AddonVitestPostinstallError({ errors });
2024
2189
  }
2190
+ logger2.line(1);
2025
2191
  }
2026
2192
  __name(postInstall, "postInstall");
2193
+ async function getPackageNameFromPath(input) {
2194
+ const path = input.startsWith("file://") ? fileURLToPath(input) : input;
2195
+ if (!isAbsolute(path)) {
2196
+ return path;
2197
+ }
2198
+ const packageJsonPath = up2({ cwd: path });
2199
+ if (!packageJsonPath) {
2200
+ throw new Error(`Could not find package.json in path: ${path}`);
2201
+ }
2202
+ const { default: packageJson } = await import(pathToFileURL(packageJsonPath).href, {
2203
+ with: { type: "json" }
2204
+ });
2205
+ return packageJson.name;
2206
+ }
2207
+ __name(getPackageNameFromPath, "getPackageNameFromPath");
2208
+ async function getStorybookInfo({ configDir, packageManager: pkgMgr }) {
2209
+ const packageManager = JsPackageManagerFactory.getPackageManager({ force: pkgMgr, configDir });
2210
+ const { packageJson } = packageManager.primaryPackageJson;
2211
+ const config = await loadMainConfig({ configDir });
2212
+ const { presets } = await experimental_loadStorybook({
2213
+ configDir,
2214
+ packageJson
2215
+ });
2216
+ const framework = await presets.apply("framework", {});
2217
+ const core = await presets.apply("core", {});
2218
+ const { builder, renderer } = core;
2219
+ if (!builder) {
2220
+ throw new Error("Could not detect your Storybook builder.");
2221
+ }
2222
+ const frameworkPackageName = await getPackageNameFromPath(
2223
+ typeof framework === "string" ? framework : framework.name
2224
+ );
2225
+ const builderPackageName = await getPackageNameFromPath(
2226
+ typeof builder === "string" ? builder : builder.name
2227
+ );
2228
+ let rendererPackageName;
2229
+ if (renderer) {
2230
+ rendererPackageName = await getPackageNameFromPath(renderer);
2231
+ }
2232
+ return {
2233
+ frameworkPackageName,
2234
+ builderPackageName,
2235
+ rendererPackageName,
2236
+ addons: getAddonNames(config)
2237
+ };
2238
+ }
2239
+ __name(getStorybookInfo, "getStorybookInfo");
2027
2240
  export {
2028
2241
  postInstall as default
2029
2242
  };