






















@@ -0,0 +1,82 @@
1+import { describe, expect, it } from "vitest";
2+import {
3+normalizeHeadersInitForFetch,
4+normalizeRequestInitHeadersForFetch,
5+} from "./fetch-headers.js";
6+7+function createHeadersWithSymbol(enumerable: boolean): HeadersInit {
8+const headers = { "Content-Type": "application/json" } as Record<string, string> & {
9+[key: symbol]: unknown;
10+};
11+Object.defineProperty(headers, Symbol("sensitiveHeaders"), {
12+value: new Set(["content-type"]),
13+ enumerable,
14+});
15+return headers;
16+}
17+18+describe("normalizeHeadersInitForFetch", () => {
19+it("keeps Headers instances unchanged", () => {
20+const headers = new Headers({ Accept: "application/json" });
21+22+expect(normalizeHeadersInitForFetch(headers)).toBe(headers);
23+});
24+25+it("keeps tuple headers unchanged", () => {
26+const headers: HeadersInit = [["Accept", "application/json"]];
27+28+expect(normalizeHeadersInitForFetch(headers)).toBe(headers);
29+});
30+31+it("keeps plain string-key dictionaries unchanged when they have no symbol keys", () => {
32+const headers = { Accept: "application/json" };
33+34+expect(normalizeHeadersInitForFetch(headers)).toBe(headers);
35+});
36+37+it.each([
38+{ enumerable: true, name: "enumerable" },
39+{ enumerable: false, name: "non-enumerable" },
40+])("drops $name own symbol keys from plain header dictionaries", ({ enumerable }) => {
41+const headers = createHeadersWithSymbol(enumerable);
42+43+const normalized = normalizeHeadersInitForFetch(headers);
44+45+expect(normalized).not.toBe(headers);
46+expect(Object.getOwnPropertySymbols(normalized as object)).toEqual([]);
47+expect(new Headers(normalized).get("content-type")).toBe("application/json");
48+expect(Object.getOwnPropertySymbols(headers as object)).toHaveLength(1);
49+});
50+51+it("preserves non-enumerable string header keys when dropping symbol keys", () => {
52+const headers = createHeadersWithSymbol(false);
53+Object.defineProperty(headers, "X-Hidden", {
54+value: "yes",
55+enumerable: false,
56+});
57+58+const normalized = normalizeHeadersInitForFetch(headers);
59+60+expect(Object.getOwnPropertySymbols(normalized as object)).toEqual([]);
61+expect(new Headers(normalized).get("x-hidden")).toBe("yes");
62+expect(new Headers(normalized).get("content-type")).toBe("application/json");
63+});
64+});
65+66+describe("normalizeRequestInitHeadersForFetch", () => {
67+it("returns the original init when headers do not need normalization", () => {
68+const init: RequestInit = { headers: { Accept: "application/json" } };
69+70+expect(normalizeRequestInitHeadersForFetch(init)).toBe(init);
71+});
72+73+it("returns a cloned init with symbol-free headers when needed", () => {
74+const init: RequestInit = { headers: createHeadersWithSymbol(false) };
75+76+const normalized = normalizeRequestInitHeadersForFetch(init);
77+78+expect(normalized).not.toBe(init);
79+expect(Object.getOwnPropertySymbols(normalized?.headers as object)).toEqual([]);
80+expect(Object.getOwnPropertySymbols(init.headers as object)).toHaveLength(1);
81+});
82+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。