feat: group imported threads into project archives
This commit is contained in:
121
tests/conversation-home-items.test.ts
Normal file
121
tests/conversation-home-items.test.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { mkdtemp, rm } from "node:fs/promises";
|
||||
|
||||
let runtimeRoot = "";
|
||||
let readState: (typeof import("../src/lib/boss-data"))["readState"];
|
||||
let getConversationHomeItems: (typeof import("../src/lib/boss-projections"))["getConversationHomeItems"];
|
||||
let getConversationFolderView: (typeof import("../src/lib/boss-projections"))["getConversationFolderView"];
|
||||
|
||||
async function setup() {
|
||||
if (runtimeRoot) return;
|
||||
runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-conversation-home-"));
|
||||
process.env.BOSS_RUNTIME_ROOT = runtimeRoot;
|
||||
process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json");
|
||||
|
||||
const [data, projections] = await Promise.all([
|
||||
import("../src/lib/boss-data.ts"),
|
||||
import("../src/lib/boss-projections.ts"),
|
||||
]);
|
||||
readState = data.readState;
|
||||
getConversationHomeItems = projections.getConversationHomeItems;
|
||||
getConversationFolderView = projections.getConversationFolderView;
|
||||
}
|
||||
|
||||
test.after(async () => {
|
||||
if (runtimeRoot) {
|
||||
await rm(runtimeRoot, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
function buildImportedThreadProject(deviceId: string, id: string, folderName: string, codexFolderRef: string, threadName: string, threadId: string, lastMessageAt: string) {
|
||||
return {
|
||||
id,
|
||||
name: threadName,
|
||||
pinned: false,
|
||||
systemPinned: false,
|
||||
deviceIds: [deviceId],
|
||||
preview: `最近消息:${threadName}`,
|
||||
updatedAt: lastMessageAt,
|
||||
lastMessageAt,
|
||||
isGroup: false,
|
||||
threadMeta: {
|
||||
projectId: id,
|
||||
threadId,
|
||||
threadDisplayName: threadName,
|
||||
folderName,
|
||||
activityIconCount: 1,
|
||||
updatedAt: lastMessageAt,
|
||||
codexFolderRef,
|
||||
codexThreadRef: threadId,
|
||||
},
|
||||
groupMembers: [],
|
||||
createdByAgent: true,
|
||||
collaborationMode: "development" as const,
|
||||
approvalState: "not_required" as const,
|
||||
unreadCount: 0,
|
||||
riskLevel: "low" as const,
|
||||
messages: [],
|
||||
goals: [],
|
||||
versions: [],
|
||||
};
|
||||
}
|
||||
|
||||
test("conversation home groups multiple imported threads by folder while keeping single-thread projects direct", async () => {
|
||||
await setup();
|
||||
const state = await readState();
|
||||
|
||||
state.projects = state.projects.filter((project) => project.id === "master-agent");
|
||||
state.projects.push(
|
||||
buildImportedThreadProject(
|
||||
"mac-studio",
|
||||
"boss-thread-1",
|
||||
"Boss",
|
||||
"boss",
|
||||
"归档确认",
|
||||
"thread-1",
|
||||
"2026-03-30T11:00:00+08:00",
|
||||
),
|
||||
buildImportedThreadProject(
|
||||
"mac-studio",
|
||||
"boss-thread-2",
|
||||
"Boss",
|
||||
"boss",
|
||||
"发布回滚",
|
||||
"thread-2",
|
||||
"2026-03-30T12:00:00+08:00",
|
||||
),
|
||||
buildImportedThreadProject(
|
||||
"mac-studio",
|
||||
"yuandi-thread-1",
|
||||
"源地",
|
||||
"yuandi",
|
||||
"首页回归",
|
||||
"thread-3",
|
||||
"2026-03-30T10:00:00+08:00",
|
||||
),
|
||||
);
|
||||
|
||||
const homeItems = getConversationHomeItems(state);
|
||||
const bossFolder = homeItems.find((item) => item.conversationType === "folder_archive");
|
||||
const directThread = homeItems.find((item) => item.projectId === "yuandi-thread-1");
|
||||
|
||||
assert.ok(bossFolder, "expected grouped folder item for multi-thread project");
|
||||
assert.equal(bossFolder?.threadTitle, "Boss");
|
||||
assert.equal(bossFolder?.threadCount, 2);
|
||||
assert.equal(bossFolder?.folderKey, "mac-studio:boss");
|
||||
|
||||
assert.ok(directThread, "expected single-thread project to stay direct");
|
||||
assert.equal(directThread?.conversationType, "single_device");
|
||||
assert.equal(directThread?.threadTitle, "首页回归");
|
||||
|
||||
const folderView = getConversationFolderView(state, "mac-studio:boss");
|
||||
assert.ok(folderView, "expected folder detail view");
|
||||
assert.equal(folderView?.threadCount, 2);
|
||||
assert.deepEqual(
|
||||
folderView?.threads.map((item) => item.threadTitle),
|
||||
["发布回滚", "归档确认"],
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user