@itmetsam/samurai-framework 0.1.0 → 0.2.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 +129 -0
- package/bin/samurai.mjs +31 -0
- package/dist/api.js +3 -0
- package/dist/assert/assertion-error.d.ts +23 -0
- package/dist/assert/assertion-error.js +45 -0
- package/dist/assert/expect.d.ts +55 -0
- package/dist/assert/expect.js +188 -0
- package/dist/browser/browser-context.d.ts +91 -0
- package/dist/browser/browser-context.js +146 -0
- package/dist/browser/browser-finder.d.ts +2 -0
- package/dist/browser/browser-finder.js +95 -0
- package/dist/browser/browser.d.ts +95 -0
- package/dist/browser/browser.js +372 -0
- package/dist/browser/context-tree.d.ts +23 -0
- package/dist/browser/context-tree.js +60 -0
- package/dist/browser/dialog.d.ts +37 -0
- package/dist/browser/dialog.js +61 -0
- package/dist/browser/download.d.ts +71 -0
- package/dist/browser/download.js +137 -0
- package/dist/browser/downloads-dir.d.ts +8 -0
- package/dist/browser/downloads-dir.js +38 -0
- package/dist/browser/emulation.d.ts +61 -0
- package/dist/browser/emulation.js +144 -0
- package/dist/browser/file-chooser.d.ts +39 -0
- package/dist/browser/file-chooser.js +86 -0
- package/dist/browser/file-paths.d.ts +4 -0
- package/dist/browser/file-paths.js +18 -0
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.js +4 -0
- package/dist/browser/navigation-error.d.ts +13 -0
- package/dist/browser/navigation-error.js +19 -0
- package/dist/browser/page-logs.d.ts +86 -0
- package/dist/browser/page-logs.js +149 -0
- package/dist/browser/page-wait.d.ts +9 -0
- package/dist/browser/page-wait.js +17 -0
- package/dist/browser/page.d.ts +370 -0
- package/dist/browser/page.js +1038 -0
- package/dist/browser/pdf.d.ts +72 -0
- package/dist/browser/pdf.js +37 -0
- package/dist/browser/screenshot.d.ts +29 -0
- package/dist/browser/screenshot.js +42 -0
- package/dist/cli/args.d.ts +35 -0
- package/dist/cli/args.js +69 -0
- package/dist/cli/cli.cli-test.d.ts +1 -0
- package/dist/cli/cli.cli-test.js +170 -0
- package/dist/cli/console-reporter.d.ts +15 -0
- package/dist/cli/console-reporter.js +52 -0
- package/dist/cli/init.d.ts +7 -0
- package/dist/cli/init.js +61 -0
- package/dist/cli/main.d.ts +12 -0
- package/dist/cli/main.js +156 -0
- package/dist/config/config.d.ts +24 -0
- package/dist/config/config.js +42 -0
- package/dist/config/default.d.ts +2 -0
- package/dist/config/default.js +3 -0
- package/dist/config/mask.d.ts +11 -0
- package/dist/config/mask.js +85 -0
- package/dist/config/run-settings.d.ts +28 -0
- package/dist/config/run-settings.js +61 -0
- package/dist/config/secrets.d.ts +10 -0
- package/dist/config/secrets.js +67 -0
- package/dist/config/variables.d.ts +11 -0
- package/dist/config/variables.js +26 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -0
- package/dist/locator/action-timeout-error.d.ts +25 -0
- package/dist/locator/action-timeout-error.js +35 -0
- package/dist/locator/element-state.d.ts +44 -0
- package/dist/locator/element-state.js +109 -0
- package/dist/locator/label-locator.d.ts +13 -0
- package/dist/locator/label-locator.js +49 -0
- package/dist/locator/locator.d.ts +168 -0
- package/dist/locator/locator.js +591 -0
- package/dist/locator/selector-errors.d.ts +9 -0
- package/dist/locator/selector-errors.js +15 -0
- package/dist/locator/selector.d.ts +60 -0
- package/dist/locator/selector.js +113 -0
- package/dist/locator/text-locator.d.ts +13 -0
- package/dist/logger/index.d.ts +2 -0
- package/dist/logger/index.js +30 -0
- package/dist/network/data-collector.d.ts +26 -0
- package/dist/network/data-collector.js +77 -0
- package/dist/network/network-tracker.d.ts +94 -0
- package/dist/network/network-tracker.js +198 -0
- package/dist/network/network-wait.d.ts +16 -0
- package/dist/network/network-wait.js +24 -0
- package/dist/network/response.d.ts +22 -0
- package/dist/network/response.js +42 -0
- package/dist/network/router.d.ts +120 -0
- package/dist/network/router.js +343 -0
- package/dist/network/url-match.d.ts +8 -0
- package/dist/network/url-match.js +38 -0
- package/dist/recorder/apply.d.ts +3 -0
- package/dist/recorder/apply.js +10 -0
- package/dist/recorder/capture.d.ts +18 -0
- package/dist/recorder/capture.js +198 -0
- package/dist/recorder/index.d.ts +3 -0
- package/dist/recorder/index.js +3 -0
- package/dist/recorder/normalise.d.ts +68 -0
- package/dist/recorder/normalise.js +104 -0
- package/dist/recorder/ranking.d.ts +9 -0
- package/dist/recorder/ranking.js +21 -0
- package/dist/recorder/recorder.d.ts +52 -0
- package/dist/recorder/recorder.js +143 -0
- package/dist/recorder/session.d.ts +49 -0
- package/dist/recorder/session.js +113 -0
- package/dist/runner/module-type.d.ts +6 -0
- package/dist/runner/module-type.js +29 -0
- package/dist/runner/page-logs-report.d.ts +40 -0
- package/dist/runner/page-logs-report.js +44 -0
- package/dist/runner/prepare-run.d.ts +14 -0
- package/dist/runner/prepare-run.js +20 -0
- package/dist/runner/project.d.ts +17 -0
- package/dist/runner/project.js +33 -0
- package/dist/runner/registry.d.ts +7 -0
- package/dist/runner/registry.js +40 -0
- package/dist/runner/reporter.d.ts +43 -0
- package/dist/runner/reporter.js +83 -0
- package/dist/runner/run.d.ts +27 -0
- package/dist/runner/run.js +34 -0
- package/dist/runner/test-error.d.ts +3 -0
- package/dist/runner/test-error.js +18 -0
- package/dist/runner/test-runner.d.ts +44 -0
- package/dist/runner/test-runner.js +205 -0
- package/dist/script/call-function.d.ts +34 -0
- package/dist/script/call-function.js +71 -0
- package/dist/script/element-handle.d.ts +10 -0
- package/{src/script/element-handle.ts → dist/script/element-handle.js} +4 -4
- package/dist/script/helpers.d.ts +28 -0
- package/dist/script/helpers.js +50 -0
- package/dist/script/preload.d.ts +31 -0
- package/dist/script/preload.js +71 -0
- package/dist/script/serialize.d.ts +29 -0
- package/dist/script/serialize.js +207 -0
- package/dist/steps/build.d.ts +5 -0
- package/dist/steps/build.js +38 -0
- package/dist/steps/edit.d.ts +30 -0
- package/dist/steps/edit.js +80 -0
- package/dist/steps/emit.d.ts +6 -0
- package/dist/steps/emit.js +73 -0
- package/dist/steps/index.d.ts +5 -0
- package/dist/steps/index.js +4 -0
- package/dist/steps/model.d.ts +103 -0
- package/dist/steps/model.js +1 -0
- package/dist/steps/parse.d.ts +3 -0
- package/dist/steps/parse.js +272 -0
- package/dist/transport/bidi-connection.d.ts +46 -0
- package/dist/transport/bidi-connection.js +176 -0
- package/dist/transport/bidi-error.d.ts +10 -0
- package/dist/transport/bidi-error.js +10 -0
- package/dist/transport/subscriptions.d.ts +36 -0
- package/dist/transport/subscriptions.js +81 -0
- package/{src → dist}/types/test.d.ts +10 -4
- package/dist/wait/wait-until.d.ts +20 -0
- package/dist/wait/wait-until.js +63 -0
- package/package.json +44 -7
- package/.claude/settings.local.json +0 -7
- package/.env.example +0 -3
- package/.github/actions/setup/action.yml +0 -16
- package/.github/workflows/ci.yml +0 -71
- package/.trunk/configs/.markdownlint.yaml +0 -2
- package/.trunk/configs/.yamllint.yaml +0 -7
- package/.trunk/configs/svgo.config.mjs +0 -14
- package/.trunk/trunk.yaml +0 -34
- package/docs/superpowers/bidi-roadmap.md +0 -60
- package/docs/superpowers/plans/2026-09-29-auto-wait.md +0 -1827
- package/docs/superpowers/plans/2026-09-29-expect.md +0 -1350
- package/docs/superpowers/plans/2026-10-01-ci.md +0 -350
- package/docs/superpowers/plans/2026-10-01-test-api-alignment.md +0 -1821
- package/docs/superpowers/recorder-roadmap.md +0 -52
- package/docs/superpowers/specs/2026-09-29-auto-wait-design.md +0 -185
- package/docs/superpowers/specs/2026-09-29-bidi-foundation-design.md +0 -130
- package/docs/superpowers/specs/2026-09-29-contexts-and-storage-design.md +0 -88
- package/docs/superpowers/specs/2026-09-29-downloads-and-file-dialogs-design.md +0 -94
- package/docs/superpowers/specs/2026-09-29-emulation-design.md +0 -88
- package/docs/superpowers/specs/2026-09-29-expect-design.md +0 -130
- package/docs/superpowers/specs/2026-09-29-locate-nodes-design.md +0 -90
- package/docs/superpowers/specs/2026-09-29-logs-and-errors-design.md +0 -87
- package/docs/superpowers/specs/2026-09-29-navigation-waits-design.md +0 -83
- package/docs/superpowers/specs/2026-09-29-network-data-design.md +0 -78
- package/docs/superpowers/specs/2026-09-29-network-interception-design.md +0 -91
- package/docs/superpowers/specs/2026-09-29-network-tracking-design.md +0 -86
- package/docs/superpowers/specs/2026-09-29-page-api-design.md +0 -90
- package/docs/superpowers/specs/2026-09-29-preload-scripts-design.md +0 -82
- package/docs/superpowers/specs/2026-09-29-script-call-function-design.md +0 -107
- package/docs/superpowers/specs/2026-09-29-set-files-design.md +0 -62
- package/docs/superpowers/specs/2026-09-29-user-prompts-design.md +0 -75
- package/docs/superpowers/specs/2026-10-01-ci-design.md +0 -106
- package/docs/superpowers/specs/2026-10-01-test-api-alignment-design.md +0 -241
- package/public/logo-dark.svg +0 -236
- package/public/logo-light.svg +0 -262
- package/samurai.config.ts +0 -7
- package/src/assert/assertion-error.test.ts +0 -55
- package/src/assert/assertion-error.ts +0 -62
- package/src/assert/expect-locator.test.ts +0 -217
- package/src/assert/expect.test.ts +0 -73
- package/src/assert/expect.ts +0 -299
- package/src/browser/browser-context.browser-test.ts +0 -201
- package/src/browser/browser-context.test.ts +0 -407
- package/src/browser/browser-context.ts +0 -208
- package/src/browser/browser-finder.ts +0 -110
- package/src/browser/browser.test.ts +0 -88
- package/src/browser/browser.ts +0 -515
- package/src/browser/context-tree.test.ts +0 -86
- package/src/browser/context-tree.ts +0 -70
- package/src/browser/dialog.browser-test.ts +0 -144
- package/src/browser/dialog.test.ts +0 -322
- package/src/browser/dialog.ts +0 -83
- package/src/browser/download.test.ts +0 -161
- package/src/browser/download.ts +0 -172
- package/src/browser/downloads-dir.test.ts +0 -75
- package/src/browser/downloads-dir.ts +0 -39
- package/src/browser/emulation.browser-test.ts +0 -186
- package/src/browser/emulation.test.ts +0 -200
- package/src/browser/emulation.ts +0 -204
- package/src/browser/file-chooser.test.ts +0 -142
- package/src/browser/file-chooser.ts +0 -99
- package/src/browser/file-paths.ts +0 -18
- package/src/browser/goto.browser-test.ts +0 -44
- package/src/browser/navigation-error.ts +0 -26
- package/src/browser/navigation.browser-test.ts +0 -172
- package/src/browser/page-api.browser-test.ts +0 -228
- package/src/browser/page-logs.browser-test.ts +0 -119
- package/src/browser/page-logs.test.ts +0 -212
- package/src/browser/page-logs.ts +0 -208
- package/src/browser/page-wait.ts +0 -19
- package/src/browser/page.test.ts +0 -1567
- package/src/browser/page.ts +0 -1176
- package/src/browser/pdf.ts +0 -62
- package/src/browser/screenshot.ts +0 -65
- package/src/browser/transfers.browser-test.ts +0 -180
- package/src/config/config.ts +0 -33
- package/src/config/default.ts +0 -5
- package/src/config/fixtures.test.ts +0 -137
- package/src/config/mask.test.ts +0 -143
- package/src/config/mask.ts +0 -87
- package/src/config/run-settings.test.ts +0 -163
- package/src/config/run-settings.ts +0 -114
- package/src/config/secrets.ts +0 -70
- package/src/config/variables.ts +0 -31
- package/src/index.ts +0 -10
- package/src/locator/action-timeout-error.test.ts +0 -83
- package/src/locator/action-timeout-error.ts +0 -72
- package/src/locator/element-state.test.ts +0 -181
- package/src/locator/element-state.ts +0 -159
- package/src/locator/locate-nodes.browser-test.ts +0 -169
- package/src/locator/locator-actions.test.ts +0 -355
- package/src/locator/locator-chain.test.ts +0 -292
- package/src/locator/locator.browser-test.ts +0 -137
- package/src/locator/locator.test.ts +0 -179
- package/src/locator/locator.ts +0 -656
- package/src/locator/selector-errors.ts +0 -18
- package/src/locator/selector.test.ts +0 -124
- package/src/locator/selector.ts +0 -107
- package/src/locator/set-files.browser-test.ts +0 -141
- package/src/locator/set-files.test.ts +0 -191
- package/src/locator/text-locator.test.ts +0 -118
- package/src/logger/index.test.ts +0 -28
- package/src/logger/index.ts +0 -40
- package/src/network/data-collector.test.ts +0 -111
- package/src/network/data-collector.ts +0 -92
- package/src/network/network-data.browser-test.ts +0 -192
- package/src/network/network-tracker.browser-test.ts +0 -151
- package/src/network/network-tracker.test.ts +0 -307
- package/src/network/network-tracker.ts +0 -286
- package/src/network/network-wait.ts +0 -28
- package/src/network/response.test.ts +0 -93
- package/src/network/response.ts +0 -58
- package/src/network/router.browser-test.ts +0 -260
- package/src/network/router.test.ts +0 -528
- package/src/network/router.ts +0 -420
- package/src/network/url-match.test.ts +0 -69
- package/src/network/url-match.ts +0 -41
- package/src/runner/page-logs-report.test.ts +0 -144
- package/src/runner/page-logs-report.ts +0 -82
- package/src/runner/prepare-run.test.ts +0 -33
- package/src/runner/prepare-run.ts +0 -36
- package/src/runner/registry.test.ts +0 -59
- package/src/runner/registry.ts +0 -46
- package/src/runner/reporter.test.ts +0 -73
- package/src/runner/reporter.ts +0 -109
- package/src/runner/test-error.test.ts +0 -39
- package/src/runner/test-error.ts +0 -20
- package/src/runner/test-runner.ts +0 -184
- package/src/script/call-function.browser-test.ts +0 -112
- package/src/script/call-function.test.ts +0 -174
- package/src/script/call-function.ts +0 -113
- package/src/script/helpers.test.ts +0 -116
- package/src/script/helpers.ts +0 -68
- package/src/script/preload.browser-test.ts +0 -144
- package/src/script/preload.test.ts +0 -180
- package/src/script/preload.ts +0 -102
- package/src/script/serialize.test.ts +0 -182
- package/src/script/serialize.ts +0 -203
- package/src/testing/browser-fixture.ts +0 -18
- package/src/testing/fake-websocket.ts +0 -72
- package/src/testing/stub-connector.ts +0 -154
- package/src/tests/index.spec.ts +0 -30
- package/src/transport/bidi-connection.test.ts +0 -155
- package/src/transport/bidi-connection.ts +0 -256
- package/src/transport/bidi-error.ts +0 -23
- package/src/transport/foundation.browser-test.ts +0 -73
- package/src/transport/subscriptions.test.ts +0 -140
- package/src/transport/subscriptions.ts +0 -110
- package/src/types/bidi-commands.test-d.ts +0 -55
- package/src/wait/wait-until.test.ts +0 -117
- package/src/wait/wait-until.ts +0 -86
- package/tsconfig.json +0 -44
- /package/{src/api.ts → dist/api.d.ts} +0 -0
- /package/{src/locator/text-locator.ts → dist/locator/text-locator.js} +0 -0
- /package/{src → dist}/types/bidi-modules/browser.d.ts +0 -0
- /package/{src → dist}/types/bidi-modules/browsing-context.d.ts +0 -0
- /package/{src → dist}/types/bidi-modules/emulation.d.ts +0 -0
- /package/{src → dist}/types/bidi-modules/input.d.ts +0 -0
- /package/{src → dist}/types/bidi-modules/log.d.ts +0 -0
- /package/{src → dist}/types/bidi-modules/network.d.ts +0 -0
- /package/{src → dist}/types/bidi-modules/permissions.d.ts +0 -0
- /package/{src → dist}/types/bidi-modules/script.d.ts +0 -0
- /package/{src → dist}/types/bidi-modules/session.d.ts +0 -0
- /package/{src → dist}/types/bidi-modules/storage.d.ts +0 -0
- /package/{src → dist}/types/bidi-modules/web-extensions.d.ts +0 -0
- /package/{src → dist}/types/bidi-protocols/command.d.ts +0 -0
- /package/{src → dist}/types/bidi-protocols/error.d.ts +0 -0
- /package/{src → dist}/types/bidi-protocols/event.d.ts +0 -0
- /package/{src → dist}/types/bidi.d.ts +0 -0
- /package/{src → dist}/types/browser.d.ts +0 -0
- /package/{src → dist}/types/config.d.ts +0 -0
- /package/{src → dist}/types/env.d.ts +0 -0
|
@@ -1,528 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { afterEach, beforeEach, describe, it, mock } from "node:test";
|
|
3
|
-
import { ContextTree } from "../browser/context-tree.js";
|
|
4
|
-
import logger from "../logger/index.js";
|
|
5
|
-
import { autoReply, FakeWebSocket, tick } from "../testing/fake-websocket.js";
|
|
6
|
-
import { BiDiConnector } from "../transport/bidi-connection.js";
|
|
7
|
-
import { Router, type Route } from "./router.js";
|
|
8
|
-
|
|
9
|
-
const TREE = [
|
|
10
|
-
{ context: "top", parent: null, children: [{ context: "frame", parent: "top", children: [] }] },
|
|
11
|
-
{ context: "other", parent: null, children: [] },
|
|
12
|
-
];
|
|
13
|
-
|
|
14
|
-
const stops: Array<() => void> = [];
|
|
15
|
-
let warn: ReturnType<typeof mock.method>;
|
|
16
|
-
let error: ReturnType<typeof mock.method>;
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
warn = mock.method(logger, "warn", () => logger);
|
|
19
|
-
error = mock.method(logger, "error", () => logger);
|
|
20
|
-
});
|
|
21
|
-
afterEach(() => {
|
|
22
|
-
mock.restoreAll();
|
|
23
|
-
stops.splice(0).forEach((stop) => stop());
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
interface Options {
|
|
27
|
-
routeTimeout?: number;
|
|
28
|
-
handlers?: Record<string, (params: any) => object | Error>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async function setup({ routeTimeout = 5000, handlers = {} }: Options = {}) {
|
|
32
|
-
const ws = new FakeWebSocket();
|
|
33
|
-
const connector = new BiDiConnector(ws as unknown as WebSocket);
|
|
34
|
-
let intercepts = 0;
|
|
35
|
-
stops.push(
|
|
36
|
-
autoReply(ws, {
|
|
37
|
-
"browsingContext.getTree": () => ({ contexts: TREE }),
|
|
38
|
-
"network.addIntercept": () => ({ intercept: `i${++intercepts}` }),
|
|
39
|
-
...handlers,
|
|
40
|
-
}),
|
|
41
|
-
);
|
|
42
|
-
const tree = await ContextTree.create(connector);
|
|
43
|
-
const router = new Router(connector, tree, "top", { routeTimeout });
|
|
44
|
-
const commands = (method: string) => ws.sent.filter((m) => m.method === method).map((m) => m.params as any);
|
|
45
|
-
const blocked = (id: string, url: string, extra: { context?: string; intercepts?: string[]; isBlocked?: boolean; method?: string; headers?: Array<{ name: string; value: object }> } = {}) =>
|
|
46
|
-
ws.emitEvent("network.beforeRequestSent", {
|
|
47
|
-
context: extra.context ?? "top",
|
|
48
|
-
isBlocked: extra.isBlocked ?? true,
|
|
49
|
-
intercepts: extra.intercepts ?? ["i1"],
|
|
50
|
-
navigation: null,
|
|
51
|
-
redirectCount: 0,
|
|
52
|
-
timestamp: 0,
|
|
53
|
-
request: {
|
|
54
|
-
request: id,
|
|
55
|
-
url,
|
|
56
|
-
method: extra.method ?? "GET",
|
|
57
|
-
headers: extra.headers ?? [{ name: "Accept", value: { type: "string", value: "*/*" } }],
|
|
58
|
-
cookies: [],
|
|
59
|
-
headersSize: 0,
|
|
60
|
-
bodySize: null,
|
|
61
|
-
destination: "script",
|
|
62
|
-
initiatorType: "fetch",
|
|
63
|
-
timings: {},
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
return { ws, router, commands, blocked };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const header = (name: string, value: string) => ({ name, value: { type: "string", value } });
|
|
70
|
-
|
|
71
|
-
describe("registering routes", () => {
|
|
72
|
-
it("sends one intercept, for this page, however many routes", async () => {
|
|
73
|
-
const { router, commands } = await setup();
|
|
74
|
-
await router.route("**/api/**", () => {});
|
|
75
|
-
await router.route(/\.png$/, () => {});
|
|
76
|
-
assert.deepEqual(commands("network.addIntercept"), [{ phases: ["beforeRequestSent"], contexts: ["top"] }]);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it("concurrent route() calls share one intercept", async () => {
|
|
80
|
-
const { router, commands } = await setup();
|
|
81
|
-
await Promise.all([router.route("**/a", () => {}), router.route("**/b", () => {}), router.route(/c/, () => {})]);
|
|
82
|
-
assert.equal(commands("network.addIntercept").length, 1);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("with only exact URLs the browser is asked to block just those", async () => {
|
|
86
|
-
const { router, commands } = await setup();
|
|
87
|
-
await router.route("https://example.test/api/users", () => {});
|
|
88
|
-
await router.route("https://example.test/api/items?page=1", () => {});
|
|
89
|
-
assert.deepEqual(commands("network.addIntercept").map((c) => c.urlPatterns), [
|
|
90
|
-
[{ type: "string", pattern: "https://example.test/api/users" }],
|
|
91
|
-
[
|
|
92
|
-
{ type: "string", pattern: "https://example.test/api/users" },
|
|
93
|
-
{ type: "string", pattern: "https://example.test/api/items?page=1" },
|
|
94
|
-
],
|
|
95
|
-
]);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it("adding a glob widens the intercept: the new one is added before the old one is removed", async () => {
|
|
99
|
-
const { ws, router } = await setup();
|
|
100
|
-
await router.route("https://example.test/api/users", () => {});
|
|
101
|
-
await router.route("**/images/*", () => {});
|
|
102
|
-
const order = ws.sent.filter((m) => m.method === "network.addIntercept" || m.method === "network.removeIntercept").map((m) => m.method);
|
|
103
|
-
assert.deepEqual(order, ["network.addIntercept", "network.addIntercept", "network.removeIntercept"]);
|
|
104
|
-
assert.equal((ws.sent.filter((m) => m.method === "network.addIntercept")[1]!.params as any).urlPatterns, undefined);
|
|
105
|
-
assert.deepEqual(ws.sent.find((m) => m.method === "network.removeIntercept")!.params, { intercept: "i1" });
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it("an exact string that is not in URL-normal form is not handed to the browser as a pattern", async () => {
|
|
109
|
-
const { router, commands } = await setup();
|
|
110
|
-
await router.route("https://example.test", () => {}); // the browser would read it as https://example.test/
|
|
111
|
-
assert.equal(commands("network.addIntercept")[0].urlPatterns, undefined);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it("falls back to blocking everything when the browser rejects url patterns, and remembers", async () => {
|
|
115
|
-
const rejected = Object.assign(new Error("urlPatterns not supported"), { code: "invalid argument" });
|
|
116
|
-
let attempts = 0;
|
|
117
|
-
const { router, commands } = await setup({
|
|
118
|
-
handlers: {
|
|
119
|
-
"network.addIntercept": (params) => {
|
|
120
|
-
attempts++;
|
|
121
|
-
return params.urlPatterns ? rejected : { intercept: `i${attempts}` };
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
await router.route("https://example.test/a", () => {});
|
|
126
|
-
await router.unrouteAll();
|
|
127
|
-
await router.route("https://example.test/b", () => {});
|
|
128
|
-
const withPatterns = commands("network.addIntercept").filter((c) => c.urlPatterns);
|
|
129
|
-
assert.equal(withPatterns.length, 1, "asked once, then remembered");
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe("what a blocked request does", () => {
|
|
134
|
-
it("goes to the matching handler, with the request described", async () => {
|
|
135
|
-
const { router, blocked } = await setup();
|
|
136
|
-
let seen!: Route;
|
|
137
|
-
await router.route("**/api/**", (route) => {
|
|
138
|
-
seen = route;
|
|
139
|
-
return route.continue();
|
|
140
|
-
});
|
|
141
|
-
blocked("r1", "https://example.test/api/users", { method: "POST", headers: [header("Content-Type", "application/json")] });
|
|
142
|
-
await tick(20);
|
|
143
|
-
const request = seen.request();
|
|
144
|
-
assert.equal(request.url, "https://example.test/api/users");
|
|
145
|
-
assert.equal(request.method, "POST");
|
|
146
|
-
assert.deepEqual(request.headers, { "content-type": "application/json" });
|
|
147
|
-
assert.equal(request.id, "r1");
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it("continues unchanged when no route matches", async () => {
|
|
151
|
-
const { router, blocked, commands } = await setup();
|
|
152
|
-
await router.route("**/api/**", () => {});
|
|
153
|
-
blocked("r1", "https://example.test/other.css");
|
|
154
|
-
await tick(20);
|
|
155
|
-
assert.deepEqual(commands("network.continueRequest"), [{ request: "r1" }]);
|
|
156
|
-
assert.equal(commands("network.failRequest").length + commands("network.provideResponse").length, 0);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it("the newest matching route answers first; fallback passes to the next", async () => {
|
|
160
|
-
const { router, blocked, commands } = await setup();
|
|
161
|
-
const order: string[] = [];
|
|
162
|
-
await router.route("**/api/**", (route) => {
|
|
163
|
-
order.push("old");
|
|
164
|
-
return route.fulfill({ status: 201 });
|
|
165
|
-
});
|
|
166
|
-
await router.route("**/api/users", async (route) => {
|
|
167
|
-
order.push("new");
|
|
168
|
-
await route.fallback();
|
|
169
|
-
});
|
|
170
|
-
blocked("r1", "https://example.test/api/users");
|
|
171
|
-
await tick(30);
|
|
172
|
-
assert.deepEqual(order, ["new", "old"]);
|
|
173
|
-
assert.equal(commands("network.provideResponse")[0].statusCode, 201);
|
|
174
|
-
assert.equal(commands("network.continueRequest").length, 0, "answered once");
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it("fallback on the last matching route continues the request unchanged", async () => {
|
|
178
|
-
const { router, blocked, commands } = await setup();
|
|
179
|
-
await router.route("**/api/**", (route) => route.fallback());
|
|
180
|
-
blocked("r1", "https://example.test/api/users");
|
|
181
|
-
await tick(30);
|
|
182
|
-
assert.deepEqual(commands("network.continueRequest"), [{ request: "r1" }]);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it("ignores requests that are not blocked, of other pages, or blocked by someone else's intercept", async () => {
|
|
186
|
-
const { router, blocked, ws } = await setup();
|
|
187
|
-
let calls = 0;
|
|
188
|
-
await router.route("**", () => {
|
|
189
|
-
calls++;
|
|
190
|
-
});
|
|
191
|
-
const before = ws.sent.length;
|
|
192
|
-
blocked("r1", "https://e.test/a", { isBlocked: false });
|
|
193
|
-
blocked("r2", "https://e.test/b", { context: "other" });
|
|
194
|
-
blocked("r3", "https://e.test/c", { intercepts: ["someone-elses"] });
|
|
195
|
-
await tick(30);
|
|
196
|
-
assert.equal(calls, 0);
|
|
197
|
-
assert.equal(ws.sent.length, before);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
it("handles requests of an iframe of the page", async () => {
|
|
201
|
-
const { router, blocked, commands } = await setup();
|
|
202
|
-
await router.route("**", (route) => route.abort());
|
|
203
|
-
blocked("r1", "https://e.test/frame.js", { context: "frame" });
|
|
204
|
-
await tick(20);
|
|
205
|
-
assert.deepEqual(commands("network.failRequest"), [{ request: "r1" }]);
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
describe("Route.fulfill", () => {
|
|
210
|
-
async function fulfilled(options: Parameters<Route["fulfill"]>[0]) {
|
|
211
|
-
const { router, blocked, commands } = await setup();
|
|
212
|
-
await router.route("**", (route) => route.fulfill(options));
|
|
213
|
-
blocked("r1", "https://example.test/x");
|
|
214
|
-
await tick(20);
|
|
215
|
-
return commands("network.provideResponse")[0];
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
it("answers 200 OK with no body by default", async () => {
|
|
219
|
-
const sent = await fulfilled({});
|
|
220
|
-
assert.deepEqual(sent, {
|
|
221
|
-
request: "r1",
|
|
222
|
-
statusCode: 200,
|
|
223
|
-
reasonPhrase: "OK",
|
|
224
|
-
headers: [header("content-length", "0")],
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it("json becomes the body, with its content type and length", async () => {
|
|
229
|
-
const sent = await fulfilled({ json: [{ id: 1 }] });
|
|
230
|
-
assert.deepEqual(sent.body, { type: "string", value: '[{"id":1}]' });
|
|
231
|
-
assert.deepEqual(sent.headers, [header("content-type", "application/json"), header("content-length", "10")]);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
it("a string body is sent as text, its length counted in bytes", async () => {
|
|
235
|
-
const sent = await fulfilled({ status: 404, body: "héllo", contentType: "text/plain" });
|
|
236
|
-
assert.equal(sent.statusCode, 404);
|
|
237
|
-
assert.equal(sent.reasonPhrase, "Not Found");
|
|
238
|
-
assert.deepEqual(sent.body, { type: "string", value: "héllo" });
|
|
239
|
-
assert.deepEqual(sent.headers, [header("content-type", "text/plain"), header("content-length", "6")]);
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it("a Buffer body is sent as base64", async () => {
|
|
243
|
-
const sent = await fulfilled({ body: Buffer.from([0, 1, 2, 255]) });
|
|
244
|
-
assert.deepEqual(sent.body, { type: "base64", value: Buffer.from([0, 1, 2, 255]).toString("base64") });
|
|
245
|
-
assert.deepEqual(sent.headers.find((h: any) => h.name === "content-length"), header("content-length", "4"));
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
it("your headers win: content-type and content-length are only added when missing, whatever their case", async () => {
|
|
249
|
-
const sent = await fulfilled({
|
|
250
|
-
json: { a: 1 },
|
|
251
|
-
headers: { "Content-Type": "application/vnd.api+json", "CONTENT-LENGTH": "99", "x-mock": "1" },
|
|
252
|
-
});
|
|
253
|
-
assert.deepEqual(sent.headers, [
|
|
254
|
-
header("Content-Type", "application/vnd.api+json"),
|
|
255
|
-
header("CONTENT-LENGTH", "99"),
|
|
256
|
-
header("x-mock", "1"),
|
|
257
|
-
]);
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it("json and body together are refused", async () => {
|
|
261
|
-
const { router, blocked } = await setup();
|
|
262
|
-
let failure: unknown;
|
|
263
|
-
await router.route("**", async (route) => {
|
|
264
|
-
failure = await route.fulfill({ json: 1, body: "x" }).catch((err: Error) => err);
|
|
265
|
-
await route.abort();
|
|
266
|
-
});
|
|
267
|
-
blocked("r1", "https://example.test/x");
|
|
268
|
-
await tick(30);
|
|
269
|
-
assert.ok(failure instanceof TypeError);
|
|
270
|
-
});
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
describe("Route.continue and Route.abort", () => {
|
|
274
|
-
it("continue() sends only the request", async () => {
|
|
275
|
-
const { router, blocked, commands } = await setup();
|
|
276
|
-
await router.route("**", (route) => route.continue());
|
|
277
|
-
blocked("r1", "https://example.test/x");
|
|
278
|
-
await tick(20);
|
|
279
|
-
assert.deepEqual(commands("network.continueRequest"), [{ request: "r1" }]);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it("continue() overrides url, method and headers", async () => {
|
|
283
|
-
const { router, blocked, commands } = await setup();
|
|
284
|
-
await router.route("**", (route) =>
|
|
285
|
-
route.continue({
|
|
286
|
-
url: "https://example.test/other",
|
|
287
|
-
method: "PUT",
|
|
288
|
-
headers: { ...route.request().headers, "x-test": "1" },
|
|
289
|
-
}),
|
|
290
|
-
);
|
|
291
|
-
blocked("r1", "https://example.test/x");
|
|
292
|
-
await tick(20);
|
|
293
|
-
assert.deepEqual(commands("network.continueRequest"), [
|
|
294
|
-
{
|
|
295
|
-
request: "r1",
|
|
296
|
-
url: "https://example.test/other",
|
|
297
|
-
method: "PUT",
|
|
298
|
-
headers: [header("accept", "*/*"), header("x-test", "1")],
|
|
299
|
-
},
|
|
300
|
-
]);
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
it("a new body brings its own content-length: the browser would keep the old one and cut the body off", async () => {
|
|
304
|
-
const { router, blocked, commands } = await setup();
|
|
305
|
-
await router.route("**", (route) => route.continue({ postData: "héllo body" }));
|
|
306
|
-
blocked("r1", "https://example.test/x", {
|
|
307
|
-
method: "POST",
|
|
308
|
-
headers: [header("Accept", "*/*"), header("Content-Length", "4")],
|
|
309
|
-
});
|
|
310
|
-
await tick(20);
|
|
311
|
-
assert.deepEqual(commands("network.continueRequest"), [
|
|
312
|
-
{
|
|
313
|
-
request: "r1",
|
|
314
|
-
headers: [header("accept", "*/*"), header("content-length", "11")],
|
|
315
|
-
body: { type: "string", value: "héllo body" },
|
|
316
|
-
},
|
|
317
|
-
]);
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
it("the content-length of a new body replaces one in the headers you pass, whatever its case", async () => {
|
|
321
|
-
const { router, blocked, commands } = await setup();
|
|
322
|
-
await router.route("**", (route) =>
|
|
323
|
-
route.continue({ postData: "12345", headers: { ...route.request().headers, "Content-Length": "999", "x-a": "1" } }),
|
|
324
|
-
);
|
|
325
|
-
blocked("r1", "https://example.test/x", { method: "POST", headers: [header("Content-Length", "4")] });
|
|
326
|
-
await tick(20);
|
|
327
|
-
assert.deepEqual(commands("network.continueRequest")[0].headers, [header("x-a", "1"), header("content-length", "5")]);
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
it("continue() sends a Buffer as base64, counted in bytes", async () => {
|
|
331
|
-
const { router, blocked, commands } = await setup();
|
|
332
|
-
await router.route("**", (route) => route.continue({ postData: Buffer.from([1, 2, 3, 255]) }));
|
|
333
|
-
blocked("r1", "https://example.test/x", { method: "POST" });
|
|
334
|
-
await tick(20);
|
|
335
|
-
const sent = commands("network.continueRequest")[0];
|
|
336
|
-
assert.deepEqual(sent.body, { type: "base64", value: Buffer.from([1, 2, 3, 255]).toString("base64") });
|
|
337
|
-
assert.deepEqual(sent.headers.find((h: any) => h.name === "content-length"), header("content-length", "4"));
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
it("abort() fails the request", async () => {
|
|
341
|
-
const { router, blocked, commands } = await setup();
|
|
342
|
-
await router.route(/\.png$/, (route) => route.abort());
|
|
343
|
-
blocked("r1", "https://example.test/a.png");
|
|
344
|
-
await tick(20);
|
|
345
|
-
assert.deepEqual(commands("network.failRequest"), [{ request: "r1" }]);
|
|
346
|
-
});
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
describe("every blocked request is resolved exactly once", () => {
|
|
350
|
-
it("a second resolution throws", async () => {
|
|
351
|
-
const { router, blocked, commands } = await setup();
|
|
352
|
-
const outcomes: string[] = [];
|
|
353
|
-
await router.route("**", async (route) => {
|
|
354
|
-
await route.fulfill({});
|
|
355
|
-
for (const second of [() => route.continue(), () => route.abort(), () => route.fulfill({}), () => route.fallback()]) {
|
|
356
|
-
outcomes.push(await second().then(() => "ok", (err: Error) => err.message));
|
|
357
|
-
}
|
|
358
|
-
});
|
|
359
|
-
blocked("r1", "https://example.test/x");
|
|
360
|
-
await tick(30);
|
|
361
|
-
assert.deepEqual(outcomes, Array(4).fill("route already handled"));
|
|
362
|
-
assert.equal(commands("network.provideResponse").length, 1);
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
it("a handler that throws fails the request and the error is kept", async () => {
|
|
366
|
-
const { router, blocked, commands } = await setup();
|
|
367
|
-
await router.route("**", () => {
|
|
368
|
-
throw new Error("handler bug");
|
|
369
|
-
});
|
|
370
|
-
blocked("r1", "https://example.test/x");
|
|
371
|
-
await tick(30);
|
|
372
|
-
assert.deepEqual(commands("network.failRequest"), [{ request: "r1" }]);
|
|
373
|
-
assert.equal(router.errors.length, 1);
|
|
374
|
-
assert.match(router.errors[0]!.message, /route handler for https:\/\/example\.test\/x threw: handler bug/);
|
|
375
|
-
assert.ok(error.mock.callCount() >= 1);
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
it("a handler that throws after answering keeps the answer and reports the error", async () => {
|
|
379
|
-
const { router, blocked, commands } = await setup();
|
|
380
|
-
await router.route("**", async (route) => {
|
|
381
|
-
await route.fulfill({});
|
|
382
|
-
throw new Error("late bug");
|
|
383
|
-
});
|
|
384
|
-
blocked("r1", "https://example.test/x");
|
|
385
|
-
await tick(30);
|
|
386
|
-
assert.equal(commands("network.failRequest").length, 0);
|
|
387
|
-
assert.equal(router.errors.length, 1);
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
it("a handler that returns without answering lets the request continue, with a warning", async () => {
|
|
391
|
-
const { router, blocked, commands } = await setup();
|
|
392
|
-
await router.route("**", () => {});
|
|
393
|
-
blocked("r1", "https://example.test/x");
|
|
394
|
-
await tick(30);
|
|
395
|
-
assert.deepEqual(commands("network.continueRequest"), [{ request: "r1" }]);
|
|
396
|
-
assert.equal(warn.mock.callCount(), 1);
|
|
397
|
-
assert.match(String((warn.mock.calls[0]!.arguments as unknown[])[0]), /did not answer/);
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
it("an async handler is awaited: answering later is not overtaken by the default", async () => {
|
|
401
|
-
const { router, blocked, commands } = await setup();
|
|
402
|
-
await router.route("**", async (route) => {
|
|
403
|
-
await tick(40);
|
|
404
|
-
await route.fulfill({ status: 202 });
|
|
405
|
-
});
|
|
406
|
-
blocked("r1", "https://example.test/x");
|
|
407
|
-
await tick(15);
|
|
408
|
-
assert.equal(commands("network.continueRequest").length, 0, "still waiting for the handler");
|
|
409
|
-
await tick(60);
|
|
410
|
-
assert.equal(commands("network.provideResponse")[0].statusCode, 202);
|
|
411
|
-
assert.equal(commands("network.continueRequest").length, 0);
|
|
412
|
-
assert.equal(warn.mock.callCount(), 0);
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
it("a route pending longer than routeTimeout is continued, and the error is logged", async () => {
|
|
416
|
-
const { router, blocked, commands } = await setup({ routeTimeout: 50 });
|
|
417
|
-
await router.route("**", async () => {
|
|
418
|
-
await tick(300); // never answers within the timeout
|
|
419
|
-
});
|
|
420
|
-
blocked("r1", "https://example.test/x");
|
|
421
|
-
await tick(120);
|
|
422
|
-
assert.deepEqual(commands("network.continueRequest"), [{ request: "r1" }]);
|
|
423
|
-
assert.ok(error.mock.callCount() >= 1);
|
|
424
|
-
const [template, , timeout] = error.mock.calls[0]!.arguments as unknown[];
|
|
425
|
-
assert.match(String(template), /did not answer within %dms/);
|
|
426
|
-
assert.equal(timeout, 50);
|
|
427
|
-
await tick(300); // the handler finishing later must not send anything more
|
|
428
|
-
assert.equal(commands("network.continueRequest").length, 1);
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
it("the browser refusing an answer reaches the handler as a BiDiError", async () => {
|
|
432
|
-
const gone = Object.assign(new Error("request is gone"), { code: "no such request" });
|
|
433
|
-
const { router, blocked } = await setup({ handlers: { "network.provideResponse": () => gone } });
|
|
434
|
-
let caught: unknown;
|
|
435
|
-
await router.route("**", async (route) => {
|
|
436
|
-
caught = await route.fulfill({}).catch((err: Error) => err);
|
|
437
|
-
});
|
|
438
|
-
blocked("r1", "https://example.test/x");
|
|
439
|
-
await tick(30);
|
|
440
|
-
assert.equal((caught as Error).name, "BiDiError");
|
|
441
|
-
assert.equal((caught as { code: string }).code, "no such request");
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
describe("removing routes", () => {
|
|
446
|
-
it("unroute removes the route; the last one takes the intercept and the listener with it", async () => {
|
|
447
|
-
const { ws, router, commands, blocked } = await setup();
|
|
448
|
-
await router.route("**/a", () => {});
|
|
449
|
-
await router.unroute("**/a");
|
|
450
|
-
assert.deepEqual(commands("network.removeIntercept"), [{ intercept: "i1" }]);
|
|
451
|
-
await tick(10);
|
|
452
|
-
assert.ok(ws.sent.some((m) => m.method === "session.unsubscribe"));
|
|
453
|
-
const before = ws.sent.length;
|
|
454
|
-
blocked("r1", "https://e.test/a");
|
|
455
|
-
await tick(20);
|
|
456
|
-
assert.equal(ws.sent.length, before);
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
it("unroute by pattern and handler removes only that pair", async () => {
|
|
460
|
-
const { router, blocked, commands } = await setup();
|
|
461
|
-
const first = () => {};
|
|
462
|
-
const second = (route: Route) => route.abort();
|
|
463
|
-
await router.route("**/a", first);
|
|
464
|
-
await router.route("**/a", second);
|
|
465
|
-
await router.unroute("**/a", second);
|
|
466
|
-
blocked("r1", "https://e.test/a");
|
|
467
|
-
await tick(30);
|
|
468
|
-
assert.equal(commands("network.failRequest").length, 0);
|
|
469
|
-
assert.equal(commands("network.removeIntercept").length, 0, "one route is left");
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
it("unroute without a handler removes every route for that pattern", async () => {
|
|
473
|
-
const { router, blocked, commands } = await setup();
|
|
474
|
-
await router.route(/a/, () => {});
|
|
475
|
-
await router.route(/a/, () => {});
|
|
476
|
-
await router.route("**/b", () => {});
|
|
477
|
-
await router.unroute(/a/);
|
|
478
|
-
blocked("r1", "https://e.test/b");
|
|
479
|
-
await tick(30);
|
|
480
|
-
assert.equal(commands("network.continueRequest").length, 1, "the b route is still here (it did not answer, so the request continues)");
|
|
481
|
-
assert.equal(commands("network.removeIntercept").length, 0);
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
it("removing a route continues the requests it still holds", async () => {
|
|
485
|
-
const { router, blocked, commands } = await setup();
|
|
486
|
-
await router.route("**/slow", async () => {
|
|
487
|
-
await tick(500);
|
|
488
|
-
});
|
|
489
|
-
blocked("r1", "https://e.test/slow");
|
|
490
|
-
await tick(20);
|
|
491
|
-
await router.unroute("**/slow");
|
|
492
|
-
assert.deepEqual(commands("network.continueRequest"), [{ request: "r1" }]);
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
it("unrouteAll removes everything, and a new route starts again", async () => {
|
|
496
|
-
const { router, commands } = await setup();
|
|
497
|
-
await router.route("**/a", () => {});
|
|
498
|
-
await router.route(/b/, () => {});
|
|
499
|
-
await router.unrouteAll();
|
|
500
|
-
assert.equal(commands("network.removeIntercept").length, 1);
|
|
501
|
-
await router.route("**/c", () => {});
|
|
502
|
-
assert.equal(commands("network.addIntercept").length, 2);
|
|
503
|
-
});
|
|
504
|
-
|
|
505
|
-
it("dispose continues pending requests, removes the intercept and stops listening; it is idempotent", async () => {
|
|
506
|
-
const { ws, router, blocked, commands } = await setup();
|
|
507
|
-
await router.route("**", async () => {
|
|
508
|
-
await tick(500);
|
|
509
|
-
});
|
|
510
|
-
blocked("r1", "https://e.test/x");
|
|
511
|
-
await tick(20);
|
|
512
|
-
await router.dispose();
|
|
513
|
-
assert.deepEqual(commands("network.continueRequest"), [{ request: "r1" }]);
|
|
514
|
-
assert.equal(commands("network.removeIntercept").length, 1);
|
|
515
|
-
const before = ws.sent.length;
|
|
516
|
-
blocked("r2", "https://e.test/y");
|
|
517
|
-
await tick(20);
|
|
518
|
-
assert.equal(ws.sent.length, before);
|
|
519
|
-
await assert.doesNotReject(router.dispose());
|
|
520
|
-
assert.equal(commands("network.removeIntercept").length, 1);
|
|
521
|
-
});
|
|
522
|
-
|
|
523
|
-
it("route() after dispose is refused", async () => {
|
|
524
|
-
const { router } = await setup();
|
|
525
|
-
await router.dispose();
|
|
526
|
-
await assert.rejects(router.route("**", () => {}), /disposed/);
|
|
527
|
-
});
|
|
528
|
-
});
|