diff --git a/lib/api/src/lib/stories.ts b/lib/api/src/lib/stories.ts index 87b9c70f16f..08404b3af2c 100644 --- a/lib/api/src/lib/stories.ts +++ b/lib/api/src/lib/stories.ts @@ -268,10 +268,11 @@ export interface PreparedStoryIndex { export const transformSetStoriesStoryDataToStoriesHash = ( data: SetStoriesStoryData, - { provider }: { provider: Provider } + { provider, docsMode }: { provider: Provider; docsMode: boolean } ) => transformStoryIndexToStoriesHash(transformSetStoriesStoryDataToPreparedStoryIndex(data), { provider, + docsMode, }); const transformSetStoriesStoryDataToPreparedStoryIndex = ( @@ -339,8 +340,10 @@ export const transformStoryIndexToStoriesHash = ( index: PreparedStoryIndex, { provider, + docsMode, }: { provider: Provider; + docsMode: boolean; } ): StoriesHash => { if (!index.v) throw new Error('Composition: Missing stories.json version'); @@ -361,6 +364,8 @@ export const transformStoryIndexToStoriesHash = ( } const storiesHashOutOfOrder = Object.values(entryValues).reduce((acc, item) => { + if (docsMode && item.type !== 'docs') return acc; + // First, split the title into a set of names, separated by '/' and trimmed. const { title } = item; const groups = title.trim().split(TITLE_PATH_SEPARATOR); diff --git a/lib/api/src/modules/stories.ts b/lib/api/src/modules/stories.ts index 29ae812858a..7f8b791998c 100644 --- a/lib/api/src/modules/stories.ts +++ b/lib/api/src/modules/stories.ts @@ -39,7 +39,7 @@ import type { import type { Args, ModuleFn } from '../index'; import type { ComposedRef } from './refs'; -const { DOCS_MODE, FEATURES, fetch } = global; +const { FEATURES, fetch } = global; const STORY_INDEX_PATH = './index.json'; type Direction = -1 | 1; @@ -194,11 +194,6 @@ export const init: ModuleFn = ({ const { storiesHash, storyId, refs, refId } = store.getState(); const story = api.getData(storyId, refId); - if (DOCS_MODE) { - api.jumpToComponent(direction); - return; - } - // cannot navigate when there's no current selection if (!story) { return; @@ -215,6 +210,7 @@ export const init: ModuleFn = ({ // Now create storiesHash by reordering the above by group const hash = transformSetStoriesStoryDataToStoriesHash(input, { provider, + docsMode: global.DOCS_MODE, }); await store.setState({ @@ -362,6 +358,7 @@ export const init: ModuleFn = ({ setStoryList: async (storyIndex: StoryIndex) => { const hash = transformStoryIndexToStoriesHash(storyIndex, { provider, + docsMode: global.DOCS_MODE, }); await store.setState({ diff --git a/lib/api/src/tests/stories.test.ts b/lib/api/src/tests/stories.test.ts index 2d5ef2397d9..5daf43d8bcc 100644 --- a/lib/api/src/tests/stories.test.ts +++ b/lib/api/src/tests/stories.test.ts @@ -1181,36 +1181,59 @@ describe('stories API', () => { expect(storedStoriesHash['component-c--story-4'].type).toBe('story'); }); - // Skip this for now, will come back soon - it.skip('prefers parameters.docsOnly to inferred docsOnly status', async () => { - mockStories.mockReset().mockReturnValue({ - 'component-a--docs': { - type: 'story', - title: 'Component A', - name: 'Docs', // Called 'Docs' rather than 'Page' - importPath: './path/to/component-a.ts', - parameters: { - docsOnly: true, + describe('docMode = true', () => { + beforeEach(() => { + global.DOCS_MODE = true; + }); + afterEach(() => { + global.DOCS_MODE = false; + }); + + it('strips out story entries', async () => { + mockStories.mockReset().mockReturnValue({ + 'component-a--page': { + id: 'component-a--page', + title: 'Component A', + name: 'Page', + importPath: './path/to/component-a.ts', }, - }, + 'component-a--story-2': { + id: 'component-a--story-2', + title: 'Component A', + name: 'Story 2', + importPath: './path/to/component-a.ts', + }, + 'component-b': { + type: 'docs', + id: 'component-b--docs', + title: 'Component B', + name: 'Docs', + importPath: './path/to/component-b.ts', + storiesImports: [], + }, + 'component-c--story-4': { + id: 'component-c--story-4', + title: 'Component c', + name: 'Story 4', + importPath: './path/to/component-c.ts', + }, + }); + + const navigate = jest.fn(); + const store = createMockStore(); + const fullAPI = Object.assign(new EventEmitter(), { + setStories: jest.fn(), + }); + + const { api, init } = initStories({ store, navigate, provider, fullAPI } as any); + Object.assign(fullAPI, api); + + await init(); + + const { storiesHash: storedStoriesHash } = store.getState(); + + expect(Object.keys(storedStoriesHash)).toEqual(['component-b', 'component-b--docs']); }); - - const navigate = jest.fn(); - const store = createMockStore(); - const fullAPI = Object.assign(new EventEmitter(), { - setStories: jest.fn(), - }); - - const { api, init } = initStories({ store, navigate, provider, fullAPI }); - Object.assign(fullAPI, api); - - await init(); - - const { storiesHash: storedStoriesHash } = store.getState(); - - // We need exact key ordering, even if in theory JS doesn't guarantee it - expect(Object.keys(storedStoriesHash)).toEqual(['component-a', 'component-a--docs']); - expect(storedStoriesHash['component-a--docs'].parameters.docsOnly).toBe(true); }); }); @@ -1354,6 +1377,97 @@ describe('stories API', () => { }); }); + it('prefers parameters.docsOnly to inferred docsOnly status', async () => { + const navigate = jest.fn(); + const store = createMockStore(); + const fullAPI = Object.assign(new EventEmitter(), { + setOptions: jest.fn(), + findRef: jest.fn(), + }); + + const { api, init } = initStories({ store, navigate, provider, fullAPI } as any); + Object.assign(fullAPI, api); + + await init(); + + const setStoriesPayload = { + v: 2, + globalParameters: { global: 'global' }, + kindParameters: { a: { kind: 'kind' } }, + stories: { + 'component-a--docs': { + type: 'story', + kind: 'Component A', + name: 'Docs', // Called 'Docs' rather than 'Page' + importPath: './path/to/component-a.ts', + parameters: { + docsOnly: true, + }, + }, + }, + }; + fullAPI.emit(SET_STORIES, setStoriesPayload); + + const { storiesHash: storedStoriesHash } = store.getState(); + expect(storedStoriesHash['component-a--docs']).toMatchObject({ + type: 'docs', + id: 'component-a--docs', + parent: 'component-a', + title: 'Component A', + name: 'Docs', + }); + }); + + describe('when DOCS_MODE = true', () => { + beforeEach(() => { + global.DOCS_MODE = true; + }); + afterEach(() => { + global.DOCS_MODE = false; + }); + + it('strips out stories entries', async () => { + const navigate = jest.fn(); + const store = createMockStore(); + const fullAPI = Object.assign(new EventEmitter(), { + setOptions: jest.fn(), + findRef: jest.fn(), + }); + + const { api, init } = initStories({ store, navigate, provider, fullAPI } as any); + Object.assign(fullAPI, api); + + await init(); + + const setStoriesPayload = { + v: 2, + globalParameters: { global: 'global' }, + kindParameters: { a: { kind: 'kind' } }, + stories: { + 'component-a--docs': { + type: 'story', + kind: 'Component A', + name: 'Docs', // Called 'Docs' rather than 'Page' + importPath: './path/to/component-a.ts', + parameters: { + docsOnly: true, + }, + }, + 'component-a--story': { + title: 'Story', + kind: 'Component A', + importPath: './path/to/component-a.ts', + parameters: { story: 'story' }, + }, + }, + }; + fullAPI.emit(SET_STORIES, setStoriesPayload); + + const { storiesHash: storedStoriesHash } = store.getState(); + expect(Object.keys(storedStoriesHash)).toEqual(['component-a', 'component-a--docs']); + }); + }); + it('normalizes parameters and calls setRef for external stories', () => { const fullAPI = Object.assign(new EventEmitter()); const navigate = jest.fn();