@jterrazz/test 5.0.0 → 5.2.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.
package/dist/index.d.cts CHANGED
@@ -128,15 +128,20 @@ interface SpawnOptions {
128
128
  /** Kill the process after this many milliseconds. */
129
129
  timeout: number;
130
130
  }
131
+ /**
132
+ * Extra environment variables to set for the child process.
133
+ * Values are merged on top of process.env. A `null` value unsets the variable.
134
+ */
135
+ type CommandEnv = Record<string, null | string>;
131
136
  /**
132
137
  * Abstract CLI interface for specification runners.
133
138
  * Implement this to plug in your command execution strategy.
134
139
  */
135
140
  interface CommandPort {
136
141
  /** Execute a CLI command with the given arguments in the given working directory. */
137
- exec(args: string, cwd: string): Promise<CommandResult>;
142
+ exec(args: string, cwd: string, env?: CommandEnv): Promise<CommandResult>;
138
143
  /** Spawn a long-running process and wait for a pattern or timeout. */
139
- spawn(args: string, cwd: string, options: SpawnOptions): Promise<CommandResult>;
144
+ spawn(args: string, cwd: string, options: SpawnOptions, env?: CommandEnv): Promise<CommandResult>;
140
145
  }
141
146
  //#endregion
142
147
  //#region src/specification/ports/server.port.d.ts
@@ -179,6 +184,33 @@ declare class TableAssertion {
179
184
  }): Promise<void>;
180
185
  toBeEmpty(): Promise<void>;
181
186
  }
