Merge pull request #16224 from storybookjs/16049-v7-composition

Core: Support composing stories in both v6 and v7 modes
This commit is contained in:
Michael Shilman 2021-10-04 22:40:58 +08:00 committed by GitHub
commit 2302ccbdc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 104 additions and 18 deletions

View File

@ -5,9 +5,11 @@ import {
StoriesRaw,
StoryInput,
StoriesHash,
transformStoryIndexToStoriesHash,
StoryIndexStory,
} from '../lib/stories';
import { ModuleFn } from '../index';
import { ModuleFn, StoryId } from '../index';
const { location, fetch } = global;
@ -19,6 +21,7 @@ type Versions = Record<string, string>;
export type SetRefData = Partial<
Omit<ComposedRef, 'stories'> & {
v: number;
stories?: StoriesRaw;
}
>;
@ -148,7 +151,7 @@ export const init: ModuleFn = ({ store, provider, singleStory }, { runCheck = tr
//
// then we fetch metadata if the above fetch succeeded
const loadedData: { error?: Error; stories?: StoriesRaw; loginUrl?: string } = {};
const loadedData: { error?: Error; v?: number; stories?: StoriesRaw; loginUrl?: string } = {};
const query = version ? `?version=${version}` : '';
const credentials = isPublic ? 'omit' : 'include';
@ -209,18 +212,28 @@ export const init: ModuleFn = ({ store, provider, singleStory }, { runCheck = tr
return refs;
},
setRef: (id, { stories, ...rest }, ready = false) => {
setRef: (id, { stories, v, ...rest }, ready = false) => {
if (singleStory) return;
const { storyMapper = defaultStoryMapper } = provider.getConfig();
const ref = api.getRefs()[id];
const after = stories
? addRefIds(
transformStoriesRawToStoriesHash(map(stories, ref, { storyMapper }), { provider }),
ref
)
: undefined;
api.updateRef(id, { stories: after, ...rest, ready });
let storiesHash: StoriesHash;
if (stories) {
if (v === 2) {
storiesHash = transformStoriesRawToStoriesHash(map(stories, ref, { storyMapper }), {
provider,
});
} else if (!v) {
throw new Error('Composition: Missing stories.json version');
} else {
const index = (stories as unknown) as Record<StoryId, StoryIndexStory>;
storiesHash = transformStoryIndexToStoriesHash({ v, stories: index }, { provider });
}
storiesHash = addRefIds(storiesHash, ref);
}
api.updateRef(id, { stories: storiesHash, ...rest, ready });
},
updateRef: (id, data) => {

View File

@ -480,11 +480,15 @@ export const init: ModuleFn = ({
const { ref } = getEventMetadata(this, fullAPI);
fullAPI.updateStory(id, { ...update, prepared: true }, ref);
if (!store.getState().hasCalledSetOptions) {
const { options } = update.parameters;
checkDeprecatedOptionParameters(options);
fullAPI.setOptions(options);
store.setState({ hasCalledSetOptions: true });
if (!ref) {
if (!store.getState().hasCalledSetOptions) {
const { options } = update.parameters;
checkDeprecatedOptionParameters(options);
fullAPI.setOptions(options);
store.setState({ hasCalledSetOptions: true });
}
} else {
fullAPI.updateRef(ref.id, { ready: true });
}
});

View File

@ -260,11 +260,11 @@ describe('Refs API', () => {
setupResponses(
{
ok: true,
response: async () => ({ stories: {} }),
response: async () => ({ v: 2, stories: {} }),
},
{
ok: true,
response: async () => ({ stories: {} }),
response: async () => ({ v: 3, stories: {} }),
},
{
ok: true,
@ -418,7 +418,7 @@ describe('Refs API', () => {
},
{
ok: true,
response: async () => ({ stories: {} }),
response: async () => ({ v: 2, stories: {} }),
},
{
ok: true,
@ -621,4 +621,40 @@ describe('Refs API', () => {
`);
});
});
it('errors on unknown version', async () => {
// given
const { api } = initRefs({ provider, store }, { runCheck: false });
setupResponses(
{
ok: true,
response: async () => ({ v: 2, stories: {} }),
},
{
ok: true,
response: async () => ({ stories: {} }),
},
{
ok: true,
response: async () => {
throw new Error('not ok');
},
},
{
ok: true,
response: async () => ({
versions: {},
}),
}
);
await expect(
api.checkRef({
id: 'fake',
url: 'https://example.com',
title: 'Fake',
})
).rejects.toThrow('Composition: Missing stories.json version');
});
});

View File

@ -999,6 +999,7 @@ describe('stories API', () => {
args: { c: 'd' },
});
});
it('sets options the first time it is called', async () => {
const navigate = jest.fn();
const store = createMockStore();
@ -1026,6 +1027,38 @@ describe('stories API', () => {
expect(fullAPI.setOptions).not.toHaveBeenCalled();
});
it('sets the ref to ready when it is an external story', async () => {
const navigate = jest.fn();
const store = createMockStore();
const fullAPI = Object.assign(new EventEmitter(), {
setStories: jest.fn(),
updateRef: jest.fn(),
});
const { api, init } = initStories({ store, navigate, provider, fullAPI });
Object.assign(fullAPI, api);
getEventMetadata.mockReturnValueOnce({
sourceType: 'external',
ref: { id: 'refId', stories: { 'a--1': { args: { a: 'b' } } } },
});
await init();
fullAPI.emit(STORY_PREPARED, {
id: 'a--1',
});
expect(fullAPI.updateRef.mock.calls.length).toBe(2);
expect(fullAPI.updateRef.mock.calls[0][1]).toEqual({
stories: { 'a--1': { args: { a: 'b' }, prepared: true } },
});
expect(fullAPI.updateRef.mock.calls[1][1]).toEqual({
ready: true,
});
});
});
describe('v2 SET_STORIES event', () => {