diff --git a/code/addons/test/package.json b/code/addons/test/package.json index 1652327a9801..56170beaa0e2 100644 --- a/code/addons/test/package.json +++ b/code/addons/test/package.json @@ -85,7 +85,6 @@ "@storybook/icons": "^1.2.12", "@storybook/instrumenter": "workspace:*", "@storybook/test": "workspace:*", - "@storybook/theming": "workspace:*", "polished": "^4.2.2", "prompts": "^2.4.0", "ts-dedent": "^2.2.0" diff --git a/code/addons/test/src/postinstall.ts b/code/addons/test/src/postinstall.ts index fc7fc1e8d862..55f97eb6b0da 100644 --- a/code/addons/test/src/postinstall.ts +++ b/code/addons/test/src/postinstall.ts @@ -2,13 +2,17 @@ import { existsSync } from 'node:fs'; import * as fs from 'node:fs/promises'; import { writeFile } from 'node:fs/promises'; +import { traverse } from 'storybook/internal/babel'; import { JsPackageManagerFactory, extractProperFrameworkName, loadAllPresets, loadMainConfig, + serverResolve, validateFrameworkName, + versions, } from 'storybook/internal/common'; +import { readConfig, writeConfig } from 'storybook/internal/csf-tools'; import { colors, logger } from 'storybook/internal/node-logger'; // eslint-disable-next-line depend/ban-dependencies @@ -57,6 +61,51 @@ export default async function postInstall(options: PostinstallOptions) { // if Vitest is installed, we use the same version to keep consistency across Vitest packages const vitestVersionToInstall = vitestVersionSpecifier ?? 'latest'; + const mainJsPath = serverResolve(resolve(options.configDir, 'main')) as string; + const config = await readConfig(mainJsPath); + + const hasCustomWebpackConfig = !!config.getFieldNode(['webpackFinal']); + + if (info.frameworkPackageName === '@storybook/nextjs' && !hasCustomWebpackConfig) { + const out = options.yes + ? { + migrateToExperimentalNextjsVite: true, + } + : await prompts({ + type: 'confirm', + name: 'migrateToExperimentalNextjsVite', + message: dedent` + The addon requires the use of @storybook/experimental-nextjs-vite to work with Next.js. + https://storybook.js.org/docs/writing-tests/test-addon#install-and-set-up + + Do you want to migrate? + `, + initial: true, + }); + + if (out.migrateToExperimentalNextjsVite) { + await packageManager.addDependencies({ installAsDevDependencies: true }, [ + `@storybook/experimental-nextjs-vite@${versions['@storybook/experimental-nextjs-vite']}`, + ]); + + await packageManager.removeDependencies({}, ['@storybook/nextjs']); + + // eslint-disable-next-line no-underscore-dangle + traverse(config._ast, { + StringLiteral(path) { + if (path.node.value === '@storybook/nextjs') { + path.node.value = '@storybook/experimental-nextjs-vite'; + } + }, + }); + + await writeConfig(config, mainJsPath); + + info.frameworkPackageName = '@storybook/experimental-nextjs-vite'; + info.builderPackageName = '@storybook/builder-vite'; + } + } + const annotationsImport = [ '@storybook/nextjs', '@storybook/experimental-nextjs-vite', @@ -71,11 +120,16 @@ export default async function postInstall(options: PostinstallOptions) { ) ? info.rendererPackageName : null; + const isRendererSupported = !!annotationsImport; const prerequisiteCheck = async () => { const reasons = []; + if (hasCustomWebpackConfig) { + reasons.push('• The addon can not be used with a custom Webpack configuration.'); + } + if ( info.frameworkPackageName !== '@storybook/nextjs' && info.builderPackageName !== '@storybook/builder-vite' @@ -149,9 +203,7 @@ export default async function postInstall(options: PostinstallOptions) { return; } - const interactionsAddon = info.addons.find((addon) => addon.includes(addonInteractionsName)); - - if (!!interactionsAddon) { + if (info.hasAddonInteractions) { let shouldUninstall = options.yes; if (!options.yes) { printInfo( @@ -188,10 +240,9 @@ export default async function postInstall(options: PostinstallOptions) { ], { shell: true, + stdio: 'inherit', } ); - } else { - return; } } @@ -282,7 +333,7 @@ export default async function postInstall(options: PostinstallOptions) { logger.plain(colors.gray(` ${vitestSetupFile}`)); const previewExists = EXTENSIONS.map((ext) => resolve(options.configDir, `preview${ext}`)).some( - (config) => existsSync(config) + existsSync ); const a11yAddon = info.addons.find((addon) => addon.includes(addonA11yName)); @@ -489,7 +540,7 @@ const getVitestPluginInfo = (framework: string) => { frameworkPluginCall = 'storybookReactNativeWeb()'; } - // spaces for file identation + // spaces for file indentation frameworkPluginImport = `\n${frameworkPluginImport}`; frameworkPluginDocs = frameworkPluginDocs ? `\n ${frameworkPluginDocs}` : ''; frameworkPluginCall = frameworkPluginCall ? `\n ${frameworkPluginCall},` : ''; @@ -507,7 +558,6 @@ async function getStorybookInfo({ configDir, packageManager: pkgMgr }: Postinsta const frameworkName = typeof framework === 'string' ? framework : framework?.name; validateFrameworkName(frameworkName); const frameworkPackageName = extractProperFrameworkName(frameworkName); - const addons = getAddonNames(config); const presets = await loadAllPresets({ corePresets: [join(frameworkName, 'preset')], @@ -519,6 +569,8 @@ async function getStorybookInfo({ configDir, packageManager: pkgMgr }: Postinsta isCritical: true, }); + const hasAddonInteractions = !!(await presets.apply('ADDON_INTERACTIONS_IN_USE', false)); + const core = await presets.apply('core', {}); const { builder, renderer } = core; @@ -546,6 +598,7 @@ async function getStorybookInfo({ configDir, packageManager: pkgMgr }: Postinsta frameworkPackageName, builderPackageName, rendererPackageName, - addons, + hasAddonInteractions, + addons: getAddonNames(config), }; } diff --git a/code/addons/test/src/utils.ts b/code/addons/test/src/utils.ts index 066f09af15f1..053f4eec4ffe 100644 --- a/code/addons/test/src/utils.ts +++ b/code/addons/test/src/utils.ts @@ -1,6 +1,5 @@ import { type StorybookTheme, useTheme } from 'storybook/internal/theming'; - -import type { StorybookConfig } from '@storybook/types'; +import type { StorybookConfig } from 'storybook/internal/types'; import Filter from 'ansi-to-html'; import stripAnsi from 'strip-ansi'; diff --git a/code/yarn.lock b/code/yarn.lock index f0862ce5333e..e6f690cb347c 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6403,7 +6403,6 @@ __metadata: "@storybook/icons": "npm:^1.2.12" "@storybook/instrumenter": "workspace:*" "@storybook/test": "workspace:*" - "@storybook/theming": "workspace:*" "@types/istanbul-lib-report": "npm:^3.0.3" "@types/node": "npm:^22.0.0" "@types/semver": "npm:^7"