@msw/playwright 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -37,11 +37,24 @@ interface Fixtures {
37
37
  network: NetworkFixture
38
38
  }
39
39
 
40
- export const test = testBase.extend<Fixtures>({
41
- // Create a fixture that will control the network in your tests.
42
- network: createNetworkFixture({
43
- initialHandlers: handlers,
44
- }),
40
+ const test = testBase.extend<Fixtures>({
41
+ // Initial list of the network handlers.
42
+ handlers: [[], { option: true }],
43
+
44
+ // A fixture you use to control the network in your tests.
45
+ network: [
46
+ async ({ context, handlers }, use) => {
47
+ const network = defineNetworkFixture({
48
+ context,
49
+ handlers,
50
+ })
51
+
52
+ await network.enable()
53
+ await use(network)
54
+ await network.disable()
55
+ },
56
+ { auto: true },
57
+ ],
45
58
  })
46
59
  ```
47
60
 
package/build/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { LifeCycleEventsMap, RequestHandler, SetupApi, UnhandledRequestStrategy, WebSocketHandler } from "msw";
2
- import { BrowserContext, PlaywrightTestArgs, PlaywrightWorkerArgs, TestFixture } from "@playwright/test";
1
+ import { AnyHandler, LifeCycleEventsMap, SetupApi, UnhandledRequestStrategy } from "msw";
2
+ import { BrowserContext } from "@playwright/test";
3
3
 
4
4
  //#region src/fixture.d.ts
5
- interface CreateNetworkFixtureArgs {
6
- initialHandlers?: Array<RequestHandler | WebSocketHandler>;
5
+ interface NetworkFixtureOptions {
6
+ context: BrowserContext;
7
+ handlers?: Array<AnyHandler>;
7
8
  onUnhandledRequest?: UnhandledRequestStrategy;
8
9
  /**
9
10
  * Skip common asset requests (e.g. `*.html`, `*.css`, `*.js`, etc).
@@ -14,51 +15,16 @@ interface CreateNetworkFixtureArgs {
14
15
  */
15
16
  skipAssetRequests?: boolean;
16
17
  }
17
- /**
18
- * Creates a fixture that controls the network in your tests.
19
- *
20
- * @note The returned fixture already has the `auto` option set to `true`.
21
- *
22
- * **Usage**
23
- * ```ts
24
- * import { test as testBase } from '@playwright/test'
25
- * import { createNetworkFixture, type WorkerFixture } from '@msw/playwright'
26
- *
27
- * interface Fixtures {
28
- * network: WorkerFixture
29
- * }
30
- *
31
- * export const test = testBase.extend<Fixtures>({
32
- * network: createNetworkFixture()
33
- * })
34
- * ```
35
- */
36
- declare function createNetworkFixture(args?: CreateNetworkFixtureArgs): [TestFixture<NetworkFixture, PlaywrightTestArgs & PlaywrightWorkerArgs>, {
37
- auto: boolean;
38
- }];
18
+ type NetworkFixture = Omit<SetupApi<LifeCycleEventsMap>, 'dispose'> & {
19
+ enable: () => Promise<void>;
20
+ disable: () => Promise<void>;
21
+ };
22
+ declare function defineNetworkFixture(options: NetworkFixtureOptions): NetworkFixture;
39
23
  /**
40
24
  * @note Use a match-all RegExp with an optional group as the predicate
41
25
  * for the `page.route()`/`page.unroute()` calls. Playwright treats given RegExp
42
26
  * as the handler ID, which allows us to remove only those handlers introduces by us
43
27
  * without carrying the reference to the handler function around.
44
28
  */
45
-
46
- declare class NetworkFixture extends SetupApi<LifeCycleEventsMap> {
47
- protected args: {
48
- context: BrowserContext;
49
- skipAssetRequests: boolean;
50
- initialHandlers: Array<RequestHandler | WebSocketHandler>;
51
- onUnhandledRequest?: UnhandledRequestStrategy;
52
- };
53
- constructor(args: {
54
- context: BrowserContext;
55
- skipAssetRequests: boolean;
56
- initialHandlers: Array<RequestHandler | WebSocketHandler>;
57
- onUnhandledRequest?: UnhandledRequestStrategy;
58
- });
59
- start(): Promise<void>;
60
- stop(): Promise<void>;
61
- private getPageUrl;
62
- }
63
29
  //#endregion
64
- export { CreateNetworkFixtureArgs, NetworkFixture, createNetworkFixture };
30
+ export { NetworkFixture, NetworkFixtureOptions, defineNetworkFixture };
package/build/index.js CHANGED
@@ -3,37 +3,13 @@ import { RequestHandler, SetupApi, WebSocketHandler, handleRequest, isCommonAsse
3
3
  import { CancelableCloseEvent, CancelableMessageEvent } from "@mswjs/interceptors/WebSocket";
4
4
 
5
5
  //#region src/fixture.ts
6
- /**
7
- * Creates a fixture that controls the network in your tests.
8
- *
9
- * @note The returned fixture already has the `auto` option set to `true`.
10
- *
11
- * **Usage**
12
- * ```ts
13
- * import { test as testBase } from '@playwright/test'
14
- * import { createNetworkFixture, type WorkerFixture } from '@msw/playwright'
15
- *
16
- * interface Fixtures {
17
- * network: WorkerFixture
18
- * }
19
- *
20
- * export const test = testBase.extend<Fixtures>({
21
- * network: createNetworkFixture()
22
- * })
23
- * ```
24
- */
25
- function createNetworkFixture(args) {
26
- return [async ({ context }, use) => {
27
- const worker = new NetworkFixture({
28
- context,
29
- skipAssetRequests: args?.skipAssetRequests ?? true,
30
- initialHandlers: args?.initialHandlers || [],
31
- onUnhandledRequest: args?.onUnhandledRequest
32
- });
33
- await worker.start();
34
- await use(worker);
35
- await worker.stop();
36
- }, { auto: true }];
6
+ function defineNetworkFixture(options) {
7
+ return new SetupPlaywrightApi({
8
+ context: options.context,
9
+ initialHandlers: options.handlers || [],
10
+ onUnhandledRequest: options.onUnhandledRequest,
11
+ skipAssetRequests: options.skipAssetRequests ?? true
12
+ });
37
13
  }
38
14
  /**
39
15
  * @note Use a match-all RegExp with an optional group as the predicate
@@ -42,13 +18,13 @@ function createNetworkFixture(args) {
42
18
  * without carrying the reference to the handler function around.
43
19
  */
44
20
  const INTERNAL_MATCH_ALL_REG_EXP = /.+(__MSW_PLAYWRIGHT_PREDICATE__)?/;
45
- var NetworkFixture = class extends SetupApi {
46
- constructor(args) {
47
- super(...args.initialHandlers);
48
- this.args = args;
21
+ var SetupPlaywrightApi = class extends SetupApi {
22
+ constructor(options) {
23
+ super(...options.initialHandlers);
24
+ this.options = options;
49
25
  }
50
- async start() {
51
- await this.args.context.route(INTERNAL_MATCH_ALL_REG_EXP, async (route, request) => {
26
+ async enable() {
27
+ await this.options.context.route(INTERNAL_MATCH_ALL_REG_EXP, async (route, request) => {
52
28
  const fetchRequest = new Request(request.url(), {
53
29
  method: request.method(),
54
30
  headers: new Headers(await request.allHeaders()),
@@ -60,7 +36,7 @@ var NetworkFixture = class extends SetupApi {
60
36
  * requests through the matching logic below.
61
37
  * @see https://github.com/mswjs/playwright/issues/13
62
38
  */
63
- if (this.args.skipAssetRequests && isCommonAssetRequest(fetchRequest)) return route.continue();
39
+ if (this.options.skipAssetRequests && isCommonAssetRequest(fetchRequest)) return route.continue();
64
40
  const handlers = this.handlersController.currentHandlers().filter((handler) => {
65
41
  return handler instanceof RequestHandler;
66
42
  });
@@ -69,7 +45,7 @@ var NetworkFixture = class extends SetupApi {
69
45
  * @note Use `handleRequest` instead of `getResponse` so we can pass
70
46
  * the `onUnhandledRequest` option as-is and benefit from MSW's default behaviors.
71
47
  */
72
- const response = await handleRequest(fetchRequest, crypto.randomUUID(), handlers, { onUnhandledRequest: this.args.onUnhandledRequest || "bypass" }, this.emitter, { resolutionContext: {
48
+ const response = await handleRequest(fetchRequest, crypto.randomUUID(), handlers, { onUnhandledRequest: this.options.onUnhandledRequest || "bypass" }, this.emitter, { resolutionContext: {
73
49
  quiet: true,
74
50
  baseUrl
75
51
  } });
@@ -83,7 +59,7 @@ var NetworkFixture = class extends SetupApi {
83
59
  }
84
60
  return route.continue();
85
61
  });
86
- await this.args.context.routeWebSocket(INTERNAL_MATCH_ALL_REG_EXP, async (route) => {
62
+ await this.options.context.routeWebSocket(INTERNAL_MATCH_ALL_REG_EXP, async (route) => {
87
63
  const allWebSocketHandlers = this.handlersController.currentHandlers().filter((handler) => {
88
64
  return handler instanceof WebSocketHandler;
89
65
  });
@@ -93,7 +69,7 @@ var NetworkFixture = class extends SetupApi {
93
69
  }
94
70
  const client = new PlaywrightWebSocketClientConnection(route);
95
71
  const server = new PlaywrightWebSocketServerConnection(route);
96
- const pages = this.args.context.pages();
72
+ const pages = this.options.context.pages();
97
73
  const lastPage = pages[pages.length - 1];
98
74
  const baseUrl = lastPage ? this.getPageUrl(lastPage) : void 0;
99
75
  for (const handler of allWebSocketHandlers) await handler.run({
@@ -103,10 +79,10 @@ var NetworkFixture = class extends SetupApi {
103
79
  }, { baseUrl });
104
80
  });
105
81
  }
106
- async stop() {
82
+ async disable() {
107
83
  super.dispose();
108
- await this.args.context.unroute(INTERNAL_MATCH_ALL_REG_EXP);
109
- await unrouteWebSocket(this.args.context, INTERNAL_MATCH_ALL_REG_EXP);
84
+ await this.options.context.unroute(INTERNAL_MATCH_ALL_REG_EXP);
85
+ await unrouteWebSocket(this.options.context, INTERNAL_MATCH_ALL_REG_EXP);
110
86
  }
111
87
  getPageUrl(page) {
112
88
  const url = page.url();
@@ -266,4 +242,4 @@ async function unrouteWebSocket(target, url, handler) {
266
242
  }
267
243
 
268
244
  //#endregion
269
- export { createNetworkFixture };
245
+ export { defineNetworkFixture };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@msw/playwright",
4
- "version": "0.5.0",
4
+ "version": "0.6.0",
5
5
  "description": "Mock Service Worker binding for Playwright",
6
6
  "main": "./build/index.js",
7
7
  "types": "./build/index.d.ts",
@@ -33,7 +33,7 @@
33
33
  "node": ">=20.0.0"
34
34
  },
35
35
  "peerDependencies": {
36
- "msw": "^2.12.9"
36
+ "msw": "^2.12.10"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@epic-web/test-server": "^0.1.6",
@@ -41,7 +41,7 @@
41
41
  "@playwright/test": "^1.58.1",
42
42
  "@types/node": "^22.15.29",
43
43
  "@types/sinon": "^21.0.0",
44
- "msw": "^2.12.9",
44
+ "msw": "^2.12.10",
45
45
  "sinon": "^21.0.1",
46
46
  "tsdown": "^0.12.7",
47
47
  "typescript": "^5.9.3",
package/src/fixture.ts CHANGED
@@ -2,21 +2,18 @@ import { invariant } from 'outvariant'
2
2
  import type {
3
3
  BrowserContext,
4
4
  Page,
5
- PlaywrightTestArgs,
6
- PlaywrightWorkerArgs,
7
5
  Request as PlaywrightRequest,
8
6
  Route,
9
- TestFixture,
10
7
  WebSocketRoute,
11
8
  } from '@playwright/test'
9
+ import { WebSocketHandler } from 'msw'
12
10
  import {
13
- type LifeCycleEventsMap,
14
- type UnhandledRequestStrategy,
15
11
  SetupApi,
16
- RequestHandler,
17
- WebSocketHandler,
18
12
  handleRequest,
19
13
  isCommonAssetRequest,
14
+ type AnyHandler,
15
+ type LifeCycleEventsMap,
16
+ type UnhandledRequestStrategy,
20
17
  } from 'msw'
21
18
  import {
22
19
  type WebSocketClientEventMap,
@@ -27,9 +24,11 @@ import {
27
24
  WebSocketClientConnectionProtocol,
28
25
  WebSocketServerConnectionProtocol,
29
26
  } from '@mswjs/interceptors/WebSocket'
27
+ import { RequestHandler } from 'msw'
30
28
 
31
- export interface CreateNetworkFixtureArgs {
32
- initialHandlers?: Array<RequestHandler | WebSocketHandler>
29
+ export interface NetworkFixtureOptions {
30
+ context: BrowserContext
31
+ handlers?: Array<AnyHandler>
33
32
  onUnhandledRequest?: UnhandledRequestStrategy
34
33
  /**
35
34
  * Skip common asset requests (e.g. `*.html`, `*.css`, `*.js`, etc).
@@ -41,46 +40,27 @@ export interface CreateNetworkFixtureArgs {
41
40
  skipAssetRequests?: boolean
42
41
  }
43
42
 
44
- /**
45
- * Creates a fixture that controls the network in your tests.
46
- *
47
- * @note The returned fixture already has the `auto` option set to `true`.
48
- *
49
- * **Usage**
50
- * ```ts
51
- * import { test as testBase } from '@playwright/test'
52
- * import { createNetworkFixture, type WorkerFixture } from '@msw/playwright'
53
- *
54
- * interface Fixtures {
55
- * network: WorkerFixture
56
- * }
57
- *
58
- * export const test = testBase.extend<Fixtures>({
59
- * network: createNetworkFixture()
60
- * })
61
- * ```
62
- */
63
- export function createNetworkFixture(
64
- args?: CreateNetworkFixtureArgs,
65
- ): [
66
- TestFixture<NetworkFixture, PlaywrightTestArgs & PlaywrightWorkerArgs>,
67
- { auto: boolean },
68
- ] {
69
- return [
70
- async ({ context }, use) => {
71
- const worker = new NetworkFixture({
72
- context,
73
- skipAssetRequests: args?.skipAssetRequests ?? true,
74
- initialHandlers: args?.initialHandlers || [],
75
- onUnhandledRequest: args?.onUnhandledRequest,
76
- })
43
+ export type NetworkFixture = Omit<SetupApi<LifeCycleEventsMap>, 'dispose'> & {
44
+ enable: () => Promise<void>
45
+ disable: () => Promise<void>
46
+ }
47
+
48
+ export function defineNetworkFixture(
49
+ options: NetworkFixtureOptions,
50
+ ): NetworkFixture {
51
+ return new SetupPlaywrightApi({
52
+ context: options.context,
53
+ initialHandlers: options.handlers || [],
54
+ onUnhandledRequest: options.onUnhandledRequest,
55
+ skipAssetRequests: options.skipAssetRequests ?? true,
56
+ })
57
+ }
77
58
 
78
- await worker.start()
79
- await use(worker)
80
- await worker.stop()
81
- },
82
- { auto: true },
83
- ]
59
+ interface SetupPlaywrightOptions {
60
+ context: BrowserContext
61
+ initialHandlers: Array<AnyHandler>
62
+ onUnhandledRequest?: UnhandledRequestStrategy
63
+ skipAssetRequests?: boolean
84
64
  }
85
65
 
86
66
  /**
@@ -91,21 +71,14 @@ export function createNetworkFixture(
91
71
  */
92
72
  export const INTERNAL_MATCH_ALL_REG_EXP = /.+(__MSW_PLAYWRIGHT_PREDICATE__)?/
93
73
 
94
- export class NetworkFixture extends SetupApi<LifeCycleEventsMap> {
95
- constructor(
96
- protected args: {
97
- context: BrowserContext
98
- skipAssetRequests: boolean
99
- initialHandlers: Array<RequestHandler | WebSocketHandler>
100
- onUnhandledRequest?: UnhandledRequestStrategy
101
- },
102
- ) {
103
- super(...args.initialHandlers)
74
+ class SetupPlaywrightApi extends SetupApi<LifeCycleEventsMap> {
75
+ constructor(private readonly options: SetupPlaywrightOptions) {
76
+ super(...options.initialHandlers)
104
77
  }
105
78
 
106
- public async start(): Promise<void> {
79
+ public async enable(): Promise<void> {
107
80
  // Handle HTTP requests.
108
- await this.args.context.route(
81
+ await this.options.context.route(
109
82
  INTERNAL_MATCH_ALL_REG_EXP,
110
83
  async (route: Route, request: PlaywrightRequest) => {
111
84
  const fetchRequest = new Request(request.url(), {
@@ -120,7 +93,10 @@ export class NetworkFixture extends SetupApi<LifeCycleEventsMap> {
120
93
  * requests through the matching logic below.
121
94
  * @see https://github.com/mswjs/playwright/issues/13
122
95
  */
123
- if (this.args.skipAssetRequests && isCommonAssetRequest(fetchRequest)) {
96
+ if (
97
+ this.options.skipAssetRequests &&
98
+ isCommonAssetRequest(fetchRequest)
99
+ ) {
124
100
  return route.continue()
125
101
  }
126
102
 
@@ -143,7 +119,7 @@ export class NetworkFixture extends SetupApi<LifeCycleEventsMap> {
143
119
  crypto.randomUUID(),
144
120
  handlers,
145
121
  {
146
- onUnhandledRequest: this.args.onUnhandledRequest || 'bypass',
122
+ onUnhandledRequest: this.options.onUnhandledRequest || 'bypass',
147
123
  },
148
124
  this.emitter,
149
125
  {
@@ -173,7 +149,7 @@ export class NetworkFixture extends SetupApi<LifeCycleEventsMap> {
173
149
  )
174
150
 
175
151
  // Handle WebSocket connections.
176
- await this.args.context.routeWebSocket(
152
+ await this.options.context.routeWebSocket(
177
153
  INTERNAL_MATCH_ALL_REG_EXP,
178
154
  async (route) => {
179
155
  const allWebSocketHandlers = this.handlersController
@@ -190,7 +166,7 @@ export class NetworkFixture extends SetupApi<LifeCycleEventsMap> {
190
166
  const client = new PlaywrightWebSocketClientConnection(route)
191
167
  const server = new PlaywrightWebSocketServerConnection(route)
192
168
 
193
- const pages = this.args.context.pages()
169
+ const pages = this.options.context.pages()
194
170
  const lastPage = pages[pages.length - 1]
195
171
  const baseUrl = lastPage ? this.getPageUrl(lastPage) : undefined
196
172
 
@@ -210,10 +186,10 @@ export class NetworkFixture extends SetupApi<LifeCycleEventsMap> {
210
186
  )
211
187
  }
212
188
 
213
- public async stop(): Promise<void> {
189
+ public async disable(): Promise<void> {
214
190
  super.dispose()
215
- await this.args.context.unroute(INTERNAL_MATCH_ALL_REG_EXP)
216
- await unrouteWebSocket(this.args.context, INTERNAL_MATCH_ALL_REG_EXP)
191
+ await this.options.context.unroute(INTERNAL_MATCH_ALL_REG_EXP)
192
+ await unrouteWebSocket(this.options.context, INTERNAL_MATCH_ALL_REG_EXP)
217
193
  }
218
194
 
219
195
  private getPageUrl(page: Page): string | undefined {
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export {
2
- type CreateNetworkFixtureArgs,
2
+ defineNetworkFixture,
3
3
  type NetworkFixture,
4
- createNetworkFixture,
4
+ type NetworkFixtureOptions,
5
5
  } from './fixture.js'