@cortexmemory/cli 0.27.4 → 0.28.0
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/dist/commands/db.d.ts.map +1 -1
- package/dist/commands/db.js +18 -6
- package/dist/commands/db.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +74 -34
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.js +3 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +12 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/app-template-sync.d.ts.map +1 -1
- package/dist/utils/app-template-sync.js +3 -1
- package/dist/utils/app-template-sync.js.map +1 -1
- package/dist/utils/init/quickstart-setup.d.ts.map +1 -1
- package/dist/utils/init/quickstart-setup.js.map +1 -1
- package/package.json +4 -4
- package/templates/basic/.env.local.example +23 -0
- package/templates/basic/README.md +181 -56
- package/templates/basic/package-lock.json +2180 -406
- package/templates/basic/package.json +23 -5
- package/templates/basic/src/__tests__/chat.test.ts +340 -0
- package/templates/basic/src/__tests__/cortex.test.ts +260 -0
- package/templates/basic/src/__tests__/display.test.ts +455 -0
- package/templates/basic/src/__tests__/e2e/fact-extraction.test.ts +498 -0
- package/templates/basic/src/__tests__/e2e/memory-flow.test.ts +355 -0
- package/templates/basic/src/__tests__/e2e/server-e2e.test.ts +414 -0
- package/templates/basic/src/__tests__/helpers/test-utils.ts +345 -0
- package/templates/basic/src/__tests__/integration/chat-flow.test.ts +422 -0
- package/templates/basic/src/__tests__/integration/server.test.ts +441 -0
- package/templates/basic/src/__tests__/llm.test.ts +344 -0
- package/templates/basic/src/chat.ts +300 -0
- package/templates/basic/src/cortex.ts +203 -0
- package/templates/basic/src/display.ts +425 -0
- package/templates/basic/src/index.ts +194 -64
- package/templates/basic/src/llm.ts +214 -0
- package/templates/basic/src/server.ts +280 -0
- package/templates/basic/vitest.config.ts +33 -0
- package/templates/basic/vitest.e2e.config.ts +28 -0
- package/templates/basic/vitest.integration.config.ts +25 -0
- package/templates/vercel-ai-quickstart/app/api/auth/check/route.ts +1 -1
- package/templates/vercel-ai-quickstart/app/api/auth/login/route.ts +6 -9
- package/templates/vercel-ai-quickstart/app/api/auth/register/route.ts +14 -18
- package/templates/vercel-ai-quickstart/app/api/auth/setup/route.ts +4 -7
- package/templates/vercel-ai-quickstart/app/api/chat/route.ts +28 -11
- package/templates/vercel-ai-quickstart/app/api/chat-v6/route.ts +19 -13
- package/templates/vercel-ai-quickstart/app/api/conversations/route.ts +16 -16
- package/templates/vercel-ai-quickstart/app/globals.css +24 -9
- package/templates/vercel-ai-quickstart/app/page.tsx +25 -13
- package/templates/vercel-ai-quickstart/components/AdminSetup.tsx +3 -1
- package/templates/vercel-ai-quickstart/components/AuthProvider.tsx +6 -6
- package/templates/vercel-ai-quickstart/components/ChatHistorySidebar.tsx +19 -8
- package/templates/vercel-ai-quickstart/components/ChatInterface.tsx +41 -14
- package/templates/vercel-ai-quickstart/components/LoginScreen.tsx +10 -5
- package/templates/vercel-ai-quickstart/lib/agents/memory-agent.ts +3 -3
- package/templates/vercel-ai-quickstart/lib/password.ts +5 -5
- package/templates/vercel-ai-quickstart/next.config.js +10 -2
- package/templates/vercel-ai-quickstart/package.json +18 -11
- package/templates/vercel-ai-quickstart/test-api.mjs +131 -100
- package/templates/vercel-ai-quickstart/tests/e2e/chat-memory-flow.test.ts +73 -44
- package/templates/vercel-ai-quickstart/tests/helpers/mock-cortex.ts +40 -40
- package/templates/vercel-ai-quickstart/tests/integration/auth.test.ts +8 -8
- package/templates/vercel-ai-quickstart/tests/integration/conversations.test.ts +12 -8
- package/templates/vercel-ai-quickstart/tests/unit/password.test.ts +4 -1
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for display.ts
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
6
|
+
import {
|
|
7
|
+
printOrchestrationStart,
|
|
8
|
+
printLayerUpdate,
|
|
9
|
+
printOrchestrationComplete,
|
|
10
|
+
printRecallResults,
|
|
11
|
+
printWelcome,
|
|
12
|
+
printError,
|
|
13
|
+
printInfo,
|
|
14
|
+
printSuccess,
|
|
15
|
+
} from "../display.js";
|
|
16
|
+
import type { LayerEvent } from "../cortex.js";
|
|
17
|
+
|
|
18
|
+
describe("display", () => {
|
|
19
|
+
let consoleLogs: string[] = [];
|
|
20
|
+
const originalConsoleLog = console.log;
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
consoleLogs = [];
|
|
24
|
+
console.log = vi.fn((...args) => {
|
|
25
|
+
consoleLogs.push(args.join(" "));
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
console.log = originalConsoleLog;
|
|
31
|
+
vi.clearAllMocks();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("printOrchestrationStart", () => {
|
|
35
|
+
it("prints header with box drawing", () => {
|
|
36
|
+
printOrchestrationStart("test-orchestration-id");
|
|
37
|
+
|
|
38
|
+
const output = consoleLogs.join("\n");
|
|
39
|
+
expect(output).toContain("┌");
|
|
40
|
+
expect(output).toContain("MEMORY ORCHESTRATION");
|
|
41
|
+
expect(output).toContain("├");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("clears previous state on new orchestration", () => {
|
|
45
|
+
printOrchestrationStart("first-id");
|
|
46
|
+
printOrchestrationStart("second-id");
|
|
47
|
+
|
|
48
|
+
// Should have printed headers twice
|
|
49
|
+
const headerCount = consoleLogs.filter((log) =>
|
|
50
|
+
log.includes("MEMORY ORCHESTRATION"),
|
|
51
|
+
).length;
|
|
52
|
+
expect(headerCount).toBe(2);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe("printLayerUpdate", () => {
|
|
57
|
+
it("prints layer status on completion", () => {
|
|
58
|
+
printOrchestrationStart("test-id");
|
|
59
|
+
consoleLogs = []; // Clear header output
|
|
60
|
+
|
|
61
|
+
const event: LayerEvent = {
|
|
62
|
+
layer: "memorySpace",
|
|
63
|
+
status: "complete",
|
|
64
|
+
timestamp: Date.now(),
|
|
65
|
+
latencyMs: 10,
|
|
66
|
+
data: { id: "test-space" },
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
printLayerUpdate(event);
|
|
70
|
+
|
|
71
|
+
const output = consoleLogs.join("\n");
|
|
72
|
+
expect(output).toContain("📦");
|
|
73
|
+
expect(output).toContain("Memory Space");
|
|
74
|
+
expect(output).toContain("✓");
|
|
75
|
+
expect(output).toContain("complete");
|
|
76
|
+
expect(output).toContain("(10ms)");
|
|
77
|
+
expect(output).toContain("test-space");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("skips in_progress status", () => {
|
|
81
|
+
printOrchestrationStart("test-id");
|
|
82
|
+
consoleLogs = [];
|
|
83
|
+
|
|
84
|
+
const event: LayerEvent = {
|
|
85
|
+
layer: "user",
|
|
86
|
+
status: "in_progress",
|
|
87
|
+
timestamp: Date.now(),
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
printLayerUpdate(event);
|
|
91
|
+
|
|
92
|
+
// Should not print anything for in_progress
|
|
93
|
+
expect(consoleLogs.length).toBe(0);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("prints user layer data", () => {
|
|
97
|
+
printOrchestrationStart("test-id");
|
|
98
|
+
consoleLogs = [];
|
|
99
|
+
|
|
100
|
+
const event: LayerEvent = {
|
|
101
|
+
layer: "user",
|
|
102
|
+
status: "complete",
|
|
103
|
+
timestamp: Date.now(),
|
|
104
|
+
data: { id: "user-123", name: "Test User" },
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
printLayerUpdate(event);
|
|
108
|
+
|
|
109
|
+
const output = consoleLogs.join("\n");
|
|
110
|
+
expect(output).toContain("👤");
|
|
111
|
+
expect(output).toContain("user-123");
|
|
112
|
+
expect(output).toContain("Test User");
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("prints agent layer data", () => {
|
|
116
|
+
printOrchestrationStart("test-id");
|
|
117
|
+
consoleLogs = [];
|
|
118
|
+
|
|
119
|
+
const event: LayerEvent = {
|
|
120
|
+
layer: "agent",
|
|
121
|
+
status: "complete",
|
|
122
|
+
timestamp: Date.now(),
|
|
123
|
+
data: { id: "agent-123", name: "Test Agent" },
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
printLayerUpdate(event);
|
|
127
|
+
|
|
128
|
+
const output = consoleLogs.join("\n");
|
|
129
|
+
expect(output).toContain("🤖");
|
|
130
|
+
expect(output).toContain("agent-123");
|
|
131
|
+
expect(output).toContain("Test Agent");
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("prints conversation layer data", () => {
|
|
135
|
+
printOrchestrationStart("test-id");
|
|
136
|
+
consoleLogs = [];
|
|
137
|
+
|
|
138
|
+
const event: LayerEvent = {
|
|
139
|
+
layer: "conversation",
|
|
140
|
+
status: "complete",
|
|
141
|
+
timestamp: Date.now(),
|
|
142
|
+
data: { id: "conv-123", messageCount: 5, preview: "Hello world" },
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
printLayerUpdate(event);
|
|
146
|
+
|
|
147
|
+
const output = consoleLogs.join("\n");
|
|
148
|
+
expect(output).toContain("💬");
|
|
149
|
+
expect(output).toContain("conv-123");
|
|
150
|
+
expect(output).toContain("Messages: 5");
|
|
151
|
+
expect(output).toContain("Hello world");
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("prints vector layer data", () => {
|
|
155
|
+
printOrchestrationStart("test-id");
|
|
156
|
+
consoleLogs = [];
|
|
157
|
+
|
|
158
|
+
const event: LayerEvent = {
|
|
159
|
+
layer: "vector",
|
|
160
|
+
status: "complete",
|
|
161
|
+
timestamp: Date.now(),
|
|
162
|
+
data: { dimensions: 1536, importance: 85 },
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
printLayerUpdate(event);
|
|
166
|
+
|
|
167
|
+
const output = consoleLogs.join("\n");
|
|
168
|
+
expect(output).toContain("🎯");
|
|
169
|
+
expect(output).toContain("1536 dimensions");
|
|
170
|
+
expect(output).toContain("Importance: 85");
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("prints facts layer data with revision badge", () => {
|
|
174
|
+
printOrchestrationStart("test-id");
|
|
175
|
+
consoleLogs = [];
|
|
176
|
+
|
|
177
|
+
const event: LayerEvent = {
|
|
178
|
+
layer: "facts",
|
|
179
|
+
status: "complete",
|
|
180
|
+
timestamp: Date.now(),
|
|
181
|
+
revisionAction: "ADD",
|
|
182
|
+
data: {
|
|
183
|
+
facts: [
|
|
184
|
+
{ content: "User likes coffee", factType: "preference", confidence: 90 },
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
printLayerUpdate(event);
|
|
190
|
+
|
|
191
|
+
const output = consoleLogs.join("\n");
|
|
192
|
+
expect(output).toContain("💡");
|
|
193
|
+
expect(output).toContain("[NEW]");
|
|
194
|
+
expect(output).toContain("User likes coffee");
|
|
195
|
+
expect(output).toContain("preference");
|
|
196
|
+
expect(output).toContain("90%");
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("prints superseded facts", () => {
|
|
200
|
+
printOrchestrationStart("test-id");
|
|
201
|
+
consoleLogs = [];
|
|
202
|
+
|
|
203
|
+
const event: LayerEvent = {
|
|
204
|
+
layer: "facts",
|
|
205
|
+
status: "complete",
|
|
206
|
+
timestamp: Date.now(),
|
|
207
|
+
revisionAction: "SUPERSEDE",
|
|
208
|
+
supersededFacts: ["Old fact 1", "Old fact 2"],
|
|
209
|
+
data: { facts: [{ content: "New fact" }] },
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
printLayerUpdate(event);
|
|
213
|
+
|
|
214
|
+
const output = consoleLogs.join("\n");
|
|
215
|
+
expect(output).toContain("[SUPERSEDED]");
|
|
216
|
+
expect(output).toContain("Superseded:");
|
|
217
|
+
expect(output).toContain("Old fact 1");
|
|
218
|
+
expect(output).toContain("Old fact 2");
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it("prints graph layer data", () => {
|
|
222
|
+
printOrchestrationStart("test-id");
|
|
223
|
+
consoleLogs = [];
|
|
224
|
+
|
|
225
|
+
const event: LayerEvent = {
|
|
226
|
+
layer: "graph",
|
|
227
|
+
status: "complete",
|
|
228
|
+
timestamp: Date.now(),
|
|
229
|
+
data: { nodes: 5, edges: 8 },
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
printLayerUpdate(event);
|
|
233
|
+
|
|
234
|
+
const output = consoleLogs.join("\n");
|
|
235
|
+
expect(output).toContain("🕸️");
|
|
236
|
+
expect(output).toContain("Nodes: 5");
|
|
237
|
+
expect(output).toContain("Edges: 8");
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it("prints skipped status", () => {
|
|
241
|
+
printOrchestrationStart("test-id");
|
|
242
|
+
consoleLogs = [];
|
|
243
|
+
|
|
244
|
+
const event: LayerEvent = {
|
|
245
|
+
layer: "graph",
|
|
246
|
+
status: "skipped",
|
|
247
|
+
timestamp: Date.now(),
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
printLayerUpdate(event);
|
|
251
|
+
|
|
252
|
+
const output = consoleLogs.join("\n");
|
|
253
|
+
expect(output).toContain("○");
|
|
254
|
+
expect(output).toContain("skipped");
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it("prints error status", () => {
|
|
258
|
+
printOrchestrationStart("test-id");
|
|
259
|
+
consoleLogs = [];
|
|
260
|
+
|
|
261
|
+
const event: LayerEvent = {
|
|
262
|
+
layer: "vector",
|
|
263
|
+
status: "error",
|
|
264
|
+
timestamp: Date.now(),
|
|
265
|
+
error: "Embedding failed",
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
printLayerUpdate(event);
|
|
269
|
+
|
|
270
|
+
const output = consoleLogs.join("\n");
|
|
271
|
+
expect(output).toContain("✗");
|
|
272
|
+
expect(output).toContain("error");
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it("ignores unknown layers", () => {
|
|
276
|
+
printOrchestrationStart("test-id");
|
|
277
|
+
consoleLogs = [];
|
|
278
|
+
|
|
279
|
+
const event: LayerEvent = {
|
|
280
|
+
layer: "unknown-layer" as string,
|
|
281
|
+
status: "complete",
|
|
282
|
+
timestamp: Date.now(),
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
printLayerUpdate(event);
|
|
286
|
+
|
|
287
|
+
// Should not print anything for unknown layer
|
|
288
|
+
expect(consoleLogs.length).toBe(0);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
describe("printOrchestrationComplete", () => {
|
|
293
|
+
it("prints total time", () => {
|
|
294
|
+
printOrchestrationStart("test-id");
|
|
295
|
+
consoleLogs = [];
|
|
296
|
+
|
|
297
|
+
printOrchestrationComplete(150);
|
|
298
|
+
|
|
299
|
+
const output = consoleLogs.join("\n");
|
|
300
|
+
expect(output).toContain("Total: 150ms");
|
|
301
|
+
expect(output).toContain("└");
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it("does nothing when no orchestration is active", () => {
|
|
305
|
+
// Don't call printOrchestrationStart
|
|
306
|
+
consoleLogs = [];
|
|
307
|
+
|
|
308
|
+
printOrchestrationComplete(100);
|
|
309
|
+
|
|
310
|
+
// First call should work, second should not print
|
|
311
|
+
printOrchestrationStart("test-id");
|
|
312
|
+
printOrchestrationComplete(100);
|
|
313
|
+
const firstCount = consoleLogs.length;
|
|
314
|
+
|
|
315
|
+
printOrchestrationComplete(100); // No active orchestration now
|
|
316
|
+
|
|
317
|
+
expect(consoleLogs.length).toBe(firstCount);
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
describe("printRecallResults", () => {
|
|
322
|
+
it("prints empty results message", () => {
|
|
323
|
+
printRecallResults([], []);
|
|
324
|
+
|
|
325
|
+
const output = consoleLogs.join("\n");
|
|
326
|
+
expect(output).toContain("MEMORY RECALL");
|
|
327
|
+
expect(output).toContain("No relevant memories found");
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it("prints memories", () => {
|
|
331
|
+
const memories = [
|
|
332
|
+
{ content: "User said hello", importance: 80 },
|
|
333
|
+
{ content: "User asked about weather", importance: 60 },
|
|
334
|
+
];
|
|
335
|
+
|
|
336
|
+
printRecallResults(memories, []);
|
|
337
|
+
|
|
338
|
+
const output = consoleLogs.join("\n");
|
|
339
|
+
expect(output).toContain("🎯 2 relevant memories:");
|
|
340
|
+
expect(output).toContain("User said hello");
|
|
341
|
+
expect(output).toContain("[80]");
|
|
342
|
+
expect(output).toContain("User asked about weather");
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it("prints facts", () => {
|
|
346
|
+
const facts = [
|
|
347
|
+
{ content: "User's name is Alex", factType: "identity" },
|
|
348
|
+
{ content: "User works at Acme", factType: "employment" },
|
|
349
|
+
];
|
|
350
|
+
|
|
351
|
+
printRecallResults([], facts);
|
|
352
|
+
|
|
353
|
+
const output = consoleLogs.join("\n");
|
|
354
|
+
expect(output).toContain("💡 2 known facts:");
|
|
355
|
+
expect(output).toContain("User's name is Alex");
|
|
356
|
+
expect(output).toContain("(identity)");
|
|
357
|
+
expect(output).toContain("User works at Acme");
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it("truncates long lists", () => {
|
|
361
|
+
const memories = Array(10)
|
|
362
|
+
.fill(null)
|
|
363
|
+
.map((_, i) => ({ content: `Memory ${i}` }));
|
|
364
|
+
|
|
365
|
+
printRecallResults(memories, []);
|
|
366
|
+
|
|
367
|
+
const output = consoleLogs.join("\n");
|
|
368
|
+
expect(output).toContain("... and 5 more");
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
describe("printWelcome", () => {
|
|
373
|
+
it("prints CLI mode welcome", () => {
|
|
374
|
+
printWelcome("cli");
|
|
375
|
+
|
|
376
|
+
const output = consoleLogs.join("\n");
|
|
377
|
+
expect(output).toContain("🧠 Cortex Memory");
|
|
378
|
+
expect(output).toContain("Basic Demo");
|
|
379
|
+
expect(output).toContain("Type a message");
|
|
380
|
+
expect(output).toContain("/recall");
|
|
381
|
+
expect(output).toContain("/exit");
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it("prints server mode welcome", () => {
|
|
385
|
+
printWelcome("server");
|
|
386
|
+
|
|
387
|
+
const output = consoleLogs.join("\n");
|
|
388
|
+
expect(output).toContain("🧠 Cortex Memory");
|
|
389
|
+
expect(output).toContain("Server mode");
|
|
390
|
+
expect(output).toContain("POST /chat");
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
describe("printError", () => {
|
|
395
|
+
it("prints error message", () => {
|
|
396
|
+
printError("Something went wrong");
|
|
397
|
+
|
|
398
|
+
const output = consoleLogs.join("\n");
|
|
399
|
+
expect(output).toContain("❌ Error:");
|
|
400
|
+
expect(output).toContain("Something went wrong");
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
it("prints stack trace in debug mode", () => {
|
|
404
|
+
const originalDebug = process.env.DEBUG;
|
|
405
|
+
process.env.DEBUG = "true";
|
|
406
|
+
|
|
407
|
+
const error = new Error("Test error");
|
|
408
|
+
printError("Failed", error);
|
|
409
|
+
|
|
410
|
+
const output = consoleLogs.join("\n");
|
|
411
|
+
expect(output).toContain("Test error");
|
|
412
|
+
|
|
413
|
+
process.env.DEBUG = originalDebug;
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
describe("printInfo", () => {
|
|
418
|
+
it("prints info message with icon", () => {
|
|
419
|
+
printInfo("Some information");
|
|
420
|
+
|
|
421
|
+
const output = consoleLogs.join("\n");
|
|
422
|
+
expect(output).toContain("ℹ");
|
|
423
|
+
expect(output).toContain("Some information");
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
describe("printSuccess", () => {
|
|
428
|
+
it("prints success message with checkmark", () => {
|
|
429
|
+
printSuccess("Operation completed");
|
|
430
|
+
|
|
431
|
+
const output = consoleLogs.join("\n");
|
|
432
|
+
expect(output).toContain("✓");
|
|
433
|
+
expect(output).toContain("Operation completed");
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
describe("box drawing", () => {
|
|
438
|
+
it("maintains consistent box width", () => {
|
|
439
|
+
printOrchestrationStart("test-id");
|
|
440
|
+
|
|
441
|
+
// All lines with box characters should have consistent width
|
|
442
|
+
const boxLines = consoleLogs.filter(
|
|
443
|
+
(line) =>
|
|
444
|
+
line.includes("│") || line.includes("┌") || line.includes("└"),
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
const firstLineLength = boxLines[0]?.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
448
|
+
|
|
449
|
+
boxLines.forEach((line) => {
|
|
450
|
+
const cleanLine = line.replace(/\x1b\[[0-9;]*m/g, "");
|
|
451
|
+
expect(cleanLine.length).toBe(firstLineLength);
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
});
|