diff --git a/MIGRATION.md b/MIGRATION.md index c8997fc..f6f6459 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -3,6 +3,7 @@ - [From 1.x.x to 2.x.x](#from-1xx-to-2xx) - [MSW required version is now ^2.0.0](#msw-required-version-is-now-200) - [mswDecorator is deprecated in favor of mswLoader](#mswdecorator-is-deprecated-in-favor-of-mswloader) + - [parameters.msw Array notation deprecated in favor of Object notation](#parametersmsw-array-notation-deprecated-in-favor-of-object-notation) ## From 1.x.x to 2.x.x @@ -12,7 +13,9 @@ The addon now requires your MSW version to be 2.0.0 or higher. This means you wi ### mswDecorator is deprecated in favor of mswLoader -Using MSW in a decorator worked for most scenarios, but there's a slight chance the service worker will not get registered in time. As a result, a story that requests data might actually request real data. Since v1.7.0, this addon provided a `mswLoader` to use instead of the `mswDecorator`. Loaders get executed before a story renders, differently than decorators, which execute as the story renders. Please replace your `mswDecorator` with `mswLoader`, as the `mswDecorator` will be removed in the next major release. It works the same, respecting the parameters you set, so there's no need to change anything else in your codebase. +Using MSW in a decorator worked for most scenarios, but there's a slight chance the service worker will not get registered in time. As a result, a story that requests data might actually request real data. **Since v1.7.0**, this addon provided a `mswLoader` to use instead of the `mswDecorator`. Loaders get executed before a story renders, differently than decorators, which execute as the story renders. + +Please replace your `mswDecorator` with `mswLoader`, as the `mswDecorator` will be removed in the next major release. It works the same, respecting the parameters you set, so there's no need to change anything else in your codebase. ```diff // .storybook/preview.js @@ -28,3 +31,37 @@ const preview = { export default preview ``` + +### parameters.msw Array notation deprecated in favor of Object notation + +**Since v1.5.0**, this addon started supporting the `parameters.msw.handlers` object format instead of using `parameters.msw` as an Array. This change was done to follow convention for Storybook addon parameters, but also allows for more advanced usage and make the addon more future proof for upcoming features. You can find [more information here](./README.md#composing-request-handlers). + +Please migrate to this format, and the previous format will be removed in the next major release. + +```ts +// ❌ Instead of defining the msw parameter like so: +export const MyStory = { + parameters: { + msw: [...] // some handlers here + } +} + +// ✅ You should set them like so: +export const MyStory = { + parameters: { + msw: { + handlers: [...] // some handlers here + } + } +} +// ✅ Or like so: +export const MyStory = { + parameters: { + msw: { + handlers: { + someHandlerName: [...] // some handlers here + } + } + } +} +``` diff --git a/packages/msw-addon/src/applyRequestHandlers.ts b/packages/msw-addon/src/applyRequestHandlers.ts index 2bc7714..40227cf 100644 --- a/packages/msw-addon/src/applyRequestHandlers.ts +++ b/packages/msw-addon/src/applyRequestHandlers.ts @@ -1,6 +1,13 @@ import type { RequestHandler } from 'msw' import { api } from '@build-time/initialize' import type { Context } from './decorator.js' +import { deprecate } from './util.js'; + +const deprecateMessage = deprecate(` +[msw-storybook-addon] You are using parameters.msw as an Array instead of an Object with a property "handlers". This usage is deprecated and will be removed in the next release. Please use the Object syntax instead. + +More info: https://github.com/mswjs/msw-storybook-addon/blob/main/MIGRATION.md#parametersmsw-array-notation-deprecated-in-favor-of-object-notation +`) // P.S. this is used by Storybook 7 users as a way to help them migrate. // This should be removed from the package exports in a future release. @@ -14,6 +21,7 @@ export function applyRequestHandlers( } if (Array.isArray(handlersListOrObject) && handlersListOrObject.length > 0) { + deprecateMessage() // Support an Array of request handlers (backwards compatability). api.use(...handlersListOrObject) return diff --git a/packages/msw-addon/src/decorator.ts b/packages/msw-addon/src/decorator.ts index 3990ea0..ec4bd9f 100644 --- a/packages/msw-addon/src/decorator.ts +++ b/packages/msw-addon/src/decorator.ts @@ -1,6 +1,6 @@ -import { dedent } from 'ts-dedent' import type { RequestHandler } from 'msw' import { applyRequestHandlers } from './applyRequestHandlers.js' +import { deprecate } from './util.js' export type MswParameters = { msw?: @@ -14,25 +14,17 @@ export type Context = { parameters: MswParameters } -let hasBeenCalled = false -const once = (fn: () => void) => { - if (!hasBeenCalled) { - hasBeenCalled = true - fn() - } -} +const deprecateMessage = deprecate(` +[msw-storybook-addon] The mswDecorator is deprecated and will be removed in the next release. Please use the mswLoader instead. + +More info: https://github.com/mswjs/msw-storybook-addon/blob/main/MIGRATION.md#mswdecorator-is-deprecated-in-favor-of-mswloader +`) export const mswDecorator = any>( storyFn: Story, context: Context ) => { - once(() => { - console.warn(dedent` - [msw-storybook-addon] The mswDecorator is deprecated and will be removed in the next release. Please use the mswLoader instead. - - More info: https://github.com/mswjs/msw-storybook-addon/blob/main/MIGRATION.md#mswdecorator-is-deprecated-in-favor-of-mswloader - `) - }) + deprecateMessage() applyRequestHandlers(context.parameters.msw) return storyFn() } diff --git a/packages/msw-addon/src/util.ts b/packages/msw-addon/src/util.ts new file mode 100644 index 0000000..4eb13d4 --- /dev/null +++ b/packages/msw-addon/src/util.ts @@ -0,0 +1,22 @@ +import { dedent } from 'ts-dedent' + +export function once any>(fn: T): T { + let called = false; + let value: ReturnType; + + const wrapper: (...args: Parameters) => ReturnType = (...args: Parameters): ReturnType => { + if (!called) { + called = true; + value = fn(...args); + } + return value; + }; + + return wrapper as T; +} + +export function deprecate(message: string) { + return once(() => { + console.warn(dedent(message)); + }); +} \ No newline at end of file