Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Portable stories: Use internal Storybook renderers mechanism #28766

Merged
merged 22 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 0 additions & 36 deletions code/core/src/preview-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,42 +235,6 @@ export class MountMustBeDestructuredError extends StorybookError {
}
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Ensure the internal renderToCanvas method is robust and can handle all scenarios previously managed by testingLibraryRender.

}

export class TestingLibraryMustBeConfiguredError extends StorybookError {
constructor() {
super({
category: Category.PREVIEW_API,
code: 13,
message: dedent`
You must configure testingLibraryRender to use play in portable stories.

import { render } from '@testing-library/[renderer]';

setProjectAnnotations({
testingLibraryRender: render,
});

For other testing renderers, you can configure \`renderToCanvas\` like so:

import { render } from 'your-test-renderer';

setProjectAnnotations({
renderToCanvas: ({ storyFn }) => {
const Story = storyFn();

// Svelte
render(Story.Component, Story.props);

// Vue
render(Story);

// or for React
render(<Story/>);
},
});`,
});
}
}

export class NoRenderFunctionError extends StorybookError {
constructor(public data: { id: string }) {
super({
Expand Down
18 changes: 18 additions & 0 deletions code/lib/react-dom-shim/src/preventActChecks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export {};

declare const globalThis: {
IS_REACT_ACT_ENVIRONMENT?: boolean;
};

// TODO(9.0): We should actually wrap all those lines in `act`, but that might be a breaking change.
// We should make that breaking change for SB 9.0
// Write issue
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Consider wrapping all lines in act for a more robust solution in SB 9.0.

export function preventActChecks(callback: () => void): void {
const originalActEnvironment = globalThis.IS_REACT_ACT_ENVIRONMENT;
globalThis.IS_REACT_ACT_ENVIRONMENT = false;
try {
callback();
} finally {
globalThis.IS_REACT_ACT_ENVIRONMENT = originalActEnvironment;
}
Comment on lines +9 to +16
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Ensure callback does not rely on act for state updates to avoid side effects.

}
5 changes: 3 additions & 2 deletions code/lib/react-dom-shim/src/react-16.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
/* eslint-disable react/no-deprecated */
import type { ReactElement } from 'react';
import * as ReactDOM from 'react-dom';
import { preventActChecks } from './preventActChecks';

export const renderElement = async (node: ReactElement, el: Element) => {
return new Promise<null>((resolve) => {
ReactDOM.render(node, el, () => resolve(null));
preventActChecks(() => void ReactDOM.render(node, el, () => resolve(null)));
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Ensure preventActChecks does not mask legitimate act warnings.

});
};

export const unmountElement = (el: Element) => {
ReactDOM.unmountComponentAtNode(el);
preventActChecks(() => void ReactDOM.unmountComponentAtNode(el));
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Verify preventActChecks implementation to avoid side effects.

};
7 changes: 5 additions & 2 deletions code/lib/react-dom-shim/src/react-18.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { FC, ReactElement } from 'react';
import * as React from 'react';
import type { Root as ReactRoot, RootOptions } from 'react-dom/client';
import * as ReactDOM from 'react-dom/client';
import { preventActChecks } from './preventActChecks';
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Ensure preventActChecks is thoroughly tested to avoid suppressing critical warnings.


// A map of all rendered React 18 nodes
const nodes = new Map<Element, ReactRoot>();
Expand All @@ -26,15 +27,17 @@ export const renderElement = async (node: ReactElement, el: Element, rootOptions
const root = await getReactRoot(el, rootOptions);

return new Promise((resolve) => {
root.render(<WithCallback callback={() => resolve(null)}>{node}</WithCallback>);
preventActChecks(() =>
root.render(<WithCallback callback={() => resolve(null)}>{node}</WithCallback>)
);
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Wrapping root.render in preventActChecks might mask issues during rendering. Verify its necessity.

});
};

export const unmountElement = (el: Element, shouldUseNewRootApi?: boolean) => {
const root = nodes.get(el);

if (root) {
root.unmount();
preventActChecks(() => root.unmount());
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Confirm that preventActChecks does not interfere with the unmounting process.

nodes.delete(el);
}
};
Expand Down
3 changes: 1 addition & 2 deletions code/renderers/react/src/__test__/portable-stories.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { setProjectAnnotations, composeStories, composeStory } from '..';
import type { Button } from './Button';
import * as stories from './Button.stories';

setProjectAnnotations([{ testingLibraryRender: render }]);
setProjectAnnotations([]);
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Ensure that removing testingLibraryRender does not affect tests relying on it.

Copy link
Member

Choose a reason for hiding this comment

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

This is not needed anymore

Copy link
Contributor Author

Choose a reason for hiding this comment

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

setProjectAnnotations still register the react annoations. So I need to call it. And TS accepts only accepts an empty array, we probably should change that though?


// example with composeStories, returns an object with all stories composed with args/decorators
const { CSF3Primary, LoaderStory, MountInPlayFunction } = composeStories(stories);
Expand Down Expand Up @@ -77,7 +77,6 @@ describe('projectAnnotations', () => {
it('renders with default projectAnnotations', () => {
setProjectAnnotations([
{
testingLibraryRender: render,
parameters: { injected: true },
globalTypes: {
locale: { defaultValue: 'en' },
Expand Down
4 changes: 1 addition & 3 deletions code/renderers/react/src/portable-stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ export const INTERNAL_DEFAULT_PROJECT_ANNOTATIONS: ProjectAnnotations<ReactRende
...reactProjectAnnotations,
renderToCanvas: (renderContext, canvasElement) => {
if (renderContext.storyContext.testingLibraryRender == null) {
throw new TestingLibraryMustBeConfiguredError();
// Enable for 8.3
// return reactProjectAnnotations.renderToCanvas(renderContext, canvasElement);
return reactProjectAnnotations.renderToCanvas(renderContext, canvasElement);
}
const {
storyContext: { context, unboundStoryFn: Story, testingLibraryRender: render },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import type Button from './Button.svelte';
import { composeStories, composeStory, setProjectAnnotations } from '../../portable-stories';

setProjectAnnotations({ testingLibraryRender: render });
setProjectAnnotations([]);
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Ensure that removing testingLibraryRender does not affect the rendering behavior in tests.


// example with composeStories, returns an object with all stories composed with args/decorators
const { CSF3Primary, LoaderStory } = composeStories(stories);
Expand Down Expand Up @@ -82,7 +82,6 @@
globalTypes: {
locale: { defaultValue: 'en' },
},
testingLibraryRender: render,
},
]);
const WithEnglishText = composeStory(stories.CSF2StoryWithLocale, stories.default);
Expand Down Expand Up @@ -172,5 +171,5 @@
it.each(testCases)('Renders %s story', async (_storyName, Story) => {
if (_storyName === 'CSF2StoryWithLocale') return;
await Story.run();
expect(document.body).toMatchSnapshot();

Check failure on line 174 in code/renderers/svelte/src/__test__/composeStories/portable-stories.test.ts

View workflow job for this annotation

GitHub Actions / Core Unit Tests, windows-latest

src/__test__/composeStories/portable-stories.test.ts > Renders CSF2Secondary story

Error: Snapshot `Renders CSF2Secondary story 1` mismatched - Expected + Received @@ -6,8 +6,11 @@ type="button" > label coming from story args! <!----> </button> + <!----> + <!----> + <!----> </div> </body> ❯ src/__test__/composeStories/portable-stories.test.ts:174:25

Check failure on line 174 in code/renderers/svelte/src/__test__/composeStories/portable-stories.test.ts

View workflow job for this annotation

GitHub Actions / Core Unit Tests, windows-latest

src/__test__/composeStories/portable-stories.test.ts > Renders CSF2StoryWithParamsAndDecorator story

Error: Snapshot `Renders CSF2StoryWithParamsAndDecorator story 1` mismatched - Expected + Received @@ -15,8 +15,11 @@ <!----> <!----> </div> <!----> <!----> + <!----> + <!----> + <!----> </div> </body> ❯ src/__test__/composeStories/portable-stories.test.ts:174:25

Check failure on line 174 in code/renderers/svelte/src/__test__/composeStories/portable-stories.test.ts

View workflow job for this annotation

GitHub Actions / Core Unit Tests, windows-latest

src/__test__/composeStories/portable-stories.test.ts > Renders NewStory story

Error: Snapshot `Renders NewStory story 1` mismatched - Expected + Received @@ -15,8 +15,11 @@ <!----> <!----> </div> <!----> <!----> + <!----> + <!----> + <!----> </div> </body> ❯ src/__test__/composeStories/portable-stories.test.ts:174:25

Check failure on line 174 in code/renderers/svelte/src/__test__/composeStories/portable-stories.test.ts

View workflow job for this annotation

GitHub Actions / Core Unit Tests, windows-latest

src/__test__/composeStories/portable-stories.test.ts > Renders CSF3Primary story

Error: Snapshot `Renders CSF3Primary story 1` mismatched - Expected + Received @@ -6,8 +6,11 @@ type="button" > foo <!----> </button> + <!----> + <!----> + <!----> </div> </body> ❯ src/__test__/composeStories/portable-stories.test.ts:174:25

Check failure on line 174 in code/renderers/svelte/src/__test__/composeStories/portable-stories.test.ts

View workflow job for this annotation

GitHub Actions / Core Unit Tests, windows-latest

src/__test__/composeStories/portable-stories.test.ts > Renders CSF3Button story

Error: Snapshot `Renders CSF3Button story 1` mismatched - Expected + Received @@ -6,8 +6,11 @@ type="button" > foo <!----> </button> + <!----> + <!----> + <!----> </div> </body> ❯ src/__test__/composeStories/portable-stories.test.ts:174:25

Check failure on line 174 in code/renderers/svelte/src/__test__/composeStories/portable-stories.test.ts

View workflow job for this annotation

GitHub Actions / Core Unit Tests, windows-latest

src/__test__/composeStories/portable-stories.test.ts > Renders CSF3ButtonWithRender story

Error: Snapshot `Renders CSF3ButtonWithRender story 1` mismatched - Expected + Received @@ -15,8 +15,11 @@ foo <!----> </button> <!----> </div> + <!----> + <!----> + <!----> </div> </body> ❯ src/__test__/composeStories/portable-stories.test.ts:174:25

Check failure on line 174 in code/renderers/svelte/src/__test__/composeStories/portable-stories.test.ts

View workflow job for this annotation

GitHub Actions / Core Unit Tests, windows-latest

src/__test__/composeStories/portable-stories.test.ts > Renders CSF3InputFieldFilled story

Error: Snapshot `Renders CSF3InputFieldFilled story 1` mismatched - Expected + Received @@ -3,8 +3,11 @@ <input data-testid="input" formaction="http://localhost:3000/" formmethod="" /> + <!----> + <!----> + <!----> </div> </body> ❯ src/__test__/composeStories/portable-stories.test.ts:174:25

Check failure on line 174 in code/renderers/svelte/src/__test__/composeStories/portable-stories.test.ts

View workflow job for this annotation

GitHub Actions / Core Unit Tests, windows-latest

src/__test__/composeStories/portable-stories.test.ts > Renders LoaderStory story

Error: Snapshot `Renders LoaderStory story 1` mismatched - Expected + Received @@ -11,8 +11,11 @@ data-testid="spy-data" > mockFn return value </div> </div> + <!----> + <!----> + <!----> </div> </body> ❯ src/__test__/composeStories/portable-stories.test.ts:174:25
});
4 changes: 1 addition & 3 deletions code/renderers/svelte/src/portable-stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ export const INTERNAL_DEFAULT_PROJECT_ANNOTATIONS: ProjectAnnotations<SvelteRend
...svelteProjectAnnotations,
renderToCanvas: (renderContext, canvasElement) => {
if (renderContext.storyContext.testingLibraryRender == null) {
throw new TestingLibraryMustBeConfiguredError();
// Enable for 8.3
// return svelteProjectAnnotations.renderToCanvas(renderContext, canvasElement);
return svelteProjectAnnotations.renderToCanvas(renderContext, canvasElement);
Comment on lines 68 to +69
Copy link
Contributor

Choose a reason for hiding this comment

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

check: Consider logging a warning or error if testingLibraryRender is null to aid in debugging.

}
const {
storyFn,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import type Button from './Button.vue';
import { composeStories, composeStory, setProjectAnnotations } from '../../portable-stories';

setProjectAnnotations({ testingLibraryRender: render });
setProjectAnnotations([]);
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Ensure that removing testingLibraryRender does not affect other tests relying on it.


// example with composeStories, returns an object with all stories composed with args/decorators
const { CSF3Primary, LoaderStory } = composeStories(stories);
Expand Down Expand Up @@ -60,7 +60,6 @@
it('renders with default projectAnnotations', () => {
setProjectAnnotations([
{
testingLibraryRender: render,
parameters: { injected: true },
globalTypes: {
locale: { defaultValue: 'en' },
Expand Down Expand Up @@ -147,5 +146,5 @@
if (typeof Story === 'string' || _storyName === 'CSF2StoryWithLocale') return;
await Story.run();
await new Promise((resolve) => setTimeout(resolve, 0));
expect(document.body).toMatchSnapshot();

Check failure on line 149 in code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts

View workflow job for this annotation

GitHub Actions / Core Unit Tests, windows-latest

src/__tests__/composeStories/portable-stories.test.ts > Renders CSF2Secondary story

Error: Snapshot `Renders CSF2Secondary story 1` mismatched - Expected + Received @@ -1,7 +1,9 @@ <body> - <div> + <div + data-v-app="" + > <button class="storybook-button storybook-button--secondary storybook-button--medium" type="button" > label coming from story args! ❯ src/__tests__/composeStories/portable-stories.test.ts:149:25

Check failure on line 149 in code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts

View workflow job for this annotation

GitHub Actions / Core Unit Tests, windows-latest

src/__tests__/composeStories/portable-stories.test.ts > Renders CSF2StoryWithParamsAndDecorator story

Error: Snapshot `Renders CSF2StoryWithParamsAndDecorator story 1` mismatched - Expected + Received @@ -1,7 +1,9 @@ <body> - <div> + <div + data-v-app="" + > <div style="margin: 3em;" > <button class="storybook-button storybook-button--secondary storybook-button--medium" ❯ src/__tests__/composeStories/portable-stories.test.ts:149:25
});
4 changes: 1 addition & 3 deletions code/renderers/vue3/src/portable-stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ export const vueProjectAnnotations: ProjectAnnotations<VueRenderer> = {
...defaultProjectAnnotations,
renderToCanvas: (renderContext, canvasElement) => {
if (renderContext.storyContext.testingLibraryRender == null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Consider logging a warning when testingLibraryRender is not configured to inform developers of the fallback.

throw new TestingLibraryMustBeConfiguredError();
// Enable for 8.3
// return defaultProjectAnnotations.renderToCanvas(renderContext, canvasElement);
return defaultProjectAnnotations.renderToCanvas(renderContext, canvasElement);
}
const {
storyFn,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
```tsx filename="setupTest.ts" renderer="react" language="ts"
import { beforeAll } from '@jest/globals';
import { render as testingLibraryRender } from '@testing-library/react';
import { setProjectAnnotations } from '@storybook/react';
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Ensure that the internal renderToCanvas method provides equivalent functionality to testingLibraryRender.

// 👇 Import the exported annotations, if any, from the addons you're using; otherwise remove this
import * as addonAnnotations from 'my-addon/preview';
Expand All @@ -9,8 +8,6 @@ import * as previewAnnotations from './.storybook/preview';
const annotations = setProjectAnnotations([
previewAnnotations,
addonAnnotations,
// You MUST provide this option to use portable stories with vitest
{ testingLibraryRender },
]);
Copy link
Contributor

Choose a reason for hiding this comment

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

check: Verify that all necessary annotations are included to avoid missing configurations.


// Supports beforeAll hook from Storybook
Expand All @@ -19,7 +16,6 @@ beforeAll(annotations.beforeAll);

```tsx filename="setupTest.ts" renderer="vue" language="ts"
import { beforeAll } from '@jest/globals';
import { render as testingLibraryRender } from '@testing-library/vue';
import { setProjectAnnotations } from '@storybook/vue3';
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Ensure that the internal renderToCanvas method provides equivalent functionality to testingLibraryRender.

// 👇 Import the exported annotations, if any, from the addons you're using; otherwise remove this
import * as addonAnnotations from 'my-addon/preview';
Expand All @@ -28,8 +24,6 @@ import * as previewAnnotations from './.storybook/preview';
const annotations = setProjectAnnotations([
previewAnnotations,
addonAnnotations,
// You MUST provide this option to use portable stories with vitest
{ testingLibraryRender },
]);
Copy link
Contributor

Choose a reason for hiding this comment

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

check: Verify that all necessary annotations are included to avoid missing configurations.


// Supports beforeAll hook from Storybook
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import * as previewAnnotations from './.storybook/preview';
const annotations = setProjectAnnotations([
previewAnnotations,
addonAnnotations,
// You MUST provide this option to use portable stories with vitest
{ testingLibraryRender },
]);
Comment on lines 8 to 11
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Ensure that removing testingLibraryRender does not affect existing tests or configurations.


// Supports beforeAll hook from Storybook
Expand All @@ -26,8 +24,6 @@ import * as previewAnnotations from './.storybook/preview';
const annotations = setProjectAnnotations([
previewAnnotations,
addonAnnotations,
// You MUST provide this option to use portable stories with vitest
{ testingLibraryRender },
]);

// Supports beforeAll hook from Storybook
Expand Down
15 changes: 3 additions & 12 deletions docs/_snippets/portable-stories-vitest-set-project-annotations.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
```tsx filename="setupTest.ts" renderer="react" language="ts"
import { beforeAll } from 'vitest';
import { render as testingLibraryRender } from '@testing-library/react';
import { setProjectAnnotations } from '@storybook/react';
// 👇 Import the exported annotations, if any, from the addons you're using; otherwise remove this
import * as addonAnnotations from 'my-addon/preview';
import * as previewAnnotations from './.storybook/preview';

const annotations = setProjectAnnotations([
previewAnnotations,
addonAnnotations,
// You MUST provide this option to use portable stories with vitest
{ testingLibraryRender },
addonAnnotations
]);

// Run Storybook's beforeAll hook
Expand All @@ -19,17 +16,14 @@ beforeAll(annotations.beforeAll);

```tsx filename="setupTest.ts" renderer="svelte" language="ts"
import { beforeAll } from 'vitest';
import { render as testingLibraryRender } from '@testing-library/svelte';
import { setProjectAnnotations } from '@storybook/svelte';
// 👇 Import the exported annotations, if any, from the addons you're using; otherwise remove this
import * as addonAnnotations from 'my-addon/preview';
import * as previewAnnotations from './.storybook/preview';

const annotations = setProjectAnnotations([
previewAnnotations,
addonAnnotations,
// You MUST provide this option to use portable stories with vitest
{ testingLibraryRender },
addonAnnotations
]);

// Run Storybook's beforeAll hook
Expand All @@ -38,17 +32,14 @@ beforeAll(annotations.beforeAll);

```tsx filename="setupTest.ts" renderer="vue" language="ts"
import { beforeAll } from 'vitest';
import { render as testingLibraryRender } from '@testing-library/vue';
import { setProjectAnnotations } from '@storybook/vue3';
// 👇 Import the exported annotations, if any, from the addons you're using; otherwise remove this
import * as addonAnnotations from 'my-addon/preview';
import * as previewAnnotations from './.storybook/preview';

const annotations = setProjectAnnotations([
previewAnnotations,
addonAnnotations,
// You MUST provide this option to use portable stories with vitest
{ testingLibraryRender },
addonAnnotations
]);

// Run Storybook's beforeAll hook
Expand Down
3 changes: 1 addition & 2 deletions docs/api/portable-stories/portable-stories-jest.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,11 @@ sidebar:
## setProjectAnnotations

This API should be called once, before the tests run, typically in a [setup file](https://jestjs.io/docs/configuration#setupfiles-array). This will make sure that whenever `composeStories` or `composeStory` are called, the project annotations are taken into account as well.

These are the configurations needed in the setup file:
- preview annotations: those defined in `.storybook/preview.ts`
- addon annotations (optional): those exported by addons
- beforeAll: code that runs before all tests ([more info](../../writing-tests/interaction-testing.mdx#beforeall))
- testingLibraryRender: the render function from Testing Library

{/* prettier-ignore-start */}

Expand Down
9 changes: 1 addition & 8 deletions docs/api/portable-stories/portable-stories-vitest.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -166,25 +166,18 @@ sidebar:
## setProjectAnnotations

This API should be called once, before the tests run, typically in a [setup file](https://vitest.dev/config/#setupfiles). This will make sure that whenever `composeStories` or `composeStory` are called, the project annotations are taken into account as well.

These are the configurations needed in the setup file:
- preview annotations: those defined in `.storybook/preview.ts`
- addon annotations (optional): those exported by addons
- beforeAll: code that runs before all tests ([more info](../../writing-tests/interaction-testing.mdx#beforeall))
- testingLibraryRender: the render function from Testing Library

{/* prettier-ignore-start */}

<CodeSnippets path="portable-stories-vitest-set-project-annotations.md" />

{/* prettier-ignore-end */}

<Callout variant="warning">

You **must** provide `testingLibraryRenderer` to use portable stories with Vitest.

</Callout>

{/* TODO: Create issue for interest in non-Testing Library render option, with recipe, and mention here (Jest, too) */}

Sometimes a story can require an addon's [decorator](../../writing-stories/decorators.mdx) or [loader](../../writing-stories/loaders.mdx) to render properly. For example, an addon can apply a decorator that wraps your story in the necessary router context. In this case, you must include that addon's `preview` export in the project annotations set. See `addonAnnotations` in the example above.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,6 @@ By default, the test-runner provides you with the option to run multiple testing

{/* prettier-ignore-end */}

<Callout variant="warning">

You **must** provide `testingLibraryRenderer` to use portable stories with Vitest or Jest.

</Callout>

#### Configure the testing framework for portable stories

To help you migrate from Storyshots addon to Storybook's portable stories with the `composeStories` helper API, we've prepared examples to help you get started. Listed below are examples of two of the most popular testing frameworks: [Jest](https://jestjs.io/) and [Vitest](https://vitest.dev/). We recommend placing the code in a newly created `storybook.test.ts|js` file and adjusting the code accordingly, depending on your testing framework. Both examples below will:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { ReactRenderer } from '@storybook/react';
import { setProjectAnnotations } from '@storybook/nextjs';
import * as addonInteractions from '@storybook/addon-interactions/preview';
import * as addonActions from '@storybook/addon-essentials/actions/preview';
import { render } from '@testing-library/react';

/**
* For some weird reason, Jest in Nextjs throws the following error:
Expand All @@ -18,5 +17,4 @@ setProjectAnnotations([
sbAnnotations,
addonInteractions as ProjectAnnotations<ReactRenderer>, // instruments actions as spies
addonActions as ProjectAnnotations<ReactRenderer>, // creates actions from argTypes
{ testingLibraryRender: render },
]);
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import { ReactRenderer, setProjectAnnotations } from '@storybook/react';
import sbAnnotations from './.storybook/preview';
import * as addonInteractions from '@storybook/addon-interactions/preview';
import * as addonActions from '@storybook/addon-essentials/actions/preview';
import { render } from '@testing-library/react';

setProjectAnnotations([
sbAnnotations,
addonInteractions as ProjectAnnotations<ReactRenderer>, // instruments actions as spies
addonActions as ProjectAnnotations<ReactRenderer>, // creates actions from argTypes
{ testingLibraryRender: render },
]);
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe('projectAnnotations', () => {
});

it('renders with custom projectAnnotations via setProjectAnnotations', () => {
setProjectAnnotations([{ parameters: { injected: true }, testingLibraryRender: render }]);
setProjectAnnotations([{ parameters: { injected: true } }]);
const Story = composeStory(stories.CSF2StoryWithLocale, stories.default);
expect(Story.parameters?.injected).toBe(true);
});
Expand Down
Loading
Loading