storybookjs / test-runner

🚕 Turn stories into executable tests

Home Page:https://storybook.js.org/docs/writing-tests/interaction-testing

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[bug] Storybook Test Runner Timeout with waitForPageReady

shajjhusein opened this issue · comments

Describe the bug

My Storybook test runner tests are timing out with the error "Exceeded timeout of 30000 ms for a test" when using the waitForPageReady function. This issue occurs specifically in the test "Components/ImageEditor › WithInitialImage › play-test".

To Reproduce

Run your Storybook tests using the provided configuration in .storybook/test-runner.ts.
Observe the timeout error for the "Components/ImageEditor › WithInitialImage › play-test" test.
Expected behavior

Tests should take screenshots after waiting for the content to render completely, including fonts and external images.
Tests should complete within a reasonable timeframe (ideally without exceeding the timeout).
Screenshots

(Optional: Include screenshots of the Storybook test UI and the timeout error message if applicable)

System

System:
OS: Linux 5.15 Ubuntu 20.04.6 LTS (Focal Fossa)
CPU: (12) x64 12th Gen Intel(R) Core(TM) i7-1255U
Shell: 5.0.17 - /bin/bash
Binaries:
Node: 20.10.0 - ~/.nvm/versions/node/v20.10.0/bin/node
Yarn: 1.22.19 - /usr/bin/yarn
npm: 10.2.3 - ~/.nvm/versions/node/v20.10.0/bin/npm <----- active
Browsers:
Chrome: 121.0.6167.160
npmPackages:
@storybook/addon-a11y: ^8.0.2 => 8.0.2
@storybook/addon-actions: ^8.0.2 => 8.0.2
@storybook/addon-backgrounds: ^8.0.2 => 8.0.2
@storybook/addon-controls: ^8.0.2 => 8.0.2
@storybook/addon-coverage: ^0.0.9 => 0.0.9
@storybook/addon-designs: ^8.0.0 => 8.0.0
@storybook/addon-docs: ^8.0.2 => 8.0.2
@storybook/addon-interactions: ^8.0.2 => 8.0.2
@storybook/addon-links: ^8.0.2 => 8.0.2
@storybook/addon-mdx-gfm: ^8.0.2 => 8.0.2
@storybook/addon-measure: ^8.0.2 => 8.0.2
@storybook/addon-outline: ^8.0.2 => 8.0.2
@storybook/addon-storysource: ^8.0.2 => 8.0.2
@storybook/addon-themes: ^8.0.2 => 8.0.2
@storybook/addon-viewport: ^8.0.2 => 8.0.2
@storybook/addon-webpack5-compiler-babel: ^3.0.3 => 3.0.3
@storybook/jest: ^0.2.3 => 0.2.3
@storybook/preview-api: ^8.0.2 => 8.0.2
@storybook/react-webpack5: ^8.0.2 => 8.0.2
@storybook/test-runner: ^0.17.0 => 0.17.0
@storybook/testing-library: ^0.2.2 => 0.2.2
storybook: ^8.0.2 => 8.0.2
npmGlobalPackages:
@storybook/cli: 7.6.17

Additional context

The code uses waitForPageReady to wait for the entire page to be ready before taking screenshots.
While this ensures consistent results, it might be causing the timeout due to slow-loading fonts or external images.
Increasing the timeout to 30000 ms doesn't resolve the issue entirely.
Possible Solutions Explored:

Increasing the timeout (not ideal as it masks the root cause)
Using page.waitForSelector for specific elements (might not be suitable for fonts and external images affecting the entire page)
Here are two potential approaches to consider:

Optimize Font and Image Loading: Investigate the performance of fonts and external images. Look for ways to optimize their loading times (e.g., preloading fonts, using Content Delivery Networks for images).
Custom Waiting Strategy: Create a custom waiting function that combines page.waitForSelector for essential elements (like the ImageEditor component itself) with techniques to wait for network requests to finish, ensuring all resources for the component are loaded before taking screenshots.

it's not working even i have added this
test-runner-jest.js
const { getJestConfig } = require('@storybook/test-runner');

/**

  • @type {import('@jest/types').Config.InitialOptions}
    /
    module.exports = {
    // The default configuration comes from @storybook/test-runner
    ...getJestConfig(),
    /
    * Add your own overrides below

@shajjhusein I had this same issue, it seems there's no built in way to configure the playwright timeouts (e.g. navigation timeout which you are hitting) when using the storybook test runner (possible feature request for this?).

For now I'm using the following workaround (basically replace defaultPrepare from storybook):

.storybook/test-runner.ts

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

const config: TestRunnerConfig = {
  async prepare({ page, browserContext, testRunnerConfig }) {
    page.setDefaultTimeout(120 * 1000); // set here to whatever you need

    const targetURL = process.env.TARGET_URL;
    const iframeURL = new URL('iframe.html', targetURL).toString();

    if (testRunnerConfig.getHttpHeaders) {
      const headers = await testRunnerConfig.getHttpHeaders(iframeURL);
      await browserContext.setExtraHTTPHeaders(headers);
    }

    await page.goto(iframeURL, { waitUntil: 'load' }).catch((err) => {
      if (err instanceof Error && err.message.includes('ERR_CONNECTION_REFUSED')) {
        const errorMessage = `Could not access the Storybook instance at ${targetURL}. Are you sure it's running?\n\n${err.message}`;
        throw new Error(errorMessage);
      }

      throw err;
    });
  },
};

export default config;