mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-11 00:06:25 +08:00
Added basic global args mechanism to story_store
This commit is contained in:
parent
c64b99d6b8
commit
d75b4e09a0
@ -85,7 +85,7 @@ describe('preview.story_store', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('args', () => {
|
describe('args', () => {
|
||||||
it('args is initialized to the value stored in parameters.args[name] || parameters.argType[name].defaultValue', () => {
|
it('is initialized to the value stored in parameters.args[name] || parameters.argType[name].defaultValue', () => {
|
||||||
const store = new StoryStore({ channel });
|
const store = new StoryStore({ channel });
|
||||||
addStoryToStore(store, 'a', '1', () => 0, {
|
addStoryToStore(store, 'a', '1', () => 0, {
|
||||||
argTypes: {
|
argTypes: {
|
||||||
@ -201,6 +201,111 @@ describe('preview.story_store', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('globalArgs', () => {
|
||||||
|
it.skip('is initialized to the value stored in parameters.globalArgTypes[name].defaultValue', () => {
|
||||||
|
const store = new StoryStore({ channel });
|
||||||
|
addStoryToStore(store, 'a', '1', () => 0, {
|
||||||
|
argTypes: {
|
||||||
|
arg1: { defaultValue: 'arg1' },
|
||||||
|
arg2: { defaultValue: 2 },
|
||||||
|
arg3: { defaultValue: { complex: { object: ['type'] } } },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(store.getRawStory('a', '1').args).toEqual({
|
||||||
|
arg1: 'arg1',
|
||||||
|
arg2: 2,
|
||||||
|
arg3: { complex: { object: ['type'] } },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setGlobalArgs changes the global args', () => {
|
||||||
|
const store = new StoryStore({ channel });
|
||||||
|
addStoryToStore(store, 'a', '1', () => 0);
|
||||||
|
expect(store.getRawStory('a', '1').globalArgs).toEqual({});
|
||||||
|
|
||||||
|
store.setGlobalArgs({ foo: 'bar' });
|
||||||
|
expect(store.getRawStory('a', '1').globalArgs).toEqual({ foo: 'bar' });
|
||||||
|
|
||||||
|
store.setGlobalArgs({ baz: 'bing' });
|
||||||
|
expect(store.getRawStory('a', '1').globalArgs).toEqual({ foo: 'bar', baz: 'bing' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is passed to the story in the context', () => {
|
||||||
|
const storyFn = jest.fn();
|
||||||
|
const store = new StoryStore({ channel });
|
||||||
|
|
||||||
|
store.setGlobalArgs({ foo: 'bar' });
|
||||||
|
addStoryToStore(store, 'a', '1', storyFn);
|
||||||
|
store.getRawStory('a', '1').storyFn();
|
||||||
|
|
||||||
|
expect(storyFn).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
globalArgs: { foo: 'bar' },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
store.setGlobalArgs({ baz: 'bing' });
|
||||||
|
store.getRawStory('a', '1').storyFn();
|
||||||
|
|
||||||
|
expect(storyFn).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
globalArgs: { foo: 'bar', baz: 'bing' },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setGlobalArgs emits GLOBAL_ARGS_CHANGED', () => {
|
||||||
|
const onGlobalArgsChangedChannel = jest.fn();
|
||||||
|
const testChannel = mockChannel();
|
||||||
|
testChannel.on(Events.GLOBAL_ARGS_CHANGED, onGlobalArgsChangedChannel);
|
||||||
|
|
||||||
|
const store = new StoryStore({ channel: testChannel });
|
||||||
|
addStoryToStore(store, 'a', '1', () => 0);
|
||||||
|
|
||||||
|
store.setGlobalArgs({ foo: 'bar' });
|
||||||
|
expect(onGlobalArgsChangedChannel).toHaveBeenCalledWith({ foo: 'bar' });
|
||||||
|
|
||||||
|
store.setGlobalArgs({ baz: 'bing' });
|
||||||
|
expect(onGlobalArgsChangedChannel).toHaveBeenCalledWith({ foo: 'bar', baz: 'bing' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update if the CHANGE_GLOBAL_ARGS event is received', () => {
|
||||||
|
const testChannel = mockChannel();
|
||||||
|
const store = new StoryStore({ channel: testChannel });
|
||||||
|
addStoryToStore(store, 'a', '1', () => 0);
|
||||||
|
|
||||||
|
testChannel.emit(Events.CHANGE_GLOBAL_ARGS, { foo: 'bar' });
|
||||||
|
|
||||||
|
expect(store.getRawStory('a', '1').globalArgs).toEqual({ foo: 'bar' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('DOES NOT pass globalArgs as the first argument to the story if `parameters.passArgsFirst` is true', () => {
|
||||||
|
const store = new StoryStore({ channel });
|
||||||
|
|
||||||
|
const storyOne = jest.fn();
|
||||||
|
addStoryToStore(store, 'a', '1', storyOne);
|
||||||
|
|
||||||
|
store.setGlobalArgs({ foo: 'bar' });
|
||||||
|
|
||||||
|
store.getRawStory('a', '1').storyFn();
|
||||||
|
expect(storyOne).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
globalArgs: { foo: 'bar' },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const storyTwo = jest.fn();
|
||||||
|
addStoryToStore(store, 'a', '2', storyTwo, { passArgsFirst: true });
|
||||||
|
store.getRawStory('a', '2').storyFn();
|
||||||
|
expect(storyTwo).toHaveBeenCalledWith(
|
||||||
|
{},
|
||||||
|
expect.objectContaining({
|
||||||
|
globalArgs: { foo: 'bar' },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('parameterEnhancer', () => {
|
describe('parameterEnhancer', () => {
|
||||||
it('allows you to alter parameters when stories are added', () => {
|
it('allows you to alter parameters when stories are added', () => {
|
||||||
const store = new StoryStore({ channel });
|
const store = new StoryStore({ channel });
|
||||||
|
@ -22,6 +22,7 @@ import {
|
|||||||
StoreData,
|
StoreData,
|
||||||
AddStoryArgs,
|
AddStoryArgs,
|
||||||
StoreItem,
|
StoreItem,
|
||||||
|
PublishedStoreItem,
|
||||||
ErrorLike,
|
ErrorLike,
|
||||||
GetStorybookKind,
|
GetStorybookKind,
|
||||||
ParameterEnhancer,
|
ParameterEnhancer,
|
||||||
@ -75,6 +76,8 @@ export default class StoryStore {
|
|||||||
|
|
||||||
_configuring: boolean;
|
_configuring: boolean;
|
||||||
|
|
||||||
|
_globalArgs: Args;
|
||||||
|
|
||||||
_globalMetadata: StoryMetadata;
|
_globalMetadata: StoryMetadata;
|
||||||
|
|
||||||
// Keyed on kind name
|
// Keyed on kind name
|
||||||
@ -92,6 +95,8 @@ export default class StoryStore {
|
|||||||
constructor(params: { channel: Channel }) {
|
constructor(params: { channel: Channel }) {
|
||||||
// Assume we are configuring until we hear otherwise
|
// Assume we are configuring until we hear otherwise
|
||||||
this._configuring = true;
|
this._configuring = true;
|
||||||
|
|
||||||
|
this._globalArgs = {};
|
||||||
this._globalMetadata = { parameters: {}, decorators: [] };
|
this._globalMetadata = { parameters: {}, decorators: [] };
|
||||||
this._kinds = {};
|
this._kinds = {};
|
||||||
this._stories = {};
|
this._stories = {};
|
||||||
@ -115,6 +120,10 @@ export default class StoryStore {
|
|||||||
this._channel.on(Events.CHANGE_STORY_ARGS, (id: string, newArgs: Args) =>
|
this._channel.on(Events.CHANGE_STORY_ARGS, (id: string, newArgs: Args) =>
|
||||||
this.setStoryArgs(id, newArgs)
|
this.setStoryArgs(id, newArgs)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this._channel.on(Events.CHANGE_GLOBAL_ARGS, (newGlobalArgs: Args) =>
|
||||||
|
this.setGlobalArgs(newGlobalArgs)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
startConfiguring() {
|
startConfiguring() {
|
||||||
@ -247,6 +256,7 @@ export default class StoryStore {
|
|||||||
parameters,
|
parameters,
|
||||||
hooks,
|
hooks,
|
||||||
args: _stories[id].args,
|
args: _stories[id].args,
|
||||||
|
globalArgs: this._globalArgs,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pull out parameters.args.$ || .argTypes.$.defaultValue into initialArgs
|
// Pull out parameters.args.$ || .argTypes.$.defaultValue into initialArgs
|
||||||
@ -306,7 +316,20 @@ export default class StoryStore {
|
|||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
fromId = (id: string): StoreItem | null => {
|
setGlobalArgs(newGlobalArgs: Args) {
|
||||||
|
this._globalArgs = { ...this._globalArgs, ...newGlobalArgs };
|
||||||
|
this._channel.emit(Events.GLOBAL_ARGS_CHANGED, this._globalArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
setStoryArgs(id: string, newArgs: Args) {
|
||||||
|
if (!this._stories[id]) throw new Error(`No story for id ${id}`);
|
||||||
|
const { args } = this._stories[id];
|
||||||
|
this._stories[id].args = { ...args, ...newArgs };
|
||||||
|
|
||||||
|
this._channel.emit(Events.STORY_ARGS_CHANGED, id, this._stories[id].args);
|
||||||
|
}
|
||||||
|
|
||||||
|
fromId = (id: string): PublishedStoreItem | null => {
|
||||||
try {
|
try {
|
||||||
const data = this._stories[id as string];
|
const data = this._stories[id as string];
|
||||||
|
|
||||||
@ -314,7 +337,10 @@ export default class StoryStore {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return {
|
||||||
|
...data,
|
||||||
|
globalArgs: this._globalArgs,
|
||||||
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.warn('failed to get story:', this._stories);
|
logger.warn('failed to get story:', this._stories);
|
||||||
logger.error(e);
|
logger.error(e);
|
||||||
@ -434,14 +460,6 @@ export default class StoryStore {
|
|||||||
this.getStoriesForKind(kind).map(story => this.cleanHooks(story.id));
|
this.getStoriesForKind(kind).map(story => this.cleanHooks(story.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
setStoryArgs(id: string, newArgs: Args) {
|
|
||||||
if (!this._stories[id]) throw new Error(`No story for id ${id}`);
|
|
||||||
const { args } = this._stories[id];
|
|
||||||
this._stories[id].args = { ...args, ...newArgs };
|
|
||||||
|
|
||||||
this._channel.emit(Events.STORY_ARGS_CHANGED, id, this._stories[id].args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This API is a reimplementation of Storybook's original getStorybook() API.
|
// This API is a reimplementation of Storybook's original getStorybook() API.
|
||||||
// As such it may not behave *exactly* the same, but aims to. Some notes:
|
// As such it may not behave *exactly* the same, but aims to. Some notes:
|
||||||
// - It is *NOT* sorted by the user's sort function, but remains sorted in "insertion order"
|
// - It is *NOT* sorted by the user's sort function, but remains sorted in "insertion order"
|
||||||
|
@ -39,6 +39,10 @@ export type StoreItem = StoryIdentifier & {
|
|||||||
args: Args;
|
args: Args;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type PublishedStoreItem = StoreItem & {
|
||||||
|
globalArgs: Args;
|
||||||
|
};
|
||||||
|
|
||||||
export interface StoreData {
|
export interface StoreData {
|
||||||
[key: string]: StoreItem;
|
[key: string]: StoreItem;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,9 @@ enum events {
|
|||||||
CHANGE_STORY_ARGS = 'changeStoryArgs',
|
CHANGE_STORY_ARGS = 'changeStoryArgs',
|
||||||
// The values of a stories args just changed
|
// The values of a stories args just changed
|
||||||
STORY_ARGS_CHANGED = 'storyArgsChanged',
|
STORY_ARGS_CHANGED = 'storyArgsChanged',
|
||||||
|
// As above
|
||||||
|
CHANGE_GLOBAL_ARGS = 'changeGlobalArgs',
|
||||||
|
GLOBAL_ARGS_CHANGED = 'globalArgsChanged',
|
||||||
REGISTER_SUBSCRIPTION = 'registerSubscription',
|
REGISTER_SUBSCRIPTION = 'registerSubscription',
|
||||||
// Tell the manager that the user pressed a key in the preview
|
// Tell the manager that the user pressed a key in the preview
|
||||||
PREVIEW_KEYDOWN = 'previewKeydown',
|
PREVIEW_KEYDOWN = 'previewKeydown',
|
||||||
@ -56,6 +59,8 @@ export const {
|
|||||||
STORY_THREW_EXCEPTION,
|
STORY_THREW_EXCEPTION,
|
||||||
CHANGE_STORY_ARGS,
|
CHANGE_STORY_ARGS,
|
||||||
STORY_ARGS_CHANGED,
|
STORY_ARGS_CHANGED,
|
||||||
|
CHANGE_GLOBAL_ARGS,
|
||||||
|
GLOBAL_ARGS_CHANGED,
|
||||||
REGISTER_SUBSCRIPTION,
|
REGISTER_SUBSCRIPTION,
|
||||||
PREVIEW_KEYDOWN,
|
PREVIEW_KEYDOWN,
|
||||||
SELECT_STORY,
|
SELECT_STORY,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user