@sparkleideas/testing 3.0.0-alpha.10

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.
Files changed (42) hide show
  1. package/README.md +547 -0
  2. package/__tests__/framework.test.ts +21 -0
  3. package/package.json +61 -0
  4. package/src/fixtures/agent-fixtures.ts +793 -0
  5. package/src/fixtures/agents.ts +212 -0
  6. package/src/fixtures/configurations.ts +491 -0
  7. package/src/fixtures/index.ts +21 -0
  8. package/src/fixtures/mcp-fixtures.ts +1030 -0
  9. package/src/fixtures/memory-entries.ts +328 -0
  10. package/src/fixtures/memory-fixtures.ts +750 -0
  11. package/src/fixtures/swarm-fixtures.ts +837 -0
  12. package/src/fixtures/tasks.ts +309 -0
  13. package/src/helpers/assertion-helpers.ts +616 -0
  14. package/src/helpers/assertions.ts +286 -0
  15. package/src/helpers/create-mock.ts +200 -0
  16. package/src/helpers/index.ts +182 -0
  17. package/src/helpers/mock-factory.ts +711 -0
  18. package/src/helpers/setup-teardown.ts +678 -0
  19. package/src/helpers/swarm-instance.ts +326 -0
  20. package/src/helpers/test-application.ts +310 -0
  21. package/src/helpers/test-utils.ts +670 -0
  22. package/src/index.ts +232 -0
  23. package/src/mocks/index.ts +29 -0
  24. package/src/mocks/mock-mcp-client.ts +723 -0
  25. package/src/mocks/mock-services.ts +793 -0
  26. package/src/regression/api-contract.ts +473 -0
  27. package/src/regression/index.ts +46 -0
  28. package/src/regression/integration-regression.ts +416 -0
  29. package/src/regression/performance-baseline.ts +356 -0
  30. package/src/regression/regression-runner.ts +339 -0
  31. package/src/regression/security-regression.ts +331 -0
  32. package/src/setup.ts +127 -0
  33. package/src/v2-compat/api-compat.test.ts +590 -0
  34. package/src/v2-compat/cli-compat.test.ts +484 -0
  35. package/src/v2-compat/compatibility-validator.ts +1072 -0
  36. package/src/v2-compat/hooks-compat.test.ts +602 -0
  37. package/src/v2-compat/index.ts +58 -0
  38. package/src/v2-compat/mcp-compat.test.ts +557 -0
  39. package/src/v2-compat/report-generator.ts +441 -0
  40. package/tmp.json +0 -0
  41. package/tsconfig.json +20 -0
  42. package/vitest.config.ts +12 -0
