Files
Jyotisha/frontend/tests/session-title-agent.test.ts
T

85 lines
3.7 KiB
TypeScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import {
generateSessionTitle,
sanitizeSessionTitle,
shouldGenerateSessionTitle,
} from "../src/lib/session-title-agent.ts";
import { consultationAgentPublicEventSchema } from "../src/lib/consultation-agent-events.ts";
test("sanitizeSessionTitle strips quotes and trailing punctuation", () => {
assert.equal(sanitizeSessionTitle("「半年内换工作时机」。"), "半年内换工作时机");
assert.equal(sanitizeSessionTitle("\"半年内换工作时机\""), "半年内换工作时机");
});
test("sanitizeSessionTitle clips titles longer than 14 characters", () => {
assert.equal(sanitizeSessionTitle("今年下半年要不要换工作以及去哪座城市"), "今年下半年要不要换工作以及去");
});
test("sanitizeSessionTitle rejects short, wrapped, generic, or birth-stamped titles", () => {
assert.equal(sanitizeSessionTitle("问"), null);
assert.equal(sanitizeSessionTitle("换工作\n时机"), null);
assert.equal(sanitizeSessionTitle("新对话"), null);
assert.equal(sanitizeSessionTitle("1990年3月换工作"), null);
assert.equal(sanitizeSessionTitle("凌晨 04:50 的节奏"), null);
});
test("sanitizeSessionTitle keeps a valid summary", () => {
assert.equal(sanitizeSessionTitle("半年内换工作时机"), "半年内换工作时机");
});
test("shouldGenerateSessionTitle only runs on a first-round auto title", () => {
assert.equal(shouldGenerateSessionTitle({ title: "新对话", sessionType: "consultation" }, []), true);
assert.equal(shouldGenerateSessionTitle({ title: "我想问一下最近半年换工…", sessionType: "consultation" }, []), true);
assert.equal(shouldGenerateSessionTitle({ title: "新对话", sessionType: "consultation" }, [{ role: "user" }]), false);
assert.equal(shouldGenerateSessionTitle({ title: "新对话", sessionType: "birth_time_rectification" }, []), false);
assert.equal(shouldGenerateSessionTitle({ title: "9月6日 · 今日节奏", sessionType: "consultation" }, []), false);
assert.equal(shouldGenerateSessionTitle({ title: "半年内换工作时机", sessionType: "consultation" }, []), false);
});
test("generateSessionTitle times out to null and keeps the timer ref'd", async () => {
const source = readFileSync(new URL("../src/lib/session-title-agent.ts", import.meta.url), "utf8");
assert.doesNotMatch(source, /AbortSignal\.timeout/);
assert.doesNotMatch(source, /\.unref\(/);
assert.match(source, /clearTimeout/);
const pending = new Set<unknown>();
let created = 0;
const realSetTimeout = globalThis.setTimeout;
const realClearTimeout = globalThis.clearTimeout;
globalThis.setTimeout = ((handler: TimerHandler, delay?: number, ...args: unknown[]) => {
created += 1;
const id = realSetTimeout(handler, delay, ...args);
pending.add(id);
return id;
}) as typeof setTimeout;
globalThis.clearTimeout = ((id?: ReturnType<typeof setTimeout>) => {
pending.delete(id);
realClearTimeout(id);
}) as typeof clearTimeout;
try {
const title = await generateSessionTitle({
question: "我想问一下最近半年换工作的时机",
timeoutMs: 20,
generateText: () => new Promise(() => {}),
});
assert.equal(title, null);
assert.ok(created >= 1);
assert.equal(pending.size, 0);
} finally {
globalThis.setTimeout = realSetTimeout;
globalThis.clearTimeout = realClearTimeout;
}
});
test("consultation public events include session.title", () => {
const parsed = consultationAgentPublicEventSchema.parse({
type: "session.title",
title: "半年内换工作时机",
});
assert.equal(parsed.type, "session.title");
assert.equal(parsed.title, "半年内换工作时机");
});