@cachly-dev/mcp-server 0.9.22 → 0.9.24

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.
@@ -0,0 +1,505 @@
1
+ /**
2
+ * Unit tests for handler helper functions and handler logic.
3
+ *
4
+ * Covers (no real network or Redis required):
5
+ * formatInstance – status badge, memory formatting
6
+ * buildConnectionString – TLS, auth, port
7
+ * handleRoadmapTool – add, list, update, next (full in-memory flow)
8
+ * handleInstanceTool – list, create, get, connection string, delete
9
+ *
10
+ * Run: npx vitest run src/__tests__/handlers-unit.test.ts
11
+ */
12
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
13
+ import { formatInstance, buildConnectionString, handleInstanceTool, } from '../handlers/instances.js';
14
+ import { handleRoadmapTool } from '../handlers/roadmap.js';
15
+ // ── Minimal MockRedis (hashes + lists) ───────────────────────────────────────
16
+ class MockRedis {
17
+ hashes = new Map();
18
+ async hset(key, field, value) {
19
+ if (!this.hashes.has(key))
20
+ this.hashes.set(key, new Map());
21
+ this.hashes.get(key).set(field, value);
22
+ return 1;
23
+ }
24
+ async hget(key, field) {
25
+ return this.hashes.get(key)?.get(field) ?? null;
26
+ }
27
+ async hgetall(key) {
28
+ const h = this.hashes.get(key);
29
+ if (!h || h.size === 0)
30
+ return null;
31
+ const out = {};
32
+ for (const [k, v] of h)
33
+ out[k] = v;
34
+ return out;
35
+ }
36
+ /** Expose internals for test assertions */
37
+ _hashes() { return this.hashes; }
38
+ }
39
+ // ── Fixtures ──────────────────────────────────────────────────────────────────
40
+ const baseInstance = {
41
+ id: 'inst-abc123',
42
+ name: 'my-cache',
43
+ tier: 'free',
44
+ status: 'running',
45
+ region: 'eu-west',
46
+ host: 'redis.cachly.dev',
47
+ port: 6379,
48
+ password: 'supersecret',
49
+ tls_enabled: false,
50
+ memory_mb: 256,
51
+ encryption_at_rest: false,
52
+ created_at: '2026-01-01T00:00:00Z',
53
+ };
54
+ // ── formatInstance ────────────────────────────────────────────────────────────
55
+ describe('formatInstance', () => {
56
+ it('running instance shows 🟢 badge', () => {
57
+ const result = formatInstance({ ...baseInstance, status: 'running' });
58
+ expect(result).toContain('🟢');
59
+ });
60
+ it('provisioning instance shows 🟡 badge', () => {
61
+ const result = formatInstance({ ...baseInstance, status: 'provisioning' });
62
+ expect(result).toContain('🟡');
63
+ });
64
+ it('stopped/error instance shows 🔴 badge', () => {
65
+ const result = formatInstance({ ...baseInstance, status: 'stopped' });
66
+ expect(result).toContain('🔴');
67
+ const error = formatInstance({ ...baseInstance, status: 'error' });
68
+ expect(error).toContain('🔴');
69
+ });
70
+ it('includes instance name', () => {
71
+ expect(formatInstance(baseInstance)).toContain('my-cache');
72
+ });
73
+ it('includes instance id in backticks', () => {
74
+ expect(formatInstance(baseInstance)).toContain('inst-abc123');
75
+ });
76
+ it('includes tier', () => {
77
+ expect(formatInstance(baseInstance)).toContain('free');
78
+ });
79
+ it('includes region', () => {
80
+ expect(formatInstance(baseInstance)).toContain('eu-west');
81
+ });
82
+ it('displays memory < 1024 MB in MB', () => {
83
+ const result = formatInstance({ ...baseInstance, memory_mb: 512 });
84
+ expect(result).toContain('512MB');
85
+ });
86
+ it('displays memory >= 1024 MB in GB', () => {
87
+ const result = formatInstance({ ...baseInstance, memory_mb: 1024 });
88
+ expect(result).toContain('1GB');
89
+ });
90
+ it('displays 2048 MB as 2GB', () => {
91
+ const result = formatInstance({ ...baseInstance, memory_mb: 2048 });
92
+ expect(result).toContain('2GB');
93
+ });
94
+ it('displays 4096 MB as 4GB', () => {
95
+ const result = formatInstance({ ...baseInstance, memory_mb: 4096 });
96
+ expect(result).toContain('4GB');
97
+ });
98
+ });
99
+ // ── buildConnectionString ─────────────────────────────────────────────────────
100
+ describe('buildConnectionString', () => {
101
+ it('returns error message when host is absent', () => {
102
+ const result = buildConnectionString({ ...baseInstance, host: undefined });
103
+ expect(result).toContain('❌');
104
+ expect(result.toLowerCase()).toContain('not ready');
105
+ });
106
+ it('uses redis:// for non-TLS', () => {
107
+ const result = buildConnectionString({ ...baseInstance, tls_enabled: false });
108
+ expect(result).toMatch(/^redis:\/\//);
109
+ });
110
+ it('uses rediss:// for TLS', () => {
111
+ const result = buildConnectionString({ ...baseInstance, tls_enabled: true });
112
+ expect(result).toMatch(/^rediss:\/\//);
113
+ });
114
+ it('includes password in auth section', () => {
115
+ const result = buildConnectionString({ ...baseInstance, password: 'mypass' });
116
+ expect(result).toContain(':mypass@');
117
+ });
118
+ it('no auth section when password is absent', () => {
119
+ const result = buildConnectionString({ ...baseInstance, password: undefined });
120
+ expect(result).not.toContain('@');
121
+ });
122
+ it('includes host in connection string', () => {
123
+ const result = buildConnectionString(baseInstance);
124
+ expect(result).toContain('redis.cachly.dev');
125
+ });
126
+ it('includes default port 6379', () => {
127
+ const result = buildConnectionString(baseInstance);
128
+ expect(result).toContain(':6379');
129
+ });
130
+ it('includes custom port', () => {
131
+ const result = buildConnectionString({ ...baseInstance, port: 12345 });
132
+ expect(result).toContain(':12345');
133
+ });
134
+ it('TLS + auth builds correct rediss:// URL', () => {
135
+ const result = buildConnectionString({
136
+ ...baseInstance,
137
+ tls_enabled: true,
138
+ password: 'pass123',
139
+ host: 'secure.cachly.dev',
140
+ port: 6380,
141
+ });
142
+ expect(result).toBe('rediss://:pass123@secure.cachly.dev:6380');
143
+ });
144
+ it('non-TLS no-auth builds correct redis:// URL', () => {
145
+ const result = buildConnectionString({
146
+ ...baseInstance,
147
+ tls_enabled: false,
148
+ password: undefined,
149
+ host: 'open.cachly.dev',
150
+ port: 6379,
151
+ });
152
+ expect(result).toBe('redis://open.cachly.dev:6379');
153
+ });
154
+ });
155
+ // ── handleRoadmapTool ─────────────────────────────────────────────────────────
156
+ describe('handleRoadmapTool', () => {
157
+ let redis;
158
+ let getConnection;
159
+ const apiFetch = vi.fn();
160
+ const INSTANCE = 'inst-test';
161
+ beforeEach(() => {
162
+ redis = new MockRedis();
163
+ getConnection = vi.fn().mockResolvedValue(redis);
164
+ });
165
+ // ── roadmap_add ──────────────────────────────────────────────────────────────
166
+ describe('roadmap_add', () => {
167
+ it('creates a roadmap item and returns formatted output', async () => {
168
+ const result = await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Fix login bug', priority: 'high' }, getConnection, apiFetch);
169
+ expect(result).toContain('📋 **Roadmap item added**');
170
+ expect(result).toContain('Fix login bug');
171
+ expect(result).toContain('high');
172
+ expect(result).toContain('planned');
173
+ });
174
+ it('returns an ID prefixed with rm_', async () => {
175
+ const result = await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Migrate DB', priority: 'critical' }, getConnection, apiFetch);
176
+ expect(result).toMatch(/`rm_[a-z0-9_]+`/);
177
+ });
178
+ it('stores item in Redis under cachly:roadmap:{instance_id}', async () => {
179
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Add tests', priority: 'medium' }, getConnection, apiFetch);
180
+ const stored = redis._hashes().get(`cachly:roadmap:${INSTANCE}`);
181
+ expect(stored).toBeDefined();
182
+ expect(stored.size).toBe(1);
183
+ const item = JSON.parse([...stored.values()][0]);
184
+ expect(item.title).toBe('Add tests');
185
+ expect(item.status).toBe('planned');
186
+ expect(item.priority).toBe('medium');
187
+ });
188
+ it('includes milestone in output when provided', async () => {
189
+ const result = await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Release v2', priority: 'high', milestone: 'Q2-2026' }, getConnection, apiFetch);
190
+ expect(result).toContain('Q2-2026');
191
+ });
192
+ it('includes tags in output when provided', async () => {
193
+ const result = await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Cache warmup', priority: 'low', tags: ['perf', 'infra'] }, getConnection, apiFetch);
194
+ expect(result).toContain('perf');
195
+ expect(result).toContain('infra');
196
+ });
197
+ it('contains roadmap_update hint with the new item ID', async () => {
198
+ const result = await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Deploy feature', priority: 'medium' }, getConnection, apiFetch);
199
+ // Hint should reference the new item ID for marking in-progress
200
+ expect(result).toContain('roadmap_update');
201
+ expect(result).toContain('in-progress');
202
+ });
203
+ });
204
+ // ── roadmap_list ─────────────────────────────────────────────────────────────
205
+ describe('roadmap_list', () => {
206
+ it('returns empty message when no items', async () => {
207
+ const result = await handleRoadmapTool('roadmap_list', { instance_id: INSTANCE }, getConnection, apiFetch);
208
+ expect(result).toContain('empty');
209
+ expect(result).toContain('roadmap_add');
210
+ });
211
+ it('shows added item in list', async () => {
212
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Write tests', priority: 'high' }, getConnection, apiFetch);
213
+ const result = await handleRoadmapTool('roadmap_list', { instance_id: INSTANCE }, getConnection, apiFetch);
214
+ expect(result).toContain('Write tests');
215
+ });
216
+ it('shows item count', async () => {
217
+ for (let i = 0; i < 3; i++) {
218
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: `Task ${i}`, priority: 'low' }, getConnection, apiFetch);
219
+ }
220
+ const result = await handleRoadmapTool('roadmap_list', { instance_id: INSTANCE }, getConnection, apiFetch);
221
+ expect(result).toContain('3 item');
222
+ });
223
+ it('sorts critical items before low items', async () => {
224
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Low priority', priority: 'low' }, getConnection, apiFetch);
225
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Critical fix', priority: 'critical' }, getConnection, apiFetch);
226
+ const result = await handleRoadmapTool('roadmap_list', { instance_id: INSTANCE }, getConnection, apiFetch);
227
+ const critIdx = result.indexOf('Critical fix');
228
+ const lowIdx = result.indexOf('Low priority');
229
+ expect(critIdx).toBeLessThan(lowIdx);
230
+ });
231
+ it('filters by tag', async () => {
232
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Frontend task', priority: 'medium', tags: ['frontend'] }, getConnection, apiFetch);
233
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Backend task', priority: 'medium', tags: ['backend'] }, getConnection, apiFetch);
234
+ const result = await handleRoadmapTool('roadmap_list', { instance_id: INSTANCE, tag: 'frontend' }, getConnection, apiFetch);
235
+ expect(result).toContain('Frontend task');
236
+ expect(result).not.toContain('Backend task');
237
+ });
238
+ it('filters by milestone', async () => {
239
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'MVP feature', priority: 'high', milestone: 'mvp' }, getConnection, apiFetch);
240
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Post-launch', priority: 'low', milestone: 'v2' }, getConnection, apiFetch);
241
+ const result = await handleRoadmapTool('roadmap_list', { instance_id: INSTANCE, milestone: 'mvp' }, getConnection, apiFetch);
242
+ expect(result).toContain('MVP feature');
243
+ expect(result).not.toContain('Post-launch');
244
+ });
245
+ it('status=done shows only done items', async () => {
246
+ // Add and complete one item
247
+ const addResult = await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Finished task', priority: 'low' }, getConnection, apiFetch);
248
+ const idMatch = addResult.match(/`(rm_[a-z0-9_]+)`/);
249
+ const id = idMatch?.[1];
250
+ await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id, status: 'done' }, getConnection, apiFetch);
251
+ const result = await handleRoadmapTool('roadmap_list', { instance_id: INSTANCE, status: 'done' }, getConnection, apiFetch);
252
+ expect(result).toContain('Finished task');
253
+ });
254
+ it('status=open hides done items', async () => {
255
+ const addResult = await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Done item', priority: 'low' }, getConnection, apiFetch);
256
+ const id = addResult.match(/`(rm_[a-z0-9_]+)`/)[1];
257
+ await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id, status: 'done' }, getConnection, apiFetch);
258
+ const result = await handleRoadmapTool('roadmap_list', { instance_id: INSTANCE, status: 'open' }, getConnection, apiFetch);
259
+ // No open items after marking done
260
+ expect(result).toContain('No roadmap items');
261
+ });
262
+ });
263
+ // ── roadmap_update ────────────────────────────────────────────────────────────
264
+ describe('roadmap_update', () => {
265
+ async function addItem(title, priority = 'medium') {
266
+ const result = await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title, priority }, getConnection, apiFetch);
267
+ return result.match(/`(rm_[a-z0-9_]+)`/)[1];
268
+ }
269
+ it('updates status and returns confirmation', async () => {
270
+ const id = await addItem('Deploy feature');
271
+ const result = await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id, status: 'in-progress' }, getConnection, apiFetch);
272
+ expect(result).toContain('⚡');
273
+ expect(result).toContain('Deploy feature');
274
+ expect(result).toContain('in-progress');
275
+ });
276
+ it('persists status change in Redis', async () => {
277
+ const id = await addItem('Fix cache');
278
+ await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id, status: 'done' }, getConnection, apiFetch);
279
+ const stored = await redis.hget(`cachly:roadmap:${INSTANCE}`, id);
280
+ const item = JSON.parse(stored);
281
+ expect(item.status).toBe('done');
282
+ });
283
+ it('appends notes with timestamp prefix', async () => {
284
+ const id = await addItem('Refactor');
285
+ await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id, notes: 'Started refactor' }, getConnection, apiFetch);
286
+ const stored = JSON.parse((await redis.hget(`cachly:roadmap:${INSTANCE}`, id)));
287
+ expect(stored.notes).toContain('Started refactor');
288
+ expect(stored.notes).toMatch(/^\[20\d\d-/); // Date prefix like [2026-...
289
+ });
290
+ it('appends multiple notes, keeping history', async () => {
291
+ const id = await addItem('Long task');
292
+ await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id, notes: 'First update' }, getConnection, apiFetch);
293
+ await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id, notes: 'Second update' }, getConnection, apiFetch);
294
+ const stored = JSON.parse((await redis.hget(`cachly:roadmap:${INSTANCE}`, id)));
295
+ expect(stored.notes).toContain('First update');
296
+ expect(stored.notes).toContain('Second update');
297
+ });
298
+ it('returns error message for missing item ID', async () => {
299
+ const result = await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id: 'rm_nonexistent', status: 'done' }, getConnection, apiFetch);
300
+ expect(result).toContain('not found');
301
+ expect(result).toContain('roadmap_list');
302
+ });
303
+ it('updates title', async () => {
304
+ const id = await addItem('Old title');
305
+ await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id, title: 'New title' }, getConnection, apiFetch);
306
+ const stored = JSON.parse((await redis.hget(`cachly:roadmap:${INSTANCE}`, id)));
307
+ expect(stored.title).toBe('New title');
308
+ });
309
+ it('updates priority', async () => {
310
+ const id = await addItem('Task', 'low');
311
+ await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id, priority: 'critical' }, getConnection, apiFetch);
312
+ const stored = JSON.parse((await redis.hget(`cachly:roadmap:${INSTANCE}`, id)));
313
+ expect(stored.priority).toBe('critical');
314
+ });
315
+ });
316
+ // ── roadmap_next ─────────────────────────────────────────────────────────────
317
+ describe('roadmap_next', () => {
318
+ it('returns empty roadmap message when no items exist', async () => {
319
+ const result = await handleRoadmapTool('roadmap_next', { instance_id: INSTANCE }, getConnection, apiFetch);
320
+ expect(result).toContain('empty');
321
+ expect(result).toContain('roadmap_add');
322
+ });
323
+ it('returns all-done message when all items are completed', async () => {
324
+ // Add an item then mark it done
325
+ const addResult = await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Finished', priority: 'low' }, getConnection, apiFetch);
326
+ const id = addResult.match(/`(rm_[a-z0-9_]+)`/)[1];
327
+ await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id, status: 'done' }, getConnection, apiFetch);
328
+ const result = await handleRoadmapTool('roadmap_next', { instance_id: INSTANCE }, getConnection, apiFetch);
329
+ // All open items exhausted → 🎉 message
330
+ expect(result).toContain('No open roadmap items');
331
+ });
332
+ it('returns the single item when only one exists', async () => {
333
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Only task', priority: 'medium' }, getConnection, apiFetch);
334
+ const result = await handleRoadmapTool('roadmap_next', { instance_id: INSTANCE }, getConnection, apiFetch);
335
+ expect(result).toContain('Only task');
336
+ });
337
+ it('returns critical item over low item', async () => {
338
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Low task', priority: 'low' }, getConnection, apiFetch);
339
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Critical task', priority: 'critical' }, getConnection, apiFetch);
340
+ const result = await handleRoadmapTool('roadmap_next', { instance_id: INSTANCE }, getConnection, apiFetch);
341
+ expect(result).toContain('Critical task');
342
+ });
343
+ it('returns in-progress item over higher-priority planned item', async () => {
344
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Critical planned', priority: 'critical' }, getConnection, apiFetch);
345
+ const lowResult = await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Low in-progress', priority: 'low' }, getConnection, apiFetch);
346
+ const lowId = lowResult.match(/`(rm_[a-z0-9_]+)`/)[1];
347
+ await handleRoadmapTool('roadmap_update', { instance_id: INSTANCE, id: lowId, status: 'in-progress' }, getConnection, apiFetch);
348
+ const result = await handleRoadmapTool('roadmap_next', { instance_id: INSTANCE }, getConnection, apiFetch);
349
+ expect(result).toContain('Low in-progress');
350
+ expect(result).toContain('⚡');
351
+ });
352
+ it('shows remaining count', async () => {
353
+ for (let i = 0; i < 5; i++) {
354
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: `Task ${i}`, priority: 'medium' }, getConnection, apiFetch);
355
+ }
356
+ const result = await handleRoadmapTool('roadmap_next', { instance_id: INSTANCE }, getConnection, apiFetch);
357
+ expect(result).toContain('+4 more');
358
+ });
359
+ it('filters by tag', async () => {
360
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Backend', priority: 'high', tags: ['backend'] }, getConnection, apiFetch);
361
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'Frontend', priority: 'critical', tags: ['frontend'] }, getConnection, apiFetch);
362
+ // Even though Frontend has higher priority, filtering by backend should return Backend
363
+ const result = await handleRoadmapTool('roadmap_next', { instance_id: INSTANCE, tag: 'backend' }, getConnection, apiFetch);
364
+ expect(result).toContain('Backend');
365
+ expect(result).not.toContain('Frontend');
366
+ });
367
+ it('contains a roadmap_update call-to-action hint', async () => {
368
+ await handleRoadmapTool('roadmap_add', { instance_id: INSTANCE, title: 'My task', priority: 'medium' }, getConnection, apiFetch);
369
+ const result = await handleRoadmapTool('roadmap_next', { instance_id: INSTANCE }, getConnection, apiFetch);
370
+ expect(result).toContain('roadmap_update');
371
+ });
372
+ });
373
+ });
374
+ // ── handleInstanceTool ────────────────────────────────────────────────────────
375
+ describe('handleInstanceTool', () => {
376
+ const noop = vi.fn();
377
+ const getConnection = vi.fn();
378
+ beforeEach(() => {
379
+ vi.clearAllMocks();
380
+ });
381
+ it('list_instances — empty list returns helpful message', async () => {
382
+ const apiFetch = vi.fn().mockResolvedValue({ data: [] });
383
+ const result = await handleInstanceTool('list_instances', {}, getConnection, apiFetch);
384
+ expect(result).toContain('no cache instances');
385
+ expect(result).toContain('create_instance');
386
+ });
387
+ it('list_instances — returns formatted instance list', async () => {
388
+ const instances = [
389
+ { ...baseInstance, id: 'inst-1', name: 'prod-cache', status: 'running' },
390
+ { ...baseInstance, id: 'inst-2', name: 'dev-cache', status: 'provisioning' },
391
+ ];
392
+ const apiFetch = vi.fn().mockResolvedValue({ data: instances });
393
+ const result = await handleInstanceTool('list_instances', {}, getConnection, apiFetch);
394
+ expect(result).toContain('2 instance');
395
+ expect(result).toContain('prod-cache');
396
+ expect(result).toContain('dev-cache');
397
+ expect(result).toContain('🟢');
398
+ expect(result).toContain('🟡');
399
+ });
400
+ it('create_instance (free tier) — returns success without checkout URL', async () => {
401
+ const apiFetch = vi.fn().mockResolvedValue({
402
+ instance_id: 'inst-new123',
403
+ status: 'provisioning',
404
+ });
405
+ const result = await handleInstanceTool('create_instance', { name: 'my-new-cache', tier: 'free' }, getConnection, apiFetch);
406
+ expect(result).toContain('✅');
407
+ expect(result).toContain('inst-new123');
408
+ expect(result).toContain('provisioning');
409
+ expect(result).not.toContain('checkout');
410
+ expect(result).toContain('get_connection_string');
411
+ });
412
+ it('create_instance (paid tier) — returns checkout URL', async () => {
413
+ const apiFetch = vi.fn().mockResolvedValue({
414
+ instance_id: 'inst-paid-456',
415
+ checkout_url: 'https://checkout.stripe.com/pay/cs_test_abc',
416
+ status: 'pending_payment',
417
+ });
418
+ const result = await handleInstanceTool('create_instance', { name: 'pro-cache', tier: 'starter' }, getConnection, apiFetch);
419
+ expect(result).toContain('✅');
420
+ expect(result).toContain('inst-paid-456');
421
+ expect(result).toContain('💳');
422
+ expect(result).toContain('https://checkout.stripe.com');
423
+ });
424
+ it('get_instance — calls correct API endpoint and returns formatted result', async () => {
425
+ const apiFetch = vi.fn().mockResolvedValue({ ...baseInstance, status: 'running' });
426
+ const result = await handleInstanceTool('get_instance', { instance_id: 'inst-abc123' }, getConnection, apiFetch);
427
+ expect(apiFetch).toHaveBeenCalledWith('/api/v1/instances/inst-abc123');
428
+ expect(result).toContain('my-cache');
429
+ expect(result).toContain('🟢');
430
+ });
431
+ it('get_connection_string — running instance returns redis:// URL block', async () => {
432
+ const apiFetch = vi.fn().mockResolvedValue({
433
+ ...baseInstance,
434
+ status: 'running',
435
+ tls_enabled: false,
436
+ password: 'abc',
437
+ host: 'redis.cachly.dev',
438
+ port: 6379,
439
+ });
440
+ const result = await handleInstanceTool('get_connection_string', { instance_id: 'inst-abc123' }, getConnection, apiFetch);
441
+ expect(result).toContain('redis://:abc@redis.cachly.dev:6379');
442
+ expect(result).toContain('REDIS_URL');
443
+ expect(result).toContain('redis-cli');
444
+ });
445
+ it('get_connection_string — non-running instance returns not-ready message', async () => {
446
+ const apiFetch = vi.fn().mockResolvedValue({ ...baseInstance, status: 'provisioning', host: undefined });
447
+ const result = await handleInstanceTool('get_connection_string', { instance_id: 'inst-abc123' }, getConnection, apiFetch);
448
+ expect(result).toContain('not running');
449
+ expect(result).toContain('provisioning');
450
+ });
451
+ it('delete_instance without confirm — returns cancelled message without calling API', async () => {
452
+ const apiFetch = vi.fn();
453
+ const result = await handleInstanceTool('delete_instance', { instance_id: 'inst-abc123', confirm: false }, getConnection, apiFetch);
454
+ expect(result).toContain('cancelled');
455
+ expect(apiFetch).not.toHaveBeenCalled();
456
+ });
457
+ it('delete_instance with confirm=true — calls DELETE and returns success', async () => {
458
+ const apiFetch = vi.fn().mockResolvedValue({});
459
+ const result = await handleInstanceTool('delete_instance', { instance_id: 'inst-abc123', confirm: true }, getConnection, apiFetch);
460
+ expect(apiFetch).toHaveBeenCalledWith('/api/v1/instances/inst-abc123', { method: 'DELETE' });
461
+ expect(result).toContain('✅');
462
+ expect(result).toContain('inst-abc123');
463
+ });
464
+ it('list_orgs — empty org list returns hint to create org', async () => {
465
+ const apiFetch = vi.fn().mockResolvedValue({ orgs: [] });
466
+ const result = await handleInstanceTool('list_orgs', {}, getConnection, apiFetch);
467
+ expect(result).toContain('No organizations');
468
+ expect(result).toContain('create_org');
469
+ });
470
+ it('list_orgs — returns formatted org list', async () => {
471
+ const apiFetch = vi.fn().mockResolvedValue({
472
+ orgs: [
473
+ { id: 'org-1', name: 'ACME Inc.', slug: 'acme', plan: 'team', max_members: 10, member_count: 3 },
474
+ ],
475
+ });
476
+ const result = await handleInstanceTool('list_orgs', {}, getConnection, apiFetch);
477
+ expect(result).toContain('ACME Inc.');
478
+ expect(result).toContain('team');
479
+ expect(result).toContain('3/10');
480
+ });
481
+ it('create_org — returns created org details', async () => {
482
+ const apiFetch = vi.fn().mockResolvedValue({
483
+ id: 'org-new',
484
+ name: 'My Team',
485
+ slug: 'my-team',
486
+ plan: 'free',
487
+ });
488
+ const result = await handleInstanceTool('create_org', { name: 'My Team' }, getConnection, apiFetch);
489
+ expect(result).toContain('✅');
490
+ expect(result).toContain('My Team');
491
+ expect(result).toContain('invite_member');
492
+ });
493
+ it('invite_member — returns confirmation with email', async () => {
494
+ const apiFetch = vi.fn().mockResolvedValue({});
495
+ const result = await handleInstanceTool('invite_member', { org_id: 'org-1', email: 'dev@example.com', role: 'member' }, getConnection, apiFetch);
496
+ expect(result).toContain('✅');
497
+ expect(result).toContain('dev@example.com');
498
+ expect(result).toContain('member');
499
+ });
500
+ it('unknown tool name — returns null', async () => {
501
+ const result = await handleInstanceTool('nonexistent_tool', {}, getConnection, noop);
502
+ expect(result).toBeNull();
503
+ });
504
+ });
505
+ //# sourceMappingURL=handlers-unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers-unit.test.js","sourceRoot":"","sources":["../../src/__tests__/handlers-unit.test.ts"],"names":[],"mappings":"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"}