From d48a709f88b939d8f7a77bc2e88900b4ecdb7c35 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Fri, 3 Jun 2022 16:53:40 +0300 Subject: [PATCH] fix(storybook): dont generate stories for stories (#10570) ISSUES CLOSED: #10286 --- .../src/generators/stories/stories.ts | 13 +- .../generators/stories/stories-app.spec.ts | 9 +- .../react/src/generators/stories/stories.ts | 16 +- .../update-12-5-0/install-addon-essentials.ts | 17 +- .../migrate-stories-to-6-2.spec.ts | 6 +- .../migrate-stories-to-6-2.ts | 17 +- .../storybook/src/utils/utilities.spec.ts | 199 ++++++++++++++++++ packages/storybook/src/utils/utilities.ts | 61 ++++++ 8 files changed, 294 insertions(+), 44 deletions(-) create mode 100644 packages/storybook/src/utils/utilities.spec.ts diff --git a/packages/react-native/src/generators/stories/stories.ts b/packages/react-native/src/generators/stories/stories.ts index 3a5cbea055542..dbfe7d74528e3 100644 --- a/packages/react-native/src/generators/stories/stories.ts +++ b/packages/react-native/src/generators/stories/stories.ts @@ -12,6 +12,7 @@ import { containsComponentDeclaration, projectRootPath, } from '@nrwl/react/src/generators/stories/stories'; +import { isTheFileAStory } from '@nrwl/storybook/src/utils/utilities'; export async function createAllStories(tree: Tree, projectName: string) { const projects = getProjects(tree); @@ -27,7 +28,17 @@ export async function createAllStories(tree: Tree, projectName: string) { (path.endsWith('.js') && !path.endsWith('.spec.js')) || (path.endsWith('.jsx') && !path.endsWith('.spec.jsx')) ) { - componentPaths.push(path); + // Check if file is NOT a story (either ts/tsx or js/jsx) + if (!isTheFileAStory(tree, path)) { + // Since the file is not a story + // Let's see if the .stories.* file exists + const ext = path.slice(path.lastIndexOf('.')); + const storyPath = `${path.split(ext)[0]}.stories${ext}`; + + if (!tree.exists(storyPath)) { + componentPaths.push(path); + } + } } }); diff --git a/packages/react/src/generators/stories/stories-app.spec.ts b/packages/react/src/generators/stories/stories-app.spec.ts index a3a51bee88d4a..03778c39ece1c 100644 --- a/packages/react/src/generators/stories/stories-app.spec.ts +++ b/packages/react/src/generators/stories/stories-app.spec.ts @@ -88,7 +88,10 @@ describe('react:stories for applications', () => { it('should not update existing stories', async () => { // ARRANGE - appTree.write('apps/test-ui-app/src/app/nx-welcome.stories.tsx', ''); + appTree.write( + 'apps/test-ui-app/src/app/nx-welcome.stories.tsx', + `import { ComponentStory, ComponentMeta } from '@storybook/react'` + ); // ACT await storiesGenerator(appTree, { @@ -99,7 +102,9 @@ describe('react:stories for applications', () => { // ASSERT expect( appTree.read('apps/test-ui-app/src/app/nx-welcome.stories.tsx', 'utf-8') - ).toEqual(''); + ).toEqual( + `import { ComponentStory, ComponentMeta } from '@storybook/react'` + ); }); }); diff --git a/packages/react/src/generators/stories/stories.ts b/packages/react/src/generators/stories/stories.ts index dc51e5db54990..97dfc92717213 100644 --- a/packages/react/src/generators/stories/stories.ts +++ b/packages/react/src/generators/stories/stories.ts @@ -15,6 +15,7 @@ import { visitNotIgnoredFiles, } from '@nrwl/devkit'; import { join } from 'path'; +import { isTheFileAStory } from '@nrwl/storybook/src/utils/utilities'; export interface StorybookStoriesSchema { project: string; @@ -82,11 +83,16 @@ export async function createAllStories( (path.endsWith('.js') && !path.endsWith('.spec.js')) || (path.endsWith('.jsx') && !path.endsWith('.spec.jsx')) ) { - const ext = path.slice(path.lastIndexOf('.')); - const storyPath = `${path.split(ext)[0]}.stories${ext}`; - // only add component if a stories file doesnt already exist - if (!tree.exists(storyPath)) { - componentPaths.push(path); + // Check if file is NOT a story (either ts/tsx or js/jsx) + if (!isTheFileAStory(tree, path)) { + // Since the file is not a story + // Let's see if the .stories.* file exists + const ext = path.slice(path.lastIndexOf('.')); + const storyPath = `${path.split(ext)[0]}.stories${ext}`; + + if (!tree.exists(storyPath)) { + componentPaths.push(path); + } } } }); diff --git a/packages/storybook/src/migrations/update-12-5-0/install-addon-essentials.ts b/packages/storybook/src/migrations/update-12-5-0/install-addon-essentials.ts index df49477ed78c7..f1fd549db1736 100644 --- a/packages/storybook/src/migrations/update-12-5-0/install-addon-essentials.ts +++ b/packages/storybook/src/migrations/update-12-5-0/install-addon-essentials.ts @@ -7,6 +7,7 @@ import { ChangeType, } from '@nrwl/devkit'; import { findNodes } from '@nrwl/workspace/src/utilities/typescript/find-nodes'; +import { getTsSourceFile } from '../../utils/utilities'; import ts = require('typescript'); let needsInstall = false; @@ -134,22 +135,6 @@ function editRootMainJs(tree: Tree) { } } -function getTsSourceFile(host: Tree, path: string): ts.SourceFile { - const buffer = host.read(path); - if (!buffer) { - throw new Error(`Could not read TS file (${path}).`); - } - const content = buffer.toString(); - const source = ts.createSourceFile( - path, - content, - ts.ScriptTarget.Latest, - true - ); - - return source; -} - export default async function (tree: Tree) { editRootMainJs(tree); installAddonEssentials(tree); diff --git a/packages/storybook/src/migrations/update-14-0-0/migrate-stories-to-6-2/migrate-stories-to-6-2.spec.ts b/packages/storybook/src/migrations/update-14-0-0/migrate-stories-to-6-2/migrate-stories-to-6-2.spec.ts index 1c7e31bae2073..345d801e5d4a0 100644 --- a/packages/storybook/src/migrations/update-14-0-0/migrate-stories-to-6-2/migrate-stories-to-6-2.spec.ts +++ b/packages/storybook/src/migrations/update-14-0-0/migrate-stories-to-6-2/migrate-stories-to-6-2.spec.ts @@ -10,14 +10,12 @@ import { findNodes } from '@nrwl/workspace/src/utils/ast-utils'; import * as ts from 'typescript'; import { SyntaxKind } from 'typescript'; import { nxVersion } from '../../../utils/versions'; -import { - getTsSourceFile, - migrateStoriesTo62Generator, -} from './migrate-stories-to-6-2'; +import { migrateStoriesTo62Generator } from './migrate-stories-to-6-2'; import { overrideCollectionResolutionForTesting, wrapAngularDevkitSchematic, } from '@nrwl/devkit/ngcli-adapter'; +import { getTsSourceFile } from '@nrwl/storybook/src/utils/utilities'; const componentSchematic = wrapAngularDevkitSchematic( '@schematics/angular', diff --git a/packages/storybook/src/migrations/update-14-0-0/migrate-stories-to-6-2/migrate-stories-to-6-2.ts b/packages/storybook/src/migrations/update-14-0-0/migrate-stories-to-6-2/migrate-stories-to-6-2.ts index c93a526685744..34f8650e18db6 100644 --- a/packages/storybook/src/migrations/update-14-0-0/migrate-stories-to-6-2/migrate-stories-to-6-2.ts +++ b/packages/storybook/src/migrations/update-14-0-0/migrate-stories-to-6-2/migrate-stories-to-6-2.ts @@ -8,6 +8,7 @@ import { Tree, visitNotIgnoredFiles, } from '@nrwl/devkit'; +import { getTsSourceFile } from '@nrwl/storybook/src/utils/utilities'; import { fileExists } from '@nrwl/workspace/src/utilities/fileutils'; import { findNodes } from '@nrwl/workspace/src/utilities/typescript/find-nodes'; import { join, normalize } from 'path'; @@ -281,22 +282,6 @@ function findAllComponentsWithStoriesForSpecificProject( return componentFileInfos; } -export function getTsSourceFile(host: Tree, path: string): ts.SourceFile { - const buffer = host.read(path); - if (!buffer) { - throw new Error(`Could not read TS file (${path}).`); - } - const content = buffer.toString(); - const source = ts.createSourceFile( - path, - content, - ts.ScriptTarget.Latest, - true - ); - - return source; -} - async function changeSyntaxOfStory(tree: Tree, storyFilePath: string) { const file = getTsSourceFile(tree, storyFilePath); const appFileContent = tree.read(storyFilePath, 'utf-8'); diff --git a/packages/storybook/src/utils/utilities.spec.ts b/packages/storybook/src/utils/utilities.spec.ts new file mode 100644 index 0000000000000..77e8d24942431 --- /dev/null +++ b/packages/storybook/src/utils/utilities.spec.ts @@ -0,0 +1,199 @@ +import { joinPathFragments, Tree, writeJson } from '@nrwl/devkit'; +import { + overrideCollectionResolutionForTesting, + wrapAngularDevkitSchematic, +} from '@nrwl/devkit/ngcli-adapter'; +import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; +import { isTheFileAStory } from './utilities'; +import { nxVersion, storybookVersion } from './versions'; + +const componentSchematic = wrapAngularDevkitSchematic( + '@schematics/angular', + 'component' +); +const runAngularLibrarySchematic = wrapAngularDevkitSchematic( + '@schematics/angular', + 'library' +); +const runAngularStorybookSchematic = wrapAngularDevkitSchematic( + '@nrwl/angular', + 'storybook-configuration' +); + +describe('testing utilities', () => { + let appTree: Tree; + + beforeEach(async () => { + overrideCollectionResolutionForTesting({ + '@nrwl/storybook': joinPathFragments( + __dirname, + '../../../../generators.json' + ), + }); + + appTree = createTreeWithEmptyWorkspace(); + + await runAngularLibrarySchematic(appTree, { + name: 'test-ui-lib', + }); + + await componentSchematic(appTree, { + name: 'button', + project: 'test-ui-lib', + }); + + writeJson(appTree, 'package.json', { + devDependencies: { + '@nrwl/storybook': nxVersion, + '@storybook/addon-knobs': storybookVersion, + '@storybook/angular': storybookVersion, + }, + }); + writeJson(appTree, 'test-ui-lib/tsconfig.json', {}); + + await runAngularStorybookSchematic(appTree, { + name: 'test-ui-lib', + configureCypress: true, + }); + + appTree.write( + `test-ui-lib/src/lib/button/button.component.stories.ts`, + ` + import { Story, Meta } from '@storybook/react'; + import { Button } from './button'; + + export default { + component: Button, + title: 'Button', + } as Meta; + + const Template: Story = (args) =>