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

[Bug]: Unhandled exceptions are not traceable to the story they came from in @storybook/experimental-addon-test #30421

Open
tmeasday opened this issue Jan 30, 2025 · 1 comment

Comments

@tmeasday
Copy link
Member

tmeasday commented Jan 30, 2025

Describe the bug

If a component or story triggers an unhandled exception (from a promise) a generic Vitest error is thrown, with no association to the story file that triggered it. Although that error can have a stack trace, it sometimes does not so we cannot rely on the stack trace to locate the source of the error.

As an example, if we add the following to the Button.tsx file in the React Vite sandbox:

// error.ts
export async function thrower() {
  throw new Error("foo");
}

// Button.tsx
// ....
const mode = primary
    ? "storybook-button--primary"
    : "storybook-button--secondary";

  setTimeout(thrower);

  return (

And run the tests, you'll get "12 unhandled errors" which don't really reveal which stories are triggering the problems:

Image

Reproduction link

https://github.com/tmeasday/sb-vitest-unhandledrejections/tree/main

Reproduction steps

  1. Open the storybook
  2. Run tests via module
  3. Look at errors

System

Storybook Environment Info:

  System:
    OS: macOS 15.1.1
    CPU: (10) arm64 Apple M1 Pro
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.14.0 - ~/.nvm/versions/node/v20.14.0/bin/node
    Yarn: 1.22.22 - ~/.nvm/versions/node/v20.14.0/bin/yarn <----- active
    npm: 10.7.0 - ~/.nvm/versions/node/v20.14.0/bin/npm
  Browsers:
    Chrome: 132.0.6834.112
    Edge: 110.0.1587.57
    Safari: 18.1.1
  npmPackages:
    @storybook/addon-essentials: ^8.5.2 => 8.5.2
    @storybook/addon-interactions: ^8.5.2 => 8.5.2
    @storybook/addon-onboarding: ^8.5.2 => 8.5.2
    @storybook/blocks: ^8.5.2 => 8.5.2
    @storybook/experimental-addon-test: ^8.5.2 => 8.5.2
    @storybook/react: ^8.5.2 => 8.5.2
    @storybook/react-vite: ^8.5.2 => 8.5.2
    @storybook/test: ^8.5.2 => 8.5.2
    eslint-plugin-storybook: ^0.11.2 => 0.11.2
    storybook: ^8.5.2 => 8.5.2

Additional context

Maybe the fix needs to come upstream, but I believe a workaround is possible. If you add the following block to preview.ts:

// Toggle this block to see a method to catch rejections and associate with the story
window.addEventListener("unhandledrejection", function (e) {
  console.log("vvv -- Caught handled rejection -- vvv");
  console.log(e.reason);
  console.log(e.reason?.stack);
  console.log("^^^ -- Done in caught unhandled rejection -- ^^^");
});

You get console logs in the terminal like so:

Image

Notice the presence of stdout | src/stories/Button.stories.ts in those logs --- which inform you of which story was running when the error was caught. Maybe that's not 100% reliable (?) but it sure helped a lot when I was debugging these kind of issues!

Copy link
Contributor

greptile-apps bot commented Jan 30, 2025

** Disclaimer** This information might be inaccurate, due to it being generated automatically
This can be fixed by modifying the test runner in @storybook/experimental-addon-test to wrap story execution with unhandledrejection handlers. Implementation steps: 1. In code/addons/test/src/vitest/index.ts, modify the createStoryTests function to wrap story execution with: ts const unhandledRejections = []; const handler = (event) => { unhandledRejections.push({ error: event.reason, storyId: story.id }); }; window.addEventListener('unhandledrejection', handler); // After story execution window.removeEventListener('unhandledrejection', handler); if (unhandledRejections.length > 0) { throw new Error(`Unhandled rejections in story ${story.id}: ${ unhandledRejections.map(r => r.error.stack).join(' ') }`); } This will associate unhandled rejections with the specific story that triggered them.

About Greptile

This response provides a starting point for your research, not a precise solution.

Help us improve! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

Edit Issue Bot Settings · Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

No branches or pull requests

2 participants