diff --git a/tests/smoke/icon.test.ts b/tests/smoke/icon.test.ts index 01965629..37b93a8d 100644 --- a/tests/smoke/icon.test.ts +++ b/tests/smoke/icon.test.ts @@ -1,3 +1,4 @@ +// @vitest-environment node import { describe, it, expect } from "vitest"; /** @@ -14,20 +15,22 @@ const BASE = process.env.SMOKE_BASE_URL ?? "https://my.feedzero.app"; const enabled = process.env.SMOKE_TESTS === "1"; describe.skipIf(!enabled)("smoke: /api/icon", () => { + // Fixtures are our own domain: example.com has no favicon at all (its + // ?domain= answer is an empty text/plain 200, its /favicon.ico a 404), + // which is exactly the "mock encodes a belief about the service" trap + // CLAUDE.md's Tier 2.5 rule warns about. Verified with curl before use. it("serves a favicon for ?domain= with a cacheable image response", async () => { - const res = await fetch(`${BASE}/api/icon?domain=example.com`); + const res = await fetch(`${BASE}/api/icon?domain=feedzero.app`); expect(res.status).toBe(200); expect(res.headers.get("content-type")).toMatch(/^image\//); expect(res.headers.get("cache-control")).toMatch(/max-age=86400/); }); - it("proxies an explicit image url", async () => { + it("proxies an explicit image url as an image", async () => { const res = await fetch( - `${BASE}/api/icon?url=${encodeURIComponent("https://example.com/favicon.ico")}`, + `${BASE}/api/icon?url=${encodeURIComponent("https://feedzero.app/favicon.ico")}`, ); - // example.com has no favicon; the contract is that the proxy answers - // for the URL rather than rejecting the shape. - expect([200, 404, 502]).toContain(res.status); - expect(res.status).not.toBe(400); + expect(res.status).toBe(200); + expect(res.headers.get("content-type")).toMatch(/^image\//); }); });