@stratix/testing 0.1.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.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/dist/AgentTester.d.ts +120 -0
  4. package/dist/AgentTester.d.ts.map +1 -0
  5. package/dist/AgentTester.js +152 -0
  6. package/dist/AgentTester.js.map +1 -0
  7. package/dist/MockLLMProvider.d.ts +80 -0
  8. package/dist/MockLLMProvider.d.ts.map +1 -0
  9. package/dist/MockLLMProvider.js +143 -0
  10. package/dist/MockLLMProvider.js.map +1 -0
  11. package/dist/TestApplication.d.ts +64 -0
  12. package/dist/TestApplication.d.ts.map +1 -0
  13. package/dist/TestApplication.js +90 -0
  14. package/dist/TestApplication.js.map +1 -0
  15. package/dist/assertions.d.ts +41 -0
  16. package/dist/assertions.d.ts.map +1 -0
  17. package/dist/assertions.js +82 -0
  18. package/dist/assertions.js.map +1 -0
  19. package/dist/builders/EntityBuilder.d.ts +47 -0
  20. package/dist/builders/EntityBuilder.d.ts.map +1 -0
  21. package/dist/builders/EntityBuilder.js +68 -0
  22. package/dist/builders/EntityBuilder.js.map +1 -0
  23. package/dist/factories/DataFactory.d.ts +42 -0
  24. package/dist/factories/DataFactory.d.ts.map +1 -0
  25. package/dist/factories/DataFactory.js +66 -0
  26. package/dist/factories/DataFactory.js.map +1 -0
  27. package/dist/index.d.ts +11 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +13 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/testHelpers.d.ts +51 -0
  32. package/dist/testHelpers.d.ts.map +1 -0
  33. package/dist/testHelpers.js +100 -0
  34. package/dist/testHelpers.js.map +1 -0
  35. package/dist/utils/assertions.d.ts +43 -0
  36. package/dist/utils/assertions.d.ts.map +1 -0
  37. package/dist/utils/assertions.js +62 -0
  38. package/dist/utils/assertions.js.map +1 -0
  39. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 P. Andrés Carvajal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # @stratix/testing
