@tinycloudlabs/sdk-services-test 1.0.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.
@@ -0,0 +1,280 @@
1
+ /**
2
+ * MockServiceContext - Test implementation of IServiceContext
3
+ *
4
+ * Provides a configurable mock context for testing services
5
+ * without network dependencies.
6
+ */
7
+ /**
8
+ * MockServiceContext implements IServiceContext for testing.
9
+ *
10
+ * Features:
11
+ * - In-memory service registry
12
+ * - Configurable mock invoke that returns test data
13
+ * - Configurable mock fetch with pattern matching
14
+ * - Event emission tracking for assertions
15
+ * - Session state management
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const context = new MockServiceContext({
20
+ * session: createMockSession(),
21
+ * fetchResponses: new Map([
22
+ * ['/invoke', { ok: true, status: 200, body: { data: 'test' } }],
23
+ * ]),
24
+ * });
25
+ *
26
+ * const kv = new KVService({});
27
+ * kv.initialize(context);
28
+ * context.registerService('kv', kv);
29
+ *
30
+ * // Assert events were emitted
31
+ * expect(context.getEmittedEvents('service.request')).toHaveLength(1);
32
+ * ```
33
+ */
34
+ export class MockServiceContext {
35
+ constructor(config = {}) {
36
+ this._services = new Map();
37
+ this._eventHandlers = new Map();
38
+ this._emittedEvents = [];
39
+ this._abortController = new AbortController();
40
+ this._invokeCallCount = 0;
41
+ this._fetchCallCount = 0;
42
+ this._session = config.session ?? null;
43
+ this.hosts = config.hosts ?? ["https://mock.tinycloud.test"];
44
+ this._fetchResponses = config.fetchResponses ?? new Map();
45
+ this._defaultFetchResponse = config.defaultFetchResponse ?? {
46
+ ok: true,
47
+ status: 200,
48
+ statusText: "OK",
49
+ body: {},
50
+ };
51
+ this._invokeFunction = config.invoke ?? this.defaultInvoke.bind(this);
52
+ this.retryPolicy = config.retryPolicy ?? {
53
+ maxAttempts: 3,
54
+ backoff: "exponential",
55
+ baseDelayMs: 1000,
56
+ maxDelayMs: 10000,
57
+ retryableErrors: ["NETWORK_ERROR", "TIMEOUT"],
58
+ };
59
+ }
60
+ // ============================================================
61
+ // Session Management
62
+ // ============================================================
63
+ get session() {
64
+ return this._session;
65
+ }
66
+ get isAuthenticated() {
67
+ return this._session !== null;
68
+ }
69
+ /**
70
+ * Set the session (test helper).
71
+ */
72
+ setSession(session) {
73
+ this._session = session;
74
+ this.emit("session.changed", { authenticated: session !== null });
75
+ for (const service of this._services.values()) {
76
+ service.onSessionChange(session);
77
+ }
78
+ }
79
+ // ============================================================
80
+ // Platform Dependencies
81
+ // ============================================================
82
+ /**
83
+ * Default invoke implementation that returns mock headers.
84
+ */
85
+ defaultInvoke(session, service, path, action) {
86
+ return {
87
+ Authorization: `Bearer mock-token-${service}-${action}`,
88
+ "X-Mock-Service": service,
89
+ "X-Mock-Path": path,
90
+ "X-Mock-Action": action,
91
+ };
92
+ }
93
+ get invoke() {
94
+ return (session, service, path, action) => {
95
+ this._invokeCallCount++;
96
+ return this._invokeFunction(session, service, path, action);
97
+ };
98
+ }
99
+ get fetch() {
100
+ return async (url, init) => {
101
+ this._fetchCallCount++;
102
+ // Find matching response
103
+ let mockResponse = this._defaultFetchResponse;
104
+ for (const [pattern, handler] of this._fetchResponses) {
105
+ const matches = typeof pattern === "string"
106
+ ? url.includes(pattern)
107
+ : pattern.test(url);
108
+ if (matches) {
109
+ if (typeof handler === "function") {
110
+ mockResponse = await handler(url, init);
111
+ }
112
+ else {
113
+ mockResponse = handler;
114
+ }
115
+ break;
116
+ }
117
+ }
118
+ // Create mock response object
119
+ const headers = new Map(Object.entries(mockResponse.headers ?? {}).map(([k, v]) => [
120
+ k.toLowerCase(),
121
+ v,
122
+ ]));
123
+ return {
124
+ ok: mockResponse.ok,
125
+ status: mockResponse.status,
126
+ statusText: mockResponse.statusText,
127
+ headers: {
128
+ get: (name) => headers.get(name.toLowerCase()) ?? null,
129
+ },
130
+ json: async () => mockResponse.body,
131
+ text: async () => typeof mockResponse.body === "string"
132
+ ? mockResponse.body
133
+ : JSON.stringify(mockResponse.body),
134
+ };
135
+ };
136
+ }
137
+ // ============================================================
138
+ // Service Registry
139
+ // ============================================================
140
+ registerService(name, service) {
141
+ this._services.set(name, service);
142
+ }
143
+ unregisterService(name) {
144
+ this._services.delete(name);
145
+ }
146
+ getService(name) {
147
+ return this._services.get(name);
148
+ }
149
+ // ============================================================
150
+ // Event System (Telemetry)
151
+ // ============================================================
152
+ emit(event, data) {
153
+ // Record the event for assertions
154
+ this._emittedEvents.push({
155
+ event,
156
+ data,
157
+ timestamp: Date.now(),
158
+ });
159
+ // Notify handlers
160
+ const handlers = this._eventHandlers.get(event);
161
+ if (handlers) {
162
+ for (const handler of handlers) {
163
+ try {
164
+ handler(data);
165
+ }
166
+ catch {
167
+ // Swallow errors in handlers during tests
168
+ }
169
+ }
170
+ }
171
+ }
172
+ on(event, handler) {
173
+ if (!this._eventHandlers.has(event)) {
174
+ this._eventHandlers.set(event, new Set());
175
+ }
176
+ this._eventHandlers.get(event).add(handler);
177
+ return () => {
178
+ const handlers = this._eventHandlers.get(event);
179
+ if (handlers) {
180
+ handlers.delete(handler);
181
+ if (handlers.size === 0) {
182
+ this._eventHandlers.delete(event);
183
+ }
184
+ }
185
+ };
186
+ }
187
+ // ============================================================
188
+ // Lifecycle
189
+ // ============================================================
190
+ get abortSignal() {
191
+ return this._abortController.signal;
192
+ }
193
+ /**
194
+ * Abort all operations (test helper).
195
+ */
196
+ abort() {
197
+ this._abortController.abort();
198
+ this._abortController = new AbortController();
199
+ for (const service of this._services.values()) {
200
+ service.onSignOut();
201
+ }
202
+ }
203
+ // ============================================================
204
+ // Test Assertion Helpers
205
+ // ============================================================
206
+ /**
207
+ * Get all emitted events.
208
+ */
209
+ getEmittedEvents() {
210
+ return [...this._emittedEvents];
211
+ }
212
+ /**
213
+ * Get emitted events filtered by event name.
214
+ */
215
+ getEmittedEventsByName(eventName) {
216
+ return this._emittedEvents.filter((e) => e.event === eventName);
217
+ }
218
+ /**
219
+ * Check if a specific event was emitted.
220
+ */
221
+ wasEventEmitted(eventName) {
222
+ return this._emittedEvents.some((e) => e.event === eventName);
223
+ }
224
+ /**
225
+ * Get the count of events by name.
226
+ */
227
+ getEventCount(eventName) {
228
+ return this._emittedEvents.filter((e) => e.event === eventName).length;
229
+ }
230
+ /**
231
+ * Clear all recorded events.
232
+ */
233
+ clearEmittedEvents() {
234
+ this._emittedEvents = [];
235
+ }
236
+ /**
237
+ * Get the number of invoke calls.
238
+ */
239
+ get invokeCallCount() {
240
+ return this._invokeCallCount;
241
+ }
242
+ /**
243
+ * Get the number of fetch calls.
244
+ */
245
+ get fetchCallCount() {
246
+ return this._fetchCallCount;
247
+ }
248
+ /**
249
+ * Reset call counts.
250
+ */
251
+ resetCallCounts() {
252
+ this._invokeCallCount = 0;
253
+ this._fetchCallCount = 0;
254
+ }
255
+ /**
256
+ * Add a mock fetch response for a URL pattern.
257
+ */
258
+ addFetchResponse(pattern, response) {
259
+ this._fetchResponses.set(pattern, response);
260
+ }
261
+ /**
262
+ * Remove a mock fetch response.
263
+ */
264
+ removeFetchResponse(pattern) {
265
+ this._fetchResponses.delete(pattern);
266
+ }
267
+ /**
268
+ * Clear all mock fetch responses.
269
+ */
270
+ clearFetchResponses() {
271
+ this._fetchResponses.clear();
272
+ }
273
+ /**
274
+ * Set the default fetch response.
275
+ */
276
+ setDefaultFetchResponse(response) {
277
+ this._defaultFetchResponse = response;
278
+ }
279
+ }
280
+ //# sourceMappingURL=MockServiceContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockServiceContext.js","sourceRoot":"","sources":["../src/MockServiceContext.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Test Utilities for SDK Services
3
+ *
4
+ * Factory functions and helpers for creating test fixtures.
5
+ */
6
+ import type { ServiceSession } from "@tinycloudlabs/sdk-services";
7
+ import { MockServiceContext, MockServiceContextConfig, MockFetchResponse } from "./MockServiceContext";
8
+ import { MockKVService, MockKVServiceConfig } from "./MockKVService";
9
+ /**
10
+ * Options for creating a test context.
11
+ */
12
+ export interface CreateTestContextOptions extends MockServiceContextConfig {
13
+ /** Whether to include a default authenticated session */
14
+ authenticated?: boolean;
15
+ /** Custom session data */
16
+ sessionOverrides?: Partial<ServiceSession>;
17
+ }
18
+ /**
19
+ * Create a mock ServiceSession for testing.
20
+ *
21
+ * @param overrides - Optional overrides for session fields
22
+ * @returns A mock ServiceSession
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const session = createMockSession();
27
+ * const customSession = createMockSession({
28
+ * spaceId: 'space:custom-id',
29
+ * });
30
+ * ```
31
+ */
32
+ export declare function createMockSession(overrides?: Partial<ServiceSession>): ServiceSession;
33
+ /**
34
+ * Create a MockServiceContext with sensible defaults for testing.
35
+ *
36
+ * @param options - Configuration options
37
+ * @returns A configured MockServiceContext
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // Create an authenticated context
42
+ * const context = createTestContext({ authenticated: true });
43
+ *
44
+ * // Create with custom fetch responses
45
+ * const context = createTestContext({
46
+ * authenticated: true,
47
+ * fetchResponses: new Map([
48
+ * ['/invoke', { ok: true, status: 200, body: { data: 'test' } }],
49
+ * ]),
50
+ * });
51
+ * ```
52
+ */
53
+ export declare function createTestContext(options?: CreateTestContextOptions): MockServiceContext;
54
+ /**
55
+ * Create a MockKVService with initial data.
56
+ *
57
+ * @param initialData - Key-value pairs to seed the store
58
+ * @param config - Additional configuration
59
+ * @returns A configured MockKVService
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * const kv = createMockKV({
64
+ * 'user/settings': { theme: 'dark' },
65
+ * 'user/profile': { name: 'Alice' },
66
+ * });
67
+ *
68
+ * // With latency simulation
69
+ * const kv = createMockKV(
70
+ * { 'key': 'value' },
71
+ * { latencyMs: 50 }
72
+ * );
73
+ * ```
74
+ */
75
+ export declare function createMockKV(initialData?: Record<string, unknown>, config?: Omit<MockKVServiceConfig, "initialData">): MockKVService;
76
+ /**
77
+ * Wait for a specific event to be emitted from a context.
78
+ *
79
+ * @param context - The MockServiceContext to listen on
80
+ * @param eventName - The event name to wait for
81
+ * @param timeoutMs - Timeout in milliseconds (default: 5000)
82
+ * @returns Promise that resolves with the event data
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * // Wait for session change event
87
+ * const eventPromise = waitForEvent(context, 'session.changed');
88
+ * context.setSession(createMockSession());
89
+ * const eventData = await eventPromise;
90
+ * expect(eventData.authenticated).toBe(true);
91
+ * ```
92
+ */
93
+ export declare function waitForEvent(context: MockServiceContext, eventName: string, timeoutMs?: number): Promise<unknown>;
94
+ /**
95
+ * Wait for multiple events to be emitted.
96
+ *
97
+ * @param context - The MockServiceContext to listen on
98
+ * @param eventName - The event name to wait for
99
+ * @param count - Number of events to wait for
100
+ * @param timeoutMs - Timeout in milliseconds (default: 5000)
101
+ * @returns Promise that resolves with array of event data
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * // Wait for 3 service requests
106
+ * const eventsPromise = waitForEvents(context, 'service.request', 3);
107
+ * await kv.get('key1');
108
+ * await kv.get('key2');
109
+ * await kv.get('key3');
110
+ * const events = await eventsPromise;
111
+ * expect(events).toHaveLength(3);
112
+ * ```
113
+ */
114
+ export declare function waitForEvents(context: MockServiceContext, eventName: string, count: number, timeoutMs?: number): Promise<unknown[]>;
115
+ /**
116
+ * Create a mock fetch response for success scenarios.
117
+ *
118
+ * @param body - Response body
119
+ * @param headers - Optional response headers
120
+ * @returns MockFetchResponse
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * const response = mockOkResponse({ keys: ['a', 'b'] });
125
+ * context.addFetchResponse('/invoke', response);
126
+ * ```
127
+ */
128
+ export declare function mockOkResponse(body: unknown, headers?: Record<string, string>): MockFetchResponse;
129
+ /**
130
+ * Create a mock fetch response for error scenarios.
131
+ *
132
+ * @param status - HTTP status code
133
+ * @param body - Error body
134
+ * @param statusText - Optional status text
135
+ * @returns MockFetchResponse
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * const response = mockErrorResponse(404, { error: 'Not found' });
140
+ * context.addFetchResponse('/invoke', response);
141
+ * ```
142
+ */
143
+ export declare function mockErrorResponse(status: number, body?: unknown, statusText?: string): MockFetchResponse;
144
+ /**
145
+ * Create a delayed mock fetch handler for testing latency.
146
+ *
147
+ * @param response - The response to return after delay
148
+ * @param delayMs - Delay in milliseconds
149
+ * @returns Mock fetch handler function
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * context.addFetchResponse(
154
+ * '/invoke',
155
+ * delayedResponse(mockOkResponse({ data: 'test' }), 100)
156
+ * );
157
+ * ```
158
+ */
159
+ export declare function delayedResponse(response: MockFetchResponse, delayMs: number): () => Promise<MockFetchResponse>;
160
+ /**
161
+ * Create a sequence of mock responses that cycle through.
162
+ *
163
+ * @param responses - Array of responses to cycle through
164
+ * @returns Mock fetch handler function
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * // First call returns error, subsequent calls succeed
169
+ * context.addFetchResponse(
170
+ * '/invoke',
171
+ * sequenceResponses([
172
+ * mockErrorResponse(503, 'Temporarily unavailable'),
173
+ * mockOkResponse({ data: 'success' }),
174
+ * ])
175
+ * );
176
+ * ```
177
+ */
178
+ export declare function sequenceResponses(responses: MockFetchResponse[]): () => MockFetchResponse;
179
+ /**
180
+ * Assert that an operation was recorded with specific properties.
181
+ *
182
+ * @param kv - The MockKVService to check
183
+ * @param expected - Expected operation properties
184
+ * @returns Whether a matching operation was found
185
+ *
186
+ * @example
187
+ * ```typescript
188
+ * await kv.put('key', 'value');
189
+ * expect(wasOperationRecorded(kv, { type: 'put', key: 'key' })).toBe(true);
190
+ * ```
191
+ */
192
+ export declare function wasOperationRecorded(kv: MockKVService, expected: Partial<{
193
+ type: "get" | "put" | "list" | "delete" | "head";
194
+ key: string;
195
+ value: unknown;
196
+ }>): boolean;
197
+ /**
198
+ * Setup a MockKVService with a MockServiceContext.
199
+ *
200
+ * @param kvConfig - MockKVService configuration
201
+ * @param contextConfig - MockServiceContext configuration
202
+ * @returns Object with initialized kv and context
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * const { kv, context } = setupMockKV(
207
+ * { initialData: { 'key': 'value' } },
208
+ * { authenticated: true }
209
+ * );
210
+ *
211
+ * const result = await kv.get('key');
212
+ * expect(result.ok).toBe(true);
213
+ * ```
214
+ */
215
+ export declare function setupMockKV(kvConfig?: MockKVServiceConfig, contextConfig?: CreateTestContextOptions): {
216
+ kv: MockKVService;
217
+ context: MockServiceContext;
218
+ };
219
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,wBAAyB,SAAQ,wBAAwB;IACxE,yDAAyD;IACzD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0BAA0B;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CAC5C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAClC,cAAc,CAgBhB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE,wBAA6B,GACrC,kBAAkB,CAapB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAC1B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,MAAM,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,aAAa,CAAC,GAChD,aAAa,CAKf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,EACjB,SAAS,GAAE,MAAa,GACvB,OAAO,CAAC,OAAO,CAAC,CAalB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAAa,GACvB,OAAO,CAAC,OAAO,EAAE,CAAC,CAsBpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,iBAAiB,CAWnB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,OAAO,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,iBAAiB,CAUnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE,MAAM,GACd,MAAM,OAAO,CAAC,iBAAiB,CAAC,CAKlC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,iBAAiB,EAAE,GAC7B,MAAM,iBAAiB,CASzB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,aAAa,EACjB,QAAQ,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC,GACD,OAAO,CAST;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CACzB,QAAQ,CAAC,EAAE,mBAAmB,EAC9B,aAAa,CAAC,EAAE,wBAAwB,GACvC;IAAE,EAAE,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,CAMpD"}