import { test } from "node:test"; import assert from "node:assert/strict"; import { QUOTE_CHECK_METHOD, QUOTE_DRIFT_THRESHOLD, cueWindowText, quoteDrifted, quoteTokens, quoteVerification, tokenRecall, } from "./verify"; test("tokens: lowercased, punctuation stripped, split on whitespace", () => { assert.deepEqual(quoteTokens("Don't stop — the U.S. bridge, OK?"), ["dont", "stop", "the", "us", "bridge", "ok"]); assert.deepEqual(quoteTokens("Café 2019\nnew"), ["café", "2019", "new"]); assert.deepEqual(quoteTokens("…"), []); }); test("recall: a verbatim quote scores 1 however much more the window says", () => { assert.equal(tokenRecall("I was there for it.", "The bridge opened in spring, I was there for it. Anyway."), 1); }); test("recall: each window token is used once; missing tokens lower the score", () => { assert.equal(tokenRecall("the the the", "the"), 1 / 3); assert.equal(tokenRecall("he opened the bridge himself", "the bridge opened"), 3 / 5); assert.equal(tokenRecall("", "anything"), 0); assert.equal(tokenRecall("words", ""), 0); }); test("the cue window takes every cue overlapping the span ± 5 s", () => { const cues = [ { start: 0, end: 4, text: "too early" }, { start: 4, end: 6, text: "edge before" }, { start: 10, end: 20, text: "inside" }, { start: 24, end: 26, text: "edge after" }, { start: 26, end: 30, text: "too late" }, ]; assert.equal(cueWindowText(cues, 10, 20), "edge before inside edge after"); assert.equal(cueWindowText(cues, 10, 20, 0), "inside"); }); test("the block: rounded score, the time, the method; drift below the threshold", () => { const v = quoteVerification("he opened the bridge himself", "the bridge opened", "2026-10-05T12:00:00.000Z"); assert.deepEqual(v, { quoteScore: 0.6, quoteCheckedAt: "2026-10-05T12:00:00.000Z", method: QUOTE_CHECK_METHOD }); assert.equal(quoteDrifted(v), false); assert.equal(quoteDrifted({ quoteScore: QUOTE_DRIFT_THRESHOLD - 0.01 }), true); assert.equal(quoteDrifted({}), true); assert.ok(!("voiceChecked" in v), "a voice is never vouched for"); });