187
+ interface DirectorySnapshotOptions {
188
+ /** Extra path segments to ignore (in addition to default: .git, node_modules, etc.). */
189
+ ignore?: string[];
190
+ /**
191
+ * Force update mode regardless of vitest flags / env vars.
192
+ * `true` writes the fixture, `false` always asserts. Defaults to auto-detect.
193
+ */
194
+ update?: boolean;
195
+ }
196
+ declare class DirectoryAccessor {
197
+ private absPath;
198
+ private testDir;
199
+ constructor(absPath: string, testDir: string);
200
+ /**
201
+ * Compare the directory tree against `expected/{name}/` (relative to the test file).
202
+ * On mismatch, throws with a structured diff. With update mode enabled, the
203
+ * fixture is overwritten with the current contents instead.
204
+ */
205
+ toMatchFixture(name: string, options?: DirectorySnapshotOptions): Promise<void>;
206
+ /**
207
+ * List all files in the directory (recursive, sorted, ignoring defaults).
208
+ * Useful for ad-hoc assertions when you don't want a full snapshot.
209
+ */
210
+ files(options?: {
211
+ ignore?: string[];
212
+ }): Promise<string[]>;
213
+ }
182
214
  declare class ResponseAccessor {
183
215
  readonly body: unknown;
184
216
  private testDir;
@@ -209,6 +241,7 @@ declare class SpecificationResult {
209
241
  get stdout(): string;
210
242
  get stderr(): string;
211
243
  get response(): ResponseAccessor;
244
+ directory(path?: string): DirectoryAccessor;
212
245
  file(path: string): FileAccessor;
213
246
  table(tableName: string, options?: {
214
247
  service?: string;
@@ -217,6 +250,7 @@ declare class SpecificationResult {
217
250
  }
218
251
  declare class SpecificationBuilder {
219
252
  private commandArgs;
253
+ private commandEnv;
220
254
  private config;
221
255
  private fixtures;
222
256
  private label;
@@ -233,6 +267,17 @@ declare class SpecificationBuilder {
233
267
  fixture(file: string): this;
234
268
  project(name: string): this;
235
269
  mock(file: string): this;
270
+ /**
271
+ * Set environment variables for the CLI process. Merged on top of process.env.
272
+ * Use `null` to unset a variable. Multiple calls merge.
273
+ *
274
+ * The token `$WORKDIR` (in any value) is replaced with the actual working
275
+ * directory at run-time — useful for tests that need a fully isolated `HOME`.
276
+ *
277
+ * @example
278
+ * spec("...").env({ HOME: "$WORKDIR", TZ: "UTC" }).exec("status").run();
279
+ */
280
+ env(env: CommandEnv): this;
236
281
  get(path: string): this;
237
282
  post(path: string, bodyFile?: string): this;
238
283
  put(path: string, bodyFile?: string): this;
@@ -240,6 +285,7 @@ declare class SpecificationBuilder {
240
285
  exec(args: string | string[]): this;
241
286
  spawn(args: string, options: SpawnOptions): this;
242
287
  run(): Promise<SpecificationResult>;
288
+ private resolveEnv;
243
289
  private prepareWorkDir;
244
290
  private runHttpAction;
245
291
  private runCliAction;
@@ -322,8 +368,8 @@ declare function redis(options?: RedisOptions): RedisHandle;
322
368
  declare class ExecAdapter implements CommandPort {
323
369
  private command;
324
370
  constructor(command: string);
325
- exec(args: string, cwd: string): Promise<CommandResult>;
326
- spawn(args: string, cwd: string, options: SpawnOptions): Promise<CommandResult>;
371
+ exec(args: string, cwd: string, extraEnv?: CommandEnv): Promise<CommandResult>;
372
+ spawn(args: string, cwd: string, options: SpawnOptions, extraEnv?: CommandEnv): Promise<CommandResult>;
327
373
  }
328
374
  //#endregion
329
375
  //#region src/specification/adapters/fetch.adapter.d.ts
@@ -417,5 +463,90 @@ declare function e2e(options?: E2eOptions): Promise<SpecificationRunnerWithClean
417
463
  */
418
464
  declare function cli(options: CliOptions): Promise<SpecificationRunnerWithCleanup>;
419
465
  //#endregion
420
- export { type CommandPort, type CommandResult, type DatabasePort, ExecAdapter, FetchAdapter, HonoAdapter, type MockDatePort, type MockPort, Orchestrator, type ServerPort, type ServerResponse, type SpecificationResult, cli, e2e, grep, integration, mockOf, mockOfDate, normalizeOutput, postgres, redis, stripAnsi };
466
+ //#region src/infrastructure/docker/docker-port.d.ts
467
+ interface DockerContainerPort {
468
+ /** Execute a command inside the container, return stdout */
469
+ exec(cmd: string[]): Promise<string>;
470
+ /** Read a file from inside the container */
471
+ file(path: string): Promise<{
472
+ exists: boolean;
473
+ content: string;
474
+ }>;
475
+ /** Check if container is running */
476
+ isRunning(): Promise<boolean>;
477
+ /** Get container logs */
478
+ logs(tail?: number): Promise<string>;
479
+ /** Get full docker inspect JSON */
480
+ inspect(): Promise<DockerInspectResult>;
481
+ /** Check if a file/directory exists */
482
+ exists(path: string): Promise<boolean>;
483
+ }
484
+ interface DockerInspectResult {
485
+ id: string;
486
+ name: string;
487
+ state: {
488
+ running: boolean;
489
+ exitCode: number;
490
+ status: string;
491
+ };
492
+ config: {
493
+ image: string;
494
+ env: string[];
495
+ };
496
+ hostConfig: {
497
+ memory: number;
498
+ cpuQuota: number;
499
+ networkMode: string;
500
+ mounts: Array<{
501
+ source: string;
502
+ destination: string;
503
+ type: string;
504
+ }>;
505
+ };
506
+ networkSettings: {
507
+ networks: Record<string, {
508
+ gateway: string;
509
+ ipAddress: string;
510
+ }>;
511
+ };
512
+ }
513
+ //#endregion
514
+ //#region src/infrastructure/docker/docker-adapter.d.ts
515
+ /** Create a Docker container port for an existing container */
516
+ declare function dockerContainer(containerId: string): DockerContainerPort;
517
+ //#endregion
518
+ //#region src/infrastructure/docker/docker-assertion.d.ts
519
+ /** Fluent assertion builder for Docker containers */
520
+ declare class DockerAssertion {
521
+ private container;
522
+ constructor(container: DockerContainerPort);
523
+ /** Assert the container is running */
524
+ toBeRunning(): Promise<this>;
525
+ /** Assert the container is NOT running / doesn't exist */
526
+ toNotExist(): Promise<this>;
527
+ /** Assert a file exists inside the container */
528
+ toHaveFile(path: string, opts?: {
529
+ containing?: string;
530
+ }): Promise<this>;
531
+ /** Assert a file does NOT exist */
532
+ toNotHaveFile(path: string): Promise<this>;
533
+ /** Assert a directory exists */
534
+ toHaveDirectory(path: string): Promise<this>;
535
+ /** Assert a mount exists */
536
+ toHaveMount(destination: string): Promise<this>;
537
+ /** Assert network mode */
538
+ toHaveNetwork(mode: string): Promise<this>;
539
+ /** Assert memory limit */
540
+ toHaveMemoryLimit(bytes: number): Promise<this>;
541
+ /** Assert CPU quota */
542
+ toHaveCpuQuota(quota: number): Promise<this>;
543
+ /** Execute a command and return output for custom assertions */
544
+ exec(cmd: string[]): Promise<string>;
545
+ /** Read a file for custom assertions */
546
+ readFile(path: string): Promise<string>;
547
+ /** Get logs for custom assertions */
548
+ getLogs(tail?: number): Promise<string>;
549
+ }
550
+ //#endregion
551
+ export { type CommandEnv, type CommandPort, type CommandResult, type DatabasePort, type DirectoryAccessor, type DirectorySnapshotOptions, DockerAssertion, type DockerContainerPort, type DockerInspectResult, ExecAdapter, FetchAdapter, HonoAdapter, type MockDatePort, type MockPort, Orchestrator, type ServerPort, type ServerResponse, type SpecificationResult, cli, dockerContainer, e2e, grep, integration, mockOf, mockOfDate, normalizeOutput, postgres, redis, stripAnsi };
421
552
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -128,15 +128,20 @@ interface SpawnOptions {
128
128
  /** Kill the process after this many milliseconds. */
129
129
  timeout: number;
130
130
  }
131
+ /**
132
+ * Extra environment variables to set for the child process.
133
+ * Values are merged on top of process.env. A `null` value unsets the variable.
134
+ */
135
+ type CommandEnv = Record<string, null | string>;
131
136
  /**
132
137
  * Abstract CLI interface for specification runners.
133
138
  * Implement this to plug in your command execution strategy.
134
139
  */
135
140
  interface CommandPort {
136
141
  /** Execute a CLI command with the given arguments in the given working directory. */
137
- exec(args: string, cwd: string): Promise<CommandResult>;
142
+ exec(args: string, cwd: string, env?: CommandEnv): Promise<CommandResult>;
138
143
  /** Spawn a long-running process and wait for a pattern or timeout. */
139
- spawn(args: string, cwd: string, options: SpawnOptions): Promise<CommandResult>;
144
+ spawn(args: string, cwd: string, options: SpawnOptions, env?: CommandEnv): Promise<CommandResult>;
140
145
  }
141
146
  //#endregion
142
147
  //#region src/specification/ports/server.port.d.ts
@@ -179,6 +184,33 @@ declare class TableAssertion {
179
184
  }): Promise<void>;
180
185
  toBeEmpty(): Promise<void>;
181
186
  }
187
+ interface DirectorySnapshotOptions {
188
+ /** Extra path segments to ignore (in addition to default: .git, node_modules, etc.). */
189
+ ignore?: string[];
190
+ /**
191
+ * Force update mode regardless of vitest flags / env vars.
192
+ * `true` writes the fixture, `false` always asserts. Defaults to auto-detect.
193
+ */
194
+ update?: boolean;
195
+ }
196
+ declare class DirectoryAccessor {
197
+ private absPath;
198
+ private testDir;
199
+ constructor(absPath: string, testDir: string);
200
+ /**
201
+ * Compare the directory tree against `expected/{name}/` (relative to the test file).
202
+ * On mismatch, throws with a structured diff. With update mode enabled, the
203
+ * fixture is overwritten with the current contents instead.
204
+ */
205
+ toMatchFixture(name: string, options?: DirectorySnapshotOptions): Promise<void>;
206
+ /**
207
+ * List all files in the directory (recursive, sorted, ignoring defaults).
208
+ * Useful for ad-hoc assertions when you don't want a full snapshot.
209
+ */
210
+ files(options?: {
211
+ ignore?: string[];
212
+ }): Promise<string[]>;
213
+ }
182
214
  declare class ResponseAccessor {
183
215
  readonly body: unknown;
184
216
  private testDir;
@@ -209,6 +241,7 @@ declare class SpecificationResult {
209
241
  get stdout(): string;
210
242
  get stderr(): string;
211
243
  get response(): ResponseAccessor;
244
+ directory(path?: string): DirectoryAccessor;
212
245
  file(path: string): FileAccessor;
213
246
  table(tableName: string, options?: {
214
247
  service?: string;
@@ -217,6 +250,7 @@ declare class SpecificationResult {
217
250
  }
218
251
  declare class SpecificationBuilder {
219
252
  private commandArgs;
253
+ private commandEnv;
220
254
  private config;
221
255
  private fixtures;
222
256
  private label;
@@ -233,6 +267,17 @@ declare class SpecificationBuilder {
233
267
  fixture(file: string): this;
234
268
  project(name: string): this;
235
269
  mock(file: string): this;
270
+ /**
271
+ * Set environment variables for the CLI process. Merged on top of process.env.
272
+ * Use `null` to unset a variable. Multiple calls merge.
273
+ *
274
+ * The token `$WORKDIR` (in any value) is replaced with the actual working
275
+ * directory at run-time — useful for tests that need a fully isolated `HOME`.
276
+ *
277
+ * @example
278
+ * spec("...").env({ HOME: "$WORKDIR", TZ: "UTC" }).exec("status").run();
279
+ */
280
+ env(env: CommandEnv): this;
236
281
  get(path: string): this;
237
282
  post(path: string, bodyFile?: string): this;
238
283
  put(path: string, bodyFile?: string): this;
@@ -240,6 +285,7 @@ declare class SpecificationBuilder {
240
285
  exec(args: string | string[]): this;
241
286
  spawn(args: string, options: SpawnOptions): this;
242
287
  run(): Promise<SpecificationResult>;
288
+ private resolveEnv;
243
289
  private prepareWorkDir;
244
290
  private runHttpAction;
245
291
  private runCliAction;
@@ -322,8 +368,8 @@ declare function redis(options?: RedisOptions): RedisHandle;
322
368
  declare class ExecAdapter implements CommandPort {
323
369
  private command;
324
370
  constructor(command: string);
325
- exec(args: string, cwd: string): Promise<CommandResult>;
326
- spawn(args: string, cwd: string, options: SpawnOptions): Promise<CommandResult>;
371
+ exec(args: string, cwd: string, extraEnv?: CommandEnv): Promise<CommandResult>;
372
+ spawn(args: string, cwd: string, options: SpawnOptions, extraEnv?: CommandEnv): Promise<CommandResult>;
327
373
  }
328
374
  //#endregion
329
375
  //#region src/specification/adapters/fetch.adapter.d.ts
@@ -417,5 +463,90 @@ declare function e2e(options?: E2eOptions): Promise<SpecificationRunnerWithClean
417
463
  */
418
464
  declare function cli(options: CliOptions): Promise<SpecificationRunnerWithCleanup>;
419
465
  //#endregion
420
- export { type CommandPort, type CommandResult, type DatabasePort, ExecAdapter, FetchAdapter, HonoAdapter, type MockDatePort, type MockPort, Orchestrator, type ServerPort, type ServerResponse, type SpecificationResult, cli, e2e, grep, integration, mockOf, mockOfDate, normalizeOutput, postgres, redis, stripAnsi };
466
+ //#region src/infrastructure/docker/docker-port.d.ts
467
+ interface DockerContainerPort {
468
+ /** Execute a command inside the container, return stdout */
469
+ exec(cmd: string[]): Promise<string>;
470
+ /** Read a file from inside the container */
471
+ file(path: string): Promise<{
472
+ exists: boolean;
473
+ content: string;
474
+ }>;
475
+ /** Check if container is running */
476
+ isRunning(): Promise<boolean>;
477
+ /** Get container logs */
478
+ logs(tail?: number): Promise<string>;
479
+ /** Get full docker inspect JSON */
480
+ inspect(): Promise<DockerInspectResult>;
481
+ /** Check if a file/directory exists */
482
+ exists(path: string): Promise<boolean>;
483
+ }
484
+ interface DockerInspectResult {
485
+ id: string;
486
+ name: string;
487
+ state: {
488
+ running: boolean;
489
+ exitCode: number;
490
+ status: string;
491
+ };
492
+ config: {
493
+ image: string;
494
+ env: string[];
495
+ };
496
+ hostConfig: {
497
+ memory: number;
498
+ cpuQuota: number;
499
+ networkMode: string;
500
+ mounts: Array<{
501
+ source: string;
502
+ destination: string;
503
+ type: string;
504
+ }>;
505
+ };
506
+ networkSettings: {
507
+ networks: Record<string, {
508
+ gateway: string;
509
+ ipAddress: string;
510
+ }>;
511
+ };
512
+ }
513
+ //#endregion
514
+ //#region src/infrastructure/docker/docker-adapter.d.ts
515
+ /** Create a Docker container port for an existing container */
516
+ declare function dockerContainer(containerId: string): DockerContainerPort;
517
+ //#endregion
518
+ //#region src/infrastructure/docker/docker-assertion.d.ts
519
+ /** Fluent assertion builder for Docker containers */
520
+ declare class DockerAssertion {
521
+ private container;
522
+ constructor(container: DockerContainerPort);
523
+ /** Assert the container is running */
524
+ toBeRunning(): Promise<this>;
525
+ /** Assert the container is NOT running / doesn't exist */
526
+ toNotExist(): Promise<this>;
527
+ /** Assert a file exists inside the container */
528
+ toHaveFile(path: string, opts?: {
529
+ containing?: string;
530
+ }): Promise<this>;
531
+ /** Assert a file does NOT exist */
532
+ toNotHaveFile(path: string): Promise<this>;
533
+ /** Assert a directory exists */
534
+ toHaveDirectory(path: string): Promise<this>;
535
+ /** Assert a mount exists */
536
+ toHaveMount(destination: string): Promise<this>;
537
+ /** Assert network mode */
538
+ toHaveNetwork(mode: string): Promise<this>;
539
+ /** Assert memory limit */
540
+ toHaveMemoryLimit(bytes: number): Promise<this>;
541
+ /** Assert CPU quota */
542
+ toHaveCpuQuota(quota: number): Promise<this>;
543
+ /** Execute a command and return output for custom assertions */
544
+ exec(cmd: string[]): Promise<string>;
545
+ /** Read a file for custom assertions */
546
+ readFile(path: string): Promise<string>;
547
+ /** Get logs for custom assertions */
548
+ getLogs(tail?: number): Promise<string>;
549
+ }
550
+ //#endregion
551
+ export { type CommandEnv, type CommandPort, type CommandResult, type DatabasePort, type DirectoryAccessor, type DirectorySnapshotOptions, DockerAssertion, type DockerContainerPort, type DockerInspectResult, ExecAdapter, FetchAdapter, HonoAdapter, type MockDatePort, type MockPort, Orchestrator, type ServerPort, type ServerResponse, type SpecificationResult, cli, dockerContainer, e2e, grep, integration, mockOf, mockOfDate, normalizeOutput, postgres, redis, stripAnsi };
421
552
  //# sourceMappingURL=index.d.ts.map