2
+
3
+ Test utilities for Stratix applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add -D @stratix/testing
9
+ ```
10
+
11
+ ## Features
12
+
13
+ - **MockLLMProvider** - Deterministic LLM responses
14
+ - **InMemoryEventBus** - Event bus for testing
15
+ - **TestContainer** - DI container for tests
16
+ - Helper functions for test entities
17
+
18
+ ## Quick Example
19
+
20
+ ```typescript
21
+ import { MockLLMProvider } from '@stratix/testing';
22
+
23
+ const mockProvider = new MockLLMProvider({
24
+ responses: ['Mocked response'],
25
+ cost: 0.001
26
+ });
27
+
28
+ const agent = new MyAgent(mockProvider);
29
+ const result = await agent.execute(input);
30
+
31
+ // No API calls, deterministic results, zero cost
32
+ ```
33
+
34
+ ## License
35
+
36
+ MIT
@@ -0,0 +1,120 @@
1
+ import type { AIAgent, AgentResult, AgentContext } from '@stratix/primitives';
2
+ import { MockLLMProvider } from './MockLLMProvider.js';
3
+ /**
4
+ * Test configuration options
5
+ */
6
+ export interface TestOptions {
7
+ /**
8
+ * Maximum execution time before timing out (ms)
9
+ */
10
+ timeout?: number;
11
+ /**
12
+ * Whether to capture execution traces
13
+ */
14
+ enableTracing?: boolean;
15
+ /**
16
+ * Mock LLM provider to use
17
+ */
18
+ mockProvider?: MockLLMProvider;
19
+ }
20
+ /**
21
+ * Test result with additional metadata
22
+ */
23
+ export interface TestResult<TOutput> {
24
+ /**
25
+ * The agent result
26
+ */
27
+ result: AgentResult<TOutput>;
28
+ /**
29
+ * Execution duration in milliseconds
30
+ */
31
+ duration: number;
32
+ /**
33
+ * Whether the test passed
34
+ */
35
+ passed: boolean;
36
+ /**
37
+ * Error message if test failed
38
+ */
39
+ error?: string;
40
+ }
41
+ /**
42
+ * Agent tester utility for testing AI agents with deterministic responses.
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * import { AgentTester } from '@stratix/testing';
47
+ *
48
+ * describe('MyAgent', () => {
49
+ * let tester: AgentTester;
50
+ *
51
+ * beforeEach(() => {
52
+ * tester = new AgentTester();
53
+ * });
54
+ *
55
+ * it('should process input correctly', async () => {
56
+ * const agent = new MyAgent(...);
57
+ *
58
+ * tester.setMockResponse({
59
+ * content: '{"result": "success"}',
60
+ * usage: { promptTokens: 10, completionTokens: 20, totalTokens: 30 }
61
+ * });
62
+ *
63
+ * const result = await tester.test(agent, input);
64
+ *
65
+ * expect(result.passed).toBe(true);
66
+ * expect(result.result.isSuccess()).toBe(true);
67
+ * });
68
+ * });
69
+ * ```
70
+ */
71
+ export declare class AgentTester {
72
+ private mockProvider;
73
+ private options;
74
+ constructor(options?: TestOptions);
75
+ /**
76
+ * Gets the mock LLM provider
77
+ */
78
+ getMockProvider(): MockLLMProvider;
79
+ /**
80
+ * Sets a single mock response
81
+ */
82
+ setMockResponse(response: Parameters<MockLLMProvider['setResponse']>[0]): void;
83
+ /**
84
+ * Sets multiple mock responses
85
+ */
86
+ setMockResponses(responses: Parameters<MockLLMProvider['setResponses']>[0]): void;
87
+ /**
88
+ * Tests an agent with the given input
89
+ */
90
+ test<TInput, TOutput>(agent: AIAgent<TInput, TOutput>, input: TInput, context?: AgentContext): Promise<TestResult<TOutput>>;
91
+ /**
92
+ * Executes agent with timeout
93
+ */
94
+ private executeWithTimeout;
95
+ /**
96
+ * Asserts that the result is successful
97
+ */
98
+ assertSuccess<TOutput>(result: TestResult<TOutput>): asserts result is TestResult<TOutput> & {
99
+ passed: true;
100
+ };
101
+ /**
102
+ * Asserts that the result is a failure
103
+ */
104
+ assertFailure<TOutput>(result: TestResult<TOutput>): asserts result is TestResult<TOutput> & {
105
+ passed: false;
106
+ };
107
+ /**
108
+ * Asserts that execution time is within limits
109
+ */
110
+ assertDuration<TOutput>(result: TestResult<TOutput>, maxDuration: number): void;
111
+ /**
112
+ * Asserts that the mock provider was called N times
113
+ */
114
+ assertCallCount(expectedCount: number): void;
115
+ /**
116
+ * Resets the tester state
117
+ */
118
+ reset(): void;
119
+ }
120
+ //# sourceMappingURL=AgentTester.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentTester.d.ts","sourceRoot":"","sources":["../src/AgentTester.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,YAAY,CAAC,EAAE,eAAe,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,OAAO;IACjC;;OAEG;IACH,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAE7B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,OAAO,CAAc;gBAEjB,OAAO,GAAE,WAAgB;IAUrC;;OAEG;IACH,eAAe,IAAI,eAAe;IAIlC;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,UAAU,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAI9E;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,UAAU,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAIjF;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,OAAO,EACxB,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAuC/B;;OAEG;YACW,kBAAkB;IAiBhC;;OAEG;IACH,aAAa,CAAC,OAAO,EACnB,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,GAC1B,OAAO,CAAC,MAAM,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG;QAAE,MAAM,EAAE,IAAI,CAAA;KAAE;IAM3D;;OAEG;IACH,aAAa,CAAC,OAAO,EACnB,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,GAC1B,OAAO,CAAC,MAAM,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG;QAAE,MAAM,EAAE,KAAK,CAAA;KAAE;IAM5D;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAM/E;;OAEG;IACH,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAO5C;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,152 @@
1
+ import { MockLLMProvider } from './MockLLMProvider.js';
2
+ /**
3
+ * Agent tester utility for testing AI agents with deterministic responses.
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * import { AgentTester } from '@stratix/testing';
8
+ *
9
+ * describe('MyAgent', () => {
10
+ * let tester: AgentTester;
11
+ *
12
+ * beforeEach(() => {
13
+ * tester = new AgentTester();
14
+ * });
15
+ *
16
+ * it('should process input correctly', async () => {
17
+ * const agent = new MyAgent(...);
18
+ *
19
+ * tester.setMockResponse({
20
+ * content: '{"result": "success"}',
21
+ * usage: { promptTokens: 10, completionTokens: 20, totalTokens: 30 }
22
+ * });
23
+ *
24
+ * const result = await tester.test(agent, input);
25
+ *
26
+ * expect(result.passed).toBe(true);
27
+ * expect(result.result.isSuccess()).toBe(true);
28
+ * });
29
+ * });
30
+ * ```
31
+ */
32
+ export class AgentTester {
33
+ mockProvider;
34
+ options;
35
+ constructor(options = {}) {
36
+ this.options = {
37
+ timeout: 30000,
38
+ enableTracing: true,
39
+ ...options,
40
+ };
41
+ this.mockProvider = options.mockProvider || new MockLLMProvider();
42
+ }
43
+ /**
44
+ * Gets the mock LLM provider
45
+ */
46
+ getMockProvider() {
47
+ return this.mockProvider;
48
+ }
49
+ /**
50
+ * Sets a single mock response
51
+ */
52
+ setMockResponse(response) {
53
+ this.mockProvider.setResponse(response);
54
+ }
55
+ /**
56
+ * Sets multiple mock responses
57
+ */
58
+ setMockResponses(responses) {
59
+ this.mockProvider.setResponses(responses);
60
+ }
61
+ /**
62
+ * Tests an agent with the given input
63
+ */
64
+ async test(agent, input, context) {
65
+ const startTime = Date.now();
66
+ let result;
67
+ let error;
68
+ let passed = false;
69
+ try {
70
+ // Execute with timeout
71
+ result = await this.executeWithTimeout(agent, input, context);
72
+ // Check if successful
73
+ passed = result.isSuccess();
74
+ if (!passed) {
75
+ error = result.error?.message || 'Unknown error';
76
+ }
77
+ }
78
+ catch (err) {
79
+ result = {
80
+ success: false,
81
+ error: err instanceof Error ? err : new Error(String(err)),
82
+ data: undefined,
83
+ metadata: {
84
+ model: 'unknown',
85
+ duration: Date.now() - startTime,
86
+ },
87
+ };
88
+ error = err instanceof Error ? err.message : String(err);
89
+ }
90
+ const duration = Date.now() - startTime;
91
+ return {
92
+ result,
93
+ duration,
94
+ passed,
95
+ error,
96
+ };
97
+ }
98
+ /**
99
+ * Executes agent with timeout
100
+ */
101
+ async executeWithTimeout(agent, input, _context) {
102
+ const timeout = this.options.timeout;
103
+ return Promise.race([
104
+ agent.execute(input),
105
+ new Promise((_, reject) => {
106
+ setTimeout(() => {
107
+ reject(new Error(`Test timeout after ${timeout}ms`));
108
+ }, timeout);
109
+ }),
110
+ ]);
111
+ }
112
+ /**
113
+ * Asserts that the result is successful
114
+ */
115
+ assertSuccess(result) {
116
+ if (!result.passed) {
117
+ throw new Error(`Expected success but got failure: ${result.error}`);
118
+ }
119
+ }
120
+ /**
121
+ * Asserts that the result is a failure
122
+ */
123
+ assertFailure(result) {
124
+ if (result.passed) {
125
+ throw new Error('Expected failure but got success');
126
+ }
127
+ }
128
+ /**
129
+ * Asserts that execution time is within limits
130
+ */
131
+ assertDuration(result, maxDuration) {
132
+ if (result.duration > maxDuration) {
133
+ throw new Error(`Expected duration <= ${maxDuration}ms but got ${result.duration}ms`);
134
+ }
135
+ }
136
+ /**
137
+ * Asserts that the mock provider was called N times
138
+ */
139
+ assertCallCount(expectedCount) {
140
+ const actualCount = this.mockProvider.getCallCount();
141
+ if (actualCount !== expectedCount) {
142
+ throw new Error(`Expected ${expectedCount} calls but got ${actualCount}`);
143
+ }
144
+ }
145
+ /**
146
+ * Resets the tester state
147
+ */
148
+ reset() {
149
+ this.mockProvider.reset();
150
+ }
151
+ }
152
+ //# sourceMappingURL=AgentTester.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentTester.js","sourceRoot":"","sources":["../src/AgentTester.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import type { LLMProvider, ChatParams, ChatResponse, ChatChunk, EmbeddingParams, EmbeddingResponse } from '@stratix/abstractions';
2
+ /**
3
+ * Mock response configuration
4
+ */
5
+ export interface MockResponse {
6
+ content: string;
7
+ usage?: {
8
+ promptTokens: number;
9
+ completionTokens: number;
10
+ totalTokens: number;
11
+ };
12
+ finishReason?: 'stop' | 'length' | 'tool_calls' | 'content_filter';
13
+ delay?: number;
14
+ }
15
+ /**
16
+ * Mock LLM Provider for testing AI agents without making actual API calls.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const mockProvider = new MockLLMProvider();
21
+ *
22
+ * // Set deterministic response
23
+ * mockProvider.setResponse({
24
+ * content: '{"result": "success"}',
25
+ * usage: { promptTokens: 10, completionTokens: 20, totalTokens: 30 }
26
+ * });
27
+ *
28
+ * // Use in tests
29
+ * const agent = new MyAgent({ provider: mockProvider });
30
+ * const result = await agent.execute(input);
31
+ * ```
32
+ */
33
+ export declare class MockLLMProvider implements LLMProvider {
34
+ readonly name = "mock";
35
+ readonly models: string[];
36
+ private responses;
37
+ private currentResponseIndex;
38
+ private callHistory;
39
+ /**
40
+ * Sets a single response that will be returned for all calls
41
+ */
42
+ setResponse(response: MockResponse): void;
43
+ /**
44
+ * Sets multiple responses that will be returned in sequence
45
+ */
46
+ setResponses(responses: MockResponse[]): void;
47
+ /**
48
+ * Adds a response to the queue
49
+ */
50
+ addResponse(response: MockResponse): void;
51
+ /**
52
+ * Gets the call history for assertions
53
+ */
54
+ getCallHistory(): ReadonlyArray<ChatParams>;
55
+ /**
56
+ * Gets the last call made to the provider
57
+ */
58
+ getLastCall(): ChatParams | undefined;
59
+ /**
60
+ * Gets the number of calls made
61
+ */
62
+ getCallCount(): number;
63
+ /**
64
+ * Clears all responses and call history
65
+ */
66
+ reset(): void;
67
+ /**
68
+ * Implements chat method
69
+ */
70
+ chat(params: ChatParams): Promise<ChatResponse>;
71
+ /**
72
+ * Implements streamChat method
73
+ */
74
+ streamChat(params: ChatParams): AsyncIterable<ChatChunk>;
75
+ /**
76
+ * Implements embeddings method
77
+ */
78
+ embeddings(params: EmbeddingParams): Promise<EmbeddingResponse>;
79
+ }
80
+ //# sourceMappingURL=MockLLMProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockLLMProvider.d.ts","sourceRoot":"","sources":["../src/MockLLMProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,YAAY,EACZ,SAAS,EACT,eAAe,EACf,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAE/B;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY,GAAG,gBAAgB,CAAC;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,eAAgB,YAAW,WAAW;IACjD,QAAQ,CAAC,IAAI,UAAU;IACvB,QAAQ,CAAC,MAAM,WAAkB;IAEjC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,WAAW,CAAoB;IAEvC;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAKzC;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,IAAI;IAK7C;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAIzC;;OAEG;IACH,cAAc,IAAI,aAAa,CAAC,UAAU,CAAC;IAI3C;;OAEG;IACH,WAAW,IAAI,UAAU,GAAG,SAAS;IAIrC;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IA8BrD;;OAEG;IACI,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC;IA+B/D;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAgBtE"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Mock LLM Provider for testing AI agents without making actual API calls.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * const mockProvider = new MockLLMProvider();
7
+ *
8
+ * // Set deterministic response
9
+ * mockProvider.setResponse({
10
+ * content: '{"result": "success"}',
11
+ * usage: { promptTokens: 10, completionTokens: 20, totalTokens: 30 }
12
+ * });
13
+ *
14
+ * // Use in tests
15
+ * const agent = new MyAgent({ provider: mockProvider });
16
+ * const result = await agent.execute(input);
17
+ * ```
18
+ */
19
+ export class MockLLMProvider {
20
+ name = 'mock';
21
+ models = ['mock-model'];
22
+ responses = [];
23
+ currentResponseIndex = 0;
24
+ callHistory = [];
25
+ /**
26
+ * Sets a single response that will be returned for all calls
27
+ */
28
+ setResponse(response) {
29
+ this.responses = [response];
30
+ this.currentResponseIndex = 0;
31
+ }
32
+ /**
33
+ * Sets multiple responses that will be returned in sequence
34
+ */
35
+ setResponses(responses) {
36
+ this.responses = responses;
37
+ this.currentResponseIndex = 0;
38
+ }
39
+ /**
40
+ * Adds a response to the queue
41
+ */
42
+ addResponse(response) {
43
+ this.responses.push(response);
44
+ }
45
+ /**
46
+ * Gets the call history for assertions
47
+ */
48
+ getCallHistory() {
49
+ return this.callHistory;
50
+ }
51
+ /**
52
+ * Gets the last call made to the provider
53
+ */
54
+ getLastCall() {
55
+ return this.callHistory[this.callHistory.length - 1];
56
+ }
57
+ /**
58
+ * Gets the number of calls made
59
+ */
60
+ getCallCount() {
61
+ return this.callHistory.length;
62
+ }
63
+ /**
64
+ * Clears all responses and call history
65
+ */
66
+ reset() {
67
+ this.responses = [];
68
+ this.currentResponseIndex = 0;
69
+ this.callHistory = [];
70
+ }
71
+ /**
72
+ * Implements chat method
73
+ */
74
+ async chat(params) {
75
+ this.callHistory.push(params);
76
+ if (this.responses.length === 0) {
77
+ throw new Error('No mock responses configured. Use setResponse() or setResponses()');
78
+ }
79
+ const response = this.responses[this.currentResponseIndex];
80
+ // Cycle through responses or stick to last one
81
+ if (this.currentResponseIndex < this.responses.length - 1) {
82
+ this.currentResponseIndex++;
83
+ }
84
+ // Simulate delay if specified
85
+ if (response.delay) {
86
+ await new Promise((resolve) => setTimeout(resolve, response.delay));
87
+ }
88
+ return {
89
+ content: response.content,
90
+ usage: response.usage || {
91
+ promptTokens: 10,
92
+ completionTokens: 10,
93
+ totalTokens: 20,
94
+ },
95
+ finishReason: response.finishReason || 'stop',
96
+ };
97
+ }
98
+ /**
99
+ * Implements streamChat method
100
+ */
101
+ async *streamChat(params) {
102
+ this.callHistory.push(params);
103
+ if (this.responses.length === 0) {
104
+ throw new Error('No mock responses configured');
105
+ }
106
+ const response = this.responses[this.currentResponseIndex];
107
+ if (this.currentResponseIndex < this.responses.length - 1) {
108
+ this.currentResponseIndex++;
109
+ }
110
+ // Split content into chunks
111
+ const words = response.content.split(' ');
112
+ const delayPerWord = response.delay !== undefined ? response.delay / words.length : 0;
113
+ for (let i = 0; i < words.length; i++) {
114
+ const chunk = {
115
+ content: words[i] + (i < words.length - 1 ? ' ' : ''),
116
+ isComplete: i === words.length - 1,
117
+ };
118
+ if (delayPerWord > 0) {
119
+ await new Promise((resolve) => setTimeout(resolve, delayPerWord));
120
+ }
121
+ yield chunk;
122
+ }
123
+ }
124
+ /**
125
+ * Implements embeddings method
126
+ */
127
+ async embeddings(params) {
128
+ const inputs = Array.isArray(params.input) ? params.input : [params.input];
129
+ const tokenCount = inputs.join(' ').split(' ').length;
130
+ return {
131
+ embeddings: inputs.map(() => {
132
+ // Generate fake embedding vector
133
+ return Array.from({ length: 1536 }, () => Math.random());
134
+ }),
135
+ usage: {
136
+ promptTokens: tokenCount,
137
+ completionTokens: 0,
138
+ totalTokens: tokenCount,
139
+ },
140
+ };
141
+ }
142
+ }
143
+ //# sourceMappingURL=MockLLMProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockLLMProvider.js","sourceRoot":"","sources":["../src/MockLLMProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import { Application } from '@stratix/runtime';
2
+ import type { Plugin, Logger, Container } from '@stratix/abstractions';
3
+ /**
4
+ * Test Application Builder
5
+ *
6
+ * Provides a simplified way to create test applications with in-memory implementations.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const app = await TestApplication.create()
11
+ * .useInMemoryDefaults()
12
+ * .build();
13
+ *
14
+ * await app.start();
15
+ * // Run tests
16
+ * await app.stop();
17
+ * ```
18
+ */
19
+ export declare class TestApplication {
20
+ private builder;
21
+ private testContainer?;
22
+ private testLogger?;
23
+ private constructor();
24
+ /**
25
+ * Create a new test application builder
26
+ */
27
+ static create(): TestApplication;
28
+ /**
29
+ * Use in-memory defaults for testing
30
+ *
31
+ * Includes:
32
+ * - Awilix Container
33
+ * - Console Logger (error level only)
34
+ */
35
+ useInMemoryDefaults(): this;
36
+ /**
37
+ * Set a custom container
38
+ */
39
+ useContainer(container: Container): this;
40
+ /**
41
+ * Set a custom logger
42
+ */
43
+ useLogger(logger: Logger): this;
44
+ /**
45
+ * Add a custom plugin
46
+ */
47
+ usePlugin(plugin: Plugin, config?: unknown): this;
48
+ /**
49
+ * Build the application
50
+ */
51
+ build(): Promise<Application>;
52
+ }
53
+ /**
54
+ * Create and start a test application
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const app = await createTestApp();
59
+ * // Run tests
60
+ * await app.stop();
61
+ * ```
62
+ */
63
+ export declare function createTestApp(): Promise<Application>;
64
+ //# sourceMappingURL=TestApplication.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestApplication.d.ts","sourceRoot":"","sources":["../src/TestApplication.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AAGnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGvE;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,aAAa,CAAC,CAAY;IAClC,OAAO,CAAC,UAAU,CAAC,CAAS;IAE5B,OAAO;IAIP;;OAEG;IACH,MAAM,CAAC,MAAM,IAAI,eAAe;IAIhC;;;;;;OAMG;IACH,mBAAmB,IAAI,IAAI;IAS3B;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAKxC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK/B;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAKjD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;CAGpC;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,WAAW,CAAC,CAM1D"}