import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; import { isAutoDerivedSessionTitle, shouldGenerateSessionTitle } from "../src/lib/session-title.ts"; // BUG-987 and BUG-992 were two copies of one rule with nobody comparing them. // This test reads the SQL predicate from the migration. Do not paste a second copy. const migration = readFileSync( new URL("../supabase/migrations/20260925010000_rectification_session_title_result.sql", import.meta.url), "utf8", ); const functionBody = migration.match( /create or replace function public\.rectification_session_title_is_automatic[\s\S]*?as \$\$([\s\S]*?)\$\$;/, ); assert.ok(functionBody, "migration must define rectification_session_title_is_automatic"); const pattern = functionBody[1].match(/~ '([^']+)'/)?.[1]; assert.ok(pattern, "automatic-title predicate must be one quoted regex"); const sqlWouldOverwrite = new RegExp(pattern); const EN_DASH = "\u2013"; const cases: ReadonlyArray = [ ["生时校正", true], ["生时校正 · 05:07", true], [`生时校正 · 05:00${EN_DASH}05:15`, true], ["生时校正 · 9月17日", true], ["9月17日 · 生时校正", true], ["9月17日 · 生时校正 09:35", true], ["我的校正", false], ["今日节奏 · 9月17日", true], ["9月17日 · 今日节奏", true], ["9月17日 · 今日节奏 09:35", true], ]; test("SQL overwrite predicate and isAutoDerivedSessionTitle agree", () => { assert.match(pattern, new RegExp(String.raw`\[0-9\]\{2\}:\[0-9\]\{2\}${EN_DASH}\[0-9\]\{2\}:\[0-9\]\{2\}`)); assert.doesNotMatch(pattern, /\[0-9\]\{2\}:\[0-9\]\{2\}-\[0-9\]\{2\}:\[0-9\]\{2\}/); for (const [title, automatic] of cases) { assert.equal(sqlWouldOverwrite.test(title), automatic, `sql ${title}`); assert.equal(isAutoDerivedSessionTitle(title), automatic, `ts ${title}`); } assert.equal(sqlWouldOverwrite.test(`生时校正 · 05:00-05:15`), false); assert.equal(shouldGenerateSessionTitle({ title: "生时校正", sessionType: "birth_time_rectification" }, []), false); assert.equal(shouldGenerateSessionTitle({ title: "生时校正 · 05:07", sessionType: "birth_time_rectification" }, []), false); });