zcbot/tests/frontend_chat_drafts.test.mjs

51 lines
2.3 KiB
JavaScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import {
NEW_CHAT_DRAFT_ID,
chatDraftStorageKey,
clearChatDraft,
readChatDraft,
writeChatDraft,
} from "../web/static/js/chat_drafts.js";
class MemoryStorage {
constructor() { this.values = new Map(); }
getItem(key) { return this.values.get(key) ?? null; }
setItem(key, value) { this.values.set(key, String(value)); }
removeItem(key) { this.values.delete(key); }
}
test("chat drafts are isolated by user and conversation", () => {
const storage = new MemoryStorage();
writeChatDraft(storage, "user-a", "task-1", "任务一草稿", 1);
writeChatDraft(storage, "user-a", "task-2", "任务二草稿", 2);
writeChatDraft(storage, "user-b", "task-1", "另一用户草稿", 3);
assert.equal(readChatDraft(storage, "user-a", "task-1"), "任务一草稿");
assert.equal(readChatDraft(storage, "user-a", "task-2"), "任务二草稿");
assert.equal(readChatDraft(storage, "user-b", "task-1"), "另一用户草稿");
assert.notEqual(chatDraftStorageKey("user-a"), chatDraftStorageKey("user-b"));
});
test("new conversation draft persists and blank content clears it", () => {
const storage = new MemoryStorage();
writeChatDraft(storage, "user-a", NEW_CHAT_DRAFT_ID, "未创建对话", 1);
assert.equal(readChatDraft(storage, "user-a", NEW_CHAT_DRAFT_ID), "未创建对话");
clearChatDraft(storage, "user-a", NEW_CHAT_DRAFT_ID);
assert.equal(readChatDraft(storage, "user-a", NEW_CHAT_DRAFT_ID), "");
assert.equal(storage.getItem(chatDraftStorageKey("user-a")), null);
});
test("chat integrates draft save, restore, migration, and sent cleanup", () => {
const source = readFileSync(new URL("../web/static/js/chat.js", import.meta.url), "utf8");
assert.match(source, /export async function selectTask\(tid\) \{\s*persistComposerDraft\(\)/);
assert.match(source, /state\.taskId = tid;\s*restoreComposerDraft\(tid\)/);
assert.match(source, /persistComposerDraft\(t\.task_id\)/);
assert.match(source, /clearChatDraft\(localStorage, state\.userId, taskId\)/);
assert.match(source, /addEventListener\("input", \(\) => \{\s*scheduleComposerDraftSave\(\)/);
assert.match(source, /addEventListener\("pagehide", \(\) => persistComposerDraft\(\)\)/);
});