-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPlaywrightAdapter.ts
126 lines (110 loc) · 3.34 KB
/
PlaywrightAdapter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import PollyAdapter from "@pollyjs/adapter";
import type { Request, Route } from "playwright-core";
import type {
PlaywrightAdapterOptions,
PollyRequest,
PollyResponse,
} from "./types";
export class PlaywrightAdapter extends PollyAdapter<
Partial<PlaywrightAdapterOptions>
> {
public static get id() {
return "playwright";
}
public static get defaultOptions() {
return {
handleFailingRequest: (route: Route) => route.abort(),
modifyResponse: (response: PollyResponse) => ({
...response,
headers: { ...response.headers, "access-control-allow-origin": "*" },
}),
routesToIntercept: "**/*",
shouldHandleRequest: (request: Request) =>
["fetch", "xhr"].includes(request.resourceType()),
};
}
// @ts-expect-error polly.js needs this
public get defaultOptions() {
return PlaywrightAdapter.defaultOptions;
}
public readonly options!: Required<PlaywrightAdapterOptions>;
public onConnect() {
return this.options.context.route(
this.options.routesToIntercept,
this.handleRoute,
);
}
public async onDisconnect() {
try {
return await this.options.context.unroute(
this.options.routesToIntercept,
this.handleRoute,
);
} catch (e) {
// ignore errors
return undefined;
}
}
public async onFetchResponse(pollyRequest: PollyRequest) {
const { request } = pollyRequest.requestArguments;
const response = await this.options.context.request.fetch(request);
const body = await response.body();
return {
statusCode: response.status(),
headers: response.headers(),
...(this.isBufferUtf8Representable(body)
? {
body: body.toString("utf8"),
encoding: "utf8",
}
: {
body: body.toString("base64"),
encoding: "base64",
}),
};
}
public async onRespond(pollyRequest: PollyRequest, error: Error) {
const {
requestArguments: { request, route },
response,
} = pollyRequest;
if (error) {
return this.options.handleFailingRequest(route, pollyRequest, error);
}
let body: Buffer | string | undefined;
if (response?.body) {
body = this.isBufferUtf8Representable(Buffer.from(response.body, "utf8"))
? response.body
: Buffer.from(response.body, "base64");
}
return route.fulfill(
await this.options.modifyResponse(
{
status: response?.statusCode,
headers: response?.headers,
body,
},
request,
),
);
}
private handleRoute = async (route: Route, request: Request) => {
if (await this.options.shouldHandleRequest(request)) {
this.handleRequest({
url: request.url(),
method: request.method(),
headers: await request.allHeaders(),
body: request.postData() ?? undefined,
requestArguments: { route, request },
});
} else {
route.continue();
}
};
// https://github.com/Netflix/pollyjs/blob/9f4179a76d4c09f26c4cd21683bf00ac3f99ac59/packages/@pollyjs/utils/src/utils/is-buffer-utf8-representable.js
private isBufferUtf8Representable(buffer: Buffer) {
const utfEncodedBuffer = buffer.toString("utf8");
const reconstructedBuffer = Buffer.from(utfEncodedBuffer, "utf8");
return reconstructedBuffer.equals(buffer);
}
}