import type { SiteFailureSample } from "@umt/contracts"; import { createElement } from "react"; import { renderToStaticMarkup } from "react-dom/server"; import { describe, expect, it } from "vitest"; import { SiteFailureSamples } from "./site-failure-samples.tsx"; import { failureSampleFileName, failureSampleItems, failureSampleText, failureSampleTitle } from "./site-fields.ts"; // 站点页技术信息里的失败样本:一行说清是搜索 / 列表、人机验证还是页面结构变化;展开看地址、响应头、页面,可下载文本。 const sample: SiteFailureSample = { id: "0f1e2d3c-4b5a-4987-8a6b-5c4d3e2f1a0b", siteId: "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d", kind: "challenge", requestKind: "search", url: "https://audiences.me/torrents.php?search=Dune&passkey=[REDACTED]", httpStatus: 200, headers: { server: "cloudflare", "cf-ray": "8c00-HKG" }, message: "搜索:搜索页需要人机验证(Cloudflare 等),需要你在原站视图里过一次验证", rule: "gate*=cf-turnstile", body: '
', truncated: false, createdAt: "2026-10-06T07:30:05.000Z", }; const { body: _b, ...summary } = sample; const row = { ...summary, bodyBytes: 44 }; describe("站点失败样本展示", () => { it("标题区分请求类型与失败类型", () => { expect(failureSampleTitle(sample)).toBe("搜索 · 人机验证 · HTTP 200"); expect(failureSampleTitle({ kind: "parse_error", requestKind: "list", httpStatus: null })).toBe( "列表 · 页面结构无法识别", ); }); it("技术信息条目:地址、错误、规则、关键响应头、页面大小", () => { const items = failureSampleItems(row); expect(items.map((i) => i.label)).toEqual(["地址", "错误", "命中规则", "server", "cf-ray", "页面"]); expect(items[0]?.value).toContain("passkey=[REDACTED]"); }); it("下载文本带请求信息头;文件名带请求类型、类型与时间", () => { const text = failureSampleText(sample); expect(text).toContain("# 地址:https://audiences.me/torrents.php"); expect(text).toContain("# cf-ray: 8c00-HKG"); expect(text.endsWith(sample.body)).toBe(true); expect(failureSampleFileName(sample)).toBe("site-sample-search-challenge-20261006-073005.html.txt"); }); it("列表渲染:每份一行(收起),没有样本不渲染", () => { const html = renderToStaticMarkup(createElement(SiteFailureSamples, { siteId: sample.siteId, items: [row] })); expect(html).toContain("最近的失败页面"); expect(html).toContain("搜索 · 人机验证 · HTTP 200"); expect(html).toContain('aria-expanded="false"'); expect(renderToStaticMarkup(createElement(SiteFailureSamples, { siteId: sample.siteId, items: [] }))).toBe(""); }); });