mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-09 00:19:13 +08:00
add beforeAllHook to portable stories
This commit is contained in:
parent
1f6c1832f9
commit
ee0653d65d
@ -10,6 +10,7 @@ import type {
|
||||
StoryAnnotationsOrFn,
|
||||
Store_CSFExports,
|
||||
StoriesWithPartialProps,
|
||||
NamedOrDefaultProjectAnnotations,
|
||||
} from '@storybook/types';
|
||||
|
||||
// ! ATTENTION: This needs to be a relative import so it gets prebundled. This is to avoid ESM issues in Nextjs + Jest setups
|
||||
@ -34,9 +35,11 @@ import type { ReactRenderer, Meta } from '@storybook/react';
|
||||
* @param projectAnnotations - e.g. (import projectAnnotations from '../.storybook/preview')
|
||||
*/
|
||||
export function setProjectAnnotations(
|
||||
projectAnnotations: ProjectAnnotations<ReactRenderer> | ProjectAnnotations<ReactRenderer>[]
|
||||
) {
|
||||
originalSetProjectAnnotations<ReactRenderer>(projectAnnotations);
|
||||
projectAnnotations:
|
||||
| NamedOrDefaultProjectAnnotations<ReactRenderer>
|
||||
| NamedOrDefaultProjectAnnotations<ReactRenderer>[]
|
||||
): ProjectAnnotations<ReactRenderer> {
|
||||
return originalSetProjectAnnotations<ReactRenderer>(projectAnnotations);
|
||||
}
|
||||
|
||||
// This will not be necessary once we have auto preset loading
|
||||
|
@ -26,6 +26,39 @@ describe('composeStory', () => {
|
||||
tags: ['metaTag'],
|
||||
};
|
||||
|
||||
it('should return beforeAll as part of project annotations', async () => {
|
||||
const spy = vi.fn();
|
||||
const annotations = {
|
||||
beforeAll: async () => {
|
||||
spy();
|
||||
},
|
||||
};
|
||||
const finalAnnotations = setProjectAnnotations(annotations);
|
||||
await finalAnnotations.beforeAll?.();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return composed project annotations via setProjectAnnotations', () => {
|
||||
const firstAnnotations = {
|
||||
parameters: { foo: 'bar' },
|
||||
tags: ['autodocs'],
|
||||
};
|
||||
|
||||
const secondAnnotations = {
|
||||
args: {
|
||||
foo: 'bar',
|
||||
},
|
||||
};
|
||||
const finalAnnotations = setProjectAnnotations([firstAnnotations, secondAnnotations]);
|
||||
expect(finalAnnotations).toEqual(
|
||||
expect.objectContaining({
|
||||
parameters: { foo: 'bar' },
|
||||
args: { foo: 'bar' },
|
||||
tags: ['autodocs'],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should compose project annotations in all module formats', () => {
|
||||
setProjectAnnotations([defaultExportAnnotations, namedExportAnnotations]);
|
||||
|
||||
|
@ -35,8 +35,10 @@ const DEFAULT_STORY_NAME = 'Unnamed Story';
|
||||
function extractAnnotation<TRenderer extends Renderer = Renderer>(
|
||||
annotation: NamedOrDefaultProjectAnnotations<TRenderer>
|
||||
) {
|
||||
if (!annotation) return {};
|
||||
// support imports such as
|
||||
// import * as annotations from '.storybook/preview'
|
||||
// import annotations from '.storybook/preview'
|
||||
// in both cases: 1 - the file has a default export; 2 - named exports only
|
||||
return 'default' in annotation ? annotation.default : annotation;
|
||||
}
|
||||
@ -45,9 +47,11 @@ export function setProjectAnnotations<TRenderer extends Renderer = Renderer>(
|
||||
projectAnnotations:
|
||||
| NamedOrDefaultProjectAnnotations<TRenderer>
|
||||
| NamedOrDefaultProjectAnnotations<TRenderer>[]
|
||||
) {
|
||||
): ProjectAnnotations<TRenderer> {
|
||||
const annotations = Array.isArray(projectAnnotations) ? projectAnnotations : [projectAnnotations];
|
||||
globalProjectAnnotations = composeConfigs(annotations.map(extractAnnotation));
|
||||
|
||||
return globalProjectAnnotations;
|
||||
}
|
||||
|
||||
const cleanups: { storyName: string; callback: CleanupCallback }[] = [];
|
||||
@ -165,7 +169,7 @@ export function composeStory<TRenderer extends Renderer = Renderer, TArgs extend
|
||||
cleanups.push(
|
||||
...(await story.applyBeforeEach(context))
|
||||
.filter(Boolean)
|
||||
.map((callback) => ({ storyName, callback }))
|
||||
.map((callback: () => void) => ({ storyName, callback }))
|
||||
);
|
||||
},
|
||||
args: story.initialArgs as Partial<TArgs>,
|
||||
|
@ -35,8 +35,8 @@ export function setProjectAnnotations(
|
||||
projectAnnotations:
|
||||
| NamedOrDefaultProjectAnnotations<ReactRenderer>
|
||||
| NamedOrDefaultProjectAnnotations<ReactRenderer>[]
|
||||
) {
|
||||
originalSetProjectAnnotations<ReactRenderer>(projectAnnotations);
|
||||
): ProjectAnnotations<ReactRenderer> {
|
||||
return originalSetProjectAnnotations<ReactRenderer>(projectAnnotations);
|
||||
}
|
||||
|
||||
// This will not be necessary once we have auto preset loading
|
||||
|
@ -10,6 +10,7 @@ import type {
|
||||
Store_CSFExports,
|
||||
StoriesWithPartialProps,
|
||||
ComposedStoryFn,
|
||||
NamedOrDefaultProjectAnnotations,
|
||||
} from '@storybook/types';
|
||||
|
||||
import * as svelteProjectAnnotations from './entry-preview';
|
||||
@ -51,9 +52,11 @@ type MapToComposed<TModule> = {
|
||||
* @param projectAnnotations - e.g. (import projectAnnotations from '../.storybook/preview')
|
||||
*/
|
||||
export function setProjectAnnotations(
|
||||
projectAnnotations: ProjectAnnotations<SvelteRenderer> | ProjectAnnotations<SvelteRenderer>[]
|
||||
) {
|
||||
originalSetProjectAnnotations<SvelteRenderer>(projectAnnotations);
|
||||
projectAnnotations:
|
||||
| NamedOrDefaultProjectAnnotations<SvelteRenderer>
|
||||
| NamedOrDefaultProjectAnnotations<SvelteRenderer>[]
|
||||
): ProjectAnnotations<SvelteRenderer> {
|
||||
return originalSetProjectAnnotations<SvelteRenderer>(projectAnnotations);
|
||||
}
|
||||
|
||||
// This will not be necessary once we have auto preset loading
|
||||
|
@ -44,8 +44,8 @@ export function setProjectAnnotations(
|
||||
projectAnnotations:
|
||||
| NamedOrDefaultProjectAnnotations<VueRenderer>
|
||||
| NamedOrDefaultProjectAnnotations<VueRenderer>[]
|
||||
) {
|
||||
originalSetProjectAnnotations<VueRenderer>(projectAnnotations);
|
||||
): ProjectAnnotations<VueRenderer> {
|
||||
return originalSetProjectAnnotations<VueRenderer>(projectAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user