Skip to content

Commit 0c784e5

Browse files
ImLunaHeyNoamGaash
andauthored
feat: export advancedRouteFromHAR (#72)
Co-authored-by: Noam Gaash <[email protected]>
1 parent 564791b commit 0c784e5

File tree

3 files changed

+72
-58
lines changed

3 files changed

+72
-58
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.ts

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { test as base } from "@playwright/test";
1+
import { test as base, type Page } from "@playwright/test";
22
import * as fs from "fs";
33
import { AdvancedRouteFromHAR, requestResponseToEntry } from "./utils/types";
44
import { parseContent, serveFromHar } from "./utils/serveFromHar";
@@ -9,47 +9,53 @@ export { customMatcher } from "./utils/matchers/customMatcher";
99
export { parseContent } from "./utils/serveFromHar";
1010
import * as path from "path";
1111

12-
export const test = base.extend<{
13-
advancedRouteFromHAR: AdvancedRouteFromHAR;
14-
}>({
15-
advancedRouteFromHAR: async ({ page }, use) => {
16-
const originalRouteFromHAR = page.routeFromHAR.bind(page);
17-
const advancedRouteFromHAR: AdvancedRouteFromHAR = async (filename, options) => {
18-
if (options?.update) {
19-
const {matcher} = options;
20-
if (matcher && "postProcess" in matcher) {
21-
await page.route(options.url || /.*/, async (route, request) => {
22-
const resp = await route.fetch();
23-
const response = matcher.postProcess?.(await requestResponseToEntry(request, resp, await page.context().cookies())).response;
24-
if(response)
25-
route.fulfill({
26-
status: response.status,
27-
headers: Object.fromEntries(response.headers.map((header) => [header.name, header.value])),
28-
body: await parseContent(response.content, path.dirname(filename)),
29-
});
30-
});
31-
}
32-
// on update, we want to record the HAR just like the original playwright method
33-
return originalRouteFromHAR(filename, {
34-
url: options.url,
35-
update: true,
36-
updateContent: options?.updateContent,
37-
updateMode: options?.updateMode,
12+
export const advancedRouteFromHAR = async (
13+
{ page }: { page: Page },
14+
use: (fn: AdvancedRouteFromHAR) => Promise<void>,
15+
) => {
16+
const originalRouteFromHAR = page.routeFromHAR.bind(page);
17+
18+
await use(async (filename, options) => {
19+
if (options?.update) {
20+
const { matcher } = options;
21+
if (matcher && "postProcess" in matcher) {
22+
await page.route(options.url || /.*/, async (route, request) => {
23+
const resp = await route.fetch();
24+
const response = matcher.postProcess?.(
25+
await requestResponseToEntry(request, resp, await page.context().cookies()),
26+
).response;
27+
if (response)
28+
route.fulfill({
29+
status: response.status,
30+
headers: Object.fromEntries(response.headers.map((header) => [header.name, header.value])),
31+
body: await parseContent(response.content, path.dirname(filename)),
32+
});
3833
});
39-
} else {
40-
const har = JSON.parse(await fs.promises.readFile(filename, { encoding: "utf8" }));
41-
return serveFromHar(
42-
har,
43-
{
44-
...options,
45-
matcher: options?.matcher ?? defaultMatcher,
46-
dirName: path.dirname(filename),
47-
},
48-
page,
49-
);
5034
}
51-
};
35+
// on update, we want to record the HAR just like the original playwright method
36+
return originalRouteFromHAR(filename, {
37+
url: options.url,
38+
update: true,
39+
updateContent: options?.updateContent,
40+
updateMode: options?.updateMode,
41+
});
42+
} else {
43+
const har = JSON.parse(await fs.promises.readFile(filename, { encoding: "utf8" }));
44+
return serveFromHar(
45+
har,
46+
{
47+
...options,
48+
matcher: options?.matcher ?? defaultMatcher,
49+
dirName: path.dirname(filename),
50+
},
51+
page,
52+
);
53+
}
54+
});
55+
};
5256

53-
await use(advancedRouteFromHAR);
54-
},
57+
export const test = base.extend<{
58+
advancedRouteFromHAR: AdvancedRouteFromHAR;
59+
}>({
60+
advancedRouteFromHAR,
5561
});

tests/test.spec.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect } from "@playwright/test";
2-
import { defaultMatcher, test } from "../lib/index";
2+
import { defaultMatcher, test, advancedRouteFromHAR } from "../lib/index";
33
import fs from "fs";
44
import { parseContent } from "../lib/index";
55

@@ -8,6 +8,13 @@ test("sanity", async ({ page, advancedRouteFromHAR }) => {
88
await page.goto("https://demo.playwright.dev/todomvc");
99
});
1010

11+
test("sanity with import", async ({ page }) => {
12+
await advancedRouteFromHAR({ page }, async (r) => {
13+
await r("tests/har/demo-todo-app.har");
14+
});
15+
await page.goto("https://demo.playwright.dev/todomvc");
16+
});
17+
1118
test("sanity with option", async ({ page, advancedRouteFromHAR }) => {
1219
await advancedRouteFromHAR("tests/har/demo-todo-app.har", {
1320
update: false,
@@ -183,13 +190,12 @@ test("attached content", async ({ page, advancedRouteFromHAR }) => {
183190
await advancedRouteFromHAR("tests/har/temp/not-embedded.har", {
184191
matcher: async (request, entry) => {
185192
let content = await parseContent(entry.response.content, "tests/har/temp");
186-
if(typeof content === "object")
187-
content = content.toString();
188-
193+
if (typeof content === "object") content = content.toString();
194+
189195
expect(content).toBeTruthy();
190196
expect(content).toContain("category");
191197
return defaultMatcher(request, entry);
192-
}
198+
},
193199
});
194200
await page.goto("https://v2.jokeapi.dev/joke/Any?blacklistFlags=nsfw,religious,political,racist,sexist,explicit");
195201
});
@@ -202,24 +208,27 @@ test("test a joke recording with postprocess", async ({ page, advancedRouteFromH
202208
postProcess(entry) {
203209
entry.response.content.text = "This is a joke";
204210
return entry;
205-
}
206-
}
211+
},
212+
},
207213
});
208214
await page.goto("https://v2.jokeapi.dev/joke/Any?blacklistFlags=nsfw,religious,political,racist,sexist,explicit");
209215
await page.waitForSelector("text=This is a joke");
210216
await page.close();
211217
});
212218

213-
test("test a joke recording with different postprocess that was not recorded", async ({ page, advancedRouteFromHAR }) => {
219+
test("test a joke recording with different postprocess that was not recorded", async ({
220+
page,
221+
advancedRouteFromHAR,
222+
}) => {
214223
await advancedRouteFromHAR("tests/har/temp/joke-postprocess.har", {
215224
update: true,
216225
updateContent: "embed",
217226
matcher: {
218227
postProcess(entry) {
219228
entry.response.content.text = "This is not a joke";
220229
return entry;
221-
}
222-
}
230+
},
231+
},
223232
});
224233
await page.goto("https://v2.jokeapi.dev/joke/Any?blacklistFlags=nsfw,religious,political,racist,sexist,explicit");
225234
await page.waitForSelector("text=This is not a joke");
@@ -236,8 +245,8 @@ test("test a postprocess that change only part of the output", async ({ page, ad
236245
json.flags.custom = true;
237246
entry.response.content.text = JSON.stringify(json);
238247
return entry;
239-
}
240-
}
248+
},
249+
},
241250
});
242251
await page.goto("https://v2.jokeapi.dev/joke/Any?blacklistFlags=nsfw,religious,political,racist,sexist,explicit");
243252
const flags = await page.evaluate(() => {
@@ -261,4 +270,3 @@ test.fail("sensitive data file should not contain sensitive data", async () => {
261270
const data = await waitForFile("tests/har/temp/no-sensitive-data.har");
262271
expect(data).not.toContain("top secret");
263272
});
264-

0 commit comments

Comments
 (0)