-
Notifications
You must be signed in to change notification settings - Fork 39
feat(atomic): add MSW toggle for Storybook with auto-disable in production #6677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…ction Co-authored-by: louis-bompart <12366410+louis-bompart@users.noreply.github.com>
Co-authored-by: louis-bompart <12366410+louis-bompart@users.noreply.github.com>
Co-authored-by: louis-bompart <12366410+louis-bompart@users.noreply.github.com>
|
@copilot , not bad, can you make sure that when the user toggle MSW, the story does reload? |
Co-authored-by: louis-bompart <12366410+louis-bompart@users.noreply.github.com>
Added automatic page reload when toggling MSW. The decorator now tracks the previous MSW state and triggers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds conditional MSW (Mock Service Worker) support to Storybook with environment-aware defaults and a developer toggle. The changes ensure production builds use live APIs by default while preserving mocking capabilities for tests and development workflows.
Key changes:
- MSW is automatically enabled in test/dev environments but disabled in production builds
- Developers can toggle MSW on/off via a Storybook toolbar control
- Stories automatically reload when the MSW state changes to ensure the new mocking configuration takes effect
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
| } | ||
| // Check for vitest global (set by @vitest/browser) | ||
| if (typeof globalThis !== 'undefined' && '__vitest_browser__' in globalThis) { |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using in operator on globalThis doesn't provide type safety. Consider using optional chaining: globalThis.__vitest_browser__ !== undefined or type guard with hasOwnProperty.
| if (typeof globalThis !== 'undefined' && '__vitest_browser__' in globalThis) { | |
| if (typeof globalThis !== 'undefined' && globalThis.__vitest_browser__ !== undefined) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot implement, preferably with a typeGuard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented hasVitestBrowser type guard function that uses Object.hasOwn() for type-safe property checking. Commit: 9d055da
| return mswLoader(context); | ||
| } | ||
|
|
||
| // Check if MSW is enabled via the global toggle |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nullish coalescing (??) will not handle false correctly. When context.globals.msw is explicitly set to false, this expression evaluates to false as intended. However, if it's null or undefined, it falls back to isMswEnabledByDefault. This is correct behavior, but the comment on line 91 says 'Check if MSW is enabled via the global toggle' which could be clearer about the fallback logic.
| // Check if MSW is enabled via the global toggle | |
| // Determine if MSW is enabled: use the global toggle if set (including false), otherwise fall back to the default |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot implement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated comment to: "Determine if MSW is enabled: use the global toggle if set (including false), otherwise fall back to the default". Commit: 9d055da
| if (!isTestEnvironment && typeof window !== 'undefined') { | ||
| const currentMswState = context.globals?.msw; |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previousMswState tracking logic compares against context.globals?.msw which could be undefined, true, or false. This creates three distinct states, but the initial value is undefined. On first render, if context.globals.msw is undefined (not yet set by user), this will match previousMswState and no reload occurs. However, if the default value from globalTypes.defaultValue applies, there could be a mismatch between previousMswState (undefined) and the actual effective state. Consider initializing previousMswState to match the effective initial state: let previousMswState: boolean | undefined = isMswEnabledByDefault;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot implement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initialized previousMswState to isMswEnabledByDefault to avoid unnecessary reloads on first render. Commit: 9d055da
louis-bompart
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot address the comments
| if (!isTestEnvironment && typeof window !== 'undefined') { | ||
| const currentMswState = context.globals?.msw; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot implement
| return mswLoader(context); | ||
| } | ||
|
|
||
| // Check if MSW is enabled via the global toggle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot implement
| } | ||
| } | ||
| // Check for vitest global (set by @vitest/browser) | ||
| if (typeof globalThis !== 'undefined' && '__vitest_browser__' in globalThis) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot implement, preferably with a typeGuard.
Co-authored-by: louis-bompart <12366410+louis-bompart@users.noreply.github.com>
alexprudhomme
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I toggle the switch to disable, it seems to break storybook. It refreshes continually the story with a flashing error. Does it work for you ?
|
I don't think this would work for facets since the MSW facet might not exist in reality. We would have to make sure to use a 'real' facet for our MSW. Best would be to have two separate stories. |
MSW was always active in Storybook, but we need production builds to use live APIs while preserving mocking for tests and providing a developer toggle.
Changes
conditionalMswLoader): Wraps the standard loader to check environment and toolbar state before applying mockshasVitestBrowsertype guard for detecting vitest browser environment.previousMswStateis initialized to match the effective initial state to avoid unnecessary reloads on first render.Acceptance Criteria
Production build of Storybook → no mocking
Developer toolbar toggle → easy switch between mocked/live
Vitest story tests → always mocked
Non-MSW stories → unaffected
Story reloads when MSW toggle changes
Fixes [DXUI]: Improve MSW setup in Storybook #6676
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.