@msw/playwright 0.3.1 → 0.4.1
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 +22 -8
- package/build/index.d.ts +24 -5
- package/build/index.js +27 -4
- package/package.json +1 -1
- package/src/index.ts +40 -7
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ await page.evaluate(() => {
|
|
|
13
13
|
// functions from the `msw` package you want to use since
|
|
14
14
|
// you cannot reference them in `page.evaluate` directly.
|
|
15
15
|
const { worker, http, graphql } = window.msw
|
|
16
|
-
worker.use(...)
|
|
16
|
+
worker.use(...overrides)
|
|
17
17
|
})
|
|
18
18
|
```
|
|
19
19
|
|
|
@@ -30,16 +30,16 @@ npm i msw @msw/playwright
|
|
|
30
30
|
```ts
|
|
31
31
|
// playwright.setup.ts
|
|
32
32
|
import { test as testBase } from '@playwright/test'
|
|
33
|
-
import {
|
|
33
|
+
import { createNetworkFixture, type NetworkFixture } from '@msw/playwright'
|
|
34
34
|
import { handlers } from '../mocks/handlers.js'
|
|
35
35
|
|
|
36
36
|
interface Fixtures {
|
|
37
|
-
|
|
37
|
+
network: NetworkFixture
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export const test = testBase.extend<Fixtures>({
|
|
41
|
-
// Create
|
|
42
|
-
|
|
41
|
+
// Create a fixture that will control the network in your tests.
|
|
42
|
+
network: createNetworkFixture({
|
|
43
43
|
initialHandlers: handlers,
|
|
44
44
|
}),
|
|
45
45
|
})
|
|
@@ -49,10 +49,10 @@ export const test = testBase.extend<Fixtures>({
|
|
|
49
49
|
import { http, HttpResponse } from 'msw'
|
|
50
50
|
import { test } from './playwright.setup.js'
|
|
51
51
|
|
|
52
|
-
test('displays the user dashboard', async ({
|
|
53
|
-
// Access and use
|
|
52
|
+
test('displays the user dashboard', async ({ network, page }) => {
|
|
53
|
+
// Access the network fixture and use it as the `setupWorker()` API.
|
|
54
54
|
// No more disrupted context between processes.
|
|
55
|
-
|
|
55
|
+
network.use(
|
|
56
56
|
http.get('/user', () => {
|
|
57
57
|
return HttpResponse.json({
|
|
58
58
|
id: 'abc-123',
|
|
@@ -65,3 +65,17 @@ test('displays the user dashboard', async ({ worker, page }) => {
|
|
|
65
65
|
await page.goto('/dashboard')
|
|
66
66
|
})
|
|
67
67
|
```
|
|
68
|
+
|
|
69
|
+
## Comparison
|
|
70
|
+
|
|
71
|
+
### `playwright-msw`
|
|
72
|
+
|
|
73
|
+
[`playwright-msw`](https://github.com/valendres/playwright-msw) is a community package that, just like `@msw/playwright`, aims to provide a better experience when mocking APIs in your Playwright tests.
|
|
74
|
+
|
|
75
|
+
> While `playwright-msw` is a fantastic tool and a huge inspiration for this package to exist, I believe it approaches the idea at a rather complex angle. That introduces a layer of abstraction that is subjected to the "left behind" problem as it needs to map to any MSW changes explicitly.
|
|
76
|
+
|
|
77
|
+
| | `playwright-msw` | `@msw/playwright` |
|
|
78
|
+
| -------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
79
|
+
| Initialization | `createWorkerFixture()` is used as a _part_ of your custom fixture. | `createNetworkFixture()` creates _the entire_ fixture for you, pre-configured. |
|
|
80
|
+
| Implementation | Uses a custom router to match handlers and a custom wrapper around `SetupWorker` API. | Uses MSW directly. Uses `page.route()` as the source of the network to route through the handlers. |
|
|
81
|
+
| Feature set | Supports `http` and `graphql` namespaces. | Supports all namespaces (`http`, `graphql`, `ws`, any other APIs exposed by MSW in the future). |
|
package/build/index.d.ts
CHANGED
|
@@ -1,14 +1,33 @@
|
|
|
1
1
|
import { LifeCycleEventsMap, RequestHandler, SetupApi, WebSocketHandler } from "msw";
|
|
2
|
-
import { Page, TestFixture } from "@playwright/test";
|
|
2
|
+
import { Page, PlaywrightTestArgs, PlaywrightWorkerArgs, TestFixture } from "@playwright/test";
|
|
3
3
|
|
|
4
4
|
//#region src/index.d.ts
|
|
5
|
-
interface
|
|
5
|
+
interface CreateNetworkFixtureArgs {
|
|
6
6
|
initialHandlers: Array<RequestHandler | WebSocketHandler>;
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Creates a fixture that controls the network in your tests.
|
|
10
|
+
*
|
|
11
|
+
* @note The returned fixture already has the `auto` option set to `true`.
|
|
12
|
+
*
|
|
13
|
+
* **Usage**
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { test as testBase } from '@playwright/test'
|
|
16
|
+
* import { createNetworkFixture, type WorkerFixture } from '@msw/playwright'
|
|
17
|
+
*
|
|
18
|
+
* interface Fixtures {
|
|
19
|
+
* network: WorkerFixture
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* export const test = testBase.extend<Fixtures>({
|
|
23
|
+
* network: createNetworkFixture()
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
declare function createNetworkFixture(args?: CreateNetworkFixtureArgs): [TestFixture<NetworkFixture, PlaywrightTestArgs & PlaywrightWorkerArgs>, {
|
|
9
28
|
auto: boolean;
|
|
10
29
|
}];
|
|
11
|
-
declare class
|
|
30
|
+
declare class NetworkFixture extends SetupApi<LifeCycleEventsMap> {
|
|
12
31
|
#private;
|
|
13
32
|
constructor(args: {
|
|
14
33
|
page: Page;
|
|
@@ -18,4 +37,4 @@ declare class WorkerFixture extends SetupApi<LifeCycleEventsMap> {
|
|
|
18
37
|
stop(): Promise<void>;
|
|
19
38
|
}
|
|
20
39
|
//#endregion
|
|
21
|
-
export {
|
|
40
|
+
export { CreateNetworkFixtureArgs, NetworkFixture, createNetworkFixture };
|
package/build/index.js
CHANGED
|
@@ -3,9 +3,28 @@ import { RequestHandler, SetupApi, WebSocketHandler, getResponse } from "msw";
|
|
|
3
3
|
import { CancelableCloseEvent, CancelableMessageEvent } from "@mswjs/interceptors/WebSocket";
|
|
4
4
|
|
|
5
5
|
//#region src/index.ts
|
|
6
|
-
|
|
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) {
|
|
7
26
|
return [async ({ page }, use) => {
|
|
8
|
-
const worker = new
|
|
27
|
+
const worker = new NetworkFixture({
|
|
9
28
|
page,
|
|
10
29
|
initialHandlers: args?.initialHandlers || []
|
|
11
30
|
});
|
|
@@ -14,7 +33,7 @@ function createWorkerFixture(args) {
|
|
|
14
33
|
await worker.stop();
|
|
15
34
|
}, { auto: true }];
|
|
16
35
|
}
|
|
17
|
-
var
|
|
36
|
+
var NetworkFixture = class extends SetupApi {
|
|
18
37
|
#page;
|
|
19
38
|
constructor(args) {
|
|
20
39
|
super(...args.initialHandlers);
|
|
@@ -31,6 +50,10 @@ var WorkerFixture = class extends SetupApi {
|
|
|
31
50
|
return handler instanceof RequestHandler;
|
|
32
51
|
}), fetchRequest);
|
|
33
52
|
if (response) {
|
|
53
|
+
if (response.status === 0) {
|
|
54
|
+
route.abort();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
34
57
|
route.fulfill({
|
|
35
58
|
status: response.status,
|
|
36
59
|
headers: Object.fromEntries(response.headers),
|
|
@@ -203,4 +226,4 @@ var PlaywrightWebSocketServerConnection = class {
|
|
|
203
226
|
};
|
|
204
227
|
|
|
205
228
|
//#endregion
|
|
206
|
-
export {
|
|
229
|
+
export { NetworkFixture, createNetworkFixture };
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { invariant } from 'outvariant'
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
Page,
|
|
4
|
+
PlaywrightTestArgs,
|
|
5
|
+
PlaywrightWorkerArgs,
|
|
6
|
+
TestFixture,
|
|
7
|
+
WebSocketRoute,
|
|
8
|
+
} from '@playwright/test'
|
|
3
9
|
import {
|
|
4
10
|
type LifeCycleEventsMap,
|
|
5
11
|
SetupApi,
|
|
@@ -17,17 +23,39 @@ import {
|
|
|
17
23
|
WebSocketServerConnectionProtocol,
|
|
18
24
|
} from '@mswjs/interceptors/WebSocket'
|
|
19
25
|
|
|
20
|
-
export interface
|
|
26
|
+
export interface CreateNetworkFixtureArgs {
|
|
21
27
|
initialHandlers: Array<RequestHandler | WebSocketHandler>
|
|
22
28
|
}
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Creates a fixture that controls the network in your tests.
|
|
32
|
+
*
|
|
33
|
+
* @note The returned fixture already has the `auto` option set to `true`.
|
|
34
|
+
*
|
|
35
|
+
* **Usage**
|
|
36
|
+
* ```ts
|
|
37
|
+
* import { test as testBase } from '@playwright/test'
|
|
38
|
+
* import { createNetworkFixture, type WorkerFixture } from '@msw/playwright'
|
|
39
|
+
*
|
|
40
|
+
* interface Fixtures {
|
|
41
|
+
* network: WorkerFixture
|
|
42
|
+
* }
|
|
43
|
+
*
|
|
44
|
+
* export const test = testBase.extend<Fixtures>({
|
|
45
|
+
* network: createNetworkFixture()
|
|
46
|
+
* })
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function createNetworkFixture(
|
|
50
|
+
args?: CreateNetworkFixtureArgs,
|
|
26
51
|
/** @todo `onUnhandledRequest`? */
|
|
27
|
-
): [
|
|
52
|
+
): [
|
|
53
|
+
TestFixture<NetworkFixture, PlaywrightTestArgs & PlaywrightWorkerArgs>,
|
|
54
|
+
{ auto: boolean },
|
|
55
|
+
] {
|
|
28
56
|
return [
|
|
29
57
|
async ({ page }, use) => {
|
|
30
|
-
const worker = new
|
|
58
|
+
const worker = new NetworkFixture({
|
|
31
59
|
page,
|
|
32
60
|
initialHandlers: args?.initialHandlers || [],
|
|
33
61
|
})
|
|
@@ -40,7 +68,7 @@ export function createWorkerFixture(
|
|
|
40
68
|
]
|
|
41
69
|
}
|
|
42
70
|
|
|
43
|
-
export class
|
|
71
|
+
export class NetworkFixture extends SetupApi<LifeCycleEventsMap> {
|
|
44
72
|
#page: Page
|
|
45
73
|
|
|
46
74
|
constructor(args: {
|
|
@@ -68,6 +96,11 @@ export class WorkerFixture extends SetupApi<LifeCycleEventsMap> {
|
|
|
68
96
|
)
|
|
69
97
|
|
|
70
98
|
if (response) {
|
|
99
|
+
if (response.status === 0) {
|
|
100
|
+
route.abort()
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
71
104
|
route.fulfill({
|
|
72
105
|
status: response.status,
|
|
73
106
|
headers: Object.fromEntries(response.headers),
|