diff --git a/code/addons/test/src/postinstall.ts b/code/addons/test/src/postinstall.ts index c334d9f0571..3ab64f32be9 100644 --- a/code/addons/test/src/postinstall.ts +++ b/code/addons/test/src/postinstall.ts @@ -139,7 +139,7 @@ export default async function postInstall(options: PostinstallOptions) { { extends: '${viteConfig ? relative(dirname(browserWorkspaceFile), viteConfig) : ''}', plugins: [ - storybookTest(),${vitestInfo.frameworkPluginCall ? '\n' + vitestInfo.frameworkPluginCall : ''} + storybookTest(),${vitestInfo.frameworkPluginCall ? '\n ' + vitestInfo.frameworkPluginCall : ''} ], test: { browser: { diff --git a/code/lib/cli-storybook/src/add.test.ts b/code/lib/cli-storybook/src/add.test.ts index 137e60a7200..5fb009f11df 100644 --- a/code/lib/cli-storybook/src/add.test.ts +++ b/code/lib/cli-storybook/src/add.test.ts @@ -1,10 +1,13 @@ -import { describe, expect, test, vi } from 'vitest'; +import { beforeEach, describe, expect, test, vi } from 'vitest'; import { add, getVersionSpecifier } from './add'; const MockedConfig = vi.hoisted(() => { return { appendValueToArray: vi.fn(), + getFieldNode: vi.fn(), + valueToNode: vi.fn(), + appendNodeToArray: vi.fn(), }; }); const MockedPackageManager = vi.hoisted(() => { @@ -20,6 +23,12 @@ const MockedPostInstall = vi.hoisted(() => { postinstallAddon: vi.fn(), }; }); +const MockWrapRequireUtils = vi.hoisted(() => { + return { + getRequireWrapperName: vi.fn(), + wrapValueWithRequireWrapper: vi.fn(), + }; +}); const MockedConsole = { log: vi.fn(), warn: vi.fn(), @@ -35,6 +44,9 @@ vi.mock('storybook/internal/csf-tools', () => { vi.mock('./postinstallAddon', () => { return MockedPostInstall; }); +vi.mock('./automigrate/fixes/wrap-require-utils', () => { + return MockWrapRequireUtils; +}); vi.mock('storybook/internal/common', () => { return { getStorybookInfo: vi.fn(() => ({ mainConfig: {}, configDir: '' })), @@ -103,6 +115,35 @@ describe('add', () => { }); describe('add (extra)', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + test('should not add a "wrap require" to the addon when not needed', async () => { + MockedConfig.getFieldNode.mockReturnValue({}); + MockWrapRequireUtils.getRequireWrapperName.mockReturnValue(null); + await add( + '@storybook/addon-docs', + { packageManager: 'npm', skipPostinstall: true }, + MockedConsole + ); + + expect(MockWrapRequireUtils.wrapValueWithRequireWrapper).not.toHaveBeenCalled(); + expect(MockedConfig.appendValueToArray).toHaveBeenCalled(); + expect(MockedConfig.appendNodeToArray).not.toHaveBeenCalled(); + }); + test('should add a "wrap require" to the addon when applicable', async () => { + MockedConfig.getFieldNode.mockReturnValue({}); + MockWrapRequireUtils.getRequireWrapperName.mockReturnValue('require'); + await add( + '@storybook/addon-docs', + { packageManager: 'npm', skipPostinstall: true }, + MockedConsole + ); + + expect(MockWrapRequireUtils.wrapValueWithRequireWrapper).toHaveBeenCalled(); + expect(MockedConfig.appendValueToArray).not.toHaveBeenCalled(); + expect(MockedConfig.appendNodeToArray).toHaveBeenCalled(); + }); test('not warning when installing the correct version of storybook', async () => { await add( '@storybook/addon-docs', diff --git a/code/lib/cli-storybook/src/add.ts b/code/lib/cli-storybook/src/add.ts index df3ac84f140..d0e64efdf44 100644 --- a/code/lib/cli-storybook/src/add.ts +++ b/code/lib/cli-storybook/src/add.ts @@ -13,6 +13,10 @@ import { readConfig, writeConfig } from 'storybook/internal/csf-tools'; import SemVer from 'semver'; import { dedent } from 'ts-dedent'; +import { + getRequireWrapperName, + wrapValueWithRequireWrapper, +} from './automigrate/fixes/wrap-require-utils'; import { postinstallAddon } from './postinstallAddon'; export interface PostinstallOptions { @@ -136,7 +140,16 @@ export async function add( await packageManager.addDependencies({ installAsDevDependencies: true }, [addonWithVersion]); logger.log(`Adding '${addon}' to main.js addons field.`); - main.appendValueToArray(['addons'], addonName); + + const mainConfigAddons = main.getFieldNode(['addons']); + if (mainConfigAddons && getRequireWrapperName(main) !== null) { + const addonNode = main.valueToNode(addonName); + main.appendNodeToArray(['addons'], addonNode as any); + wrapValueWithRequireWrapper(main, addonNode as any); + } else { + main.appendValueToArray(['addons'], addonName); + } + await writeConfig(main); if (!skipPostinstall && isCoreAddon(addonName)) {