Image snapshots addition to StoryShots based on puppeteer
—
Enables arbitrary Puppeteer tests defined in story parameters, providing full browser automation capabilities for interactive testing scenarios.
Creates a test function that executes custom Puppeteer code against Storybook stories with full browser automation support.
/**
* Creates a test function for running arbitrary Puppeteer tests against Storybook stories
* @param customConfig - Optional configuration to override defaults
* @returns Test function with lifecycle hooks for StoryShots integration
*/
function puppeteerTest(customConfig?: Partial<PuppeteerTestConfig>): TestFunction;
interface PuppeteerTestConfig extends CommonConfig {
/** Test implementation function with optional filtering capability */
testBody: ((page: Page, options: Options) => void | Promise<void>) & {
filter?: (options: Options) => boolean;
};
}
interface TestFunction {
/** Main test execution function */
(context: { kind: string; framework: string; name: string; id: string }): Promise<void>;
/** Setup function for browser initialization */
beforeAll: (() => Promise<void>) & { timeout: number };
/** Cleanup function for browser shutdown */
afterAll: () => Promise<void>;
/** Test execution timeout in milliseconds */
timeout: number;
}
interface Options {
context: Context;
url: string;
}Usage Examples:
import initStoryshots from '@storybook/addon-storyshots';
import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';
// Basic custom test execution
initStoryshots({
suite: 'Puppeteer storyshots',
test: puppeteerTest()
});
// With custom Storybook URL
initStoryshots({
suite: 'Custom URL tests',
test: puppeteerTest({
storybookUrl: 'http://my-storybook.com:9010'
})
});
// With custom browser launch options
initStoryshots({
suite: 'SSL tests',
test: puppeteerTest({
storybookUrl: 'https://localhost:6006',
browserLaunchOptions: {
ignoreHTTPSErrors: true
}
})
});Test functions are defined in story parameters using the puppeteerTest key.
// Story parameter structure for test definitions
interface StoryParameters {
puppeteerTest?: (page: Page, options: Options) => void | Promise<void>;
}Usage Examples:
// In your story file
export const InteractiveButton = () => <Button>Click me</Button>;
InteractiveButton.parameters = {
async puppeteerTest(page) {
const button = await page.$('button');
await button.click();
// Custom assertions
const result = await page.$eval('.result', el => el.textContent);
expect(result).toBe('Button clicked');
},
};
// Complex interaction test
export const FormSubmission = () => <ContactForm />;
FormSubmission.parameters = {
async puppeteerTest(page) {
// Fill form fields
await page.type('#name', 'John Doe');
await page.type('#email', 'john@example.com');
await page.select('#country', 'US');
// Submit form
await page.click('#submit');
await page.waitForSelector('.success-message');
// Verify submission
const message = await page.$eval('.success-message', el => el.textContent);
expect(message).toContain('Thank you');
},
};The default test body reads test functions from story parameters and provides automatic filtering.
/**
* Default test implementation that reads from story parameters
* @param page - Puppeteer page instance
* @param options - Test context and URL information
* @returns Promise resolving when test completes
*/
function defaultTestBody(page: Page, options: Options): Promise<void> | null;
// Default filter function checks for puppeteerTest parameter existence
defaultTestBody.filter: (options: Options) => boolean;The test function manages browser lifecycle automatically with configurable timeouts and cleanup handling.
interface BrowserLifecycle {
/** Browser setup with configurable timeout */
beforeAll: (() => Promise<void>) & { timeout: number };
/** Browser cleanup with graceful shutdown */
afterAll: () => Promise<void>;
/** Process signal handling for cleanup */
processExitHandler: () => Promise<void>;
}Key Features:
getCustomBrowserInstall with Tessl CLI
npx tessl i tessl/npm-storybook--addon-storyshots-puppeteer