diff --git a/code/lib/cli/src/generators/configure.test.ts b/code/lib/cli/src/generators/configure.test.ts new file mode 100644 index 000000000000..4f1ba91004bb --- /dev/null +++ b/code/lib/cli/src/generators/configure.test.ts @@ -0,0 +1,163 @@ +import fse from 'fs-extra'; +import dedent from 'ts-dedent'; +import { SupportedLanguage } from '../project_types'; +import { configureMain, configurePreview } from './configure'; + +jest.mock('fs-extra'); + +describe('configureMain', () => { + beforeAll(() => { + jest.clearAllMocks(); + }); + + test('should generate main.js', async () => { + await configureMain({ + language: SupportedLanguage.JAVASCRIPT, + addons: [], + storybookConfigFolder: '.storybook', + framework: { + name: '@storybook/react-vite', + }, + }); + + const { calls } = (fse.writeFile as unknown as jest.Mock).mock; + const [mainConfigPath, mainConfigContent] = calls[0]; + + expect(mainConfigPath).toEqual('./.storybook/main.js'); + expect(mainConfigContent).toMatchInlineSnapshot(` + "/** @type { import('@storybook/react-vite').StorybookConfig } */ + const config = { + \\"stories\\": [ + \\"../stories/**/*.mdx\\", + \\"../stories/**/*.stories.@(js|jsx|ts|tsx)\\" + ], + \\"addons\\": [], + \\"framework\\": { + \\"name\\": \\"@storybook/react-vite\\" + } + }; + export default config;" + `); + }); + + test('should generate main.ts', async () => { + await configureMain({ + language: SupportedLanguage.TYPESCRIPT, + addons: [], + storybookConfigFolder: '.storybook', + framework: { + name: '@storybook/react-vite', + }, + }); + + const { calls } = (fse.writeFile as unknown as jest.Mock).mock; + const [mainConfigPath, mainConfigContent] = calls[0]; + + expect(mainConfigPath).toEqual('./.storybook/main.ts'); + expect(mainConfigContent).toMatchInlineSnapshot(` + "import type { StorybookConfig } from '@storybook/react-vite'; + + const config: StorybookConfig = { + \\"stories\\": [ + \\"../stories/**/*.mdx\\", + \\"../stories/**/*.stories.@(js|jsx|ts|tsx)\\" + ], + \\"addons\\": [], + \\"framework\\": { + \\"name\\": \\"@storybook/react-vite\\" + } + }; + export default config;" + `); + }); +}); + +describe('configurePreview', () => { + test('should generate preview.js', async () => { + await configurePreview({ + language: SupportedLanguage.JAVASCRIPT, + storybookConfigFolder: '.storybook', + }); + + const { calls } = (fse.writeFile as unknown as jest.Mock).mock; + const [previewConfigPath, previewConfigContent] = calls[0]; + + expect(previewConfigPath).toEqual('./.storybook/preview.js'); + expect(previewConfigContent).toMatchInlineSnapshot(` + "export const parameters = { + actions: { argTypesRegex: \\"^on[A-Z].*\\" }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + }" + `); + }); + + test('should generate preview.ts', async () => { + await configurePreview({ + language: SupportedLanguage.TYPESCRIPT, + storybookConfigFolder: '.storybook', + }); + + const { calls } = (fse.writeFile as unknown as jest.Mock).mock; + const [previewConfigPath, previewConfigContent] = calls[0]; + + expect(previewConfigPath).toEqual('./.storybook/preview.ts'); + expect(previewConfigContent).toMatchInlineSnapshot(` + "export const parameters = { + actions: { argTypesRegex: \\"^on[A-Z].*\\" }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + }" + `); + }); + + test('should not do anything if the framework template already included a preview', async () => { + (fse.pathExists as unknown as jest.Mock).mockReturnValueOnce(true); + await configurePreview({ + language: SupportedLanguage.TYPESCRIPT, + storybookConfigFolder: '.storybook', + }); + expect(fse.writeFile).not.toHaveBeenCalled(); + }); + + test('should add prefix if frameworkParts are passed', async () => { + await configurePreview({ + language: SupportedLanguage.TYPESCRIPT, + storybookConfigFolder: '.storybook', + frameworkPreviewParts: { + prefix: dedent` + import { setCompodocJson } from "@storybook/addon-docs/angular"; + import docJson from "../documentation.json"; + setCompodocJson(docJson); + `, + }, + }); + + const { calls } = (fse.writeFile as unknown as jest.Mock).mock; + const [previewConfigPath, previewConfigContent] = calls[0]; + + expect(previewConfigPath).toEqual('./.storybook/preview.ts'); + expect(previewConfigContent).toMatchInlineSnapshot(` + "import { setCompodocJson } from \\"@storybook/addon-docs/angular\\"; + import docJson from \\"../documentation.json\\"; + setCompodocJson(docJson); + export const parameters = { + actions: { argTypesRegex: \\"^on[A-Z].*\\" }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + }" + `); + }); +}); diff --git a/code/lib/cli/src/generators/configure.ts b/code/lib/cli/src/generators/configure.ts index 8efbf7ba0597..53400d56fe7a 100644 --- a/code/lib/cli/src/generators/configure.ts +++ b/code/lib/cli/src/generators/configure.ts @@ -47,16 +47,17 @@ export async function configureMain({ const isTypescript = language === SupportedLanguage.TYPESCRIPT || language === SupportedLanguage.TYPESCRIPT_LEGACY; - const tsTemplate = dedent`<>const config<> = <>; + const mainConfigTemplate = dedent`<>const config<> = <>; export default config;`; - const jsTemplate = dedent`export default <>;`; - - const finalTemplate = isTypescript ? tsTemplate : jsTemplate; - - const mainJsContents = finalTemplate - .replace('<>', `import { StorybookConfig } from '${custom.framework.name}';\n\n`) - .replace('<>', ': StorybookConfig') + const mainJsContents = mainConfigTemplate + .replace( + '<>', + isTypescript + ? `import type { StorybookConfig } from '${custom.framework.name}';\n\n` + : `/** @type { import('${custom.framework.name}').StorybookConfig } */\n` + ) + .replace('<>', isTypescript ? ': StorybookConfig' : '') .replace('<>', JSON.stringify(config, null, 2)); await fse.writeFile(