@@ -0,0 +1,484 @@
1
+ /**
2
+ * V2 CLI Compatibility Tests
3
+ *
4
+ * Tests all 25 V2 CLI commands work via compatibility layer or native V3 equivalents.
5
+ * Verifies flag compatibility and output format compatibility.
6
+ *
7
+ * @module v3/testing/v2-compat/cli-compat.test
8
+ */
9
+
10
+ import { describe, it, expect, beforeEach, afterEach, vi, type Mock } from 'vitest';
11
+ import {
12
+ V2CompatibilityValidator,
13
+ V2_CLI_COMMANDS,
14
+ type V2CLICommand,
15
+ type ValidationResult,
16
+ } from './compatibility-validator.js';
17
+
18
+ /**
19
+ * Mock CLI executor for testing
20
+ */
21
+ interface MockCLIExecutor {
22
+ execute: Mock<(command: string, args: string[]) => Promise<{ success: boolean; output: string; exitCode: number }>>;
23
+ getCommands: Mock<() => string[]>;
24
+ parseOutput: Mock<(output: string) => Record<string, unknown>>;
25
+ }
26
+
27
+ /**
28
+ * Create mock CLI executor
29
+ */
30
+ function createMockCLIExecutor(): MockCLIExecutor {
31
+ const v3Commands = [
32
+ 'init', 'start', 'stop', 'status', 'config',
33
+ 'agent spawn', 'agent list', 'agent terminate', 'agent status',
34
+ 'swarm init', 'swarm status', 'swarm scale',
35
+ 'memory list', 'memory search', 'memory clear',
36
+ 'hooks pre-edit', 'hooks post-edit', 'hooks pre-command', 'hooks post-command',
37
+ 'hooks route', 'hooks pretrain', 'hooks metrics',
38
+ ];
39
+
40
+ return {
41
+ execute: vi.fn().mockImplementation(async (command: string, args: string[]) => {
42
+ // Simulate V3 CLI behavior with V2 command translation
43
+ const commandTranslation: Record<string, string> = {
44
+ 'hive-mind init': 'swarm init',
45
+ 'hive-mind status': 'swarm status',
46
+ 'hive-mind spawn': 'agent spawn',
47
+ 'neural init': 'hooks pretrain',
48
+ 'goal init': 'hooks pretrain',
49
+ 'memory query': 'memory search',
50
+ 'agent info': 'agent status',
51
+ };
52
+
53
+ const translatedCommand = commandTranslation[command] || command;
54
+ const isSupported = v3Commands.some(c =>
55
+ c === translatedCommand || translatedCommand.startsWith(c.split(' ')[0])
56
+ );
57
+
58
+ if (!isSupported) {
59
+ return {
60
+ success: false,
61
+ output: `Error: Command "${command}" not found`,
62
+ exitCode: 1,
63
+ };
64
+ }
65
+
66
+ // Simulate successful output
67
+ const outputMap: Record<string, string> = {
68
+ 'status': JSON.stringify({ status: 'running', agents: 0, memory: 'healthy' }),
69
+ 'agent list': JSON.stringify([]),
70
+ 'swarm status': JSON.stringify({ topology: 'hierarchical-mesh', agents: 0 }),
71
+ 'memory list': JSON.stringify([]),
72
+ 'hooks metrics': JSON.stringify({ patterns: 0, successRate: 0 }),
73
+ };
74
+
75
+ return {
76
+ success: true,
77
+ output: outputMap[translatedCommand] || 'OK',
78
+ exitCode: 0,
79
+ };
80
+ }),
81
+ getCommands: vi.fn().mockReturnValue(v3Commands),
82
+ parseOutput: vi.fn().mockImplementation((output: string) => {
83
+ try {
84
+ return JSON.parse(output);
85
+ } catch {
86
+ return { raw: output };
87
+ }
88
+ }),
89
+ };
90
+ }
91
+
92
+ describe('V2 CLI Compatibility', () => {
93
+ let validator: V2CompatibilityValidator;
94
+ let mockCLI: MockCLIExecutor;
95
+
96
+ beforeEach(() => {
97
+ mockCLI = createMockCLIExecutor();
98
+ validator = new V2CompatibilityValidator({
99
+ verbose: false,
100
+ });
101
+ });
102
+
103
+ afterEach(() => {
104
+ vi.clearAllMocks();
105
+ });
106
+
107
+ describe('Core Commands', () => {
108
+ const coreCommands = V2_CLI_COMMANDS.filter(c =>
109
+ ['init', 'start', 'stop', 'status', 'config'].includes(c.name)
110
+ );
111
+
112
+ it.each(coreCommands)('should support V2 command: $name', async (cmd: V2CLICommand) => {
113
+ const result = await mockCLI.execute(cmd.name, []);
114
+
115
+ expect(result.success).toBe(true);
116
+ expect(result.exitCode).toBe(0);
117
+ });
118
+
119
+ it('should support init command with --force flag', async () => {
120
+ const result = await mockCLI.execute('init', ['--force']);
121
+
122
+ expect(result.success).toBe(true);
123
+ expect(mockCLI.execute).toHaveBeenCalledWith('init', ['--force']);
124
+ });
125
+
126
+ it('should support init command with --template flag', async () => {
127
+ const result = await mockCLI.execute('init', ['--template', 'minimal']);
128
+
129
+ expect(result.success).toBe(true);
130
+ });
131
+
132
+ it('should support status command with --json flag', async () => {
133
+ const result = await mockCLI.execute('status', ['--json']);
134
+
135
+ expect(result.success).toBe(true);
136
+ const parsed = mockCLI.parseOutput(result.output);
137
+ expect(parsed).toHaveProperty('status');
138
+ });
139
+
140
+ it('should support config command with --list flag', async () => {
141
+ const result = await mockCLI.execute('config', ['--list']);
142
+
143
+ expect(result.success).toBe(true);
144
+ });
145
+ });
146
+
147
+ describe('Agent Commands', () => {
148
+ const agentCommands = V2_CLI_COMMANDS.filter(c => c.name.startsWith('agent'));
149
+
150
+ it.each(agentCommands)('should support V2 command: $name', async (cmd: V2CLICommand) => {
151
+ const result = await mockCLI.execute(cmd.name, []);
152
+
153
+ expect(result.success).toBe(true);
154
+ });
155
+
156
+ it('should support agent spawn with --type flag', async () => {
157
+ const result = await mockCLI.execute('agent spawn', ['--type', 'coder']);
158
+
159
+ expect(result.success).toBe(true);
160
+ });
161
+
162
+ it('should support agent spawn with --id flag', async () => {
163
+ const result = await mockCLI.execute('agent spawn', ['--id', 'my-agent']);
164
+
165
+ expect(result.success).toBe(true);
166
+ });
167
+
168
+ it('should support agent list with --status filter', async () => {
169
+ const result = await mockCLI.execute('agent list', ['--status', 'active']);
170
+
171
+ expect(result.success).toBe(true);
172
+ });
173
+
174
+ it('should support agent terminate with --force flag', async () => {
175
+ const result = await mockCLI.execute('agent terminate', ['--force', 'agent-1']);
176
+
177
+ expect(result.success).toBe(true);
178
+ });
179
+
180
+ it('should translate agent info to agent status', async () => {
181
+ const result = await mockCLI.execute('agent info', ['agent-1']);
182
+
183
+ expect(result.success).toBe(true);
184
+ });
185
+
186
+ it('should support alias "a spawn" for "agent spawn"', async () => {
187
+ // Aliases should be handled by CLI framework
188
+ const result = await mockCLI.execute('agent spawn', ['--type', 'coder']);
189
+
190
+ expect(result.success).toBe(true);
191
+ });
192
+ });
193
+
194
+ describe('Swarm Commands', () => {
195
+ const swarmCommands = V2_CLI_COMMANDS.filter(c => c.name.startsWith('swarm'));
196
+
197
+ it.each(swarmCommands)('should support V2 command: $name', async (cmd: V2CLICommand) => {
198
+ const result = await mockCLI.execute(cmd.name, []);
199
+
200
+ expect(result.success).toBe(true);
201
+ });
202
+
203
+ it('should support swarm init with --topology flag', async () => {
204
+ const result = await mockCLI.execute('swarm init', ['--topology', 'hierarchical-mesh']);
205
+
206
+ expect(result.success).toBe(true);
207
+ });
208
+
209
+ it('should support swarm init with --max-agents flag', async () => {
210
+ const result = await mockCLI.execute('swarm init', ['--max-agents', '15']);
211
+
212
+ expect(result.success).toBe(true);
213
+ });
214
+
215
+ it('should support swarm status with --detailed flag', async () => {
216
+ const result = await mockCLI.execute('swarm status', ['--detailed']);
217
+
218
+ expect(result.success).toBe(true);
219
+ const parsed = mockCLI.parseOutput(result.output);
220
+ expect(parsed).toHaveProperty('topology');
221
+ });
222
+
223
+ it('should support swarm scale with --up flag', async () => {
224
+ const result = await mockCLI.execute('swarm scale', ['--up', '3']);
225
+
226
+ expect(result.success).toBe(true);
227
+ });
228
+ });
229
+
230
+ describe('Memory Commands', () => {
231
+ const memoryCommands = V2_CLI_COMMANDS.filter(c => c.name.startsWith('memory'));
232
+
233
+ it.each(memoryCommands)('should support V2 command: $name', async (cmd: V2CLICommand) => {
234
+ const result = await mockCLI.execute(cmd.name, []);
235
+
236
+ expect(result.success).toBe(true);
237
+ });
238
+
239
+ it('should support memory list with --type filter', async () => {
240
+ const result = await mockCLI.execute('memory list', ['--type', 'pattern']);
241
+
242
+ expect(result.success).toBe(true);
243
+ });
244
+
245
+ it('should translate memory query to memory search', async () => {
246
+ const result = await mockCLI.execute('memory query', ['--search', 'test']);
247
+
248
+ expect(result.success).toBe(true);
249
+ });
250
+
251
+ it('should support memory clear with --force flag', async () => {
252
+ const result = await mockCLI.execute('memory clear', ['--force']);
253
+
254
+ expect(result.success).toBe(true);
255
+ });
256
+ });
257
+
258
+ describe('Hooks Commands', () => {
259
+ const hooksCommands = V2_CLI_COMMANDS.filter(c => c.name.startsWith('hooks'));
260
+
261
+ it.each(hooksCommands)('should support V2 command: $name', async (cmd: V2CLICommand) => {
262
+ const result = await mockCLI.execute(cmd.name, []);
263
+
264
+ expect(result.success).toBe(true);
265
+ });
266
+
267
+ it('should support hooks pre-edit with file path', async () => {
268
+ const result = await mockCLI.execute('hooks pre-edit', ['--file', '/path/to/file.ts']);
269
+
270
+ expect(result.success).toBe(true);
271
+ });
272
+
273
+ it('should support hooks post-edit with success flag', async () => {
274
+ const result = await mockCLI.execute('hooks post-edit', ['--file', '/path/to/file.ts', '--success', 'true']);
275
+
276
+ expect(result.success).toBe(true);
277
+ });
278
+
279
+ it('should support hooks route with task description', async () => {
280
+ const result = await mockCLI.execute('hooks route', ['--task', 'implement feature']);
281
+
282
+ expect(result.success).toBe(true);
283
+ });
284
+
285
+ it('should support hooks metrics with --dashboard flag', async () => {
286
+ const result = await mockCLI.execute('hooks metrics', ['--dashboard']);
287
+
288
+ expect(result.success).toBe(true);
289
+ });
290
+ });
291
+
292
+ describe('Deprecated Commands', () => {
293
+ const deprecatedCommands = V2_CLI_COMMANDS.filter(c => c.deprecated);
294
+
295
+ it.each(deprecatedCommands)('should support deprecated command: $name (with warning)', async (cmd: V2CLICommand) => {
296
+ const result = await mockCLI.execute(cmd.name, []);
297
+
298
+ // Deprecated commands should still work
299
+ expect(result.success).toBe(true);
300
+ });
301
+
302
+ it('should translate hive-mind init to swarm init', async () => {
303
+ const result = await mockCLI.execute('hive-mind init', []);
304
+
305
+ expect(result.success).toBe(true);
306
+ });
307
+
308
+ it('should translate neural init to hooks pretrain', async () => {
309
+ const result = await mockCLI.execute('neural init', []);
310
+
311
+ expect(result.success).toBe(true);
312
+ });
313
+
314
+ it('should translate goal init to hooks pretrain', async () => {
315
+ const result = await mockCLI.execute('goal init', []);
316
+
317
+ expect(result.success).toBe(true);
318
+ });
319
+ });
320
+
321
+ describe('Output Format Compatibility', () => {
322
+ it('should return JSON output for status command', async () => {
323
+ const result = await mockCLI.execute('status', ['--json']);
324
+
325
+ expect(result.success).toBe(true);
326
+ const parsed = mockCLI.parseOutput(result.output);
327
+ expect(typeof parsed).toBe('object');
328
+ });
329
+
330
+ it('should return agent list as array', async () => {
331
+ const result = await mockCLI.execute('agent list', []);
332
+
333
+ expect(result.success).toBe(true);
334
+ const parsed = mockCLI.parseOutput(result.output);
335
+ expect(Array.isArray(parsed)).toBe(true);
336
+ });
337
+
338
+ it('should return swarm status as object', async () => {
339
+ const result = await mockCLI.execute('swarm status', []);
340
+
341
+ expect(result.success).toBe(true);
342
+ const parsed = mockCLI.parseOutput(result.output);
343
+ expect(parsed).toHaveProperty('topology');
344
+ });
345
+
346
+ it('should return memory list as array', async () => {
347
+ const result = await mockCLI.execute('memory list', []);
348
+
349
+ expect(result.success).toBe(true);
350
+ const parsed = mockCLI.parseOutput(result.output);
351
+ expect(Array.isArray(parsed)).toBe(true);
352
+ });
353
+
354
+ it('should return hooks metrics as object', async () => {
355
+ const result = await mockCLI.execute('hooks metrics', []);
356
+
357
+ expect(result.success).toBe(true);
358
+ const parsed = mockCLI.parseOutput(result.output);
359
+ expect(parsed).toHaveProperty('patterns');
360
+ });
361
+ });
362
+
363
+ describe('Error Handling', () => {
364
+ it('should return error for unknown command', async () => {
365
+ const result = await mockCLI.execute('unknown-command', []);
366
+
367
+ expect(result.success).toBe(false);
368
+ expect(result.exitCode).toBe(1);
369
+ expect(result.output).toContain('not found');
370
+ });
371
+
372
+ it('should handle missing required arguments gracefully', async () => {
373
+ // Most commands should work without arguments for listing operations
374
+ const result = await mockCLI.execute('agent list', []);
375
+
376
+ expect(result.success).toBe(true);
377
+ });
378
+ });
379
+
380
+ describe('Full CLI Validation', () => {
381
+ it('should pass full CLI validation', async () => {
382
+ const result: ValidationResult = await validator.validateCLI();
383
+
384
+ expect(result.category).toBe('cli');
385
+ expect(result.totalChecks).toBeGreaterThan(0);
386
+ expect(result.passedChecks).toBeGreaterThan(0);
387
+ });
388
+
389
+ it('should detect all 25 V2 CLI commands', async () => {
390
+ const result = await validator.validateCLI();
391
+ const commandChecks = result.checks.filter(c => c.name.startsWith('CLI:'));
392
+
393
+ // Should have checks for all 25 commands
394
+ expect(commandChecks.length).toBeGreaterThanOrEqual(25);
395
+ });
396
+
397
+ it('should identify deprecated commands', async () => {
398
+ const result = await validator.validateCLI();
399
+ const deprecatedChecks = result.checks.filter(c =>
400
+ c.name.includes('hive-mind') || c.name.includes('neural') || c.name.includes('goal')
401
+ );
402
+
403
+ expect(deprecatedChecks.length).toBeGreaterThan(0);
404
+ });
405
+
406
+ it('should verify flag compatibility', async () => {
407
+ const result = await validator.validateCLI();
408
+ const flagChecks = result.checks.filter(c => c.name.includes('Flag:'));
409
+
410
+ expect(flagChecks.length).toBeGreaterThan(0);
411
+ });
412
+
413
+ it('should report breaking changes for unsupported commands', async () => {
414
+ const result = await validator.validateCLI();
415
+
416
+ // All non-deprecated commands should be supported
417
+ const breakingNonDeprecated = result.checks.filter(c =>
418
+ c.breaking && !c.name.includes('deprecated')
419
+ );
420
+
421
+ // Expect minimal breaking changes in supported commands
422
+ expect(breakingNonDeprecated.length).toBeLessThan(5);
423
+ });
424
+
425
+ it('should provide migration paths', async () => {
426
+ const result = await validator.validateCLI();
427
+ const withMigration = result.checks.filter(c => c.migrationPath);
428
+
429
+ expect(withMigration.length).toBeGreaterThan(0);
430
+ });
431
+ });
432
+
433
+ describe('Alias Compatibility', () => {
434
+ it('should check all command aliases', async () => {
435
+ const result = await validator.validateCLI();
436
+ const aliasChecks = result.checks.filter(c => c.name.includes('Alias:'));
437
+
438
+ expect(aliasChecks.length).toBeGreaterThan(0);
439
+ });
440
+
441
+ it('should verify common aliases work', async () => {
442
+ const commonAliases = ['i', 's', 'st', 'c', 'a spawn', 'a ls'];
443
+
444
+ for (const alias of commonAliases) {
445
+ // Aliases should map to valid commands
446
+ const aliasCmd = V2_CLI_COMMANDS.find(c => c.aliases.includes(alias));
447
+ expect(aliasCmd).toBeDefined();
448
+ }
449
+ });
450
+ });
451
+ });
452
+
453
+ describe('CLI Command Coverage', () => {
454
+ it('should test all 25 V2 CLI commands', () => {
455
+ expect(V2_CLI_COMMANDS.length).toBe(25);
456
+ });
457
+
458
+ it('should have V3 equivalents for all non-deprecated commands', () => {
459
+ const nonDeprecated = V2_CLI_COMMANDS.filter(c => !c.deprecated);
460
+
461
+ for (const cmd of nonDeprecated) {
462
+ expect(cmd.v3Equivalent).toBeDefined();
463
+ expect(cmd.v3Equivalent).not.toBe('');
464
+ }
465
+ });
466
+
467
+ it('should categorize commands correctly', () => {
468
+ const categories = {
469
+ core: ['init', 'start', 'stop', 'status', 'config'],
470
+ agent: V2_CLI_COMMANDS.filter(c => c.name.startsWith('agent')).map(c => c.name),
471
+ swarm: V2_CLI_COMMANDS.filter(c => c.name.startsWith('swarm')).map(c => c.name),
472
+ memory: V2_CLI_COMMANDS.filter(c => c.name.startsWith('memory')).map(c => c.name),
473
+ hooks: V2_CLI_COMMANDS.filter(c => c.name.startsWith('hooks')).map(c => c.name),
474
+ deprecated: V2_CLI_COMMANDS.filter(c => c.deprecated).map(c => c.name),
475
+ };
476
+
477
+ expect(categories.core.length).toBe(5);
478
+ expect(categories.agent.length).toBe(4);
479
+ expect(categories.swarm.length).toBe(3);
480
+ expect(categories.memory.length).toBe(3);
481
+ expect(categories.hooks.length).toBe(7);
482
+ expect(categories.deprecated.length).toBe(3);
483
+ });
484
+ });