From 6541b89815cc453867b6df41584334b75cf7db36 Mon Sep 17 00:00:00 2001 From: "github.sudoku" <49580702+forcingfx@users.noreply.github.com> Date: Wed, 9 Sep 2026 22:35:16 +0200 Subject: [PATCH] test(smoke): make the /api/icon smoke test actually run against production The test added in #297 failed on its first live run for two reasons that the unit run could not show: example.com has no favicon (its ?domain= answer is an empty text/plain 200 and its /favicon.ico a 404), and the default happy-dom environment blocks the cross-origin fetch outright. Fixtures are now our own domain and the file runs under node like every other smoke test. Verified green against my.feedzero.app before commit. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01GQoLHbPfaTCHvPuaoqGZeJ --- tests/smoke/icon.test.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) 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\//); }); });