From 9d34fab8fbd3e0d0ba0e85327678a5bef8db42fd Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 9 Apr 2020 08:47:28 +0200 Subject: [PATCH 1/2] feat(csf): warn when there are no exported stories --- lib/core/src/client/preview/loadCsf.test.ts | 35 ++++++++++++++++++ lib/core/src/client/preview/loadCsf.ts | 41 ++++++++++++--------- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/lib/core/src/client/preview/loadCsf.test.ts b/lib/core/src/client/preview/loadCsf.test.ts index c51b589b011f..39a5c003ea80 100644 --- a/lib/core/src/client/preview/loadCsf.test.ts +++ b/lib/core/src/client/preview/loadCsf.test.ts @@ -1,8 +1,13 @@ import { ConfigApi, ClientApi, StoryStore } from '@storybook/client-api'; +import { logger } from '@storybook/client-logger'; import { RequireContext } from './types'; import { loadCsf } from './loadCsf'; +jest.mock('@storybook/client-logger', () => ({ + logger: { warn: jest.fn() }, +})); + let cbs: ((data: any) => void)[]; let mod: NodeModule; beforeEach(() => { @@ -365,4 +370,34 @@ describe('core.preview.loadCsf', () => { expect(storyStore.incrementRevision).toHaveBeenCalled(); expect(mockedStoriesOf).toHaveBeenCalledWith('a', true); }); + + it('gives a warning if there are no exported stories', () => { + const { configure } = makeMocks(); + + const input = { + a: { + default: { + title: 'MissingExportsComponent', + }, + // no named exports, will not present a story + }, + }; + configure(makeRequireContext(input), mod, 'react'); + expect(logger.warn).toHaveBeenCalled(); + }); + + it('does not give a warning if there are exported stories', () => { + const { configure } = makeMocks(); + + const input = { + a: { + default: { + title: 'MissingExportsComponent', + }, + x: () => 0, + }, + }; + configure(makeRequireContext(input), mod, 'react'); + expect(logger.warn).not.toHaveBeenCalled(); + }); }); diff --git a/lib/core/src/client/preview/loadCsf.ts b/lib/core/src/client/preview/loadCsf.ts index cb8873da1a73..b0f1aadbf0ba 100644 --- a/lib/core/src/client/preview/loadCsf.ts +++ b/lib/core/src/client/preview/loadCsf.ts @@ -113,24 +113,29 @@ const loadStories = ( kind.addDecorator(decorator); }); - Object.keys(exports).forEach((key) => { - if (isExportStory(key, meta)) { - const storyFn = exports[key]; - const { name, parameters, decorators, args, argTypes } = storyFn.story || {}; - const decoratorParams = decorators ? { decorators } : null; - const exportName = storyNameFromExport(key); - const idParams = { __id: toId(componentId || kindName, exportName) }; - - const storyParams = { - ...parameters, - ...decoratorParams, - ...idParams, - args, - argTypes, - }; - kind.add(name || exportName, storyFn, storyParams); - } - }); + const storyExports = Object.keys(exports); + if (storyExports.length === 0) { + logger.warn(`Found a storyfile for "${kindName}" but no exported stories.`); + } else { + storyExports.forEach((key) => { + if (isExportStory(key, meta)) { + const storyFn = exports[key]; + const { name, parameters, decorators, args, argTypes } = storyFn.story || {}; + const decoratorParams = decorators ? { decorators } : null; + const exportName = storyNameFromExport(key); + const idParams = { __id: toId(componentId || kindName, exportName) }; + + const storyParams = { + ...parameters, + ...decoratorParams, + ...idParams, + args, + argTypes, + }; + kind.add(name || exportName, storyFn, storyParams); + } + }); + } }); previousExports = currentExports; }; From e7a95edf24d6ebf9d04230ecc4c9821fa1dd2e74 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 9 Apr 2020 10:09:23 +0200 Subject: [PATCH 2/2] refactor(load-csf): improve message and code logic --- lib/core/src/client/preview/loadCsf.ts | 45 ++++++++++++++------------ 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/lib/core/src/client/preview/loadCsf.ts b/lib/core/src/client/preview/loadCsf.ts index b0f1aadbf0ba..357a7569d79f 100644 --- a/lib/core/src/client/preview/loadCsf.ts +++ b/lib/core/src/client/preview/loadCsf.ts @@ -1,6 +1,7 @@ import { ConfigApi, ClientApi, StoryStore } from '@storybook/client-api'; import { isExportStory, storyNameFromExport, toId } from '@storybook/csf'; import { logger } from '@storybook/client-logger'; +import dedent from 'ts-dedent'; import { Loadable, LoaderFunction, RequireContext } from './types'; @@ -115,27 +116,31 @@ const loadStories = ( const storyExports = Object.keys(exports); if (storyExports.length === 0) { - logger.warn(`Found a storyfile for "${kindName}" but no exported stories.`); - } else { - storyExports.forEach((key) => { - if (isExportStory(key, meta)) { - const storyFn = exports[key]; - const { name, parameters, decorators, args, argTypes } = storyFn.story || {}; - const decoratorParams = decorators ? { decorators } : null; - const exportName = storyNameFromExport(key); - const idParams = { __id: toId(componentId || kindName, exportName) }; - - const storyParams = { - ...parameters, - ...decoratorParams, - ...idParams, - args, - argTypes, - }; - kind.add(name || exportName, storyFn, storyParams); - } - }); + logger.warn( + dedent`Found a story file for "${kindName}" but no exported stories. + Check the docs for reference: https://storybook.js.org/docs/formats/component-story-format/` + ); + return; } + + storyExports.forEach((key) => { + if (isExportStory(key, meta)) { + const storyFn = exports[key]; + const { name, parameters, decorators, args, argTypes } = storyFn.story || {}; + const decoratorParams = decorators ? { decorators } : null; + const exportName = storyNameFromExport(key); + const idParams = { __id: toId(componentId || kindName, exportName) }; + + const storyParams = { + ...parameters, + ...decoratorParams, + ...idParams, + args, + argTypes, + }; + kind.add(name || exportName, storyFn, storyParams); + } + }); }); previousExports = currentExports; };