@jterrazz/test 3.1.0 → 3.3.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,381 @@
1
+ import { DeepMockProxy } from "vitest-mock-extended";
2
+
3
+ //#region src/mocking/mock-of-date.d.ts
4
+ interface MockDatePort {
5
+ reset: () => void;
6
+ set: (date: Date | number | string) => void;
7
+ }
8
+ declare const mockOfDate: MockDatePort;
9
+ //#endregion
10
+ //#region src/mocking/mock-of.d.ts
11
+ type MockPort = <T>() => DeepMockProxy<T>;
12
+ declare const mockOf: MockPort;
13
+ //#endregion
14
+ //#region src/specification/ports/database.port.d.ts
15
+ /**
16
+ * Abstract database interface for specification runners.
17
+ * Implement this to plug in your database stack.
18
+ */
19
+ interface DatabasePort {
20
+ /** Execute raw SQL (for seeding test data). */
21
+ seed(sql: string): Promise<void>;
22
+ /** Query a table and return rows as arrays of values. */
23
+ query(table: string, columns: string[]): Promise<unknown[][]>;
24
+ /** Reset database to clean state between tests. */
25
+ reset(): Promise<void>;
26
+ }
27
+ //#endregion
28
+ //#region src/infrastructure/services/service.port.d.ts
29
+ /**
30
+ * A service handle — returned by factory functions like postgres(), redis().
31
+ * Mutable: connectionString is populated after the orchestrator starts containers.
32
+ */
33
+ interface ServiceHandle {
34
+ /** Service type identifier. */
35
+ readonly type: string;
36
+ /** Compose service name (if linked). */
37
+ readonly composeName: null | string;
38
+ /** Default container port for this service type. */
39
+ readonly defaultPort: number;
40
+ /** Default Docker image for this service type. */
41
+ readonly defaultImage: string;
42
+ /** Environment variables to pass to the container. */
43
+ readonly environment: Record<string, string>;
44
+ /** Connection string — populated after start. */
45
+ connectionString: string;
46
+ /** Whether this service has been started. */
47
+ started: boolean;
48
+ /** Build the connection string from host and port. */
49
+ buildConnectionString(host: string, port: number): string;
50
+ /** Create a DatabasePort adapter (if this is a database). Returns null otherwise. */
51
+ createDatabaseAdapter(): DatabasePort | null;
52
+ /** Verify the service is ready and accepting connections. Throws with context if not. */
53
+ healthcheck(): Promise<void>;
54
+ /** Run initialization scripts (e.g., init.sql). Throws with SQL error context if it fails. */
55
+ initialize(composeDir: string): Promise<void>;
56
+ /** Reset state between tests (truncate tables, flush cache, etc.) */
57
+ reset(): Promise<void>;
58
+ }
59
+ //#endregion
60
+ //#region src/infrastructure/orchestrator.d.ts
61
+ interface OrchestratorOptions {
62
+ services: ServiceHandle[];
63
+ mode: "e2e" | "integration";
64
+ root?: string;
65
+ }
66
+ /**
67
+ * Orchestrator for test infrastructure.
68
+ * Integration: starts services via testcontainers.
69
+ * E2E: runs full docker compose up.
70
+ */
71
+ declare class Orchestrator {
72
+ private services;
73
+ private mode;
74
+ private root;
75
+ private running;
76
+ private composeStack;
77
+ private composeHandles;
78
+ private started;
79
+ constructor(options: OrchestratorOptions);
80
+ /**
81
+ * Start declared services via testcontainers (integration mode).
82
+ * Reads image/env config from docker-compose.test.yaml if a service has compose: "name".
83
+ */
84
+ start(): Promise<void>;
85
+ /**
86
+ * Stop testcontainers (integration mode).
87
+ */
88
+ stop(): Promise<void>;
89
+ /**
90
+ * Start full docker compose stack (e2e mode).
91
+ * Auto-detects infra services and creates handles for them.
92
+ */
93
+ startCompose(): Promise<void>;
94
+ /**
95
+ * Stop docker compose stack (e2e mode).
96
+ */
97
+ stopCompose(): Promise<void>;
98
+ /**
99
+ * Get a database service by compose name, or the first one if no name given.
100
+ */
101
+ getDatabase(serviceName?: string): DatabasePort | null;
102
+ /**
103
+ * Get all database services keyed by compose name.
104
+ */
105
+ getDatabases(): Map<string, DatabasePort>;
106
+ /**
107
+ * Get app URL from compose (e2e mode).
108
+ */
109
+ getAppUrl(): null | string;
110
+ }
111
+ //#endregion
112
+ //#region src/specification/ports/command.port.d.ts
113
+ /**
114
+ * Result of executing a CLI command.
115
+ */
116
+ interface CommandResult {
117
+ exitCode: number;
118
+ stdout: string;
119
+ stderr: string;
120
+ }
121
+ /**
122
+ * Abstract CLI interface for specification runners.
123
+ * Implement this to plug in your command execution strategy.
124
+ */
125
+ interface CommandPort {
126
+ /** Execute a CLI command with the given arguments in the given working directory. */
127
+ exec(args: string, cwd: string): Promise<CommandResult>;
128
+ }
129
+ //#endregion
130
+ //#region src/specification/ports/server.port.d.ts
131
+ /**
132
+ * HTTP response returned by a server port.
133
+ */
134
+ interface ServerResponse {
135
+ status: number;
136
+ body: unknown;
137
+ headers: Record<string, string>;
138
+ }
139
+ /**
140
+ * Abstract server interface for specification runners.
141
+ * Integration mode uses in-process app, E2E mode uses real HTTP.
142
+ */
143
+ interface ServerPort {
144
+ /** Send an HTTP request and return the response. */
145
+ request(method: string, path: string, body?: unknown): Promise<ServerResponse>;
146
+ }
147
+ //#endregion
148
+ //#region src/specification/specification.d.ts
149
+ interface SpecificationConfig {
150
+ command?: CommandPort;
151
+ database?: DatabasePort;
152
+ databases?: Map<string, DatabasePort>;
153
+ fixturesRoot?: string;
154
+ server?: ServerPort;
155
+ }
156
+ interface RequestInfo {
157
+ body?: unknown;
158
+ method: string;
159
+ path: string;
160
+ }
161
+ declare class SpecificationResult {
162
+ private commandResult?;
163
+ private config;
164
+ private requestInfo?;
165
+ private response?;
166
+ private testDir;
167
+ private workDir?;
168
+ constructor(options: {
169
+ commandResult?: CommandResult;
170
+ config: SpecificationConfig;
171
+ requestInfo?: RequestInfo;
172
+ response?: ServerResponse;
173
+ testDir: string;
174
+ workDir?: string;
175
+ });
176
+ expectStatus(code: number): this;
177
+ expectResponse(file: string): this;
178
+ expectExitCode(code: number): this;
179
+ expectStdout(file: string): this;
180
+ expectStdoutContains(str: string): this;
181
+ expectStderr(file: string): this;
182
+ expectStderrContains(str: string): this;
183
+ expectTable(table: string, options: {
184
+ columns: string[];
185
+ rows: unknown[][];
186
+ service?: string;
187
+ }): Promise<this>;
188
+ expectFile(path: string): this;
189
+ expectNoFile(path: string): this;
190
+ expectFileContains(path: string, content: string): this;
191
+ private resolveDatabase;
192
+ private resolveWorkPath;
193
+ }
194
+ declare class SpecificationBuilder {
195
+ private commandArgs;
196
+ private config;
197
+ private fixtures;
198
+ private label;
199
+ private mocks;
200
+ private projectName;
201
+ private request;
202
+ private seeds;
203
+ private testDir;
204
+ constructor(config: SpecificationConfig, testDir: string, label: string);
205
+ seed(file: string, options?: {
206
+ service?: string;
207
+ }): this;
208
+ fixture(file: string): this;
209
+ project(name: string): this;
210
+ mock(file: string): this;
211
+ get(path: string): this;
212
+ post(path: string, bodyFile?: string): this;
213
+ put(path: string, bodyFile?: string): this;
214
+ delete(path: string): this;
215
+ exec(args: string): this;
216
+ run(): Promise<SpecificationResult>;
217
+ private prepareWorkDir;
218
+ private runHttpAction;
219
+ private runCliAction;
220
+ }
221
+ type SpecificationRunner = (label: string) => SpecificationBuilder;
222
+ //#endregion
223
+ //#region src/infrastructure/services/postgres.d.ts
224
+ interface PostgresOptions {
225
+ /** Map to a service in docker-compose.test.yaml. */
226
+ compose?: string;
227
+ /** Override image. */
228
+ image?: string;
229
+ /** Override environment variables. */
230
+ env?: Record<string, string>;
231
+ }
232
+ declare class PostgresHandle implements DatabasePort, ServiceHandle {
233
+ readonly type = "postgres";
234
+ readonly composeName: null | string;
235
+ readonly defaultPort = 5432;
236
+ readonly defaultImage: string;
237
+ readonly environment: Record<string, string>;
238
+ connectionString: string;
239
+ started: boolean;
240
+ constructor(options?: PostgresOptions);
241
+ buildConnectionString(host: string, port: number): string;
242
+ createDatabaseAdapter(): DatabasePort;
243
+ healthcheck(): Promise<void>;
244
+ initialize(composeDir: string): Promise<void>;
245
+ private getClient;
246
+ seed(sql: string): Promise<void>;
247
+ query(table: string, columns: string[]): Promise<unknown[][]>;
248
+ reset(): Promise<void>;
249
+ }
250
+ /**
251
+ * Create a PostgreSQL service handle.
252
+ *
253
+ * @example
254
+ * const db = postgres({ compose: "db" });
255
+ * // After start: db.connectionString is populated
256
+ */
257
+ declare function postgres(options?: PostgresOptions): PostgresHandle;
258
+ //#endregion
259
+ //#region src/infrastructure/services/redis.d.ts
260
+ interface RedisOptions {
261
+ /** Map to a service in docker-compose.test.yaml. */
262
+ compose?: string;
263
+ /** Override image. */
264
+ image?: string;
265
+ }
266
+ declare class RedisHandle implements ServiceHandle {
267
+ readonly type = "redis";
268
+ readonly composeName: null | string;
269
+ readonly defaultPort = 6379;
270
+ readonly defaultImage: string;
271
+ readonly environment: Record<string, string>;
272
+ connectionString: string;
273
+ started: boolean;
274
+ constructor(options?: RedisOptions);
275
+ buildConnectionString(host: string, port: number): string;
276
+ createDatabaseAdapter(): DatabasePort | null;
277
+ healthcheck(): Promise<void>;
278
+ initialize(): Promise<void>;
279
+ reset(): Promise<void>;
280
+ }
281
+ /**
282
+ * Create a Redis service handle.
283
+ *
284
+ * @example
285
+ * const cache = redis({ compose: "cache" });
286
+ * // After start: cache.connectionString is populated
287
+ */
288
+ declare function redis(options?: RedisOptions): RedisHandle;
289
+ //#endregion
290
+ //#region src/specification/adapters/exec.adapter.d.ts
291
+ /**
292
+ * Executes CLI commands via execSync.
293
+ * Used by cli() for local command execution.
294
+ */
295
+ declare class ExecAdapter implements CommandPort {
296
+ private command;
297
+ constructor(command: string);
298
+ exec(args: string, cwd: string): Promise<CommandResult>;
299
+ }
300
+ //#endregion
301
+ //#region src/specification/adapters/fetch.adapter.d.ts
302
+ /**
303
+ * Server adapter for real HTTP — sends actual fetch requests.
304
+ * Used by e2e() specification runner.
305
+ */
306
+ declare class FetchAdapter implements ServerPort {
307
+ private baseUrl;
308
+ constructor(url: string);
309
+ request(method: string, path: string, body?: unknown): Promise<ServerResponse>;
310
+ }
311
+ //#endregion
312
+ //#region src/specification/adapters/hono.adapter.d.ts
313
+ /**
314
+ * Server adapter for Hono — in-process requests, no real HTTP.
315
+ * Used by integration() specification runner.
316
+ */
317
+ declare class HonoAdapter implements ServerPort {
318
+ private app;
319
+ constructor(app: {
320
+ request: (path: string, init?: RequestInit) => Promise<Response> | Response;
321
+ });
322
+ request(method: string, path: string, body?: unknown): Promise<ServerResponse>;
323
+ }
324
+ //#endregion
325
+ //#region src/infrastructure/reporter.d.ts
326
+ declare function stripAnsi(str: string): string;
327
+ declare function normalizeOutput(str: string): string;
328
+ //#endregion
329
+ //#region src/specification/index.d.ts
330
+ type HonoApp = {
331
+ fetch: (...args: any[]) => any;
332
+ request: (path: string, init?: RequestInit) => Promise<Response> | Response;
333
+ };
334
+ interface IntegrationOptions {
335
+ /** Factory that returns a Hono app — called after services start. */
336
+ app: () => HonoApp;
337
+ /** Project root for compose detection (relative paths supported). */
338
+ root?: string;
339
+ /** Declared services — started via testcontainers. */
340
+ services: ServiceHandle[];
341
+ }
342
+ interface E2eOptions {
343
+ /** Project root — must contain docker/compose.test.yaml. */
344
+ root?: string;
345
+ }
346
+ interface CliOptions {
347
+ /** CLI command to run (resolved from node_modules/.bin or PATH). */
348
+ command: string;
349
+ /** Project root — base dir for .project() fixture lookup (relative paths supported). */
350
+ root?: string;
351
+ /** Optional infrastructure services (started via testcontainers). */
352
+ services?: ServiceHandle[];
353
+ }
354
+ interface SpecificationRunnerWithCleanup extends SpecificationRunner {
355
+ cleanup: () => Promise<void>;
356
+ orchestrator: Orchestrator;
357
+ }
358
+ /**
359
+ * Create an integration specification runner.
360
+ * Starts infra containers via testcontainers, app runs in-process.
361
+ */
362
+ declare function integration(options: IntegrationOptions): Promise<SpecificationRunnerWithCleanup>;
363
+ /**
364
+ * Create an E2E specification runner.
365
+ * Starts full docker compose stack. App URL and database auto-detected.
366
+ */
367
+ declare function e2e(options?: E2eOptions): Promise<SpecificationRunnerWithCleanup>;
368
+ /**
369
+ * Create a CLI specification runner.
370
+ * Runs CLI commands against fixture projects. Optionally starts infrastructure.
371
+ *
372
+ * @example
373
+ * export const spec = await cli({
374
+ * command: resolve(import.meta.dirname, "../../bin/my-cli.sh"),
375
+ * root: "../fixtures",
376
+ * });
377
+ */
378
+ declare function cli(options: CliOptions): Promise<SpecificationRunnerWithCleanup>;
379
+ //#endregion
380
+ export { type CommandPort, type CommandResult, type DatabasePort, ExecAdapter, FetchAdapter, HonoAdapter, type MockDatePort, type MockPort, Orchestrator, type ServerPort, type ServerResponse, cli, e2e, integration, mockOf, mockOfDate, normalizeOutput, postgres, redis, stripAnsi };
381
+ //# sourceMappingURL=index.d.cts.map