Skip to content

Commit

Permalink
Merge pull request #22118 from storybookjs/tom/21798-fix-useParameter…
Browse files Browse the repository at this point in the history
…-simpler

Restore `useParameter` using `DOCS_PREPARED`
  • Loading branch information
shilman authored Apr 18, 2023
2 parents fdadeb7 + 03fecfe commit 2c89991
Show file tree
Hide file tree
Showing 18 changed files with 312 additions and 41 deletions.
32 changes: 30 additions & 2 deletions code/e2e-tests/addon-backgrounds.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ test.describe('addon-backgrounds', () => {
await new SbPage(page).waitUntilLoaded();
});

const backgroundToolbarSelector = '[title="Change the background of the preview"]';
const gridToolbarSelector = '[title="Apply a grid to the preview"]';

test('should have a dark background', async ({ page }) => {
const sbPage = new SbPage(page);

await sbPage.navigateToStory('example/button', 'primary');
await sbPage.selectToolbar('[title="Change the background of the preview"]', '#list-item-dark');
await sbPage.selectToolbar(backgroundToolbarSelector, '#list-item-dark');

await expect(sbPage.getCanvasBodyElement()).toHaveCSS('background-color', 'rgb(51, 51, 51)');
});
Expand All @@ -23,8 +26,33 @@ test.describe('addon-backgrounds', () => {
const sbPage = new SbPage(page);

await sbPage.navigateToStory('example/button', 'primary');
await sbPage.selectToolbar('[title="Apply a grid to the preview"]');
await sbPage.selectToolbar(gridToolbarSelector);

await expect(sbPage.getCanvasBodyElement()).toHaveCSS('background-image', /linear-gradient/);
});

test('button should appear for story pages', async ({ page }) => {
const sbPage = new SbPage(page);

await sbPage.navigateToStory('example/button', 'primary');
await expect(sbPage.page.locator(backgroundToolbarSelector)).toBeVisible();
});

test('button should appear for attached docs pages', async ({ page }) => {
const sbPage = new SbPage(page);

await sbPage.navigateToStory('example/button', 'docs');
await expect(sbPage.page.locator(backgroundToolbarSelector)).toBeVisible();
});

