Skip to content

Commit

Permalink
deprecate msw parameter as an array
Browse files Browse the repository at this point in the history
  • Loading branch information
yannbf committed Apr 15, 2024
1 parent c4f877b commit 133be34
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 16 deletions.
39 changes: 38 additions & 1 deletion MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand All @@ -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
}
}
}
}
```
8 changes: 8 additions & 0 deletions packages/msw-addon/src/applyRequestHandlers.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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
Expand Down
22 changes: 7 additions & 15 deletions packages/msw-addon/src/decorator.ts
Original file line number Diff line number Diff line change
@@ -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?:
Expand All @@ -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 = <Story extends (...args: any[]) => 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()
}
22 changes: 22 additions & 0 deletions packages/msw-addon/src/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { dedent } from 'ts-dedent'

export function once<T extends (...args: any[]) => any>(fn: T): T {
let called = false;
let value: ReturnType<T>;

const wrapper: (...args: Parameters<T>) => ReturnType<T> = (...args: Parameters<T>): ReturnType<T> => {
if (!called) {
called = true;
value = fn(...args);
}
return value;
};

return wrapper as T;
}

export function deprecate(message: string) {
return once(() => {
console.warn(dedent(message));
});
}

0 comments on commit 133be34

Please sign in to comment.