mswjs / msw-storybook-addon

Mock API requests in Storybook with Mock Service Worker.
https://msw-sb.vercel.app
MIT License
397 stars 40 forks source link

Should per story handlers work on the Docs tab when all stories are presented on the same page? #83

Open solace opened 2 years ago

solace commented 2 years ago

I'm not certain if this is actually related to #63, but when I have multiple stories displayed on the Docs page with different returns on the same handler endpoint/method, only the last one is applied. Works fine on the individual story canvases as they're treated independently.

In addition to the example provided in #63, if there is a story without any handlers placed last, it causes all of the others to fail with the error that no handlers have been defined.

Should this actually work on the Docs tab?

Currently using @latest for msw, storybook/react, and msw-storybook-addon.

kettanaito commented 2 years ago

Hey, @solace. Thanks for raising this.

On a technical level, when you load multiple stories at once, all of them begin to communicate with a single worker. But even more, all of them share the same list of handlers because this is how MSW manages handlers internally. So if the latest story appends a runtime handler, let's say, then it will affect all the other stories as well, given they make a matching request.

If you wish for the same requests to be handled differently while in the same browser context, that is not supported. The worker has no idea which exact story is making a particular request in order to understand what response must be returned for that particular story. This is a rather challenging task to solve—scoping the response lookup.

I'm not that familiar with multi-story setup in Storybook, but if each story is a separate iframe then we could theoretically base the response lookup on the iframe id in the worker. I still find this an edge case from the MSW's perspective, as you're effectively loading multiple apps under a single page and expect different frames to receive different responses. Not sure if the solution we could try would benefit anything else but this particular use case.

What do you think about this, @yannbf? Are those stories indeed loaded as separate iframes on the same page?

solace commented 2 years ago

Hi @kettanaito, that makes perfect sense and it is a tricky issue to resolve.

The docs page showing multiple stories on the page by default is convenient, but given the nature of the problem, it might be better to use custom docs pages when using storybook with msw. Could this caveat be added to the addon docs?

Thanks!

tnzk commented 2 years ago

I've encountered the same issue. I'm not sure how the docs page work, but a separate service worker inside each iframe wouldn't be an option?

isimmons commented 1 year ago

It seems in v7 they don't even work without a docs page. Related issue ? #82

Code from @yannbf course on newline but updated to storybook v7, react 18, vite and the new syntax. I removed autodocs so there is no docs page but it still doesn't work.

export const Default: Story = {
  name: "Default Story",
  parameters: {
    msw: {
      handlers: [
        rest.get(BASE_URL, (_req, res, ctx) => res(ctx.json(restaurants))),
      ],
    },
  },
};

export const Loading: Story = {
  name: "Loading Story",
  parameters: {
    msw: {
      handlers: [
        rest.get(BASE_URL, (_req, res, ctx) => res(ctx.delay("infinite"))),
      ],
    },
  },
};

Would it be best when using msw to make 2 separate stories pages for the same component?

UPDATE: I just tried separating them out into 2 separate stories files so there under separate listings and still have the issue.

UPDATE 2: I started a new project with storybook 7.0.20 and now the stories work correctly without autodocs page. Just the docs page still doesn't work

nachten commented 1 year ago

Please look at the following at issue as I understand from @jonniebigodes this is a bug, please solve this in a future release.

somewonderfulguy commented 1 year ago

Hi @isimmons, I didn't try to use mock per story, but I set it on global level in preview.tsx. And it works just fine. However, this does not fix issue in docs.

Here's the snippet inside this file:

if (typeof global.process === 'undefined') {
  const { worker } = require('../src/api/offline')
  worker.start({
    onUnhandledRequest(req, print) {
      if (
        whiteListEndpoints.some((endpoint) =>
          req.url.pathname.includes(endpoint)
        )
      ) {
        return
      }
      print.warning()
    }
  })
}

And the offline.ts:

import { setupWorker } from 'msw'

import { userHandlers } from './userApi/userMSW'
import { someOtherHandlers } from './someOtherApi/someOtherMSW'
import { soOnSoForthHandlers } from './soOnSoForthApi/soOnSoForthMSW'

export const worker = setupWorker(...userHandlers, ...someOtherHandlers, ...soOnSoForthHandlers)

Deps:

"react": "^18.2.0",
"storybook": "7.0.22",
"msw": "^1.2.2"
nisiyuan commented 3 months ago

I've encountered the same issue。Now I will turn to use customize doc。Hope to support it ,thanks