Skip to content

Commit

Permalink
Merge pull request #24645 from storybookjs/docs_test_runner_updates
Browse files Browse the repository at this point in the history
Docs: Test runner minor fixes
jonniebigodes authored Nov 20, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents 3cd454c + 567318e commit 0b50467
Showing 32 changed files with 582 additions and 95 deletions.
15 changes: 15 additions & 0 deletions docs/snippets/common/my-component-exclude-tags.story.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```js
// MyComponent.stories.js|jsx

import { MyComponent } from './MyComponent';

export default {
component: MyComponent,
tags: ['no-tests'], // 👈 Provides the `no-tests` tag to all stories in this file
};

export const ExcludeStory = {
//👇 Adds the `no-tests` tag to this story to exclude it from the tests when enabled in the test-runner configuration
tags: ['no-tests'],
};
```
21 changes: 21 additions & 0 deletions docs/snippets/common/my-component-exclude-tags.story.ts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
```ts
// MyComponent.stories.ts|tsx

// Replace your-framework with the name of your framework
import type { Meta, StoryObj } from '@storybook/your-framework';

import { MyComponent } from './MyComponent';

const meta: Meta<typeof MyComponent> = {
component: MyComponent,
tags: ['no-tests'], // 👈 Provides the `no-tests` tag to all stories in this file
};

export default meta;
type Story = StoryObj<typeof MyComponent>;

export const ExcludeStory: Story = {
//👇 Adds the `no-tests` tag to this story to exclude it from the tests when enabled in the test-runner configuration
tags: ['no-tests'],
};
```
15 changes: 15 additions & 0 deletions docs/snippets/common/my-component-include-tags.story.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```js
// MyComponent.stories.js|jsx

import { MyComponent } from './MyComponent';

export default {
component: MyComponent,
tags: ['test-only'], // 👈 Provides the `test-only` tag to all stories in this file
};

export const IncludeStory = {
//👇 Adds the `test-only` tag to this story to be included in the tests when enabled in the test-runner configuration
tags: ['test-only'],
};
```
21 changes: 21 additions & 0 deletions docs/snippets/common/my-component-include-tags.story.ts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
```ts
// MyComponent.stories.ts|tsx

// Replace your-framework with the name of your framework
import type { Meta, StoryObj } from '@storybook/your-framework';

import { MyComponent } from './MyComponent';

const meta: Meta<typeof MyComponent> = {
component: MyComponent,
tags: ['test-only'], // 👈 Provides the `test-only` tag to all stories in this file
};

export default meta;
type Story = StoryObj<typeof MyComponent>;

export const IncludeStory: Story = {
//👇 Adds the `test-only` tag to this story to be included in the tests when enabled in the test-runner configuration
tags: ['test-only'],
};
```
15 changes: 15 additions & 0 deletions docs/snippets/common/my-component-skip-tags.story.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```js
// MyComponent.stories.js|jsx

import { MyComponent } from './MyComponent';

export default {
component: MyComponent,
tags: ['skip-test'], // 👈 Provides the `skip-test` tag to all stories in this file
};

export const SkipStory = {
//👇 Adds the `skip-test` tag to this story to allow it to be skipped in the tests when enabled in the test-runner configuration
tags: ['skip-test'],
};
```
21 changes: 21 additions & 0 deletions docs/snippets/common/my-component-skip-tags.story.ts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
```ts
// MyComponent.stories.ts|tsx

// Replace your-framework with the name of your framework
import type { Meta, StoryObj } from '@storybook/your-framework';

import { MyComponent } from './MyComponent';

const meta: Meta<typeof MyComponent> = {
component: MyComponent,
tags: ['skip-test'], // 👈 Provides the `skip-test` tag to all stories in this file
};

export default meta;
type Story = StoryObj<typeof MyComponent>;

export const SkipStory: Story = {
//👇 Adds the `skip-test` tag to this story to allow it to be skipped in the tests when enabled in the test-runner configuration
tags: ['skip-test'],
};
```
6 changes: 3 additions & 3 deletions docs/snippets/common/test-runner-a11y-config.js.mdx
Original file line number Diff line number Diff line change
@@ -4,14 +4,14 @@
const { injectAxe, checkA11y } = require('axe-playwright');

