Files
pikasTech-HWLAB/web/hwlab-cloud-web/session-tabs.test.ts
T

104 lines
4.0 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import { activeSessionKeyFromRuntime, sessionTabsFromConversations, sessionTabsFromMessages } from "./app-session-tabs.ts";
test("session tabs group messages and filter the active session", () => {
const messages = [
message("user", "ses_alpha", "cnv_alpha", "trc_alpha_1", "sent", "2026-06-03T00:00:01Z"),
message("agent", "ses_alpha", "cnv_alpha", "trc_alpha_1", "completed", "2026-06-03T00:00:02Z"),
message("user", "ses_beta", "cnv_beta", "trc_beta_1", "sent", "2026-06-03T00:00:03Z"),
message("agent", "ses_beta", "cnv_beta", "trc_beta_1", "running", "2026-06-03T00:00:04Z")
];
const view = sessionTabsFromMessages(messages, { activeSessionKey: "ses_alpha" });
assert.equal(view.tabs.length, 2);
assert.equal(view.activeKey, "ses_alpha");
assert.deepEqual(view.messages.map((item) => item.traceId), ["trc_alpha_1", "trc_alpha_1"]);
assert.equal(view.tabs.find((tab) => tab.key === "ses_beta")?.status, "running");
});
test("session tabs default to newest session when no preferred key is active", () => {
const messages = [
message("agent", "ses_old", "cnv_old", "trc_old", "completed", "2026-06-03T00:00:01Z"),
message("agent", "ses_new", "cnv_new", "trc_new", "completed", "2026-06-03T00:00:05Z")
];
const view = sessionTabsFromMessages(messages, { activeSessionKey: "missing" });
assert.equal(view.activeKey, "ses_new");
assert.deepEqual(view.messages.map((item) => item.sessionId), ["ses_new"]);
});
test("session tabs keep first-turn user and agent messages together when session id arrives later", () => {
const messages = [
{ ...message("user", null, "cnv_first", "trc_first", "sent", "2026-06-03T00:00:01Z"), sessionId: null },
message("agent", "ses_first", "cnv_first", "trc_first", "completed", "2026-06-03T00:00:02Z")
];
const view = sessionTabsFromMessages(messages, { activeSessionKey: "cnv_first" });
assert.equal(view.tabs.length, 1);
assert.equal(view.activeKey, "ses_first");
assert.equal(view.tabs[0].status, "completed");
assert.deepEqual(view.messages.map((item) => item.role), ["user", "agent"]);
});
test("runtime active session prefers current request session before global state", () => {
const key = activeSessionKeyFromRuntime({
currentRequest: { sessionId: "ses_current", conversationId: "cnv_current" },
sessionId: "ses_global",
conversationId: "cnv_global"
});
assert.equal(key, "ses_current");
});
test("session tabs use account conversations and keep the selected session active", () => {
const view = sessionTabsFromConversations([
conversation("cnv_old", "ses_old", "trc_old", "idle", "2026-06-03T00:00:01Z"),
conversation("cnv_new", "ses_new", "trc_new", "running", "2026-06-03T00:00:03Z")
], { selectedConversationId: "cnv_old" });
assert.equal(view.tabs.length, 2);
assert.equal(view.activeConversation?.conversationId, "cnv_old");
assert.equal(view.tabs[0].conversationId, "cnv_new");
assert.equal(view.tabs.find((tab) => tab.conversationId === "cnv_new")?.subtitle, "处理中");
});
test("session tabs default to newest visible conversation", () => {
const view = sessionTabsFromConversations([
conversation("cnv_a", "ses_a", "trc_a", "idle", "2026-06-03T00:00:01Z"),
conversation("cnv_b", "ses_b", "trc_b", "completed", "2026-06-03T00:00:05Z")
], { selectedConversationId: "missing" });
assert.equal(view.activeConversation?.conversationId, "cnv_b");
assert.equal(view.activeKey, "ses_b");
});
function message(role, sessionId, conversationId, traceId, status, createdAt) {
return {
id: `${role}_${traceId}`,
role,
title: role,
text: traceId,
status,
sessionId,
conversationId,
traceId,
createdAt
};
}
function conversation(conversationId, sessionId, traceId, status, updatedAt) {
return {
conversationId,
sessionId,
status,
updatedAt,
lastTraceId: traceId,
messages: [{ role: "agent", text: traceId, status, traceId, updatedAt }]
};
}