playwright-write-guard 0.2.0 → 0.3.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 +256 -68
- package/bin/suggest.mjs +56 -0
- package/package.json +3 -2
- package/src/core.mjs +40 -0
- package/src/fixture.mjs +68 -29
- package/src/install.mjs +327 -64
- package/types/core.d.ts +59 -1
- package/types/install.d.ts +59 -8
package/types/install.d.ts
CHANGED
|
@@ -1,26 +1,40 @@
|
|
|
1
1
|
// playwright-write-guard/install: the installer every entry point shares.
|
|
2
2
|
|
|
3
|
-
import type { BrowserContext } from 'playwright-core';
|
|
3
|
+
import type { APIRequestContext, BrowserContext } from 'playwright-core';
|
|
4
4
|
import type { Config, Policy } from './core.js';
|
|
5
5
|
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* A request the guard judged: a write it blocked or observed (`block`, `observe`), a write a
|
|
8
|
+
* caller's route fulfilled or aborted (`mocked`), or an allowed GET or HEAD that looks side
|
|
9
|
+
* effecting (`suspect`). Also a WebSocket refused under `websockets: "block"` (`block`, no `method`).
|
|
10
|
+
*/
|
|
7
11
|
export interface RequestEvent {
|
|
8
12
|
kind: 'request';
|
|
9
|
-
action: 'block' | 'observe';
|
|
13
|
+
action: 'block' | 'observe' | 'mocked' | 'suspect';
|
|
10
14
|
reason: string;
|
|
11
15
|
/** The effective method, upper case. Absent for a refused WebSocket. */
|
|
12
16
|
method?: string;
|
|
13
17
|
/** The effective URL, or the refused WebSocket's URL. */
|
|
14
18
|
url: string;
|
|
19
|
+
/**
|
|
20
|
+
* Present only for a send through a request client: `"request-client"` for an
|
|
21
|
+
* `APIRequestContext`, `"node-fetch"` for Node's `fetch`. Absent for a browser request.
|
|
22
|
+
*/
|
|
23
|
+
via?: 'request-client' | 'node-fetch';
|
|
15
24
|
/** The effective `content-type` header, when the request has one. */
|
|
16
25
|
contentType?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Present whenever `method` is: the effective request's header names, lower case, unique,
|
|
28
|
+
* sorted with `Array.prototype.sort`. Never the values. `[]` when it has no headers.
|
|
29
|
+
*/
|
|
30
|
+
headerNames?: string[];
|
|
17
31
|
/** Only with `logBodies: true`: the first 500 characters of the effective body, when the request has one. */
|
|
18
32
|
body?: string;
|
|
19
33
|
/** ISO 8601 timestamp. */
|
|
20
34
|
at: string;
|
|
21
35
|
}
|
|
22
36
|
|
|
23
|
-
/** A destructive control the page blocked or observed. */
|
|
37
|
+
/** A destructive control, or a suspect navigating link, the page blocked or observed. */
|
|
24
38
|
export interface ControlEvent {
|
|
25
39
|
kind: 'control';
|
|
26
40
|
action: 'block' | 'observe';
|
|
@@ -32,7 +46,7 @@ export interface ControlEvent {
|
|
|
32
46
|
}
|
|
33
47
|
|
|
34
48
|
/** A WebSocket opened under `websockets: "allow"`. Counts in neither `blocked` nor `observed`. */
|
|
35
|
-
export interface
|
|
49
|
+
export interface WebSocketOpenEvent {
|
|
36
50
|
kind: 'websocket';
|
|
37
51
|
action: 'open';
|
|
38
52
|
url: string;
|
|
@@ -40,18 +54,40 @@ export interface WebSocketEvent {
|
|
|
40
54
|
at: string;
|
|
41
55
|
}
|
|
42
56
|
|
|
57
|
+
/**
|
|
58
|
+
* An outbound WebSocket text frame matching `websocketWrites`: dropped (`block`, read-only)
|
|
59
|
+
* or forwarded (`observe`, observe). Counts in `blocked` or `observed`.
|
|
60
|
+
*/
|
|
61
|
+
export interface WebSocketFrameEvent {
|
|
62
|
+
kind: 'websocket';
|
|
63
|
+
action: 'block' | 'observe';
|
|
64
|
+
reason: string;
|
|
65
|
+
/** The socket's URL. */
|
|
66
|
+
url: string;
|
|
67
|
+
/** Only with `logBodies: true`: the first 500 characters of the frame. */
|
|
68
|
+
frame?: string;
|
|
69
|
+
/** ISO 8601 timestamp. */
|
|
70
|
+
at: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type WebSocketEvent = WebSocketOpenEvent | WebSocketFrameEvent;
|
|
74
|
+
|
|
43
75
|
/** One event the guard recorded. */
|
|
44
76
|
export type GuardEvent = RequestEvent | ControlEvent | WebSocketEvent;
|
|
45
77
|
|
|
46
78
|
export interface GuardRecord {
|
|
47
79
|
installed: true;
|
|
48
80
|
policy: Policy;
|
|
49
|
-
/** Requests the guard judged at egress, each counted once, at its first egress. WebSockets
|
|
81
|
+
/** Requests the guard judged at browser egress, each counted once, at its first egress. No WebSockets, mocks or request-client sends. */
|
|
50
82
|
routed_requests: number;
|
|
51
|
-
/** Request and
|
|
83
|
+
/** Request, control and websocket events with `action: "block"`. */
|
|
52
84
|
blocked: number;
|
|
53
|
-
/** Request and
|
|
85
|
+
/** Request, control and websocket events with `action: "observe"`. */
|
|
54
86
|
observed: number;
|
|
87
|
+
/** Request events with `action: "mocked"`. */
|
|
88
|
+
mocked: number;
|
|
89
|
+
/** Request events with `action: "suspect"`. */
|
|
90
|
+
suspect: number;
|
|
55
91
|
events: GuardEvent[];
|
|
56
92
|
}
|
|
57
93
|
|
|
@@ -60,6 +96,21 @@ export interface GuardHandle {
|
|
|
60
96
|
record(): GuardRecord;
|
|
61
97
|
/** Resolves after the last pending log append with the final record. The guard stays active until the context closes. */
|
|
62
98
|
close(): Promise<GuardRecord>;
|
|
99
|
+
/**
|
|
100
|
+
* A proxy over `client` whose sends (`fetch`, `get`, `post`, `put`, `patch`, `delete`,
|
|
101
|
+
* `head`) are judged with this guard's config and recorded here with
|
|
102
|
+
* `via: "request-client"`; a blocked send rejects with
|
|
103
|
+
* `write-guard: <METHOD> <URL> through APIRequestContext is refused under read-only`.
|
|
104
|
+
* Relative URLs resolve against `baseURL` when given. Every property that is not a send method reads through, with methods bound to the raw client.
|
|
105
|
+
*/
|
|
106
|
+
guardRequestClient<T extends APIRequestContext>(client: T, options?: { baseURL?: string }): T;
|
|
107
|
+
/**
|
|
108
|
+
* A function with `fetchFn`'s signature that judges each call with this guard's config,
|
|
109
|
+
* records it here with `via: "node-fetch"`, and either rejects with
|
|
110
|
+
* `write-guard: <METHOD> <URL> through fetch is refused under read-only` or returns
|
|
111
|
+
* `fetchFn(input, init)` with the same arguments.
|
|
112
|
+
*/
|
|
113
|
+
guardFetch<F extends (input: any, init?: any) => Promise<any>>(fetchFn: F): F;
|
|
63
114
|
}
|
|
64
115
|
|
|
65
116
|
/**
|