@jterrazz/test 3.3.1 → 3.4.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.cjs CHANGED
@@ -4901,7 +4901,7 @@ var Orchestrator = class {
4901
4901
  //#endregion
4902
4902
  //#region src/specification/adapters/exec.adapter.ts
4903
4903
  /**
4904
- * Executes CLI commands via execSync.
4904
+ * Executes CLI commands via execSync (blocking) or spawn (long-running).
4905
4905
  * Used by cli() for local command execution.
4906
4906
  */
4907
4907
  var ExecAdapter = class {
@@ -4937,6 +4937,55 @@ var ExecAdapter = class {
4937
4937
  };
4938
4938
  }
4939
4939
  }
4940
+ async spawn(args, cwd, options) {
4941
+ const env = {
4942
+ ...process.env,
4943
+ INIT_CWD: void 0
4944
+ };
4945
+ return new Promise((resolve) => {
4946
+ let stdout = "";
4947
+ let stderr = "";
4948
+ let resolved = false;
4949
+ const child = (0, node_child_process.spawn)(this.command, args.split(/\s+/).filter(Boolean), {
4950
+ cwd,
4951
+ env,
4952
+ stdio: [
4953
+ "pipe",
4954
+ "pipe",
4955
+ "pipe"
4956
+ ]
4957
+ });
4958
+ const finish = (exitCode) => {
4959
+ if (resolved) return;
4960
+ resolved = true;
4961
+ child.kill("SIGTERM");
4962
+ resolve({
4963
+ exitCode,
4964
+ stdout,
4965
+ stderr
4966
+ });
4967
+ };
4968
+ let patternMatched = false;
4969
+ const checkPattern = () => {
4970
+ if (!patternMatched && (stdout.includes(options.waitFor) || stderr.includes(options.waitFor))) {
4971
+ patternMatched = true;
4972
+ finish(0);
4973
+ }
4974
+ };
4975
+ child.stdout?.on("data", (data) => {
4976
+ stdout += data.toString();
4977
+ checkPattern();
4978
+ });
4979
+ child.stderr?.on("data", (data) => {
4980
+ stderr += data.toString();
4981
+ checkPattern();
4982
+ });
4983
+ child.on("exit", (code) => {
4984
+ if (!patternMatched) finish(code === 0 ? 1 : code ?? 1);
4985
+ });
4986
+ setTimeout(() => finish(124), options.timeout);
4987
+ });
4988
+ }
4940
4989
  };
4941
4990
  //#endregion
4942
4991
  //#region src/specification/adapters/fetch.adapter.ts
@@ -5095,6 +5144,7 @@ var SpecificationBuilder = class {
5095
5144
  projectName = null;
5096
5145
  request = null;
5097
5146
  seeds = [];
5147
+ spawnConfig = null;
5098
5148
  testDir;
5099
5149
  constructor(config, testDir, label) {
5100
5150
  this.config = config;
@@ -5154,11 +5204,18 @@ var SpecificationBuilder = class {
5154
5204
  this.commandArgs = args;
5155
5205
  return this;
5156
5206
  }
5207
+ spawn(args, options) {
5208
+ this.spawnConfig = {
5209
+ args,
5210
+ options
5211
+ };
5212
+ return this;
5213
+ }
5157
5214
  async run() {
5158
5215
  const hasHttpAction = this.request !== null;
5159
- const hasCliAction = this.commandArgs !== null;
5216
+ const hasCliAction = this.commandArgs !== null || this.spawnConfig !== null;
5160
5217
  if (!hasHttpAction && !hasCliAction) throw new Error(`Specification "${this.label}": no action defined. Call .get(), .post(), .exec(), etc. before .run()`);
5161
- if (hasHttpAction && hasCliAction) throw new Error(`Specification "${this.label}": cannot mix HTTP (.get/.post) and CLI (.exec) actions`);
5218
+ if (hasHttpAction && hasCliAction) throw new Error(`Specification "${this.label}": cannot mix HTTP (.get/.post) and CLI (.exec/.spawn) actions`);
5162
5219
  let workDir = null;
5163
5220
  if (hasCliAction) workDir = this.prepareWorkDir();
5164
5221
  if (this.config.databases) for (const db of this.config.databases.values()) await db.reset();
@@ -5205,8 +5262,21 @@ var SpecificationBuilder = class {
5205
5262
  }
5206
5263
  async runCliAction(workDir) {
5207
5264
  if (!this.config.command) throw new Error("CLI actions require a command adapter (use cli())");
5265
+ let commandResult;
5266
+ if (this.spawnConfig) commandResult = await this.config.command.spawn(this.spawnConfig.args, workDir, this.spawnConfig.options);
5267
+ else if (Array.isArray(this.commandArgs)) {
5268
+ commandResult = {
5269
+ exitCode: 0,
5270
+ stdout: "",
5271
+ stderr: ""
5272
+ };
5273
+ for (const args of this.commandArgs) {
5274
+ commandResult = await this.config.command.exec(args, workDir);
5275
+ if (commandResult.exitCode !== 0) break;
5276
+ }
5277
+ } else commandResult = await this.config.command.exec(this.commandArgs, workDir);
5208
5278
  return new SpecificationResult({
5209
- commandResult: await this.config.command.exec(this.commandArgs, workDir),
5279
+ commandResult,
5210
5280
  config: this.config,
5211
5281
  testDir: this.testDir,
5212
5282
  workDir