@asifkibria/claude-code-toolkit 1.3.1 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -1
- package/dist/__tests__/alerts.test.d.ts +2 -0
- package/dist/__tests__/alerts.test.d.ts.map +1 -0
- package/dist/__tests__/alerts.test.js +195 -0
- package/dist/__tests__/alerts.test.js.map +1 -0
- package/dist/__tests__/bookmarks.test.d.ts +2 -0
- package/dist/__tests__/bookmarks.test.d.ts.map +1 -0
- package/dist/__tests__/bookmarks.test.js +170 -0
- package/dist/__tests__/bookmarks.test.js.map +1 -0
- package/dist/__tests__/bulk.test.d.ts +2 -0
- package/dist/__tests__/bulk.test.d.ts.map +1 -0
- package/dist/__tests__/bulk.test.js +245 -0
- package/dist/__tests__/bulk.test.js.map +1 -0
- package/dist/__tests__/dashboard.test.js +2 -2
- package/dist/__tests__/dashboard.test.js.map +1 -1
- package/dist/__tests__/git.test.d.ts +2 -0
- package/dist/__tests__/git.test.d.ts.map +1 -0
- package/dist/__tests__/git.test.js +216 -0
- package/dist/__tests__/git.test.js.map +1 -0
- package/dist/__tests__/logs.test.d.ts +2 -0
- package/dist/__tests__/logs.test.d.ts.map +1 -0
- package/dist/__tests__/logs.test.js +196 -0
- package/dist/__tests__/logs.test.js.map +1 -0
- package/dist/__tests__/search.test.d.ts +2 -0
- package/dist/__tests__/search.test.d.ts.map +1 -0
- package/dist/__tests__/search.test.js +155 -0
- package/dist/__tests__/search.test.js.map +1 -0
- package/dist/cli.js +269 -12
- package/dist/cli.js.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/bookmarks.d.ts +69 -0
- package/dist/lib/bookmarks.d.ts.map +1 -0
- package/dist/lib/bookmarks.js +225 -0
- package/dist/lib/bookmarks.js.map +1 -0
- package/dist/lib/bulk.d.ts +78 -0
- package/dist/lib/bulk.d.ts.map +1 -0
- package/dist/lib/bulk.js +257 -0
- package/dist/lib/bulk.js.map +1 -0
- package/dist/lib/dashboard-ui.d.ts.map +1 -1
- package/dist/lib/dashboard-ui.js +425 -19
- package/dist/lib/dashboard-ui.js.map +1 -1
- package/dist/lib/dashboard.d.ts.map +1 -1
- package/dist/lib/dashboard.js +398 -20
- package/dist/lib/dashboard.js.map +1 -1
- package/dist/lib/export.d.ts +41 -0
- package/dist/lib/export.d.ts.map +1 -0
- package/dist/lib/export.js +428 -0
- package/dist/lib/export.js.map +1 -0
- package/dist/lib/git.d.ts.map +1 -1
- package/dist/lib/git.js +2 -1
- package/dist/lib/git.js.map +1 -1
- package/dist/lib/mcp-validator.d.ts.map +1 -1
- package/dist/lib/mcp-validator.js +2 -1
- package/dist/lib/mcp-validator.js.map +1 -1
- package/dist/lib/scanner.d.ts.map +1 -1
- package/dist/lib/scanner.js +2 -12
- package/dist/lib/scanner.js.map +1 -1
- package/dist/lib/security.d.ts.map +1 -1
- package/dist/lib/security.js +12 -1
- package/dist/lib/security.js.map +1 -1
- package/dist/lib/session-recovery.d.ts.map +1 -1
- package/dist/lib/session-recovery.js +25 -2
- package/dist/lib/session-recovery.js.map +1 -1
- package/dist/lib/utils.d.ts +15 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +78 -0
- package/dist/lib/utils.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Then ask Claude: "Check your health" or "Fix any issues"
|
|
|
52
52
|
| **Session Recovery** | Fix broken sessions, repair corrupted files, extract content |
|
|
53
53
|
| **Search** | Full-text search across all conversations |
|
|
54
54
|
| **Security** | Secret detection, PII scanning, session auditing |
|
|
55
|
-
| **Storage** | Analytics, cleanup, archiving, snapshots |
|
|
55
|
+
| **Storage** | Analytics, cleanup, archiving, snapshots, **project purge** |
|
|
56
56
|
| **Monitoring** | Web dashboard, alerts, quotas, real-time updates |
|
|
57
57
|
| **MCP** | Server validation, performance tracking |
|
|
58
58
|
| **Git** | Link sessions to branches/commits |
|
|
@@ -128,6 +128,18 @@ cct archive --days 60 # Archive old conversations
|
|
|
128
128
|
cct trace clean # Selective trace cleanup
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
+
### 5b. Project-Level Cleanup
|
|
132
|
+
|
|
133
|
+
Delete all sessions, files, and directories for a specific project.
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
cct bulk-delete --project "my-app" # Delete sessions for a project
|
|
137
|
+
cct bulk-archive --project "my-app" # Archive sessions for a project
|
|
138
|
+
cct bulk-delete --project "my-app" --days 30 # Only sessions older than 30 days
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Dashboard**: The Sessions tab has a project filter dropdown with **Archive All**, **Delete Sessions**, and **Purge Project** buttons. Purge removes the entire project directory from `~/.claude/projects/`.
|
|
142
|
+
|
|
131
143
|
### 6. Git Integration
|
|
132
144
|
|
|
133
145
|
Link your Claude sessions to git branches and commits.
|
|
@@ -226,6 +238,9 @@ cct mcp-validate --test
|
|
|
226
238
|
| `cct restore` | Restore from backup |
|
|
227
239
|
| `cct cleanup` | Delete old backups |
|
|
228
240
|
| `cct export` | Export conversation |
|
|
241
|
+
| `cct bulk-delete` | **Delete sessions by project/age** |
|
|
242
|
+
| `cct bulk-archive` | **Archive sessions by project/age** |
|
|
243
|
+
| `cct bulk-export` | Export multiple sessions |
|
|
229
244
|
|
|
230
245
|
---
|
|
231
246
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alerts.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/alerts.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import * as os from "os";
|
|
5
|
+
import { checkAlerts, checkQuotas, formatAlertsReport, formatQuotasReport, } from "../lib/alerts.js";
|
|
6
|
+
const TEST_DIR = path.join(os.tmpdir(), "cct-alerts-test");
|
|
7
|
+
const PROJECTS_DIR = path.join(TEST_DIR, "projects");
|
|
8
|
+
function createSession(projectName, fileName, content, sizeOverride) {
|
|
9
|
+
const dir = path.join(PROJECTS_DIR, projectName);
|
|
10
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
11
|
+
const filePath = path.join(dir, fileName);
|
|
12
|
+
fs.writeFileSync(filePath, content, "utf-8");
|
|
13
|
+
return filePath;
|
|
14
|
+
}
|
|
15
|
+
function setFileAge(filePath, days) {
|
|
16
|
+
const mtime = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
|
17
|
+
fs.utimesSync(filePath, mtime, mtime);
|
|
18
|
+
}
|
|
19
|
+
describe("Alerts Module", () => {
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
if (fs.existsSync(TEST_DIR))
|
|
22
|
+
fs.rmSync(TEST_DIR, { recursive: true });
|
|
23
|
+
fs.mkdirSync(PROJECTS_DIR, { recursive: true });
|
|
24
|
+
});
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
if (fs.existsSync(TEST_DIR))
|
|
27
|
+
fs.rmSync(TEST_DIR, { recursive: true });
|
|
28
|
+
});
|
|
29
|
+
describe("checkAlerts", () => {
|
|
30
|
+
it("should return empty alerts when no projects dir exists", () => {
|
|
31
|
+
const result = checkAlerts(path.join(TEST_DIR, "nonexistent"));
|
|
32
|
+
expect(result.alerts).toHaveLength(0);
|
|
33
|
+
expect(result.critical).toBe(0);
|
|
34
|
+
expect(result.warning).toBe(0);
|
|
35
|
+
expect(result.info).toBe(0);
|
|
36
|
+
});
|
|
37
|
+
it("should return no alerts for clean small session set", () => {
|
|
38
|
+
createSession("proj1", "session1.jsonl", JSON.stringify({ type: "user", message: { role: "user", content: [] } }));
|
|
39
|
+
const result = checkAlerts(TEST_DIR);
|
|
40
|
+
expect(result.alerts.length).toBe(0);
|
|
41
|
+
});
|
|
42
|
+
it("should warn when session count exceeds limit", () => {
|
|
43
|
+
for (let i = 0; i < 5; i++) {
|
|
44
|
+
createSession(`proj${i}`, `session${i}.jsonl`, JSON.stringify({ type: "user" }));
|
|
45
|
+
}
|
|
46
|
+
const result = checkAlerts(TEST_DIR, { maxSessions: 3 });
|
|
47
|
+
const sessionAlert = result.alerts.find(a => a.category === "session" && a.title.includes("count"));
|
|
48
|
+
expect(sessionAlert).toBeDefined();
|
|
49
|
+
expect(sessionAlert.severity).toBe("warning");
|
|
50
|
+
});
|
|
51
|
+
it("should detect corrupted sessions", () => {
|
|
52
|
+
createSession("proj1", "corrupt.jsonl", "not valid json");
|
|
53
|
+
const result = checkAlerts(TEST_DIR);
|
|
54
|
+
const corruptAlert = result.alerts.find(a => a.title.includes("Corrupted"));
|
|
55
|
+
expect(corruptAlert).toBeDefined();
|
|
56
|
+
expect(corruptAlert.severity).toBe("warning");
|
|
57
|
+
});
|
|
58
|
+
it("should detect empty sessions when more than 3 exist", () => {
|
|
59
|
+
for (let i = 0; i < 4; i++) {
|
|
60
|
+
createSession("proj1", `empty${i}.jsonl`, "");
|
|
61
|
+
}
|
|
62
|
+
const result = checkAlerts(TEST_DIR);
|
|
63
|
+
const emptyAlert = result.alerts.find(a => a.title.includes("Empty"));
|
|
64
|
+
expect(emptyAlert).toBeDefined();
|
|
65
|
+
expect(emptyAlert.severity).toBe("info");
|
|
66
|
+
});
|
|
67
|
+
it("should create info alert for old sessions", () => {
|
|
68
|
+
const f = createSession("proj1", "old.jsonl", JSON.stringify({ type: "user" }));
|
|
69
|
+
setFileAge(f, 100);
|
|
70
|
+
const result = checkAlerts(TEST_DIR, { maxRetentionDays: 30 });
|
|
71
|
+
const retentionAlert = result.alerts.find(a => a.category === "retention");
|
|
72
|
+
expect(retentionAlert).toBeDefined();
|
|
73
|
+
expect(retentionAlert.severity).toBe("info");
|
|
74
|
+
});
|
|
75
|
+
it("should sort alerts with critical first", () => {
|
|
76
|
+
for (let i = 0; i < 5; i++) {
|
|
77
|
+
createSession(`proj${i}`, `s${i}.jsonl`, JSON.stringify({ type: "user" }));
|
|
78
|
+
}
|
|
79
|
+
const f = createSession("oldproj", "old.jsonl", JSON.stringify({ type: "user" }));
|
|
80
|
+
setFileAge(f, 100);
|
|
81
|
+
const result = checkAlerts(TEST_DIR, { maxSessions: 3, maxRetentionDays: 30 });
|
|
82
|
+
if (result.alerts.length > 1) {
|
|
83
|
+
const severityOrder = { critical: 0, warning: 1, info: 2 };
|
|
84
|
+
for (let i = 0; i < result.alerts.length - 1; i++) {
|
|
85
|
+
expect(severityOrder[result.alerts[i].severity]).toBeLessThanOrEqual(severityOrder[result.alerts[i + 1].severity]);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
it("should include actionable field and action text", () => {
|
|
90
|
+
for (let i = 0; i < 5; i++) {
|
|
91
|
+
createSession(`proj${i}`, `s${i}.jsonl`, JSON.stringify({ type: "user" }));
|
|
92
|
+
}
|
|
93
|
+
const result = checkAlerts(TEST_DIR, { maxSessions: 3 });
|
|
94
|
+
const actionableAlerts = result.alerts.filter(a => a.actionable);
|
|
95
|
+
expect(actionableAlerts.length).toBeGreaterThan(0);
|
|
96
|
+
expect(actionableAlerts[0].action).toBeTruthy();
|
|
97
|
+
});
|
|
98
|
+
it("should count alert severities correctly", () => {
|
|
99
|
+
createSession("proj1", "corrupt.jsonl", "not valid json");
|
|
100
|
+
for (let i = 0; i < 5; i++) {
|
|
101
|
+
createSession(`proj${i}`, `s${i}.jsonl`, JSON.stringify({ type: "user" }));
|
|
102
|
+
}
|
|
103
|
+
const result = checkAlerts(TEST_DIR, { maxSessions: 3 });
|
|
104
|
+
expect(result.warning).toBe(result.alerts.filter(a => a.severity === "warning").length);
|
|
105
|
+
expect(result.critical).toBe(result.alerts.filter(a => a.severity === "critical").length);
|
|
106
|
+
expect(result.info).toBe(result.alerts.filter(a => a.severity === "info").length);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe("checkQuotas", () => {
|
|
110
|
+
it("should return empty array when no projects dir exists", () => {
|
|
111
|
+
const result = checkQuotas(undefined, path.join(TEST_DIR, "nonexistent"));
|
|
112
|
+
expect(result).toHaveLength(0);
|
|
113
|
+
});
|
|
114
|
+
it("should return quotas for storage and session count", () => {
|
|
115
|
+
createSession("proj1", "s1.jsonl", JSON.stringify({ type: "user" }));
|
|
116
|
+
const result = checkQuotas({ maxStorageMB: 500, maxSessions: 100 }, TEST_DIR);
|
|
117
|
+
const storageQuota = result.find(q => q.name === "Storage");
|
|
118
|
+
const sessionQuota = result.find(q => q.name === "Sessions");
|
|
119
|
+
expect(storageQuota).toBeDefined();
|
|
120
|
+
expect(sessionQuota).toBeDefined();
|
|
121
|
+
});
|
|
122
|
+
it("should mark quota as exceeded when over limit", () => {
|
|
123
|
+
for (let i = 0; i < 5; i++) {
|
|
124
|
+
createSession(`proj${i}`, `s${i}.jsonl`, JSON.stringify({ type: "user" }));
|
|
125
|
+
}
|
|
126
|
+
const result = checkQuotas({ maxSessions: 3 }, TEST_DIR);
|
|
127
|
+
const sessionQuota = result.find(q => q.name === "Sessions");
|
|
128
|
+
expect(sessionQuota.exceeded).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
it("should not mark quota as exceeded when under limit", () => {
|
|
131
|
+
createSession("proj1", "s1.jsonl", JSON.stringify({ type: "user" }));
|
|
132
|
+
const result = checkQuotas({ maxSessions: 100 }, TEST_DIR);
|
|
133
|
+
const sessionQuota = result.find(q => q.name === "Sessions");
|
|
134
|
+
expect(sessionQuota.exceeded).toBe(false);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
describe("formatAlertsReport", () => {
|
|
138
|
+
it("should show clean message when no alerts", () => {
|
|
139
|
+
const report = { alerts: [], critical: 0, warning: 0, info: 0, generatedAt: new Date() };
|
|
140
|
+
const output = formatAlertsReport(report);
|
|
141
|
+
expect(output).toContain("No alerts");
|
|
142
|
+
});
|
|
143
|
+
it("should include alert title and message in output", () => {
|
|
144
|
+
const report = {
|
|
145
|
+
alerts: [{
|
|
146
|
+
id: "test",
|
|
147
|
+
severity: "warning",
|
|
148
|
+
category: "session",
|
|
149
|
+
title: "Too many sessions",
|
|
150
|
+
message: "100 sessions detected.",
|
|
151
|
+
timestamp: new Date(),
|
|
152
|
+
actionable: true,
|
|
153
|
+
action: "Run cct retention",
|
|
154
|
+
}],
|
|
155
|
+
critical: 0,
|
|
156
|
+
warning: 1,
|
|
157
|
+
info: 0,
|
|
158
|
+
generatedAt: new Date(),
|
|
159
|
+
};
|
|
160
|
+
const output = formatAlertsReport(report);
|
|
161
|
+
expect(output).toContain("Too many sessions");
|
|
162
|
+
expect(output).toContain("100 sessions detected.");
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
describe("formatQuotasReport", () => {
|
|
166
|
+
it("should show no quotas message when empty", () => {
|
|
167
|
+
const output = formatQuotasReport([]);
|
|
168
|
+
expect(output).toContain("No quotas");
|
|
169
|
+
});
|
|
170
|
+
it("should include quota name and percentage", () => {
|
|
171
|
+
const output = formatQuotasReport([{
|
|
172
|
+
name: "Storage",
|
|
173
|
+
current: 50,
|
|
174
|
+
limit: 500,
|
|
175
|
+
unit: "MB",
|
|
176
|
+
exceeded: false,
|
|
177
|
+
percentage: 10,
|
|
178
|
+
}]);
|
|
179
|
+
expect(output).toContain("Storage");
|
|
180
|
+
expect(output).toContain("10%");
|
|
181
|
+
});
|
|
182
|
+
it("should indicate exceeded quotas", () => {
|
|
183
|
+
const output = formatQuotasReport([{
|
|
184
|
+
name: "Sessions",
|
|
185
|
+
current: 150,
|
|
186
|
+
limit: 100,
|
|
187
|
+
unit: "sessions",
|
|
188
|
+
exceeded: true,
|
|
189
|
+
percentage: 150,
|
|
190
|
+
}]);
|
|
191
|
+
expect(output).toContain("EXCEEDED");
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
//# sourceMappingURL=alerts.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alerts.test.js","sourceRoot":"","sources":["../../src/__tests__/alerts.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bookmarks.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/bookmarks.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
// bookmarks.ts computes BOOKMARKS_FILE at module load using os.homedir().
|
|
5
|
+
// Use a hardcoded path to avoid circular mock issues.
|
|
6
|
+
const TEST_DIR = "/tmp/cct-bookmarks-test";
|
|
7
|
+
const BOOKMARKS_FILE = path.join(TEST_DIR, ".claude", "bookmarks.json");
|
|
8
|
+
vi.mock("os", () => ({
|
|
9
|
+
homedir: () => TEST_DIR,
|
|
10
|
+
tmpdir: () => "/tmp",
|
|
11
|
+
}));
|
|
12
|
+
async function getModule() {
|
|
13
|
+
vi.resetModules();
|
|
14
|
+
return import("../lib/bookmarks.js");
|
|
15
|
+
}
|
|
16
|
+
describe("Bookmarks Module", () => {
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
if (fs.existsSync(TEST_DIR))
|
|
19
|
+
fs.rmSync(TEST_DIR, { recursive: true });
|
|
20
|
+
fs.mkdirSync(path.join(TEST_DIR, ".claude"), { recursive: true });
|
|
21
|
+
vi.resetModules();
|
|
22
|
+
});
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
if (fs.existsSync(TEST_DIR))
|
|
25
|
+
fs.rmSync(TEST_DIR, { recursive: true });
|
|
26
|
+
});
|
|
27
|
+
describe("addBookmark", () => {
|
|
28
|
+
it("should create a new bookmark and save it", async () => {
|
|
29
|
+
const { addBookmark } = await getModule();
|
|
30
|
+
const bm = addBookmark("session-abc", 5, { label: "Important" });
|
|
31
|
+
expect(bm.sessionId).toBe("session-abc");
|
|
32
|
+
expect(bm.lineNumber).toBe(5);
|
|
33
|
+
expect(bm.label).toBe("Important");
|
|
34
|
+
expect(bm.id).toMatch(/^bm_/);
|
|
35
|
+
});
|
|
36
|
+
it("should return existing bookmark when adding duplicate", async () => {
|
|
37
|
+
const { addBookmark } = await getModule();
|
|
38
|
+
const bm1 = addBookmark("session-abc", 5);
|
|
39
|
+
const bm2 = addBookmark("session-abc", 5);
|
|
40
|
+
expect(bm1.id).toBe(bm2.id);
|
|
41
|
+
});
|
|
42
|
+
it("should update label on existing bookmark", async () => {
|
|
43
|
+
const { addBookmark } = await getModule();
|
|
44
|
+
addBookmark("session-abc", 5, { label: "Old Label" });
|
|
45
|
+
const updated = addBookmark("session-abc", 5, { label: "New Label" });
|
|
46
|
+
expect(updated.label).toBe("New Label");
|
|
47
|
+
});
|
|
48
|
+
it("should persist bookmarks to disk", async () => {
|
|
49
|
+
const { addBookmark } = await getModule();
|
|
50
|
+
addBookmark("session-xyz", 10);
|
|
51
|
+
const data = JSON.parse(fs.readFileSync(BOOKMARKS_FILE, "utf-8"));
|
|
52
|
+
expect(data.bookmarks.some((b) => b.sessionId === "session-xyz")).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe("removeBookmark", () => {
|
|
56
|
+
it("should remove an existing bookmark and return true", async () => {
|
|
57
|
+
const { addBookmark, removeBookmark } = await getModule();
|
|
58
|
+
const bm = addBookmark("session-abc", 3);
|
|
59
|
+
const result = removeBookmark(bm.id);
|
|
60
|
+
expect(result).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
it("should return false when bookmark does not exist", async () => {
|
|
63
|
+
const { removeBookmark } = await getModule();
|
|
64
|
+
const result = removeBookmark("nonexistent-id");
|
|
65
|
+
expect(result).toBe(false);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe("getSessionBookmarks", () => {
|
|
69
|
+
it("should return bookmarks for a session sorted by line number", async () => {
|
|
70
|
+
const { addBookmark, getSessionBookmarks } = await getModule();
|
|
71
|
+
addBookmark("session-abc", 10);
|
|
72
|
+
addBookmark("session-abc", 2);
|
|
73
|
+
addBookmark("session-abc", 7);
|
|
74
|
+
const bms = getSessionBookmarks("session-abc");
|
|
75
|
+
expect(bms.map(b => b.lineNumber)).toEqual([2, 7, 10]);
|
|
76
|
+
});
|
|
77
|
+
it("should return empty array when no bookmarks for session", async () => {
|
|
78
|
+
const { getSessionBookmarks } = await getModule();
|
|
79
|
+
const bms = getSessionBookmarks("session-no-bookmarks");
|
|
80
|
+
expect(bms).toHaveLength(0);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe("tagSession", () => {
|
|
84
|
+
it("should create a new session tag entry", async () => {
|
|
85
|
+
const { tagSession } = await getModule();
|
|
86
|
+
const tag = tagSession("session-abc", { tags: ["frontend", "bug"], name: "My Session" });
|
|
87
|
+
expect(tag.sessionId).toBe("session-abc");
|
|
88
|
+
expect(tag.tags).toContain("frontend");
|
|
89
|
+
expect(tag.name).toBe("My Session");
|
|
90
|
+
});
|
|
91
|
+
it("should deduplicate tags", async () => {
|
|
92
|
+
const { tagSession } = await getModule();
|
|
93
|
+
const tag = tagSession("session-abc", { tags: ["frontend", "frontend", "bug"] });
|
|
94
|
+
expect(tag.tags.filter((t) => t === "frontend")).toHaveLength(1);
|
|
95
|
+
});
|
|
96
|
+
it("should update existing session tag", async () => {
|
|
97
|
+
const { tagSession } = await getModule();
|
|
98
|
+
tagSession("session-abc", { name: "First Name" });
|
|
99
|
+
const updated = tagSession("session-abc", { name: "Second Name" });
|
|
100
|
+
expect(updated.name).toBe("Second Name");
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
describe("starSession / getStarredSessions", () => {
|
|
104
|
+
it("should star a session", async () => {
|
|
105
|
+
const { starSession, getStarredSessions } = await getModule();
|
|
106
|
+
starSession("session-abc");
|
|
107
|
+
const starred = getStarredSessions();
|
|
108
|
+
expect(starred.some((s) => s.sessionId === "session-abc")).toBe(true);
|
|
109
|
+
});
|
|
110
|
+
it("should unstar a session", async () => {
|
|
111
|
+
const { starSession, getStarredSessions, tagSession } = await getModule();
|
|
112
|
+
starSession("session-abc");
|
|
113
|
+
tagSession("session-abc", { starred: false });
|
|
114
|
+
const starred = getStarredSessions();
|
|
115
|
+
expect(starred.some((s) => s.sessionId === "session-abc")).toBe(false);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe("addTagToSession / removeTagFromSession", () => {
|
|
119
|
+
it("should add a tag to a session", async () => {
|
|
120
|
+
const { addTagToSession } = await getModule();
|
|
121
|
+
const result = addTagToSession("session-abc", "important");
|
|
122
|
+
expect(result.tags).toContain("important");
|
|
123
|
+
});
|
|
124
|
+
it("should not duplicate tags when adding same tag twice", async () => {
|
|
125
|
+
const { addTagToSession } = await getModule();
|
|
126
|
+
addTagToSession("session-abc", "important");
|
|
127
|
+
const result = addTagToSession("session-abc", "important");
|
|
128
|
+
expect(result.tags.filter((t) => t === "important")).toHaveLength(1);
|
|
129
|
+
});
|
|
130
|
+
it("should remove a tag from a session", async () => {
|
|
131
|
+
const { addTagToSession, removeTagFromSession } = await getModule();
|
|
132
|
+
addTagToSession("session-abc", "to-remove");
|
|
133
|
+
const result = removeTagFromSession("session-abc", "to-remove");
|
|
134
|
+
expect(result.tags).not.toContain("to-remove");
|
|
135
|
+
});
|
|
136
|
+
it("should return null when session not found for removeTagFromSession", async () => {
|
|
137
|
+
const { removeTagFromSession } = await getModule();
|
|
138
|
+
const result = removeTagFromSession("nonexistent-session", "tag");
|
|
139
|
+
expect(result).toBeNull();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe("clearAllBookmarks", () => {
|
|
143
|
+
it("should clear all bookmarks and tags and return counts", async () => {
|
|
144
|
+
const { addBookmark, tagSession, clearAllBookmarks } = await getModule();
|
|
145
|
+
addBookmark("session-1", 1);
|
|
146
|
+
addBookmark("session-2", 2);
|
|
147
|
+
tagSession("session-1", { name: "Test" });
|
|
148
|
+
const result = clearAllBookmarks();
|
|
149
|
+
expect(result.bookmarksCleared).toBe(2);
|
|
150
|
+
expect(result.tagsCleared).toBe(1);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
describe("formatBookmarkReport", () => {
|
|
154
|
+
it("should format summary report correctly", async () => {
|
|
155
|
+
const { formatBookmarkReport } = await getModule();
|
|
156
|
+
const summary = {
|
|
157
|
+
totalBookmarks: 3,
|
|
158
|
+
totalTaggedSessions: 2,
|
|
159
|
+
starredSessions: 1,
|
|
160
|
+
totalTags: 4,
|
|
161
|
+
topTags: [{ tag: "frontend", count: 2 }],
|
|
162
|
+
recentBookmarks: [],
|
|
163
|
+
};
|
|
164
|
+
const output = formatBookmarkReport(summary);
|
|
165
|
+
expect(output).toContain("Total Bookmarks: 3");
|
|
166
|
+
expect(output).toContain("frontend");
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
//# sourceMappingURL=bookmarks.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bookmarks.test.js","sourceRoot":"","sources":["../../src/__tests__/bookmarks.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulk.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/bulk.test.ts"],"names":[],"mappings":""}
|