From 4c51a5b3502a85e364a099473d6ad76c7a76de06 Mon Sep 17 00:00:00 2001 From: Maria Zuheros Date: Mon, 20 Jul 2026 08:03:57 +0100 Subject: [PATCH] test(header-analysis): cover the response header parsers (#2395) Adds one test file per parser, following the colocated pattern already used by x-vercel-cache. Covers the happy path, unknown data centers and headers that cannot be parsed. --- .../src/parser/cache-control.test.ts | 41 +++++++++++++++++++ .../src/parser/cf-cache-status.test.ts | 32 +++++++++++++++ .../header-analysis/src/parser/cf-ray.test.ts | 32 +++++++++++++++ .../src/parser/fly-request-id.test.ts | 32 +++++++++++++++ .../src/parser/x-vercel-id.test.ts | 36 ++++++++++++++++ 5 files changed, 173 insertions(+) create mode 100644 packages/header-analysis/src/parser/cache-control.test.ts create mode 100644 packages/header-analysis/src/parser/cf-cache-status.test.ts create mode 100644 packages/header-analysis/src/parser/cf-ray.test.ts create mode 100644 packages/header-analysis/src/parser/fly-request-id.test.ts create mode 100644 packages/header-analysis/src/parser/x-vercel-id.test.ts diff --git a/packages/header-analysis/src/parser/cache-control.test.ts b/packages/header-analysis/src/parser/cache-control.test.ts new file mode 100644 index 00000000..487bd6ad --- /dev/null +++ b/packages/header-analysis/src/parser/cache-control.test.ts @@ -0,0 +1,41 @@ +import { expect } from "@std/expect"; +import { describe, it } from "@std/testing/bdd"; + +import { parseCacheControlHeader } from "./cache-control"; + +describe("parseCacheControlHeader", () => { + it("reads a numeric directive value and keeps the raw directive", () => { + const [maxAge] = parseCacheControlHeader("max-age=3600"); + expect(maxAge.name).toBe("max-age"); + expect(maxAge.value).toBe(3600); + expect(maxAge.directive).toBe("max-age=3600"); + expect(maxAge.description).toContain("maximum amount of time"); + }); + + it("leaves the value undefined for a directive without one", () => { + const [noCache] = parseCacheControlHeader("no-cache"); + expect(noCache.name).toBe("no-cache"); + expect(noCache.value).toBeUndefined(); + expect(noCache.description).toContain("origin server for validation"); + }); + + it("splits every comma separated directive and trims the spacing", () => { + const result = parseCacheControlHeader( + "public, max-age=60 , must-revalidate", + ); + expect(result.map((directive) => directive.name)).toEqual([ + "public", + "max-age", + "must-revalidate", + ]); + expect(result[1].value).toBe(60); + expect(result[1].directive).toBe("max-age=60"); + }); + + it("matches the directive name case insensitively", () => { + const [maxAge] = parseCacheControlHeader("MAX-AGE=120"); + expect(maxAge.name).toBe("MAX-AGE"); + expect(maxAge.value).toBe(120); + expect(maxAge.description).toContain("maximum amount of time"); + }); +}); diff --git a/packages/header-analysis/src/parser/cf-cache-status.test.ts b/packages/header-analysis/src/parser/cf-cache-status.test.ts new file mode 100644 index 00000000..d5a81eb4 --- /dev/null +++ b/packages/header-analysis/src/parser/cf-cache-status.test.ts @@ -0,0 +1,32 @@ +import { expect } from "@std/expect"; +import { describe, it } from "@std/testing/bdd"; + +import { parseCfCacheStatus } from "./cf-cache-status"; + +describe("parseCfCacheStatus", () => { + for (const [value, expectedFragment] of [ + ["HIT", "found in Cloudflare"], + ["MISS", "did not find it"], + ["BYPASS", "not cache this asset"], + ["EXPIRED", "cache has expired"], + ["DYNAMIC", "not cached by default"], + ]) { + it(`describes the documented state ${value}`, () => { + const result = parseCfCacheStatus(value); + expect(result.value).toBe(value); + expect(result.description).toContain(expectedFragment); + }); + } + + it("matches the state case insensitively and echoes the raw header", () => { + const result = parseCfCacheStatus("hit"); + expect(result.value).toBe("hit"); + expect(result.description).toContain("found in Cloudflare"); + }); + + it("falls back to a placeholder for an unknown state", () => { + const result = parseCfCacheStatus("REVALIDATED"); + expect(result.value).toBe("REVALIDATED"); + expect(result.description).toBe("-"); + }); +}); diff --git a/packages/header-analysis/src/parser/cf-ray.test.ts b/packages/header-analysis/src/parser/cf-ray.test.ts new file mode 100644 index 00000000..10d58664 --- /dev/null +++ b/packages/header-analysis/src/parser/cf-ray.test.ts @@ -0,0 +1,32 @@ +import { expect } from "@std/expect"; +import { describe, it } from "@std/testing/bdd"; + +import { parseCfRay } from "./cf-ray"; + +describe("parseCfRay", () => { + it("resolves the data center from the iata code", () => { + const result = parseCfRay("7d4b1f9e8c2a1234-CGB"); + expect(result.status).toBe("success"); + if (result.status === "success") { + expect(result.data.code).toBe("CGB"); + expect(result.data.location).toBe("Cuiabá, Brazil"); + } + }); + + it("fails when the iata code is not in the list", () => { + const result = parseCfRay("7d4b1f9e8c2a1234-ZZZ"); + expect(result.status).toBe("failed"); + if (result.status === "failed") { + expect(result.error.message).toContain("ZZZ"); + expect(result.error.message).toContain("not listed"); + } + }); + + it("fails when the header carries no iata code", () => { + const result = parseCfRay("7d4b1f9e8c2a1234"); + expect(result.status).toBe("failed"); + if (result.status === "failed") { + expect(result.error.message).toBe("Couldn't parse the header."); + } + }); +}); diff --git a/packages/header-analysis/src/parser/fly-request-id.test.ts b/packages/header-analysis/src/parser/fly-request-id.test.ts new file mode 100644 index 00000000..c3fd32bd --- /dev/null +++ b/packages/header-analysis/src/parser/fly-request-id.test.ts @@ -0,0 +1,32 @@ +import { expect } from "@std/expect"; +import { describe, it } from "@std/testing/bdd"; + +import { parseFlyRequestId } from "./fly-request-id"; + +describe("parseFlyRequestId", () => { + it("resolves the region from the trailing iata code", () => { + const result = parseFlyRequestId("01h2abcxyz9876-ams"); + expect(result.status).toBe("success"); + if (result.status === "success") { + expect(result.data.code).toBe("ams"); + expect(result.data.location).toBe("Amsterdam, Netherlands"); + } + }); + + it("fails when the region is not in the list", () => { + const result = parseFlyRequestId("01h2abcxyz9876-zzz"); + expect(result.status).toBe("failed"); + if (result.status === "failed") { + expect(result.error.message).toContain("zzz"); + expect(result.error.message).toContain("not listed"); + } + }); + + it("fails when the header carries no region code", () => { + const result = parseFlyRequestId("0123456789"); + expect(result.status).toBe("failed"); + if (result.status === "failed") { + expect(result.error.message).toBe("Couldn't parse the header."); + } + }); +}); diff --git a/packages/header-analysis/src/parser/x-vercel-id.test.ts b/packages/header-analysis/src/parser/x-vercel-id.test.ts new file mode 100644 index 00000000..ece9a28b --- /dev/null +++ b/packages/header-analysis/src/parser/x-vercel-id.test.ts @@ -0,0 +1,36 @@ +import { expect } from "@std/expect"; +import { describe, it } from "@std/testing/bdd"; + +import { parseXVercelId } from "./x-vercel-id"; + +describe("parseXVercelId", () => { + it("resolves every region in the id chain, in order", () => { + const result = parseXVercelId("arn1::bom1::qwert-1700000000000-abc123"); + expect(result.status).toBe("success"); + if (result.status === "success") { + expect(result.data.map((region) => region.code)).toEqual([ + "arn1", + "bom1", + ]); + expect(result.data[0].location).toBe("Stockholm, Sweden"); + expect(result.data[1].location).toBe("Mumbai, India"); + } + }); + + it("resolves a single region id", () => { + const result = parseXVercelId("arn1::qwert-1700000000000-abc123"); + expect(result.status).toBe("success"); + if (result.status === "success") { + expect(result.data).toHaveLength(1); + expect(result.data[0].code).toBe("arn1"); + } + }); + + it("fails when the header carries no region id", () => { + const result = parseXVercelId("no-regions-here"); + expect(result.status).toBe("failed"); + if (result.status === "failed") { + expect(result.error.message).toBe("Couldn't parse the header."); + } + }); +}); -- 2.51.2