test('button should appear for unattached docs pages', async ({ page }) => {
const sbPage = new SbPage(page);

// We start on the introduction page by default.
await sbPage.page.waitForURL((url) =>
url.search.includes(`path=/docs/example-introduction--docs`)
);

await expect(sbPage.page.locator(backgroundToolbarSelector)).toBeVisible();
});
});
3 changes: 3 additions & 0 deletions code/lib/core-events/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ enum events {
PRELOAD_ENTRIES = 'preloadStories',
// The story has been loaded into the store, we have parameters/args/etc
STORY_PREPARED = 'storyPrepared',
// The a docs entry has been loaded into the store, we have parameters
DOCS_PREPARED = 'docsPrepared',
// The next 6 events are emitted by the StoryRenderer when rendering the current story
STORY_CHANGED = 'storyChanged',
STORY_UNCHANGED = 'storyUnchanged',
Expand Down Expand Up @@ -73,6 +75,7 @@ export const {
CHANNEL_CREATED,
CONFIG_ERROR,
CURRENT_STORY_WAS_SET,
DOCS_PREPARED,
DOCS_RENDERED,
FORCE_RE_RENDER,
FORCE_REMOUNT,
Expand Down
2 changes: 1 addition & 1 deletion code/lib/manager-api/src/lib/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ export const transformStoryIndexToStoriesHash = (
depth: paths.length,
parent: paths[paths.length - 1],
renderLabel,
...(item.type !== 'docs' && { prepared: !!item.parameters }),
prepared: !!item.parameters,

// deprecated fields
kind: item.title,
Expand Down
40 changes: 37 additions & 3 deletions code/lib/manager-api/src/modules/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import type {
StoryIndex,
API_LoadedRefData,
API_IndexHash,
StoryPreparedPayload,
DocsPreparedPayload,
API_DocsEntry,
} from '@storybook/types';
import {
PRELOAD_ENTRIES,
Expand All @@ -31,6 +34,7 @@ import {
CONFIG_ERROR,
CURRENT_STORY_WAS_SET,
STORY_MISSING,
DOCS_PREPARED,
} from '@storybook/core-events';
import { logger } from '@storybook/client-logger';

Expand All @@ -54,7 +58,10 @@ type Direction = -1 | 1;
type ParameterName = string;

type ViewMode = 'story' | 'info' | 'settings' | string | undefined;
type StoryUpdate = Pick<API_StoryEntry, 'parameters' | 'initialArgs' | 'argTypes' | 'args'>;
type StoryUpdate = Partial<
Pick<API_StoryEntry, 'prepared' | 'parameters' | 'initialArgs' | 'argTypes' | 'args'>
>;
type DocsUpdate = Partial<Pick<API_DocsEntry, 'prepared' | 'parameters'>>;

export interface SubState extends API_LoadedRefData {
storyId: StoryId;
Expand Down Expand Up @@ -93,6 +100,7 @@ export interface SubAPI {
): StoryId;
fetchIndex: () => Promise<void>;
updateStory: (storyId: StoryId, update: StoryUpdate, ref?: API_ComposedRef) => Promise<void>;
updateDocs: (storyId: StoryId, update: DocsUpdate, ref?: API_ComposedRef) => Promise<void>;
setPreviewInitialized: (ref?: ComposedRef) => Promise<void>;
}

Expand Down Expand Up @@ -157,7 +165,7 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({
: storyIdOrCombo;
const data = api.getData(storyId, refId);

if (data?.type === 'story') {
if (['story', 'docs'].includes(data?.type)) {
const { parameters } = data;

if (parameters) {
Expand Down Expand Up @@ -370,6 +378,27 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({
await fullAPI.updateRef(refId, { index });
}
},
updateDocs: async (
docsId: StoryId,
update: DocsUpdate,
ref?: API_ComposedRef
): Promise<void> => {
if (!ref) {
const { index } = store.getState();
index[docsId] = {
...index[docsId],
...update,
} as API_DocsEntry;
await store.setState({ index });
} else {
const { id: refId, index } = ref;
index[docsId] = {
...index[docsId],
...update,
} as API_DocsEntry;
await fullAPI.updateRef(refId, { index });
}
},
setPreviewInitialized: async (ref?: ComposedRef): Promise<void> => {
if (!ref) {
store.setState({ previewInitialized: true });
Expand Down Expand Up @@ -428,7 +457,7 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({
}
});

fullAPI.on(STORY_PREPARED, function handler({ id, ...update }) {
fullAPI.on(STORY_PREPARED, function handler({ id, ...update }: StoryPreparedPayload) {
const { ref, sourceType } = getEventMetadata(this, fullAPI);
fullAPI.updateStory(id, { ...update, prepared: true }, ref);

Expand Down Expand Up @@ -458,6 +487,11 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({
}
});

fullAPI.on(DOCS_PREPARED, function handler({ id, ...update }: DocsPreparedPayload) {
const { ref } = getEventMetadata(this, fullAPI);
fullAPI.updateStory(id, { ...update, prepared: true }, ref);
});

fullAPI.on(SET_INDEX, function handler(index: API_PreparedStoryIndex) {
const { ref } = getEventMetadata(this, fullAPI);

Expand Down
53 changes: 52 additions & 1 deletion code/lib/manager-api/src/tests/stories.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ jest.mock('@storybook/global', () => ({
const getEventMetadataMock = getEventMetadata as ReturnType<typeof jest.fn>;

const mockEntries: StoryIndex['entries'] = {
'component-a--docs': {
type: 'docs',
id: 'component-a--docs',
title: 'Component A',
name: 'Docs',
importPath: './path/to/component-a.ts',
storiesImports: [],
},
'component-a--story-1': {
type: 'story',
id: 'component-a--story-1',
Expand Down Expand Up @@ -139,6 +147,7 @@ describe('stories API', () => {
// We need exact key ordering, even if in theory JS doesn't guarantee it
expect(Object.keys(index)).toEqual([
'component-a',
'component-a--docs',
'component-a--story-1',
'component-a--story-2',
'component-b',
Expand All @@ -147,7 +156,17 @@ describe('stories API', () => {
expect(index['component-a']).toMatchObject({
type: 'component',
id: 'component-a',
children: ['component-a--story-1', 'component-a--story-2'],
children: ['component-a--docs', 'component-a--story-1', 'component-a--story-2'],
});

expect(index['component-a--docs']).toMatchObject({
type: 'docs',
id: 'component-a--docs',
parent: 'component-a',
title: 'Component A',
name: 'Docs',
storiesImports: [],
prepared: false,
});

expect(index['component-a--story-1']).toMatchObject({
Expand Down Expand Up @@ -232,6 +251,7 @@ describe('stories API', () => {
// We need exact key ordering, even if in theory JS doesn't guarantee it
expect(Object.keys(index)).toEqual([
'component-a',
'component-a--docs',
'component-a--story-1',
'component-a--story-2',
'component-b',
Expand Down Expand Up @@ -1424,6 +1444,37 @@ describe('stories API', () => {
});
});

describe('DOCS_PREPARED', () => {
it('prepares the docs entry', async () => {
const navigate = jest.fn();
const store = createMockStore();
const fullAPI = Object.assign(new EventEmitter(), {
setStories: jest.fn(),
setOptions: jest.fn(),
});

const { api, init } = initStoriesAndSetState({ store, navigate, provider, fullAPI } as any);
Object.assign(fullAPI, api);

await init();
fullAPI.emit(STORY_PREPARED, {
id: 'component-a--docs',
parameters: { a: 'b' },
});

const { index } = store.getState();
expect(index['component-a--docs']).toMatchObject({
type: 'docs',
id: 'component-a--docs',
parent: 'component-a',
title: 'Component A',
name: 'Docs',
prepared: true,
parameters: { a: 'b' },
});
});
});

describe('CONFIG_ERROR', () => {
it('sets previewInitialized to true, local', async () => {
const navigate = jest.fn();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ export const componentTwoExports = {
default: { title: 'Component Two' },
c: { args: { foo: 'c' } },
};
export const attachedDocsExports = {
default: jest.fn(),
};
export const unattachedDocsExports = {
default: jest.fn(),
};
Expand All @@ -49,6 +52,7 @@ export const importFn: jest.Mocked<ModuleImportFn> = jest.fn(
async (path: string) =>
({
'./src/ComponentOne.stories.js': componentOneExports,
'./src/ComponentOne.mdx': attachedDocsExports,
'./src/ComponentTwo.stories.js': componentTwoExports,
'./src/Introduction.mdx': unattachedDocsExports,
'./src/ExtraComponentOne.stories.js': extraComponentOneExports,
Expand Down Expand Up @@ -80,7 +84,16 @@ export const storyIndex: StoryIndex = {
name: 'Docs',
importPath: './src/ComponentOne.stories.js',
storiesImports: ['./src/ExtraComponentOne.stories.js'],
tags: ['autodocs'],
tags: ['autodocs', 'docs'],
},
'component-one--attached-docs': {
type: 'docs',
id: 'component-one--attached-docs',
title: 'Component One',
name: 'Attached Docs',
importPath: './src/ComponentOne.mdx',
storiesImports: ['./src/ComponentOne.stories.js'],
tags: ['attached-mdx', 'docs'],
},
'component-one--a': {
type: 'story',
Expand Down Expand Up @@ -110,7 +123,7 @@ export const storyIndex: StoryIndex = {
name: 'Docs',
importPath: './src/ComponentTwo.stories.js',
storiesImports: [],
tags: ['autodocs'],
tags: ['autodocs', 'docs'],
},
'component-two--c': {
type: 'story',
Expand All @@ -126,6 +139,7 @@ export const storyIndex: StoryIndex = {
name: 'Docs',
importPath: './src/Introduction.mdx',
storiesImports: ['./src/ComponentTwo.stories.js'],
tags: ['unattached-mdx', 'docs'],
},
},
};
Expand Down
Loading

0 comments on commit 2c89991

Please sign in to comment.