@sparkleideas/testing 3.0.0-alpha.7
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 +547 -0
- package/__tests__/framework.test.ts +21 -0
- package/package.json +61 -0
- package/src/fixtures/agent-fixtures.ts +793 -0
- package/src/fixtures/agents.ts +212 -0
- package/src/fixtures/configurations.ts +491 -0
- package/src/fixtures/index.ts +21 -0
- package/src/fixtures/mcp-fixtures.ts +1030 -0
- package/src/fixtures/memory-entries.ts +328 -0
- package/src/fixtures/memory-fixtures.ts +750 -0
- package/src/fixtures/swarm-fixtures.ts +837 -0
- package/src/fixtures/tasks.ts +309 -0
- package/src/helpers/assertion-helpers.ts +616 -0
- package/src/helpers/assertions.ts +286 -0
- package/src/helpers/create-mock.ts +200 -0
- package/src/helpers/index.ts +182 -0
- package/src/helpers/mock-factory.ts +711 -0
- package/src/helpers/setup-teardown.ts +678 -0
- package/src/helpers/swarm-instance.ts +326 -0
- package/src/helpers/test-application.ts +310 -0
- package/src/helpers/test-utils.ts +670 -0
- package/src/index.ts +232 -0
- package/src/mocks/index.ts +29 -0
- package/src/mocks/mock-mcp-client.ts +723 -0
- package/src/mocks/mock-services.ts +793 -0
- package/src/regression/api-contract.ts +473 -0
- package/src/regression/index.ts +46 -0
- package/src/regression/integration-regression.ts +416 -0
- package/src/regression/performance-baseline.ts +356 -0
- package/src/regression/regression-runner.ts +339 -0
- package/src/regression/security-regression.ts +331 -0
- package/src/setup.ts +127 -0
- package/src/v2-compat/api-compat.test.ts +590 -0
- package/src/v2-compat/cli-compat.test.ts +484 -0
- package/src/v2-compat/compatibility-validator.ts +1072 -0
- package/src/v2-compat/hooks-compat.test.ts +602 -0
- package/src/v2-compat/index.ts +58 -0
- package/src/v2-compat/mcp-compat.test.ts +557 -0
- package/src/v2-compat/report-generator.ts +441 -0
- package/tmp.json +0 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +12 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V3 Claude-Flow Swarm Test Instance
|
|
3
|
+
*
|
|
4
|
+
* Creates isolated swarm instances for testing
|
|
5
|
+
* Supports 15-agent V3 swarm topology testing
|
|
6
|
+
*/
|
|
7
|
+
import { vi, type Mock } from 'vitest';
|
|
8
|
+
import { createMock, type MockedInterface, InteractionRecorder } from './create-mock.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Agent types for V3 15-agent swarm
|
|
12
|
+
*/
|
|
13
|
+
export type V3AgentType =
|
|
14
|
+
| 'queen-coordinator'
|
|
15
|
+
| 'security-architect'
|
|
16
|
+
| 'security-auditor'
|
|
17
|
+
| 'memory-specialist'
|
|
18
|
+
| 'swarm-specialist'
|
|
19
|
+
| 'integration-architect'
|
|
20
|
+
| 'performance-engineer'
|
|
21
|
+
| 'core-architect'
|
|
22
|
+
| 'test-architect'
|
|
23
|
+
| 'project-coordinator'
|
|
24
|
+
| 'coder'
|
|
25
|
+
| 'reviewer'
|
|
26
|
+
| 'tester'
|
|
27
|
+
| 'planner'
|
|
28
|
+
| 'researcher';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Swarm topology types
|
|
32
|
+
*/
|
|
33
|
+
export type SwarmTopology = 'hierarchical' | 'mesh' | 'adaptive' | 'hierarchical-mesh';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Agent interface for swarm testing
|
|
37
|
+
*/
|
|
38
|
+
export interface SwarmAgent {
|
|
39
|
+
id: string;
|
|
40
|
+
type: V3AgentType;
|
|
41
|
+
status: 'idle' | 'busy' | 'terminated';
|
|
42
|
+
capabilities: string[];
|
|
43
|
+
execute(task: SwarmTask): Promise<SwarmTaskResult>;
|
|
44
|
+
communicate(message: SwarmMessage): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Swarm message interface
|
|
49
|
+
*/
|
|
50
|
+
export interface SwarmMessage {
|
|
51
|
+
from: string;
|
|
52
|
+
to: string | 'broadcast';
|
|
53
|
+
type: 'task' | 'result' | 'status' | 'coordination';
|
|
54
|
+
payload: unknown;
|
|
55
|
+
timestamp: Date;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Swarm task interface
|
|
60
|
+
*/
|
|
61
|
+
export interface SwarmTask {
|
|
62
|
+
id: string;
|
|
63
|
+
type: string;
|
|
64
|
+
payload: unknown;
|
|
65
|
+
priority: number;
|
|
66
|
+
assignedTo?: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Swarm task result
|
|
71
|
+
*/
|
|
72
|
+
export interface SwarmTaskResult {
|
|
73
|
+
taskId: string;
|
|
74
|
+
agentId: string;
|
|
75
|
+
success: boolean;
|
|
76
|
+
output?: unknown;
|
|
77
|
+
error?: Error;
|
|
78
|
+
duration: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Swarm coordination result
|
|
83
|
+
*/
|
|
84
|
+
export interface SwarmCoordinationResult {
|
|
85
|
+
success: boolean;
|
|
86
|
+
completedTasks: number;
|
|
87
|
+
failedTasks: number;
|
|
88
|
+
totalDuration: number;
|
|
89
|
+
agentMetrics: Map<string, AgentMetrics>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Agent metrics
|
|
94
|
+
*/
|
|
95
|
+
export interface AgentMetrics {
|
|
96
|
+
tasksCompleted: number;
|
|
97
|
+
tasksFailed: number;
|
|
98
|
+
averageTaskDuration: number;
|
|
99
|
+
totalDuration: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Create a test swarm instance with mocked agents
|
|
104
|
+
*/
|
|
105
|
+
export function createSwarmTestInstance(config?: {
|
|
106
|
+
topology?: SwarmTopology;
|
|
107
|
+
agentTypes?: V3AgentType[];
|
|
108
|
+
}): SwarmTestInstance {
|
|
109
|
+
const topology = config?.topology ?? 'hierarchical-mesh';
|
|
110
|
+
const agentTypes = config?.agentTypes ?? [
|
|
111
|
+
'queen-coordinator',
|
|
112
|
+
'security-architect',
|
|
113
|
+
'security-auditor',
|
|
114
|
+
'memory-specialist',
|
|
115
|
+
'swarm-specialist',
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
return new SwarmTestInstance(topology, agentTypes);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Swarm test instance class
|
|
123
|
+
*/
|
|
124
|
+
export class SwarmTestInstance {
|
|
125
|
+
private agents: Map<string, MockedInterface<SwarmAgent>> = new Map();
|
|
126
|
+
private messages: SwarmMessage[] = [];
|
|
127
|
+
private taskResults: SwarmTaskResult[] = [];
|
|
128
|
+
private interactionRecorder: InteractionRecorder;
|
|
129
|
+
private isInitialized = false;
|
|
130
|
+
|
|
131
|
+
constructor(
|
|
132
|
+
public readonly topology: SwarmTopology,
|
|
133
|
+
private readonly agentTypes: V3AgentType[]
|
|
134
|
+
) {
|
|
135
|
+
this.interactionRecorder = new InteractionRecorder();
|
|
136
|
+
this.initializeAgents();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private initializeAgents(): void {
|
|
140
|
+
for (const type of this.agentTypes) {
|
|
141
|
+
const id = `${type}-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
142
|
+
const agent = this.createMockAgent(id, type);
|
|
143
|
+
this.agents.set(id, agent);
|
|
144
|
+
this.interactionRecorder.track(id, agent);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private createMockAgent(id: string, type: V3AgentType): MockedInterface<SwarmAgent> {
|
|
149
|
+
const mock = createMock<SwarmAgent>();
|
|
150
|
+
|
|
151
|
+
// Set default properties
|
|
152
|
+
Object.defineProperty(mock, 'id', { value: id, writable: false });
|
|
153
|
+
Object.defineProperty(mock, 'type', { value: type, writable: false });
|
|
154
|
+
Object.defineProperty(mock, 'status', { value: 'idle', writable: true });
|
|
155
|
+
Object.defineProperty(mock, 'capabilities', {
|
|
156
|
+
value: this.getCapabilitiesForType(type),
|
|
157
|
+
writable: false
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Configure default behavior
|
|
161
|
+
mock.execute.mockImplementation(async (task: SwarmTask) => {
|
|
162
|
+
const result: SwarmTaskResult = {
|
|
163
|
+
taskId: task.id,
|
|
164
|
+
agentId: id,
|
|
165
|
+
success: true,
|
|
166
|
+
duration: Math.random() * 100 + 10,
|
|
167
|
+
};
|
|
168
|
+
this.taskResults.push(result);
|
|
169
|
+
return result;
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
mock.communicate.mockImplementation(async (message: SwarmMessage) => {
|
|
173
|
+
this.messages.push(message);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
return mock;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private getCapabilitiesForType(type: V3AgentType): string[] {
|
|
180
|
+
const capabilities: Record<V3AgentType, string[]> = {
|
|
181
|
+
'queen-coordinator': ['orchestration', 'task-distribution', 'agent-management'],
|
|
182
|
+
'security-architect': ['security-design', 'threat-modeling', 'security-review'],
|
|
183
|
+
'security-auditor': ['cve-detection', 'vulnerability-scanning', 'security-testing'],
|
|
184
|
+
'memory-specialist': ['memory-optimization', 'agentdb-integration', 'caching'],
|
|
185
|
+
'swarm-specialist': ['coordination', 'consensus', 'communication'],
|
|
186
|
+
'integration-architect': ['api-design', 'system-integration', 'compatibility'],
|
|
187
|
+
'performance-engineer': ['optimization', 'benchmarking', 'profiling'],
|
|
188
|
+
'core-architect': ['ddd-design', 'architecture', 'domain-modeling'],
|
|
189
|
+
'test-architect': ['tdd', 'test-design', 'quality-assurance'],
|
|
190
|
+
'project-coordinator': ['project-management', 'scheduling', 'reporting'],
|
|
191
|
+
'coder': ['coding', 'implementation', 'debugging'],
|
|
192
|
+
'reviewer': ['code-review', 'quality-check', 'suggestions'],
|
|
193
|
+
'tester': ['testing', 'test-execution', 'coverage'],
|
|
194
|
+
'planner': ['planning', 'estimation', 'roadmap'],
|
|
195
|
+
'researcher': ['research', 'analysis', 'documentation'],
|
|
196
|
+
};
|
|
197
|
+
return capabilities[type];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Initialize the swarm
|
|
202
|
+
*/
|
|
203
|
+
async initialize(): Promise<void> {
|
|
204
|
+
this.isInitialized = true;
|
|
205
|
+
// Simulate initialization delay
|
|
206
|
+
await new Promise(resolve => setTimeout(resolve, 1));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get an agent by type
|
|
211
|
+
*/
|
|
212
|
+
getAgent(type: V3AgentType): MockedInterface<SwarmAgent> | undefined {
|
|
213
|
+
for (const [_, agent] of this.agents) {
|
|
214
|
+
if ((agent as unknown as SwarmAgent).type === type) {
|
|
215
|
+
return agent;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get all agents
|
|
223
|
+
*/
|
|
224
|
+
getAllAgents(): MockedInterface<SwarmAgent>[] {
|
|
225
|
+
return Array.from(this.agents.values());
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Get agent by ID
|
|
230
|
+
*/
|
|
231
|
+
getAgentById(id: string): MockedInterface<SwarmAgent> | undefined {
|
|
232
|
+
return this.agents.get(id);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Get all messages
|
|
237
|
+
*/
|
|
238
|
+
getMessages(): SwarmMessage[] {
|
|
239
|
+
return [...this.messages];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get task results
|
|
244
|
+
*/
|
|
245
|
+
getTaskResults(): SwarmTaskResult[] {
|
|
246
|
+
return [...this.taskResults];
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Get interaction order for behavior verification
|
|
251
|
+
*/
|
|
252
|
+
getInteractionOrder(): string[] {
|
|
253
|
+
return this.interactionRecorder.getInteractionOrder();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Get all interactions
|
|
258
|
+
*/
|
|
259
|
+
getInteractions(): Array<{ name: string; method: string; args: unknown[] }> {
|
|
260
|
+
return this.interactionRecorder.getInteractions();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Coordinate a task across agents
|
|
265
|
+
*/
|
|
266
|
+
async coordinate(task: SwarmTask): Promise<SwarmCoordinationResult> {
|
|
267
|
+
if (!this.isInitialized) {
|
|
268
|
+
throw new Error('Swarm not initialized');
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const startTime = Date.now();
|
|
272
|
+
const results: SwarmTaskResult[] = [];
|
|
273
|
+
|
|
274
|
+
// Simulate coordination based on topology
|
|
275
|
+
const queen = this.getAgent('queen-coordinator');
|
|
276
|
+
if (queen && this.topology.includes('hierarchical')) {
|
|
277
|
+
await queen.communicate({
|
|
278
|
+
from: 'coordinator',
|
|
279
|
+
to: 'broadcast',
|
|
280
|
+
type: 'task',
|
|
281
|
+
payload: task,
|
|
282
|
+
timestamp: new Date(),
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Execute task on appropriate agent
|
|
287
|
+
for (const agent of this.agents.values()) {
|
|
288
|
+
const result = await agent.execute(task);
|
|
289
|
+
results.push(result);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const completedTasks = results.filter(r => r.success).length;
|
|
293
|
+
const failedTasks = results.filter(r => !r.success).length;
|
|
294
|
+
|
|
295
|
+
return {
|
|
296
|
+
success: failedTasks === 0,
|
|
297
|
+
completedTasks,
|
|
298
|
+
failedTasks,
|
|
299
|
+
totalDuration: Date.now() - startTime,
|
|
300
|
+
agentMetrics: new Map(),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Shutdown the swarm
|
|
306
|
+
*/
|
|
307
|
+
async shutdown(): Promise<void> {
|
|
308
|
+
for (const agent of this.agents.values()) {
|
|
309
|
+
Object.defineProperty(agent, 'status', { value: 'terminated', writable: true });
|
|
310
|
+
}
|
|
311
|
+
this.isInitialized = false;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Reset the swarm state
|
|
316
|
+
*/
|
|
317
|
+
reset(): void {
|
|
318
|
+
this.messages = [];
|
|
319
|
+
this.taskResults = [];
|
|
320
|
+
this.interactionRecorder.clear();
|
|
321
|
+
|
|
322
|
+
for (const agent of this.agents.values()) {
|
|
323
|
+
vi.clearAllMocks();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V3 Claude-Flow Test Application Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates isolated test instances of the application
|
|
5
|
+
* Following London School principles for dependency injection
|
|
6
|
+
*/
|
|
7
|
+
import { vi, type Mock } from 'vitest';
|
|
8
|
+
import { createMock, type MockedInterface } from './create-mock.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Core domain interfaces for testing
|
|
12
|
+
*/
|
|
13
|
+
export interface IEventBus {
|
|
14
|
+
publish(event: DomainEvent): Promise<void>;
|
|
15
|
+
subscribe(eventType: string, handler: EventHandler): void;
|
|
16
|
+
unsubscribe(eventType: string, handler: EventHandler): void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ITaskManager {
|
|
20
|
+
create(task: TaskDefinition): Promise<Task>;
|
|
21
|
+
execute(taskId: string): Promise<TaskResult>;
|
|
22
|
+
cancel(taskId: string): Promise<void>;
|
|
23
|
+
getStatus(taskId: string): Promise<TaskStatus>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface IAgentLifecycle {
|
|
27
|
+
spawn(config: AgentConfig): Promise<Agent>;
|
|
28
|
+
terminate(agentId: string): Promise<void>;
|
|
29
|
+
getAgent(agentId: string): Promise<Agent | null>;
|
|
30
|
+
listAgents(): Promise<Agent[]>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface IMemoryService {
|
|
34
|
+
store(key: string, value: unknown, metadata?: MemoryMetadata): Promise<void>;
|
|
35
|
+
retrieve(key: string): Promise<unknown>;
|
|
36
|
+
search(query: VectorQuery): Promise<SearchResult[]>;
|
|
37
|
+
delete(key: string): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ISecurityService {
|
|
41
|
+
validatePath(path: string): boolean;
|
|
42
|
+
hashPassword(password: string): Promise<string>;
|
|
43
|
+
verifyPassword(password: string, hash: string): Promise<boolean>;
|
|
44
|
+
executeSecurely(command: string, options?: ExecuteOptions): Promise<ExecuteResult>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface ISwarmCoordinator {
|
|
48
|
+
initialize(config: SwarmConfig): Promise<void>;
|
|
49
|
+
coordinate(agents: Agent[], task: Task): Promise<CoordinationResult>;
|
|
50
|
+
shutdown(): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Type definitions for domain objects
|
|
55
|
+
*/
|
|
56
|
+
export interface DomainEvent {
|
|
57
|
+
type: string;
|
|
58
|
+
payload: unknown;
|
|
59
|
+
timestamp: Date;
|
|
60
|
+
correlationId?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type EventHandler = (event: DomainEvent) => Promise<void>;
|
|
64
|
+
|
|
65
|
+
export interface TaskDefinition {
|
|
66
|
+
name: string;
|
|
67
|
+
type: string;
|
|
68
|
+
payload: unknown;
|
|
69
|
+
priority?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface Task {
|
|
73
|
+
id: string;
|
|
74
|
+
name: string;
|
|
75
|
+
type: string;
|
|
76
|
+
status: TaskStatus;
|
|
77
|
+
payload: unknown;
|
|
78
|
+
createdAt: Date;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export type TaskStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
82
|
+
|
|
83
|
+
export interface TaskResult {
|
|
84
|
+
taskId: string;
|
|
85
|
+
success: boolean;
|
|
86
|
+
output?: unknown;
|
|
87
|
+
error?: Error;
|
|
88
|
+
duration: number;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface AgentConfig {
|
|
92
|
+
type: string;
|
|
93
|
+
name: string;
|
|
94
|
+
capabilities: string[];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface Agent {
|
|
98
|
+
id: string;
|
|
99
|
+
type: string;
|
|
100
|
+
name: string;
|
|
101
|
+
status: 'idle' | 'busy' | 'terminated';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface MemoryMetadata {
|
|
105
|
+
ttl?: number;
|
|
106
|
+
tags?: string[];
|
|
107
|
+
embedding?: number[];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface VectorQuery {
|
|
111
|
+
embedding: number[];
|
|
112
|
+
topK: number;
|
|
113
|
+
threshold?: number;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface SearchResult {
|
|
117
|
+
key: string;
|
|
118
|
+
value: unknown;
|
|
119
|
+
score: number;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface ExecuteOptions {
|
|
123
|
+
timeout?: number;
|
|
124
|
+
cwd?: string;
|
|
125
|
+
shell?: boolean;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface ExecuteResult {
|
|
129
|
+
stdout: string;
|
|
130
|
+
stderr: string;
|
|
131
|
+
exitCode: number;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface SwarmConfig {
|
|
135
|
+
topology: 'hierarchical' | 'mesh' | 'adaptive';
|
|
136
|
+
maxAgents: number;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface CoordinationResult {
|
|
140
|
+
success: boolean;
|
|
141
|
+
results: TaskResult[];
|
|
142
|
+
duration: number;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Test application builder with full dependency injection
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* const app = createTestApplication()
|
|
150
|
+
* .withMockEventBus()
|
|
151
|
+
* .withMockTaskManager()
|
|
152
|
+
* .build();
|
|
153
|
+
*
|
|
154
|
+
* await app.services.taskManager.create(task);
|
|
155
|
+
* expect(app.mocks.eventBus.publish).toHaveBeenCalled();
|
|
156
|
+
*/
|
|
157
|
+
export function createTestApplication(): TestApplicationBuilder {
|
|
158
|
+
return new TestApplicationBuilder();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Test application structure with mocked services
|
|
163
|
+
*/
|
|
164
|
+
export interface TestApplication {
|
|
165
|
+
services: {
|
|
166
|
+
eventBus: IEventBus;
|
|
167
|
+
taskManager: ITaskManager;
|
|
168
|
+
agentLifecycle: IAgentLifecycle;
|
|
169
|
+
memoryService: IMemoryService;
|
|
170
|
+
securityService: ISecurityService;
|
|
171
|
+
swarmCoordinator: ISwarmCoordinator;
|
|
172
|
+
};
|
|
173
|
+
mocks: {
|
|
174
|
+
eventBus: MockedInterface<IEventBus>;
|
|
175
|
+
taskManager: MockedInterface<ITaskManager>;
|
|
176
|
+
agentLifecycle: MockedInterface<IAgentLifecycle>;
|
|
177
|
+
memoryService: MockedInterface<IMemoryService>;
|
|
178
|
+
securityService: MockedInterface<ISecurityService>;
|
|
179
|
+
swarmCoordinator: MockedInterface<ISwarmCoordinator>;
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Builder class for constructing test applications
|
|
185
|
+
*/
|
|
186
|
+
class TestApplicationBuilder {
|
|
187
|
+
private eventBus: MockedInterface<IEventBus> = createMock<IEventBus>();
|
|
188
|
+
private taskManager: MockedInterface<ITaskManager> = createMock<ITaskManager>();
|
|
189
|
+
private agentLifecycle: MockedInterface<IAgentLifecycle> = createMock<IAgentLifecycle>();
|
|
190
|
+
private memoryService: MockedInterface<IMemoryService> = createMock<IMemoryService>();
|
|
191
|
+
private securityService: MockedInterface<ISecurityService> = createMock<ISecurityService>();
|
|
192
|
+
private swarmCoordinator: MockedInterface<ISwarmCoordinator> = createMock<ISwarmCoordinator>();
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Configure mock event bus with default behavior
|
|
196
|
+
*/
|
|
197
|
+
withMockEventBus(configure?: (mock: MockedInterface<IEventBus>) => void): this {
|
|
198
|
+
this.eventBus = createMock<IEventBus>();
|
|
199
|
+
this.eventBus.publish.mockResolvedValue(undefined);
|
|
200
|
+
configure?.(this.eventBus);
|
|
201
|
+
return this;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Configure mock task manager with default behavior
|
|
206
|
+
*/
|
|
207
|
+
withMockTaskManager(configure?: (mock: MockedInterface<ITaskManager>) => void): this {
|
|
208
|
+
this.taskManager = createMock<ITaskManager>();
|
|
209
|
+
this.taskManager.create.mockImplementation(async (def: TaskDefinition) => ({
|
|
210
|
+
id: `task-${Date.now()}`,
|
|
211
|
+
name: def.name,
|
|
212
|
+
type: def.type,
|
|
213
|
+
status: 'pending' as TaskStatus,
|
|
214
|
+
payload: def.payload,
|
|
215
|
+
createdAt: new Date(),
|
|
216
|
+
}));
|
|
217
|
+
this.taskManager.execute.mockResolvedValue({
|
|
218
|
+
taskId: 'test-task',
|
|
219
|
+
success: true,
|
|
220
|
+
duration: 100,
|
|
221
|
+
});
|
|
222
|
+
configure?.(this.taskManager);
|
|
223
|
+
return this;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Configure mock agent lifecycle with default behavior
|
|
228
|
+
*/
|
|
229
|
+
withMockAgentLifecycle(configure?: (mock: MockedInterface<IAgentLifecycle>) => void): this {
|
|
230
|
+
this.agentLifecycle = createMock<IAgentLifecycle>();
|
|
231
|
+
this.agentLifecycle.spawn.mockImplementation(async (config: AgentConfig) => ({
|
|
232
|
+
id: `agent-${Date.now()}`,
|
|
233
|
+
type: config.type,
|
|
234
|
+
name: config.name,
|
|
235
|
+
status: 'idle' as const,
|
|
236
|
+
}));
|
|
237
|
+
this.agentLifecycle.listAgents.mockResolvedValue([]);
|
|
238
|
+
configure?.(this.agentLifecycle);
|
|
239
|
+
return this;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Configure mock memory service with default behavior
|
|
244
|
+
*/
|
|
245
|
+
withMockMemoryService(configure?: (mock: MockedInterface<IMemoryService>) => void): this {
|
|
246
|
+
this.memoryService = createMock<IMemoryService>();
|
|
247
|
+
this.memoryService.store.mockResolvedValue(undefined);
|
|
248
|
+
this.memoryService.retrieve.mockResolvedValue(null);
|
|
249
|
+
this.memoryService.search.mockResolvedValue([]);
|
|
250
|
+
configure?.(this.memoryService);
|
|
251
|
+
return this;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Configure mock security service with default behavior
|
|
256
|
+
*/
|
|
257
|
+
withMockSecurityService(configure?: (mock: MockedInterface<ISecurityService>) => void): this {
|
|
258
|
+
this.securityService = createMock<ISecurityService>();
|
|
259
|
+
this.securityService.validatePath.mockReturnValue(true);
|
|
260
|
+
this.securityService.hashPassword.mockResolvedValue('hashed');
|
|
261
|
+
this.securityService.verifyPassword.mockResolvedValue(true);
|
|
262
|
+
this.securityService.executeSecurely.mockResolvedValue({
|
|
263
|
+
stdout: '',
|
|
264
|
+
stderr: '',
|
|
265
|
+
exitCode: 0,
|
|
266
|
+
});
|
|
267
|
+
configure?.(this.securityService);
|
|
268
|
+
return this;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Configure mock swarm coordinator with default behavior
|
|
273
|
+
*/
|
|
274
|
+
withMockSwarmCoordinator(configure?: (mock: MockedInterface<ISwarmCoordinator>) => void): this {
|
|
275
|
+
this.swarmCoordinator = createMock<ISwarmCoordinator>();
|
|
276
|
+
this.swarmCoordinator.initialize.mockResolvedValue(undefined);
|
|
277
|
+
this.swarmCoordinator.coordinate.mockResolvedValue({
|
|
278
|
+
success: true,
|
|
279
|
+
results: [],
|
|
280
|
+
duration: 0,
|
|
281
|
+
});
|
|
282
|
+
this.swarmCoordinator.shutdown.mockResolvedValue(undefined);
|
|
283
|
+
configure?.(this.swarmCoordinator);
|
|
284
|
+
return this;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Build the test application with all configured mocks
|
|
289
|
+
*/
|
|
290
|
+
build(): TestApplication {
|
|
291
|
+
return {
|
|
292
|
+
services: {
|
|
293
|
+
eventBus: this.eventBus as IEventBus,
|
|
294
|
+
taskManager: this.taskManager as ITaskManager,
|
|
295
|
+
agentLifecycle: this.agentLifecycle as IAgentLifecycle,
|
|
296
|
+
memoryService: this.memoryService as IMemoryService,
|
|
297
|
+
securityService: this.securityService as ISecurityService,
|
|
298
|
+
swarmCoordinator: this.swarmCoordinator as ISwarmCoordinator,
|
|
299
|
+
},
|
|
300
|
+
mocks: {
|
|
301
|
+
eventBus: this.eventBus,
|
|
302
|
+
taskManager: this.taskManager,
|
|
303
|
+
agentLifecycle: this.agentLifecycle,
|
|
304
|
+
memoryService: this.memoryService,
|
|
305
|
+
securityService: this.securityService,
|
|
306
|
+
swarmCoordinator: this.swarmCoordinator,
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
}
|