diff options
| author | astarring <zouzhigang85@gmail.com> | 2026-09-09 02:35:42 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-09 00:05:42 +0530 |
| commit | 8d7a067c8d82a592bfb3dcacf05305c39550cbc6 (patch) | |
| tree | cf6641e0d8ab749542adc4e605787e4e525b24b6 /test | |
| parent | 6f455ed015b1b39324c45813a42b33ddb63e4bc9 (diff) | |
feat: add per-tab request headers (#30)
Expose explicit set and clear tools so environment-routed pages can be opened without leaking header values or carrying headers across unrelated browsing.
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
Co-authored-by: zouzhigang <zouzhigang@bytedance.com>
Diffstat (limited to 'test')
| -rw-r--r-- | test/cdp/commands-test.ts | 5 | ||||
| -rw-r--r-- | test/domains/headers-test.ts | 95 | ||||
| -rw-r--r-- | test/domains/registry-test.ts | 2 |
3 files changed, 102 insertions, 0 deletions
diff --git a/test/cdp/commands-test.ts b/test/cdp/commands-test.ts index ad1b057..738189d 100644 --- a/test/cdp/commands-test.ts +++ b/test/cdp/commands-test.ts @@ -42,6 +42,11 @@ describe("cdp command table", () => { const r = decodeResult("Nope.method" as "Page.enable", {}); assert.equal(r.success, false); }); + + test("accepts an empty Network.setExtraHTTPHeaders response", () => { + const r = decodeResult("Network.setExtraHTTPHeaders", {}); + assert.equal(r.success, true); + }); }); describe("Accessibility.getFullAXTree schema", () => { diff --git a/test/domains/headers-test.ts b/test/domains/headers-test.ts new file mode 100644 index 0000000..4a268c2 --- /dev/null +++ b/test/domains/headers-test.ts @@ -0,0 +1,95 @@ +import { describe, test } from "node:test"; +import assert from "node:assert/strict"; +import { Compile } from "typebox/compile"; +import { clearHeadersTool, setHeadersTool } from "../../src/domains/headers"; +import type { HandlerContext } from "../../src/util/tool"; +import { createFakeClient, type FakeClient } from "./fake-client"; + +const ctxFor = (fake: FakeClient): HandlerContext => ({ + client: fake.client, + signal: undefined, + onUpdate: () => {}, + extensionCtx: undefined as never, +}); + +describe("browser_set_headers", () => { + test("sets headers on the current owned tab without echoing values", async () => { + const fake = await createFakeClient(); + const result = await setHeadersTool.handler( + { + headers: { + "x-tt-env": "ppe_mini_game_rating_phase4", + "x-use-ppe": "1", + }, + }, + ctxFor(fake), + ); + + assert.equal(result.success, true); + if (!result.success) return; + assert.doesNotMatch(result.data.text, /ppe_mini_game_rating_phase4/); + assert.deepEqual(result.data.details, { + targetId: "t1", + headerNames: ["x-tt-env", "x-use-ppe"], + count: 2, + }); + assert.deepEqual(fake.callsTo("Network.setExtraHTTPHeaders"), [ + { + method: "Network.setExtraHTTPHeaders", + params: { + headers: { + "x-tt-env": "ppe_mini_game_rating_phase4", + "x-use-ppe": "1", + }, + }, + sessionId: "s1", + }, + ]); + }); + + test("refuses a current tab that is not owned by the harness", async () => { + const fake = await createFakeClient(); + fake.ownership.remove("t1"); + const result = await setHeadersTool.handler({ headers: { "x-test": "value" } }, ctxFor(fake)); + + assert.equal(result.success, false); + if (result.success) return; + assert.equal(result.error.kind, "invalid_state"); + assert.match(result.error.message, /not owned/); + assert.equal(fake.callsTo("Network.setExtraHTTPHeaders").length, 0); + }); + + test("schema rejects empty or malformed header sets", () => { + const validate = Compile(setHeadersTool.parameters); + assert.equal(validate.Check({ headers: {} }), false); + assert.equal(validate.Check({ headers: { "x-test": "line one\nline two" } }), false); + assert.equal(validate.Check({ headers: { "x-test": "value" } }), true); + }); + + test("handler rejects invalid HTTP header names", async () => { + const fake = await createFakeClient(); + const result = await setHeadersTool.handler({ headers: { "bad name": "value" } }, ctxFor(fake)); + + assert.equal(result.success, false); + if (result.success) return; + assert.equal(result.error.kind, "invalid_state"); + assert.match(result.error.message, /Invalid HTTP header name/); + assert.equal(fake.callsTo("Network.setExtraHTTPHeaders").length, 0); + }); +}); + +describe("browser_clear_headers", () => { + test("clears extra headers on the current owned tab", async () => { + const fake = await createFakeClient(); + const result = await clearHeadersTool.handler({}, ctxFor(fake)); + + assert.equal(result.success, true); + assert.deepEqual(fake.callsTo("Network.setExtraHTTPHeaders"), [ + { + method: "Network.setExtraHTTPHeaders", + params: { headers: {} }, + sessionId: "s1", + }, + ]); + }); +}); diff --git a/test/domains/registry-test.ts b/test/domains/registry-test.ts index 2003b6c..be020a3 100644 --- a/test/domains/registry-test.ts +++ b/test/domains/registry-test.ts @@ -34,6 +34,8 @@ const SERIALIZED = new Set([ "browser_print_to_pdf", "browser_viewport_resize", "browser_drag_and_drop", + "browser_set_headers", + "browser_clear_headers", "browser_web_search", ]); |
