summaryrefslogtreecommitdiff
path: root/workers/apex/test/uagate.test.ts
blob: f4c16c66a750ad04150dfec04c6a9cce574b6246 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { describe, it, expect } from "vitest";
import { uaVerdict } from "../src/uagate";
import policy from "../ua-policy.json";

describe("UA gate (§3.2.1) — ships log-only for AI crawlers", () => {
  it("search engines always allowed", () => {
    expect(uaVerdict("Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)", policy)).toBe("allow");
    expect(uaVerdict("Mozilla/5.0 (compatible; bingbot/2.0)", policy)).toBe("allow");
  });
  it("AI-training crawlers are log-only initially", () => {
    expect(uaVerdict("GPTBot/1.0", policy)).toBe("log");
    expect(uaVerdict("CCBot/2.0", policy)).toBe("log");
  });
  it("named abusers blocked", () => {
    expect(uaVerdict("EvilScraper/0.1", { ...policy, block: ["EvilScraper"] })).toBe("block");
  });
  it("unknown UA → allow (fail-open for humans)", () => {
    expect(uaVerdict("Mozilla/5.0 (X11; Linux x86_64) Firefox/128.0", policy)).toBe("allow");
  });
  it("block takes precedence over allow on a UA matching both lists", () => {
    const dualMatch = { ...policy, allow: ["Googlebot"], block: ["Googlebot EvilScraper"] };
    expect(uaVerdict("Mozilla/5.0 (compatible; Googlebot EvilScraper/1.0)", dualMatch)).toBe("block");
  });
});