Skip to content

Commit a99b0bd

Browse files
authored
Merge pull request #97 from hqwlkj/refactor/extract-dropdown-components
refactor: Extract dropdown components
2 parents abde38c + e0bde60 commit a99b0bd

9 files changed

Lines changed: 705 additions & 370 deletions

File tree

src/tests/sessionList.test.ts

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { test } from "node:test";
22
import assert from "node:assert/strict";
3-
import { formatSessionTitle } from "../ui";
3+
import { formatSessionTitle, filterSessions, formatSessionStatus } from "../ui";
4+
import type { SessionEntry } from "../session";
45

56
test("formatSessionTitle replaces newlines with spaces", () => {
67
assert.equal(formatSessionTitle("first line\nsecond line\r\nthird"), "first line second line third");
@@ -9,3 +10,108 @@ test("formatSessionTitle replaces newlines with spaces", () => {
910
test("formatSessionTitle truncates after normalizing whitespace", () => {
1011
assert.equal(formatSessionTitle("one\n two three", 10), "one two th…");
1112
});
13+
14+
test("formatSessionStatus maps status values to display labels", () => {
15+
assert.equal(formatSessionStatus("completed"), "done");
16+
assert.equal(formatSessionStatus("processing"), "running");
17+
assert.equal(formatSessionStatus("pending"), "pending");
18+
assert.equal(formatSessionStatus("waiting_for_user"), "waiting");
19+
assert.equal(formatSessionStatus("failed"), "failed");
20+
assert.equal(formatSessionStatus("interrupted"), "stopped");
21+
assert.equal(formatSessionStatus("unknown_status" as any), "unknown_status");
22+
});
23+
24+
test("filterSessions returns all sessions when query is empty", () => {
25+
const sessions = buildSessions([{ summary: "Fix login bug" }, { summary: "Add dark mode" }]);
26+
assert.equal(filterSessions(sessions, "").length, 2);
27+
assert.equal(filterSessions(sessions, " ").length, 2);
28+
});
29+
30+
test("filterSessions matches by summary (case-insensitive)", () => {
31+
const sessions = buildSessions([
32+
{ summary: "Fix login bug" },
33+
{ summary: "Add dark mode" },
34+
{ summary: "Refactor auth module" },
35+
]);
36+
37+
assert.equal(filterSessions(sessions, "login").length, 1);
38+
assert.equal(filterSessions(sessions, "LOGIN").length, 1);
39+
assert.equal(filterSessions(sessions, "Login").length, 1);
40+
});
41+
42+
test("filterSessions matches by status (case-insensitive)", () => {
43+
const sessions = buildSessions([
44+
{ summary: "Task 1", status: "completed" },
45+
{ summary: "Task 2", status: "failed" },
46+
{ summary: "Task 3", status: "completed" },
47+
]);
48+
49+
assert.equal(filterSessions(sessions, "failed").length, 1);
50+
assert.equal(filterSessions(sessions, "completed").length, 2);
51+
});
52+
53+
test("filterSessions matches by failReason", () => {
54+
const sessions = buildSessions([
55+
{ summary: "Task 1", status: "failed", failReason: "API key not found" },
56+
{ summary: "Task 2", status: "completed" },
57+
]);
58+
59+
assert.equal(filterSessions(sessions, "API key").length, 1);
60+
assert.equal(filterSessions(sessions, "not found").length, 1);
61+
});
62+
63+
test("filterSessions matches by assistantReply", () => {
64+
const sessions = buildSessions([
65+
{ summary: "Task 1", assistantReply: "The bug was fixed by updating the config." },
66+
{ summary: "Task 2", assistantReply: "Dark mode has been added successfully." },
67+
]);
68+
69+
assert.equal(filterSessions(sessions, "dark mode").length, 1);
70+
assert.equal(filterSessions(sessions, "config").length, 1);
71+
});
72+
73+
test("filterSessions returns empty array when no match", () => {
74+
const sessions = buildSessions([{ summary: "Fix login bug" }, { summary: "Add dark mode" }]);
75+
76+
assert.equal(filterSessions(sessions, "nonexistent").length, 0);
77+
});
78+
79+
test("filterSessions matches across multiple fields on same session", () => {
80+
const sessions = buildSessions([
81+
{ summary: "Fix login bug", status: "failed", failReason: "Timeout error" },
82+
{ summary: "Add dark mode", status: "completed" },
83+
]);
84+
85+
// Should match the first session via status
86+
assert.equal(filterSessions(sessions, "failed").length, 1);
87+
// Should match the first session via failReason
88+
assert.equal(filterSessions(sessions, "timeout").length, 1);
89+
// Partial summary match
90+
assert.equal(filterSessions(sessions, "login").length, 1);
91+
});
92+
93+
test("filterSessions handles sessions with null fields", () => {
94+
const sessions = buildSessions([{ summary: null }, { summary: "Valid summary" }]);
95+
96+
assert.equal(filterSessions(sessions, "valid").length, 1);
97+
assert.equal(filterSessions(sessions, "summary").length, 1);
98+
});
99+
100+
function buildSessions(overrides: Array<Partial<SessionEntry>>): SessionEntry[] {
101+
return overrides.map((override, i) => ({
102+
id: `session-${i}`,
103+
summary: override.summary ?? null,
104+
assistantReply: override.assistantReply ?? null,
105+
assistantThinking: null,
106+
assistantRefusal: null,
107+
toolCalls: null,
108+
status: override.status ?? "completed",
109+
failReason: override.failReason ?? null,
110+
usage: null,
111+
usagePerModel: null,
112+
activeTokens: 0,
113+
createTime: new Date().toISOString(),
114+
updateTime: new Date().toISOString(),
115+
processes: null,
116+
}));
117+
}

0 commit comments

Comments
 (0)