Skip to content

Commit

Permalink
Core: Fix default sorting of docs-only stories (#9504)
Browse files Browse the repository at this point in the history
Core: Fix default sorting of docs-only stories
  • Loading branch information
shilman committed Jan 17, 2020
2 parents b1afe49 + d60b374 commit 3a4f187
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 15 deletions.
5 changes: 5 additions & 0 deletions examples/official-storybook/intro.stories.mdx
@@ -0,0 +1,5 @@
<Meta title="About/Intro" />

# Official-storybook

Welcome to `official-storybook`, a collection of test cases and demos for `@storybook/react` and all its addons.
1 change: 1 addition & 0 deletions examples/official-storybook/main.js
@@ -1,5 +1,6 @@
module.exports = {
stories: [
// FIXME: Breaks e2e tests './intro.stories.mdx',
'../../lib/ui/src/**/*.stories.(js|tsx|mdx)',
'../../lib/components/src/**/*.stories.(js|tsx|mdx)',
'./stories/**/*.stories.(js|tsx|mdx)',
Expand Down
10 changes: 6 additions & 4 deletions lib/client-api/src/client_api.test.ts
Expand Up @@ -514,21 +514,23 @@ describe('preview.client_api', () => {
clientApi: { storiesOf, getStorybook },
channel,
} = getContext(undefined);
const module0 = new MockModule();
const module1 = new MockModule();
const module2 = new MockModule();
channel.emit = jest.fn();

expect(getStorybook()).toEqual([]);

storiesOf('kind0', module0).add('story0-docs-only', jest.fn(), { docsOnly: true });
storiesOf('kind1', module1).add('story1', jest.fn());
storiesOf('kind2', module2).add('story2', jest.fn());

// storyStore debounces so we need to wait for the next tick
await new Promise(r => setTimeout(r, 0));

let [event, storiesHash] = channel.emit.mock.calls[0];
let [event, args] = channel.emit.mock.calls[0];
expect(event).toEqual(Events.SET_STORIES);
expect(Object.values(storiesHash.stories).map(v => v.kind)).toEqual(['kind1', 'kind2']);
expect(Object.values(args.stories).map(v => v.kind)).toEqual(['kind0', 'kind1', 'kind2']);
expect(getStorybook().map(story => story.kind)).toEqual(['kind1', 'kind2']);

channel.emit.mockClear();
Expand All @@ -540,10 +542,10 @@ describe('preview.client_api', () => {

await new Promise(r => setTimeout(r, 0));
// eslint-disable-next-line prefer-destructuring
[event, storiesHash] = channel.emit.mock.calls[0];
[event, args] = channel.emit.mock.calls[0];

expect(event).toEqual(Events.SET_STORIES);
expect(Object.values(storiesHash.stories).map(v => v.kind)).toEqual(['kind1', 'kind2']);
expect(Object.values(args.stories).map(v => v.kind)).toEqual(['kind0', 'kind1', 'kind2']);
expect(getStorybook().map(story => story.kind)).toEqual(['kind1', 'kind2']);
});
});
Expand Down
28 changes: 17 additions & 11 deletions lib/client-api/src/story_store.ts
Expand Up @@ -55,6 +55,8 @@ interface StoryOptions {
includeDocsOnly?: boolean;
}

type KindOrder = Record<string, number>;

const isStoryDocsOnly = (parameters?: Parameters) => {
return parameters && parameters.docsOnly;
};
Expand All @@ -81,6 +83,8 @@ export default class StoryStore extends EventEmitter {

_selection: Selection;

_kindOrder: KindOrder;

constructor(params: { channel: Channel }) {
super();

Expand All @@ -90,6 +94,7 @@ export default class StoryStore extends EventEmitter {
this._selection = {} as any;
this._channel = params.channel;
this._error = undefined;
this._kindOrder = {};
}

setChannel = (channel: Channel) => {
Expand Down Expand Up @@ -133,17 +138,11 @@ export default class StoryStore extends EventEmitter {
stable.inplace(stories, sortFn);
} else {
// NOTE: when kinds are HMR'ed they get temporarily removed from the `_data` array
// and thus lose order. However in `_legacydata` they just get zeroed out, meaning
// that the order is preserved. Here we can use this to preserve the load
// order if there is no sort function, although it's a hack.
const kindOrder = Object.values(this._legacydata).reduce(
(acc: Record<string, number>, { kind }: any, idx: number) => {
acc[kind] = idx;
return acc;
},
{}
// and thus lose order. However `_kindOrder` preservers the original load order
stable.inplace(
stories,
(s1, s2) => this._kindOrder[s1[1].kind] - this._kindOrder[s2[1].kind]
);
stable.inplace(stories, (s1, s2) => kindOrder[s1[1].kind] - kindOrder[s2[1].kind]);
}
}
// removes function values from all stories so they are safe to transport over the channel
Expand Down Expand Up @@ -252,11 +251,18 @@ export default class StoryStore extends EventEmitter {
parameters,
};

// LEGACY DATA
// Don't store docs-only stories in legacy data because
// existing clients (at the time?!), e.g. storyshots/chromatic
// are not necessarily equipped to process them
if (!isStoryDocsOnly(parameters)) {
this.addLegacyStory({ kind, name, storyFn, parameters });
}

// Store 1-based order of kind loading to preserve sorting on HMR
if (!this._kindOrder[kind]) {
this._kindOrder[kind] = 1 + Object.keys(this._kindOrder).length;
}

// LET'S SEND IT TO THE MANAGER
this.pushToManager();
}
Expand Down

1 comment on commit 3a4f187

@vercel
Copy link

@vercel vercel bot commented on 3a4f187 Jan 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.