@jterrazz/test 3.2.0 → 3.3.1
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/build.cjs +2 -2
- package/dist/build.js +1 -1
- package/dist/index.cjs +274 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -20
- package/dist/index.d.ts +85 -20
- package/dist/index.js +273 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,9 +2,10 @@ import { i as __require, o as __toESM, t as __commonJSMin } from "./chunk.js";
|
|
|
2
2
|
import { t as require_dist$1 } from "./dist.js";
|
|
3
3
|
import MockDatePackage from "mockdate";
|
|
4
4
|
import { mockDeep } from "vitest-mock-extended";
|
|
5
|
+
import { cpSync, existsSync, mkdtempSync, readFileSync } from "node:fs";
|
|
5
6
|
import { dirname, isAbsolute, resolve } from "node:path";
|
|
6
7
|
import { execSync } from "node:child_process";
|
|
7
|
-
import {
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
8
9
|
//#region src/mocking/mock-of-date.ts
|
|
9
10
|
const mockOfDate = MockDatePackage;
|
|
10
11
|
//#endregion
|
|
@@ -279,6 +280,60 @@ function formatResponseDiff(file, expected, actual) {
|
|
|
279
280
|
}
|
|
280
281
|
return lines.join("\n");
|
|
281
282
|
}
|
|
283
|
+
function formatExitCodeError(expected, received, stdout, stderr) {
|
|
284
|
+
const lines = [];
|
|
285
|
+
lines.push(`Expected exit code: ${GREEN}${expected}${RESET}`);
|
|
286
|
+
lines.push(`Received exit code: ${RED}${received}${RESET}`);
|
|
287
|
+
if (stdout.trim()) {
|
|
288
|
+
lines.push("");
|
|
289
|
+
lines.push(`${DIM}stdout:${RESET}`);
|
|
290
|
+
for (const line of stdout.trim().split("\n").slice(-15)) lines.push(` ${DIM}${line}${RESET}`);
|
|
291
|
+
}
|
|
292
|
+
if (stderr.trim()) {
|
|
293
|
+
lines.push("");
|
|
294
|
+
lines.push(`${DIM}stderr:${RESET}`);
|
|
295
|
+
for (const line of stderr.trim().split("\n").slice(-15)) lines.push(` ${RED}${line}${RESET}`);
|
|
296
|
+
}
|
|
297
|
+
return lines.join("\n");
|
|
298
|
+
}
|
|
299
|
+
function formatStdoutDiff(file, expected, actual) {
|
|
300
|
+
const lines = [];
|
|
301
|
+
lines.push(`Output mismatch (${file})`);
|
|
302
|
+
lines.push("");
|
|
303
|
+
lines.push(`${GREEN}- Expected${RESET}`);
|
|
304
|
+
lines.push(`${RED}+ Received${RESET}`);
|
|
305
|
+
lines.push("");
|
|
306
|
+
const expectedLines = expected.split("\n");
|
|
307
|
+
const actualLines = actual.split("\n");
|
|
308
|
+
const maxLines = Math.max(expectedLines.length, actualLines.length);
|
|
309
|
+
for (let i = 0; i < maxLines; i++) {
|
|
310
|
+
const exp = expectedLines[i];
|
|
311
|
+
const act = actualLines[i];
|
|
312
|
+
if (exp === act) lines.push(` ${exp}`);
|
|
313
|
+
else {
|
|
314
|
+
if (exp !== void 0) lines.push(`${GREEN}- ${exp}${RESET}`);
|
|
315
|
+
if (act !== void 0) lines.push(`${RED}+ ${act}${RESET}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return lines.join("\n");
|
|
319
|
+
}
|
|
320
|
+
function formatFileMissing(path) {
|
|
321
|
+
return `Expected file to exist: ${RED}${path}${RESET}`;
|
|
322
|
+
}
|
|
323
|
+
function formatFileUnexpected(path) {
|
|
324
|
+
return `Expected file NOT to exist: ${RED}${path}${RESET}`;
|
|
325
|
+
}
|
|
326
|
+
function formatFileContentMismatch(path, expected, actual) {
|
|
327
|
+
const lines = [];
|
|
328
|
+
lines.push(`File "${path}" does not contain expected content`);
|
|
329
|
+
lines.push("");
|
|
330
|
+
lines.push(`${GREEN}Expected to contain:${RESET}`);
|
|
331
|
+
lines.push(` ${GREEN}${expected}${RESET}`);
|
|
332
|
+
lines.push("");
|
|
333
|
+
lines.push(`${RED}Actual content (first 20 lines):${RESET}`);
|
|
334
|
+
for (const line of actual.split("\n").slice(0, 20)) lines.push(` ${DIM}${line}${RESET}`);
|
|
335
|
+
return lines.join("\n");
|
|
336
|
+
}
|
|
282
337
|
function rowLabel(n) {
|
|
283
338
|
return n === 1 ? "1 row" : `${n} rows`;
|
|
284
339
|
}
|
|
@@ -4842,6 +4897,46 @@ var Orchestrator = class {
|
|
|
4842
4897
|
}
|
|
4843
4898
|
};
|
|
4844
4899
|
//#endregion
|
|
4900
|
+
//#region src/specification/adapters/exec.adapter.ts
|
|
4901
|
+
/**
|
|
4902
|
+
* Executes CLI commands via execSync.
|
|
4903
|
+
* Used by cli() for local command execution.
|
|
4904
|
+
*/
|
|
4905
|
+
var ExecAdapter = class {
|
|
4906
|
+
command;
|
|
4907
|
+
constructor(command) {
|
|
4908
|
+
this.command = command;
|
|
4909
|
+
}
|
|
4910
|
+
async exec(args, cwd) {
|
|
4911
|
+
const env = {
|
|
4912
|
+
...process.env,
|
|
4913
|
+
INIT_CWD: void 0
|
|
4914
|
+
};
|
|
4915
|
+
try {
|
|
4916
|
+
return {
|
|
4917
|
+
exitCode: 0,
|
|
4918
|
+
stdout: execSync(`${this.command} ${args}`, {
|
|
4919
|
+
cwd,
|
|
4920
|
+
encoding: "utf8",
|
|
4921
|
+
env,
|
|
4922
|
+
stdio: [
|
|
4923
|
+
"pipe",
|
|
4924
|
+
"pipe",
|
|
4925
|
+
"pipe"
|
|
4926
|
+
]
|
|
4927
|
+
}),
|
|
4928
|
+
stderr: ""
|
|
4929
|
+
};
|
|
4930
|
+
} catch (error) {
|
|
4931
|
+
return {
|
|
4932
|
+
exitCode: error.status ?? 1,
|
|
4933
|
+
stdout: error.stdout?.toString() ?? "",
|
|
4934
|
+
stderr: error.stderr?.toString() ?? ""
|
|
4935
|
+
};
|
|
4936
|
+
}
|
|
4937
|
+
}
|
|
4938
|
+
};
|
|
4939
|
+
//#endregion
|
|
4845
4940
|
//#region src/specification/adapters/fetch.adapter.ts
|
|
4846
4941
|
/**
|
|
4847
4942
|
* Server adapter for real HTTP — sends actual fetch requests.
|
|
@@ -4904,25 +4999,60 @@ var HonoAdapter = class {
|
|
|
4904
4999
|
//#endregion
|
|
4905
5000
|
//#region src/specification/specification.ts
|
|
4906
5001
|
var SpecificationResult = class {
|
|
4907
|
-
|
|
5002
|
+
commandResult;
|
|
4908
5003
|
config;
|
|
4909
|
-
testDir;
|
|
4910
5004
|
requestInfo;
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
this.
|
|
5005
|
+
response;
|
|
5006
|
+
testDir;
|
|
5007
|
+
workDir;
|
|
5008
|
+
constructor(options) {
|
|
5009
|
+
this.response = options.response;
|
|
5010
|
+
this.commandResult = options.commandResult;
|
|
5011
|
+
this.config = options.config;
|
|
5012
|
+
this.testDir = options.testDir;
|
|
5013
|
+
this.requestInfo = options.requestInfo;
|
|
5014
|
+
this.workDir = options.workDir;
|
|
4916
5015
|
}
|
|
4917
5016
|
expectStatus(code) {
|
|
5017
|
+
if (!this.response || !this.requestInfo) throw new Error("expectStatus requires an HTTP action (.get(), .post(), etc.)");
|
|
4918
5018
|
if (this.response.status !== code) throw new Error(formatStatusError(code, this.response.status, this.requestInfo, this.response.body));
|
|
4919
5019
|
return this;
|
|
4920
5020
|
}
|
|
4921
5021
|
expectResponse(file) {
|
|
5022
|
+
if (!this.response) throw new Error("expectResponse requires an HTTP action (.get(), .post(), etc.)");
|
|
4922
5023
|
const expected = JSON.parse(readFileSync(resolve(this.testDir, "responses", file), "utf8"));
|
|
4923
5024
|
if (JSON.stringify(this.response.body) !== JSON.stringify(expected)) throw new Error(formatResponseDiff(file, expected, this.response.body));
|
|
4924
5025
|
return this;
|
|
4925
5026
|
}
|
|
5027
|
+
expectExitCode(code) {
|
|
5028
|
+
if (!this.commandResult) throw new Error("expectExitCode requires a CLI action (.exec())");
|
|
5029
|
+
if (this.commandResult.exitCode !== code) throw new Error(formatExitCodeError(code, this.commandResult.exitCode, this.commandResult.stdout, this.commandResult.stderr));
|
|
5030
|
+
return this;
|
|
5031
|
+
}
|
|
5032
|
+
expectStdout(file) {
|
|
5033
|
+
if (!this.commandResult) throw new Error("expectStdout requires a CLI action (.exec())");
|
|
5034
|
+
const expected = readFileSync(resolve(this.testDir, "expected", file), "utf8").trim();
|
|
5035
|
+
const actual = this.commandResult.stdout.trim();
|
|
5036
|
+
if (actual !== expected) throw new Error(formatStdoutDiff(file, expected, actual));
|
|
5037
|
+
return this;
|
|
5038
|
+
}
|
|
5039
|
+
expectStdoutContains(str) {
|
|
5040
|
+
if (!this.commandResult) throw new Error("expectStdoutContains requires a CLI action (.exec())");
|
|
5041
|
+
if (!this.commandResult.stdout.includes(str)) throw new Error(`Expected stdout to contain: "${str}"\n\nActual stdout:\n${this.commandResult.stdout}`);
|
|
5042
|
+
return this;
|
|
5043
|
+
}
|
|
5044
|
+
expectStderr(file) {
|
|
5045
|
+
if (!this.commandResult) throw new Error("expectStderr requires a CLI action (.exec())");
|
|
5046
|
+
const expected = readFileSync(resolve(this.testDir, "expected", file), "utf8").trim();
|
|
5047
|
+
const actual = this.commandResult.stderr.trim();
|
|
5048
|
+
if (actual !== expected) throw new Error(formatStdoutDiff(file, expected, actual));
|
|
5049
|
+
return this;
|
|
5050
|
+
}
|
|
5051
|
+
expectStderrContains(str) {
|
|
5052
|
+
if (!this.commandResult) throw new Error("expectStderrContains requires a CLI action (.exec())");
|
|
5053
|
+
if (!this.commandResult.stderr.includes(str)) throw new Error(`Expected stderr to contain: "${str}"\n\nActual stderr:\n${this.commandResult.stderr}`);
|
|
5054
|
+
return this;
|
|
5055
|
+
}
|
|
4926
5056
|
async expectTable(table, options) {
|
|
4927
5057
|
const db = this.resolveDatabase(options.service);
|
|
4928
5058
|
if (!db) throw new Error(options.service ? `expectTable requires database "${options.service}" but it was not found` : "expectTable requires a database adapter");
|
|
@@ -4930,18 +5060,40 @@ var SpecificationResult = class {
|
|
|
4930
5060
|
if (JSON.stringify(actual) !== JSON.stringify(options.rows)) throw new Error(formatTableDiff(table, options.columns, options.rows, actual));
|
|
4931
5061
|
return this;
|
|
4932
5062
|
}
|
|
5063
|
+
expectFile(path) {
|
|
5064
|
+
if (!existsSync(this.resolveWorkPath(path))) throw new Error(formatFileMissing(path));
|
|
5065
|
+
return this;
|
|
5066
|
+
}
|
|
5067
|
+
expectNoFile(path) {
|
|
5068
|
+
if (existsSync(this.resolveWorkPath(path))) throw new Error(formatFileUnexpected(path));
|
|
5069
|
+
return this;
|
|
5070
|
+
}
|
|
5071
|
+
expectFileContains(path, content) {
|
|
5072
|
+
const resolved = this.resolveWorkPath(path);
|
|
5073
|
+
if (!existsSync(resolved)) throw new Error(formatFileMissing(path));
|
|
5074
|
+
const actual = readFileSync(resolved, "utf8");
|
|
5075
|
+
if (!actual.includes(content)) throw new Error(formatFileContentMismatch(path, content, actual));
|
|
5076
|
+
return this;
|
|
5077
|
+
}
|
|
4933
5078
|
resolveDatabase(serviceName) {
|
|
4934
5079
|
if (serviceName && this.config.databases) return this.config.databases.get(serviceName);
|
|
4935
5080
|
return this.config.database;
|
|
4936
5081
|
}
|
|
5082
|
+
resolveWorkPath(path) {
|
|
5083
|
+
if (this.workDir) return resolve(this.workDir, path);
|
|
5084
|
+
return resolve(this.testDir, path);
|
|
5085
|
+
}
|
|
4937
5086
|
};
|
|
4938
5087
|
var SpecificationBuilder = class {
|
|
5088
|
+
commandArgs = null;
|
|
4939
5089
|
config;
|
|
4940
|
-
|
|
5090
|
+
fixtures = [];
|
|
4941
5091
|
label;
|
|
4942
|
-
seeds = [];
|
|
4943
5092
|
mocks = [];
|
|
5093
|
+
projectName = null;
|
|
4944
5094
|
request = null;
|
|
5095
|
+
seeds = [];
|
|
5096
|
+
testDir;
|
|
4945
5097
|
constructor(config, testDir, label) {
|
|
4946
5098
|
this.config = config;
|
|
4947
5099
|
this.testDir = testDir;
|
|
@@ -4954,6 +5106,14 @@ var SpecificationBuilder = class {
|
|
|
4954
5106
|
});
|
|
4955
5107
|
return this;
|
|
4956
5108
|
}
|
|
5109
|
+
fixture(file) {
|
|
5110
|
+
this.fixtures.push({ file });
|
|
5111
|
+
return this;
|
|
5112
|
+
}
|
|
5113
|
+
project(name) {
|
|
5114
|
+
this.projectName = name;
|
|
5115
|
+
return this;
|
|
5116
|
+
}
|
|
4957
5117
|
mock(file) {
|
|
4958
5118
|
this.mocks.push({ file });
|
|
4959
5119
|
return this;
|
|
@@ -4967,17 +5127,17 @@ var SpecificationBuilder = class {
|
|
|
4967
5127
|
}
|
|
4968
5128
|
post(path, bodyFile) {
|
|
4969
5129
|
this.request = {
|
|
5130
|
+
bodyFile,
|
|
4970
5131
|
method: "POST",
|
|
4971
|
-
path
|
|
4972
|
-
bodyFile
|
|
5132
|
+
path
|
|
4973
5133
|
};
|
|
4974
5134
|
return this;
|
|
4975
5135
|
}
|
|
4976
5136
|
put(path, bodyFile) {
|
|
4977
5137
|
this.request = {
|
|
5138
|
+
bodyFile,
|
|
4978
5139
|
method: "PUT",
|
|
4979
|
-
path
|
|
4980
|
-
bodyFile
|
|
5140
|
+
path
|
|
4981
5141
|
};
|
|
4982
5142
|
return this;
|
|
4983
5143
|
}
|
|
@@ -4988,8 +5148,17 @@ var SpecificationBuilder = class {
|
|
|
4988
5148
|
};
|
|
4989
5149
|
return this;
|
|
4990
5150
|
}
|
|
5151
|
+
exec(args) {
|
|
5152
|
+
this.commandArgs = args;
|
|
5153
|
+
return this;
|
|
5154
|
+
}
|
|
4991
5155
|
async run() {
|
|
4992
|
-
|
|
5156
|
+
const hasHttpAction = this.request !== null;
|
|
5157
|
+
const hasCliAction = this.commandArgs !== null;
|
|
5158
|
+
if (!hasHttpAction && !hasCliAction) throw new Error(`Specification "${this.label}": no action defined. Call .get(), .post(), .exec(), etc. before .run()`);
|
|
5159
|
+
if (hasHttpAction && hasCliAction) throw new Error(`Specification "${this.label}": cannot mix HTTP (.get/.post) and CLI (.exec) actions`);
|
|
5160
|
+
let workDir = null;
|
|
5161
|
+
if (hasCliAction) workDir = this.prepareWorkDir();
|
|
4993
5162
|
if (this.config.databases) for (const db of this.config.databases.values()) await db.reset();
|
|
4994
5163
|
else if (this.config.database) await this.config.database.reset();
|
|
4995
5164
|
for (const entry of this.seeds) {
|
|
@@ -5002,13 +5171,43 @@ var SpecificationBuilder = class {
|
|
|
5002
5171
|
const sql = readFileSync(resolve(this.testDir, "seeds", entry.file), "utf8");
|
|
5003
5172
|
await db.seed(sql);
|
|
5004
5173
|
}
|
|
5174
|
+
if (this.fixtures.length > 0 && workDir) for (const entry of this.fixtures) cpSync(resolve(this.testDir, "fixtures", entry.file), resolve(workDir, entry.file), { recursive: true });
|
|
5005
5175
|
for (const entry of this.mocks) JSON.parse(readFileSync(resolve(this.testDir, "mock", entry.file), "utf8"));
|
|
5176
|
+
if (hasHttpAction) return this.runHttpAction();
|
|
5177
|
+
return this.runCliAction(workDir);
|
|
5178
|
+
}
|
|
5179
|
+
prepareWorkDir() {
|
|
5180
|
+
const tempDir = mkdtempSync(resolve(tmpdir(), "spec-cli-"));
|
|
5181
|
+
if (this.projectName && this.config.fixturesRoot) {
|
|
5182
|
+
const projectDir = resolve(this.config.fixturesRoot, this.projectName);
|
|
5183
|
+
if (!existsSync(projectDir)) throw new Error(`project("${this.projectName}"): fixture project not found at ${projectDir}`);
|
|
5184
|
+
cpSync(projectDir, tempDir, { recursive: true });
|
|
5185
|
+
}
|
|
5186
|
+
return tempDir;
|
|
5187
|
+
}
|
|
5188
|
+
async runHttpAction() {
|
|
5189
|
+
if (!this.config.server) throw new Error("HTTP actions require a server adapter (use integration() or e2e())");
|
|
5006
5190
|
let body;
|
|
5007
5191
|
if (this.request.bodyFile) body = JSON.parse(readFileSync(resolve(this.testDir, "requests", this.request.bodyFile), "utf8"));
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5192
|
+
const response = await this.config.server.request(this.request.method, this.request.path, body);
|
|
5193
|
+
return new SpecificationResult({
|
|
5194
|
+
config: this.config,
|
|
5195
|
+
requestInfo: {
|
|
5196
|
+
body,
|
|
5197
|
+
method: this.request.method,
|
|
5198
|
+
path: this.request.path
|
|
5199
|
+
},
|
|
5200
|
+
response,
|
|
5201
|
+
testDir: this.testDir
|
|
5202
|
+
});
|
|
5203
|
+
}
|
|
5204
|
+
async runCliAction(workDir) {
|
|
5205
|
+
if (!this.config.command) throw new Error("CLI actions require a command adapter (use cli())");
|
|
5206
|
+
return new SpecificationResult({
|
|
5207
|
+
commandResult: await this.config.command.exec(this.commandArgs, workDir),
|
|
5208
|
+
config: this.config,
|
|
5209
|
+
testDir: this.testDir,
|
|
5210
|
+
workDir
|
|
5012
5211
|
});
|
|
5013
5212
|
}
|
|
5014
5213
|
};
|
|
@@ -5057,21 +5256,25 @@ function resolveProjectRoot(root) {
|
|
|
5057
5256
|
return resolve(process.cwd(), root);
|
|
5058
5257
|
}
|
|
5059
5258
|
/**
|
|
5259
|
+
* Resolve a CLI command — checks node_modules/.bin, then treats as absolute/PATH.
|
|
5260
|
+
*/
|
|
5261
|
+
function resolveCommand(command, root) {
|
|
5262
|
+
if (isAbsolute(command)) return command;
|
|
5263
|
+
const binPath = resolve(root, "node_modules/.bin", command);
|
|
5264
|
+
if (existsSync(binPath)) return binPath;
|
|
5265
|
+
const cwdBinPath = resolve(process.cwd(), "node_modules/.bin", command);
|
|
5266
|
+
if (existsSync(cwdBinPath)) return cwdBinPath;
|
|
5267
|
+
return command;
|
|
5268
|
+
}
|
|
5269
|
+
/**
|
|
5060
5270
|
* Create an integration specification runner.
|
|
5061
5271
|
* Starts infra containers via testcontainers, app runs in-process.
|
|
5062
|
-
*
|
|
5063
|
-
* @example
|
|
5064
|
-
* const db = postgres({ compose: "db" });
|
|
5065
|
-
* export const spec = await integration({
|
|
5066
|
-
* services: [db],
|
|
5067
|
-
* app: () => createApp({ databaseUrl: db.connectionString }),
|
|
5068
|
-
* });
|
|
5069
5272
|
*/
|
|
5070
5273
|
async function integration(options) {
|
|
5071
5274
|
const orchestrator = new Orchestrator({
|
|
5072
|
-
services: options.services,
|
|
5073
5275
|
mode: "integration",
|
|
5074
|
-
root: resolveProjectRoot(options.root)
|
|
5276
|
+
root: resolveProjectRoot(options.root),
|
|
5277
|
+
services: options.services
|
|
5075
5278
|
});
|
|
5076
5279
|
await orchestrator.start();
|
|
5077
5280
|
const app = options.app();
|
|
@@ -5089,17 +5292,12 @@ async function integration(options) {
|
|
|
5089
5292
|
/**
|
|
5090
5293
|
* Create an E2E specification runner.
|
|
5091
5294
|
* Starts full docker compose stack. App URL and database auto-detected.
|
|
5092
|
-
*
|
|
5093
|
-
* @example
|
|
5094
|
-
* export const spec = await e2e({
|
|
5095
|
-
* root: "../fixtures/app",
|
|
5096
|
-
* });
|
|
5097
5295
|
*/
|
|
5098
5296
|
async function e2e(options = {}) {
|
|
5099
5297
|
const orchestrator = new Orchestrator({
|
|
5100
|
-
services: [],
|
|
5101
5298
|
mode: "e2e",
|
|
5102
|
-
root: resolveProjectRoot(options.root)
|
|
5299
|
+
root: resolveProjectRoot(options.root),
|
|
5300
|
+
services: []
|
|
5103
5301
|
});
|
|
5104
5302
|
await orchestrator.startCompose();
|
|
5105
5303
|
const appUrl = orchestrator.getAppUrl();
|
|
@@ -5115,7 +5313,46 @@ async function e2e(options = {}) {
|
|
|
5115
5313
|
runner.orchestrator = orchestrator;
|
|
5116
5314
|
return runner;
|
|
5117
5315
|
}
|
|
5316
|
+
/**
|
|
5317
|
+
* Create a CLI specification runner.
|
|
5318
|
+
* Runs CLI commands against fixture projects. Optionally starts infrastructure.
|
|
5319
|
+
*
|
|
5320
|
+
* @example
|
|
5321
|
+
* export const spec = await cli({
|
|
5322
|
+
* command: resolve(import.meta.dirname, "../../bin/my-cli.sh"),
|
|
5323
|
+
* root: "../fixtures",
|
|
5324
|
+
* });
|
|
5325
|
+
*/
|
|
5326
|
+
async function cli(options) {
|
|
5327
|
+
const root = resolveProjectRoot(options.root);
|
|
5328
|
+
const command = resolveCommand(options.command, root);
|
|
5329
|
+
let orchestrator = null;
|
|
5330
|
+
let database;
|
|
5331
|
+
let databases;
|
|
5332
|
+
if (options.services?.length) {
|
|
5333
|
+
orchestrator = new Orchestrator({
|
|
5334
|
+
mode: "integration",
|
|
5335
|
+
root,
|
|
5336
|
+
services: options.services
|
|
5337
|
+
});
|
|
5338
|
+
await orchestrator.start();
|
|
5339
|
+
database = orchestrator.getDatabase() ?? void 0;
|
|
5340
|
+
const dbMap = orchestrator.getDatabases();
|
|
5341
|
+
databases = dbMap.size > 0 ? dbMap : void 0;
|
|
5342
|
+
}
|
|
5343
|
+
const runner = createSpecificationRunner({
|
|
5344
|
+
command: new ExecAdapter(command),
|
|
5345
|
+
database,
|
|
5346
|
+
databases,
|
|
5347
|
+
fixturesRoot: root
|
|
5348
|
+
});
|
|
5349
|
+
runner.cleanup = async () => {
|
|
5350
|
+
if (orchestrator) await orchestrator.stop();
|
|
5351
|
+
};
|
|
5352
|
+
runner.orchestrator = orchestrator;
|
|
5353
|
+
return runner;
|
|
5354
|
+
}
|
|
5118
5355
|
//#endregion
|
|
5119
|
-
export { FetchAdapter, HonoAdapter, Orchestrator, e2e, integration, mockOf, mockOfDate, normalizeOutput, postgres, redis, stripAnsi };
|
|
5356
|
+
export { ExecAdapter, FetchAdapter, HonoAdapter, Orchestrator, cli, e2e, integration, mockOf, mockOfDate, normalizeOutput, postgres, redis, stripAnsi };
|
|
5120
5357
|
|
|
5121
5358
|
//# sourceMappingURL=index.js.map
|