/*
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api-experimental
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api
* to learn more about the test-runner hooks API.
*/
module.exports = {
async preRender(page) {
async preVisit(page) {
await injectAxe(page);
},
async postRender(page) {
async postVisit(page) {
await checkA11y(page, '#storybook-root', {
detailedReport: true,
detailedReportOptions: {
13 changes: 6 additions & 7 deletions docs/snippets/common/test-runner-a11y-config.ts.mdx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
```ts
// .storybook/test-runner.ts

import { injectAxe, checkA11y } from 'axe-playwright';

import type { TestRunnerConfig } from '@storybook/test-runner';
import { injectAxe, checkA11y } from 'axe-playwright';

/*
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api-experimental
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api
* to learn more about the test-runner hooks API.
*/
const a11yConfig: TestRunnerConfig = {
async preRender(page) {
const config: TestRunnerConfig = {
async preVisit(page) {
await injectAxe(page);
},
async postRender(page) {
async postVisit(page) {
await checkA11y(page, '#storybook-root', {
detailedReport: true,
detailedReportOptions: {
@@ -23,5 +22,5 @@ const a11yConfig: TestRunnerConfig = {
},
};

module.exports = a11yConfig;
export default config;
```
6 changes: 3 additions & 3 deletions docs/snippets/common/test-runner-a11y-configure.js.mdx
Original file line number Diff line number Diff line change
@@ -6,14 +6,14 @@ const { injectAxe, checkA11y, configureAxe } = require('axe-playwright');
const { getStoryContext } = require('@storybook/test-runner');

/*
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api-experimental
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api
* to learn more about the test-runner hooks API.
*/
module.exports = {
async preRender(page) {
async preVisit(page) {
await injectAxe(page);
},
async postRender(page, context) {
async postVisit(page, context) {
// Get the entire context of a story, including parameters, args, argTypes, etc.
const storyContext = await getStoryContext(page, context);

15 changes: 7 additions & 8 deletions docs/snippets/common/test-runner-a11y-configure.ts.mdx
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
```ts
// .storybook/test-runner.ts

import { injectAxe, checkA11y, configureAxe } from 'axe-playwright';

import type { TestRunnerConfig } from '@storybook/test-runner';
import { getStoryContext } from '@storybook/test-runner';

import type { TestRunnerConfig } from '@storybook/test-runner';
import { injectAxe, checkA11y, configureAxe } from 'axe-playwright';

/*
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api-experimental
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api
* to learn more about the test-runner hooks API.
*/
const a11yConfig: TestRunnerConfig = {
async preRender(page) {
const config: TestRunnerConfig = {
async preVisit(page) {
await injectAxe(page);
},
async postRender(page, context) {
async postVisit(page, context) {
// Get the entire context of a story, including parameters, args, argTypes, etc.
const storyContext = await getStoryContext(page, context);

@@ -33,5 +32,5 @@ const a11yConfig: TestRunnerConfig = {
},
};

module.exports = a11yConfig;
export default config;
```
9 changes: 4 additions & 5 deletions docs/snippets/common/test-runner-a11y-disable.js.mdx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
```js
// .storybook/test-runner.js

const { injectAxe, checkA11y } = require('axe-playwright');

const { getStoryContext } = require('@storybook/test-runner');

const { injectAxe, checkA11y } = require('axe-playwright');
/*
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api-experimental
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api
* to learn more about the test-runner hooks API.
*/
module.exports = {
async preRender(page) {
async preVisit(page) {
await injectAxe(page);
},
async postRender(page, context) {
async postVisit(page, context) {
// Get the entire context of a story, including parameters, args, argTypes, etc.
const storyContext = await getStoryContext(page, context);

15 changes: 7 additions & 8 deletions docs/snippets/common/test-runner-a11y-disable.ts.mdx
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
```ts
// .storybook/test-runner.ts

import { injectAxe, checkA11y } from 'axe-playwright';

import type { TestRunnerConfig } from '@storybook/test-runner';
import { getStoryContext } from '@storybook/test-runner';

import type { TestRunnerConfig } from '@storybook/test-runner';
import { injectAxe, checkA11y } from 'axe-playwright';

/*
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api-experimental
* See https://storybook.js.org/docs/react/writing-tests/test-runner#test-hook-api
* to learn more about the test-runner hooks API.
*/
const a11yConfig: TestRunnerConfig = {
async preRender(page) {
const config: TestRunnerConfig = {
async preVisit(page) {
await injectAxe(page);
},
async postRender(page, context) {
async postVisit(page, context) {
// Get the entire context of a story, including parameters, args, argTypes, etc.
const storyContext = await getStoryContext(page, context);

@@ -32,5 +31,5 @@ const a11yConfig: TestRunnerConfig = {
},
};

module.exports = a11yConfig;
export default config;
```
12 changes: 12 additions & 0 deletions docs/snippets/common/test-runner-auth.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
```js
// .storybook/test-runner.js

module.exports = {
getHttpHeaders: async (url) => {
const token = url.includes('prod') ? 'XYZ' : 'ABC';
return {
Authorization: `Bearer ${token}`,
};
},
};
```
16 changes: 16 additions & 0 deletions docs/snippets/common/test-runner-auth.ts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
```ts
// .storybook/test-runner.ts

import type { TestRunnerConfig } from '@storybook/test-runner';

const config: TestRunnerConfig = {
getHttpHeaders: async (url) => {
const token = url.includes('prod') ? 'prod-token' : 'dev-token';
return {
Authorization: `Bearer ${token}`,
};
},
};

export default config;
```
32 changes: 32 additions & 0 deletions docs/snippets/common/test-runner-custom-page-viewport.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
```js
// .storybook/test-runner.js

const { getStoryContext } = require('@storybook/test-runner');
const { MINIMAL_VIEWPORTS } = require('@storybook/addon-viewport');

const DEFAULT_VIEWPORT_SIZE = { width: 1280, height: 720 };

module.exports = {
async preVisit(page, story) {
// Accesses the story's parameters and retrieves the viewport used to render it
const context = await getStoryContext(page, story);
const viewportName = context.parameters?.viewport?.defaultViewport;
const viewportParameter = MINIMAL_VIEWPORTS[viewportName];

if (viewportParameter) {
const viewportSize = Object.entries(viewportParameter.styles).reduce(
(acc, [screen, size]) => ({
...acc,
// Converts the viewport size from percentages to numbers
[screen]: parseInt(size),
}),
{}
);
// Configures the Playwright page to use the viewport size
page.setViewportSize(viewportSize);
} else {
page.setViewportSize(DEFAULT_VIEWPORT_SIZE);
}
},
};
```
36 changes: 36 additions & 0 deletions docs/snippets/common/test-runner-custom-page-viewport.ts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
```ts
// .storybook/test-runner.js

import type { TestRunnerConfig } from '@storybook/test-runner';
import { getStoryContext } from '@storybook/test-runner';

const { MINIMAL_VIEWPORTS } = require('@storybook/addon-viewport');

const DEFAULT_VIEWPORT_SIZE = { width: 1280, height: 720 };

const config: TestRunnerConfig = {
async preVisit(page, story) {
// Accesses the story's parameters and retrieves the viewport used to render it
const context = await getStoryContext(page, story);
const viewportName = context.parameters?.viewport?.defaultViewport;
const viewportParameter = MINIMAL_VIEWPORTS[viewportName];

if (viewportParameter) {
const viewportSize = Object.entries(viewportParameter.styles).reduce(
(acc, [screen, size]) => ({
...acc,
// Converts the viewport size from percentages to numbers
[screen]: parseInt(size),
}),
{}
);
// Configures the Playwright page to use the viewport size
page.setViewportSize(viewportSize);
} else {
page.setViewportSize(DEFAULT_VIEWPORT_SIZE);
}
},
};

export default config;
```
13 changes: 8 additions & 5 deletions docs/snippets/common/test-runner-helper-function.js.mdx
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
```js
// .storybook/test-runner.js

const { getStoryContext } = require('@storybook/test-runner');
const { getStoryContext, waitForPageReady } = require('@storybook/test-runner');

module.exports = {
// Hook that is executed before the test runner starts running tests
setup() {
// Add your configuration here.
},
/* Hook to execute before a story is rendered.
/* Hook to execute before a story is initially visited before being rendered in the browser.
* The page argument is the Playwright's page object for the story.
* The context argument is a Storybook object containing the story's id, title, and name.
*/
async preRender(page, context) {
async preVisit(page, context) {
// Add your configuration here.
},
/* Hook to execute after a story is rendered.
/* Hook to execute after a story is visited and fully rendered.
* The page argument is the Playwright's page object for the story
* The context argument is a Storybook object containing the story's id, title, and name.
*/
async postRender(page, context) {
async postVisit(page, context) {
// Get the entire context of a story, including parameters, args, argTypes, etc.
const storyContext = await getStoryContext(page, context);

// This utility function is designed for image snapshot testing. It will wait for the page to be fully loaded, including all the async items (e.g., images, fonts, etc.).
await waitForPageReady(page);

// Add your configuration here.
},
};
16 changes: 9 additions & 7 deletions docs/snippets/common/test-runner-helper-function.ts.mdx
Original file line number Diff line number Diff line change
@@ -2,32 +2,34 @@
// .storybook/test-runner.ts

import type { TestRunnerConfig } from '@storybook/test-runner';

import { getStoryContext } from '@storybook/test-runner';
import { getStoryContext, waitForPageReady } from '@storybook/test-runner';

const config: TestRunnerConfig = {
// Hook that is executed before the test runner starts running tests
setup() {
// Add your configuration here.
},
/* Hook to execute before a story is rendered.
/* Hook to execute before a story is initially visited before being rendered in the browser.
* The page argument is the Playwright's page object for the story.
* The context argument is a Storybook object containing the story's id, title, and name.
*/
async preRender(page, context) {
async preVisit(page, context) {
// Add your configuration here.
},
/* Hook to execute after a story is rendered.
/* Hook to execute after a story is visited and fully rendered.
* The page argument is the Playwright's page object for the story
* The context argument is a Storybook object containing the story's id, title, and name.
*/
async postRender(page, context) {
async postVisit(page, context) {
// Get the entire context of a story, including parameters, args, argTypes, etc.
const storyContext = await getStoryContext(page, context);

// This utility function is designed for image snapshot testing. It will wait for the page to be fully loaded, including all the async items (e.g., images, fonts, etc.).
await waitForPageReady(page);

// Add your configuration here.
},
};

module.exports = config;
export default config;
```
8 changes: 4 additions & 4 deletions docs/snippets/common/test-runner-hooks-example.js.mdx
Original file line number Diff line number Diff line change
@@ -6,18 +6,18 @@ module.exports = {
setup() {
// Add your configuration here.
},
/* Hook to execute before a story is rendered.
/* Hook to execute before a story is initially visited before being rendered in the browser.
* The page argument is the Playwright's page object for the story.
* The context argument is a Storybook object containing the story's id, title, and name.
*/
async preRender(page, context) {
async preVisit(page, context) {
// Add your configuration here.
},
/* Hook to execute after a story is rendered.
/* Hook to execute after a story is visited and fully rendered.
* The page argument is the Playwright's page object for the story
* The context argument is a Storybook object containing the story's id, title, and name.
*/
async postRender(page, context) {
async postVisit(page, context) {
// Add your configuration here.
},
};
10 changes: 5 additions & 5 deletions docs/snippets/common/test-runner-hooks-example.ts.mdx
Original file line number Diff line number Diff line change
@@ -8,21 +8,21 @@ const config: TestRunnerConfig = {
setup() {
// Add your configuration here.
},
/* Hook to execute before a story is rendered.
/* Hook to execute before a story is initially visited before being rendered in the browser.
* The page argument is the Playwright's page object for the story.
* The context argument is a Storybook object containing the story's id, title, and name.
*/
async preRender(page, context) {
async preVisit(page, context) {
// Add your configuration here.
},
/* Hook to execute after a story is rendered.
/* Hook to execute after a story is visited and fully rendered.
* The page argument is the Playwright's page object for the story
* The context argument is a Storybook object containing the story's id, title, and name.
*/
async postRender(page, context) {
async postVisit(page, context) {
// Add your configuration here.
},
};

module.exports = config;
export default config;
```
11 changes: 11 additions & 0 deletions docs/snippets/common/test-runner-tags-config.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
```js
// .storybook/test-runner.js

module.exports = {
tags: {
include: ['test-only', 'pages'],
exclude: ['no-tests', 'tokens'],
skip: ['skip-test', 'layout'],
},
};
```
15 changes: 15 additions & 0 deletions docs/snippets/common/test-runner-tags-config.ts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```ts
// .storybook/test-runner.ts

import type { TestRunnerConfig } from '@storybook/test-runner';

const config: TestRunnerConfig = {
tags: {
include: ['test-only', 'pages'],
exclude: ['no-tests', 'tokens'],
skip: ['skip-test', 'layout'],
},
};

export default config;
```
9 changes: 9 additions & 0 deletions docs/snippets/common/test-runner-tags-exclude.config.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
```js
// .storybook/test-runner.js

module.exports = {
tags: {
exclude: ['no-tests'],
},
};
```
13 changes: 13 additions & 0 deletions docs/snippets/common/test-runner-tags-exclude.config.ts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
```ts
// .storybook/test-runner.ts

import type { TestRunnerConfig } from '@storybook/test-runner';

const config: TestRunnerConfig = {
tags: {
exclude: ['no-tests'],
},
};

export default config;
```
9 changes: 9 additions & 0 deletions docs/snippets/common/test-runner-tags-include.config.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
```js
// .storybook/test-runner.js

module.exports = {
tags: {
include: ['test-only'],
},
};
```
13 changes: 13 additions & 0 deletions docs/snippets/common/test-runner-tags-include.config.ts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
```ts
// .storybook/test-runner.ts

import type { TestRunnerConfig } from '@storybook/test-runner';

const config: TestRunnerConfig = {
tags: {
include: ['test-only'],
},
};

export default config;
```
9 changes: 9 additions & 0 deletions docs/snippets/common/test-runner-tags-skip.config.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
```js
// .storybook/test-runner.js

module.exports = {
tags: {
skip: ['skip-test'],
},
};
```
13 changes: 13 additions & 0 deletions docs/snippets/common/test-runner-tags-skip.config.ts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
```ts
// .storybook/test-runner.ts

import type { TestRunnerConfig } from '@storybook/test-runner';

const config: TestRunnerConfig = {
tags: {
skip: ['skip-test'],
},
};

export default config;
```
25 changes: 25 additions & 0 deletions docs/snippets/common/test-runner-waitpageready.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
```js
// .storybook/test-runner.js

const { waitForPageReady } = require('@storybook/test-runner');
const { toMatchImageSnapshot } = require('jest-image-snapshot');

const customSnapshotsDir = `${process.cwd()}/__snapshots__`;

module.exports = {
setup() {
expect.extend({ toMatchImageSnapshot });
},
async postVisit(page, context) {
// Awaits for the page to be loaded and available including assets (e.g., fonts)
await waitForPageReady(page);

// Generates a snapshot file based on the story identifier
const image = await page.screenshot();
expect(image).toMatchImageSnapshot({
customSnapshotsDir,
customSnapshotIdentifier: context.id,
});
},
};
```
29 changes: 29 additions & 0 deletions docs/snippets/common/test-runner-waitpageready.ts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
```ts
// .storybook/test-runner.ts

import type { TestRunnerConfig } from '@storybook/test-runner';
import { waitForPageReady } from '@storybook/test-runner';

import { toMatchImageSnapshot } from 'jest-image-snapshot';

const customSnapshotsDir = `${process.cwd()}/__snapshots__`;

const config: TestRunnerConfig = {
setup() {
expect.extend({ toMatchImageSnapshot });
},
async postVisit(page, context) {
// Awaits for the page to be loaded and available including assets (e.g., fonts)
await waitForPageReady(page);

// Generates a snapshot file based on the story identifier
const image = await page.screenshot();
expect(image).toMatchImageSnapshot({
customSnapshotsDir,
customSnapshotIdentifier: context.id,
});
},
};

export default config;
```
8 changes: 4 additions & 4 deletions docs/writing-tests/accessibility-testing.md
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ Out of the box, Storybook's accessibility addon includes a set of accessibility

#### Global a11y configuration

If you need to dismiss an accessibility rule or modify its settings across all stories, you can add the following to your [storybook/preview.js](../configure/overview.md#configure-story-rendering):
If you need to dismiss an accessibility rule or modify its settings across all stories, you can add the following to your [`storybook/preview.js|ts`](../configure/overview.md#configure-story-rendering):

<!-- prettier-ignore-start -->

@@ -170,7 +170,7 @@ Disable accessibility testing for stories or components by adding the following

The most accurate way to check accessibility is manually on real devices. However, you can use automated tools to catch common accessibility issues. For example, [Axe](https://www.deque.com/axe/), on average, catches upwards to [57% of WCAG issues](https://www.deque.com/blog/automated-testing-study-identifies-57-percent-of-digital-accessibility-issues/) automatically.

These tools work by auditing the rendered DOM against heuristics based on [WCAG](https://www.w3.org/WAI/standards-guidelines/wcag/) rules and other industry-accepted best practices. You can then integrate these tools into your test automation pipeline using the Storybook [test runner](./test-runner.md#test-hook-api-experimental) and [axe-playwright](https://github.com/abhinaba-ghosh/axe-playwright).
These tools work by auditing the rendered DOM against heuristics based on [WCAG](https://www.w3.org/WAI/standards-guidelines/wcag/) rules and other industry-accepted best practices. You can then integrate these tools into your test automation pipeline using the Storybook [test runner](./test-runner.md#test-hook-api) and [axe-playwright](https://github.com/abhinaba-ghosh/axe-playwright).

### Setup

@@ -190,7 +190,7 @@ Run the following command to install the required dependencies.

<!-- prettier-ignore-end -->

Add a new [configuration file](./test-runner.md#test-hook-api-experimental) inside your Storybook directory with the following inside:
Add a new [configuration file](./test-runner.md#test-hook-api) inside your Storybook directory with the following inside:

<!-- prettier-ignore-start -->

@@ -205,7 +205,7 @@ Add a new [configuration file](./test-runner.md#test-hook-api-experimental) insi

<Callout variant="info" icon="💡">

`preRender` and `postRender` are convenient hooks that allow you to extend the test runner's default configuration. They are **experimental** and subject to changes. Read more about them [here](./test-runner.md#test-hook-api-experimental).
`preVisit` and `postVisit` are convenient hooks that allow you to extend the test runner's default configuration. Read more about them [here](./test-runner.md#test-hook-api).

</Callout>

208 changes: 172 additions & 36 deletions docs/writing-tests/test-runner.md

Large diffs are not rendered by default.

0 comments on commit 0b50467

Please sign in to comment.