reg-viz/storycap

Failed to capture a screenshot for stories with click/focus options: Error: failed to find element matching selector

Closed this issue · 1 comments

When a story has click and/or focus options, storycap fails to capture a screenshot for it with Error: failed to find element matching selector "(selector)".

$ storycap http://127.0.0.1:6006 --disableCssAnimation --chromiumChannel stable --serverCmd 'yarn storybook:serve'
info Wait for connecting storybook server http://127.0.0.1:6006.
info Executable Chromium path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
info Storycap runs with managed mode
info Found 1 stories.
error Error: failed to find element matching selector ".component-textarea"
Error: Error: failed to find element matching selector ".component-textarea"
    at ElementHandle.$eval (/Users/user/workspaces/storycap-focus-issue/node_modules/puppeteer-core/lib/cjs/puppeteer/common/JSHandle.js:649:19)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async CapturingBrowser.resetIfTouched (/Users/user/workspaces/storycap-focus-issue/node_modules/storycap/lib/node/capturing-browser.js:90:13)
    at async CapturingBrowser.screenshot (/Users/user/workspaces/storycap-focus-issue/node_modules/storycap/lib/node/capturing-browser.js:319:9)
    at async time (/Users/user/workspaces/storycap-focus-issue/node_modules/storycrawler/lib/timer.js:14:20)
    at async /Users/user/workspaces/storycap-focus-issue/node_modules/storycap/lib/node/screenshot-service.js:27:39
    at async /Users/user/workspaces/storycap-focus-issue/node_modules/storycrawler/lib/async-utils.js:153:28
    at async next (/Users/user/workspaces/storycap-focus-issue/node_modules/storycrawler/lib/async-utils.js:37:30)

Here is minimum repository to reproduce this issue: https://github.com/nodaguti/storycap-focus-issue

This issue is also reproduced with Storybook v6.

Seems like puppeteer fails to find an element specified by click/focus options. If an empty this.page.evaluate() is inserted before each this.page.$eval() at resetIfTouched(), the issue will disappear.

  // Clear the browser's mouse state.
  if (screenshotOptions.click) {
+   await this.page.evaluate(() => {});
    await this.page.$eval(screenshotOptions.click, (e: unknown) => (e as HTMLElement)?.blur());
  }
  if (screenshotOptions.focus) {
+   await this.page.evaluate(() => {});
    await this.page.$eval(screenshotOptions.focus, (e: unknown) => (e as HTMLElement)?.blur());
  }

If it's acceptable to add this workaround, I'm happy to send a PR.

I'm still seeing this issue intermittent even in 4.2.0. Adding a delay to the variant seems to help, but doesn't feel like a stable version, too...