diff --git a/src/browser/setupWorker/setupWorker.ts b/src/browser/setupWorker/setupWorker.ts index 66748eb26..86064e93e 100644 --- a/src/browser/setupWorker/setupWorker.ts +++ b/src/browser/setupWorker/setupWorker.ts @@ -24,6 +24,8 @@ import { printStartMessage } from './start/utils/printStartMessage' import { printStopMessage } from './stop/utils/printStopMessage' import { supportsServiceWorker } from '../utils/supports' +const kSetupWorkerApplied = Symbol.for('msw.setupWorkerApplied') + export class SetupWorkerApi extends SetupApi implements SetupWorker @@ -180,5 +182,15 @@ export class SetupWorkerApi export function setupWorker( ...handlers: Array ): SetupWorker { - return new SetupWorkerApi(...handlers) + invariant( + Reflect.get(globalThis, kSetupWorkerApplied) == null, + devUtils.formatMessage( + 'Failed to execute `setupWorker()` more than once in the same page. Create the worker once and reuse it for the lifetime of the page. If you wish to apply a different set of request handlers, use `worker.use()` or `worker.resetHandlers()` instead.', + ), + ) + + const worker = new SetupWorkerApi(...handlers) + Reflect.set(globalThis, kSetupWorkerApplied, true) + + return worker } diff --git a/test/browser/msw-api/setup-worker/multiple-instances.mocks.ts b/test/browser/msw-api/setup-worker/multiple-instances.mocks.ts new file mode 100644 index 000000000..3d79c6ad5 --- /dev/null +++ b/test/browser/msw-api/setup-worker/multiple-instances.mocks.ts @@ -0,0 +1,7 @@ +import { setupWorker } from 'msw/browser' + +Object.assign(window, { + msw: { + setupWorker, + }, +}) diff --git a/test/browser/msw-api/setup-worker/multiple-instances.test.ts b/test/browser/msw-api/setup-worker/multiple-instances.test.ts new file mode 100644 index 000000000..6fba8928d --- /dev/null +++ b/test/browser/msw-api/setup-worker/multiple-instances.test.ts @@ -0,0 +1,36 @@ +import type { setupWorker } from 'msw/browser' +import { test, expect } from '../../playwright.extend' + +declare namespace window { + export const msw: { + setupWorker: typeof setupWorker + } +} + +test('throws an error when calling "setupWorker()" more than once on the same page', async ({ + loadExample, + page, +}) => { + await loadExample(new URL('./multiple-instances.mocks.ts', import.meta.url), { + skipActivation: true, + }) + + await page.waitForFunction(() => { + return typeof window.msw !== 'undefined' + }) + + const errorMessage = await page.evaluate(() => { + window.msw.setupWorker() + + try { + window.msw.setupWorker() + return null + } catch (error) { + return error instanceof Error ? error.message : String(error) + } + }) + + expect(errorMessage).toContain( + '[MSW] Failed to execute `setupWorker()` more than once', + ) +})