storybookjs / test-runner

🚕 Turn stories into executable tests
https://storybook.js.org/docs/writing-tests/interaction-testing
MIT License
231 stars 72 forks source link

[Bug] getStoryContext (globalThis) returns undefined #138

Open VickyKoblinski opened 2 years ago

VickyKoblinski commented 2 years ago

Describe the bug

storyContext is undefined

// test-runner.js
const { getStoryContext } = require("@storybook/test-runner");

module.exports = {
  async postRender(page, context) {
    const storyContext = await getStoryContext(page, context);
    console.log(storyContext) // undefined
    const globalThis = await page.evaluate(() => globalThis);
    console.log(globalThis) // undefined
  },
};

Steps to reproduce the behavior

Use the above file

Expected behavior

To be able to access the storyContext like here https://github.com/storybookjs/test-runner/blob/next/.storybook/test-runner.ts

Screenshots and/or logs

n/a

Environment

Additional context

~I think the problem may be because default test-runner-jest.config.js is missing the globalSetup and globalTeardown operations that this repo is using.~ I was wrong about this, test-runner-jest.config.js does get the setup and teardown from getJestConfig.

Could this be because globalThis has been introduced in Jest 28 but we're still on Jest 27?

VickyKoblinski commented 2 years ago

It turned out that globalThis.__STORYBOOK_PREVIEW__.storyStore.loadStory({ storyId }) contained circular dependencies and Playwright doesn't allow you to return Js objects with circular dependencies, which is why I was getting undefined. I'm not sure where they came from, but I think this would be common. Here's my not-so-elegant solution:

    const storyContext = await page.evaluate(
      async ({ storyId }) => {
        const getCircularReplacer = () => {
          const seen = new WeakSet();
          return (key, value) => {
            if (typeof value === "object" && value !== null) {
              if (seen.has(value)) {
                return;
              }
              seen.add(value);
            }
            return value;
          };
        };

        return JSON.parse(
          JSON.stringify(
            await globalThis.__STORYBOOK_PREVIEW__.storyStore.loadStory({ storyId }),
            getCircularReplacer()
          )
        );
      },
      {
        storyId: context.id,
      }
    );
yannbf commented 2 years ago

Oh wow! That's new to me. Thanks a lot for sharing this @VickyKoblinski ! 🙌 I'll have to chew on this for a bit. cc @shilman

myufa commented 1 year ago

Seeing the same issue, am not able to get this patch to work, @ndelangen any guidance here?

myufa commented 1 year ago

have been getting page.evaluate: TypeError: Cannot read properties of undefined (reading 'storyStore') at getStoryContext (node_modules/@storybook/test-runner/dist/cjs/playwright/hooks.js:17:15)

yannbf commented 1 year ago

@myufa can you share a reproduction for us to take a look? thanks!

MRamonLeon commented 8 months ago

Any update on this?, we're facing this too. Thank you.

zb-sj commented 6 months ago

have been getting page.evaluate: TypeError: Cannot read properties of undefined (reading 'storyStore') at getStoryContext (node_modules/@storybook/test-runner/dist/cjs/playwright/hooks.js:17:15)

~~It was issue with my test runner previsiting about:blank instead. I could get around with the "undefined (reading 'storyStore')" with if (page.url() === 'about:blank') return;~~

but now I'm getting "Timed out waiting for Storybook to load after 10 seconds."

Sorry, it was caused by an issue with not implementing defaultPrepare in my custom prepare