@jterrazz/test 3.2.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.
- package/dist/build.cjs +2 -2
- package/dist/build.js +1 -1
- package/dist/index.cjs +269 -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 +268 -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,41 @@ 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
|
+
try {
|
|
4912
|
+
return {
|
|
4913
|
+
exitCode: 0,
|
|
4914
|
+
stdout: execSync(`${this.command} ${args}`, {
|
|
4915
|
+
cwd,
|
|
4916
|
+
encoding: "utf8",
|
|
4917
|
+
stdio: [
|
|
4918
|
+
"pipe",
|
|
4919
|
+
"pipe",
|
|
4920
|
+
"pipe"
|
|
4921
|
+
]
|
|
4922
|
+
}),
|
|
4923
|
+
stderr: ""
|
|
4924
|
+
};
|
|
4925
|
+
} catch (error) {
|
|
4926
|
+
return {
|
|
4927
|
+
exitCode: error.status ?? 1,
|
|
4928
|
+
stdout: error.stdout?.toString() ?? "",
|
|
4929
|
+
stderr: error.stderr?.toString() ?? ""
|
|
4930
|
+
};
|
|
4931
|
+
}
|
|
4932
|
+
}
|
|
4933
|
+
};
|
|
4934
|
+
//#endregion
|
|
4845
4935
|
//#region src/specification/adapters/fetch.adapter.ts
|
|
4846
4936
|
/**
|
|
4847
4937
|
* Server adapter for real HTTP — sends actual fetch requests.
|
|
@@ -4904,25 +4994,60 @@ var HonoAdapter = class {
|
|
|
4904
4994
|
//#endregion
|
|
4905
4995
|
//#region src/specification/specification.ts
|
|
4906
4996
|
var SpecificationResult = class {
|
|
4907
|
-
|
|
4997
|
+
commandResult;
|
|
4908
4998
|
config;
|
|
4909
|
-
testDir;
|
|
4910
4999
|
requestInfo;
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
this.
|
|
5000
|
+
response;
|
|
5001
|
+
testDir;
|
|
5002
|
+
workDir;
|
|
5003
|
+
constructor(options) {
|
|
5004
|
+
this.response = options.response;
|
|
5005
|
+
this.commandResult = options.commandResult;
|
|
5006
|
+
this.config = options.config;
|
|
5007
|
+
this.testDir = options.testDir;
|
|
5008
|
+
this.requestInfo = options.requestInfo;
|
|
5009
|
+
this.workDir = options.workDir;
|
|
4916
5010
|
}
|
|
4917
5011
|
expectStatus(code) {
|
|
5012
|
+
if (!this.response || !this.requestInfo) throw new Error("expectStatus requires an HTTP action (.get(), .post(), etc.)");
|
|
4918
5013
|
if (this.response.status !== code) throw new Error(formatStatusError(code, this.response.status, this.requestInfo, this.response.body));
|
|
4919
5014
|
return this;
|
|
4920
5015
|
}
|
|
4921
5016
|
expectResponse(file) {
|
|
5017
|
+
if (!this.response) throw new Error("expectResponse requires an HTTP action (.get(), .post(), etc.)");
|
|
4922
5018
|
const expected = JSON.parse(readFileSync(resolve(this.testDir, "responses", file), "utf8"));
|
|
4923
5019
|
if (JSON.stringify(this.response.body) !== JSON.stringify(expected)) throw new Error(formatResponseDiff(file, expected, this.response.body));
|
|
4924
5020
|
return this;
|
|
4925
5021
|
}
|
|
5022
|
+
expectExitCode(code) {
|
|
5023
|
+
if (!this.commandResult) throw new Error("expectExitCode requires a CLI action (.exec())");
|
|
5024
|
+
if (this.commandResult.exitCode !== code) throw new Error(formatExitCodeError(code, this.commandResult.exitCode, this.commandResult.stdout, this.commandResult.stderr));
|
|
5025
|
+
return this;
|
|
5026
|
+
}
|
|
5027
|
+
expectStdout(file) {
|
|
5028
|
+
if (!this.commandResult) throw new Error("expectStdout requires a CLI action (.exec())");
|
|
5029
|
+
const expected = readFileSync(resolve(this.testDir, "expected", file), "utf8").trim();
|
|
5030
|
+
const actual = this.commandResult.stdout.trim();
|
|
5031
|
+
if (actual !== expected) throw new Error(formatStdoutDiff(file, expected, actual));
|
|
5032
|
+
return this;
|
|
5033
|
+
}
|
|
5034
|
+
expectStdoutContains(str) {
|
|
5035
|
+
if (!this.commandResult) throw new Error("expectStdoutContains requires a CLI action (.exec())");
|
|
5036
|
+
if (!this.commandResult.stdout.includes(str)) throw new Error(`Expected stdout to contain: "${str}"\n\nActual stdout:\n${this.commandResult.stdout}`);
|
|
5037
|
+
return this;
|
|
5038
|
+
}
|
|
5039
|
+
expectStderr(file) {
|
|
5040
|
+
if (!this.commandResult) throw new Error("expectStderr requires a CLI action (.exec())");
|
|
5041
|
+
const expected = readFileSync(resolve(this.testDir, "expected", file), "utf8").trim();
|
|
5042
|
+
const actual = this.commandResult.stderr.trim();
|
|
5043
|
+
if (actual !== expected) throw new Error(formatStdoutDiff(file, expected, actual));
|
|
5044
|
+
return this;
|
|
5045
|
+
}
|
|
5046
|
+
expectStderrContains(str) {
|
|
5047
|
+
if (!this.commandResult) throw new Error("expectStderrContains requires a CLI action (.exec())");
|
|
5048
|
+
if (!this.commandResult.stderr.includes(str)) throw new Error(`Expected stderr to contain: "${str}"\n\nActual stderr:\n${this.commandResult.stderr}`);
|
|
5049
|
+
return this;
|
|
5050
|
+
}
|
|
4926
5051
|
async expectTable(table, options) {
|
|
4927
5052
|
const db = this.resolveDatabase(options.service);
|
|
4928
5053
|
if (!db) throw new Error(options.service ? `expectTable requires database "${options.service}" but it was not found` : "expectTable requires a database adapter");
|
|
@@ -4930,18 +5055,40 @@ var SpecificationResult = class {
|
|
|
4930
5055
|
if (JSON.stringify(actual) !== JSON.stringify(options.rows)) throw new Error(formatTableDiff(table, options.columns, options.rows, actual));
|
|
4931
5056
|
return this;
|
|
4932
5057
|
}
|
|
5058
|
+
expectFile(path) {
|
|
5059
|
+
if (!existsSync(this.resolveWorkPath(path))) throw new Error(formatFileMissing(path));
|
|
5060
|
+
return this;
|
|
5061
|
+
}
|
|
5062
|
+
expectNoFile(path) {
|
|
5063
|
+
if (existsSync(this.resolveWorkPath(path))) throw new Error(formatFileUnexpected(path));
|
|
5064
|
+
return this;
|
|
5065
|
+
}
|
|
5066
|
+
expectFileContains(path, content) {
|
|
5067
|
+
const resolved = this.resolveWorkPath(path);
|
|
5068
|
+
if (!existsSync(resolved)) throw new Error(formatFileMissing(path));
|
|
5069
|
+
const actual = readFileSync(resolved, "utf8");
|
|
5070
|
+
if (!actual.includes(content)) throw new Error(formatFileContentMismatch(path, content, actual));
|
|
5071
|
+
return this;
|
|
5072
|
+
}
|
|
4933
5073
|
resolveDatabase(serviceName) {
|
|
4934
5074
|
if (serviceName && this.config.databases) return this.config.databases.get(serviceName);
|
|
4935
5075
|
return this.config.database;
|
|
4936
5076
|
}
|
|
5077
|
+
resolveWorkPath(path) {
|
|
5078
|
+
if (this.workDir) return resolve(this.workDir, path);
|
|
5079
|
+
return resolve(this.testDir, path);
|
|
5080
|
+
}
|
|
4937
5081
|
};
|
|
4938
5082
|
var SpecificationBuilder = class {
|
|
5083
|
+
commandArgs = null;
|
|
4939
5084
|
config;
|
|
4940
|
-
|
|
5085
|
+
fixtures = [];
|
|
4941
5086
|
label;
|
|
4942
|
-
seeds = [];
|
|
4943
5087
|
mocks = [];
|
|
5088
|
+
projectName = null;
|
|
4944
5089
|
request = null;
|
|
5090
|
+
seeds = [];
|
|
5091
|
+
testDir;
|
|
4945
5092
|
constructor(config, testDir, label) {
|
|
4946
5093
|
this.config = config;
|
|
4947
5094
|
this.testDir = testDir;
|
|
@@ -4954,6 +5101,14 @@ var SpecificationBuilder = class {
|
|
|
4954
5101
|
});
|
|
4955
5102
|
return this;
|
|
4956
5103
|
}
|
|
5104
|
+
fixture(file) {
|
|
5105
|
+
this.fixtures.push({ file });
|
|
5106
|
+
return this;
|
|
5107
|
+
}
|
|
5108
|
+
project(name) {
|
|
5109
|
+
this.projectName = name;
|
|
5110
|
+
return this;
|
|
5111
|
+
}
|
|
4957
5112
|
mock(file) {
|
|
4958
5113
|
this.mocks.push({ file });
|
|
4959
5114
|
return this;
|
|
@@ -4967,17 +5122,17 @@ var SpecificationBuilder = class {
|
|
|
4967
5122
|
}
|
|
4968
5123
|
post(path, bodyFile) {
|
|
4969
5124
|
this.request = {
|
|
5125
|
+
bodyFile,
|
|
4970
5126
|
method: "POST",
|
|
4971
|
-
path
|
|
4972
|
-
bodyFile
|
|
5127
|
+
path
|
|
4973
5128
|
};
|
|
4974
5129
|
return this;
|
|
4975
5130
|
}
|
|
4976
5131
|
put(path, bodyFile) {
|
|
4977
5132
|
this.request = {
|
|
5133
|
+
bodyFile,
|
|
4978
5134
|
method: "PUT",
|
|
4979
|
-
path
|
|
4980
|
-
bodyFile
|
|
5135
|
+
path
|
|
4981
5136
|
};
|
|
4982
5137
|
return this;
|
|
4983
5138
|
}
|
|
@@ -4988,8 +5143,17 @@ var SpecificationBuilder = class {
|
|
|
4988
5143
|
};
|
|
4989
5144
|
return this;
|
|
4990
5145
|
}
|
|
5146
|
+
exec(args) {
|
|
5147
|
+
this.commandArgs = args;
|
|
5148
|
+
return this;
|
|
5149
|
+
}
|
|
4991
5150
|
async run() {
|
|
4992
|
-
|
|
5151
|
+
const hasHttpAction = this.request !== null;
|
|
5152
|
+
const hasCliAction = this.commandArgs !== null;
|
|
5153
|
+
if (!hasHttpAction && !hasCliAction) throw new Error(`Specification "${this.label}": no action defined. Call .get(), .post(), .exec(), etc. before .run()`);
|
|
5154
|
+
if (hasHttpAction && hasCliAction) throw new Error(`Specification "${this.label}": cannot mix HTTP (.get/.post) and CLI (.exec) actions`);
|
|
5155
|
+
let workDir = null;
|
|
5156
|
+
if (hasCliAction) workDir = this.prepareWorkDir();
|
|
4993
5157
|
if (this.config.databases) for (const db of this.config.databases.values()) await db.reset();
|
|
4994
5158
|
else if (this.config.database) await this.config.database.reset();
|
|
4995
5159
|
for (const entry of this.seeds) {
|
|
@@ -5002,13 +5166,43 @@ var SpecificationBuilder = class {
|
|
|
5002
5166
|
const sql = readFileSync(resolve(this.testDir, "seeds", entry.file), "utf8");
|
|
5003
5167
|
await db.seed(sql);
|
|
5004
5168
|
}
|
|
5169
|
+
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
5170
|
for (const entry of this.mocks) JSON.parse(readFileSync(resolve(this.testDir, "mock", entry.file), "utf8"));
|
|
5171
|
+
if (hasHttpAction) return this.runHttpAction();
|
|
5172
|
+
return this.runCliAction(workDir);
|
|
5173
|
+
}
|
|
5174
|
+
prepareWorkDir() {
|
|
5175
|
+
const tempDir = mkdtempSync(resolve(tmpdir(), "spec-cli-"));
|
|
5176
|
+
if (this.projectName && this.config.fixturesRoot) {
|
|
5177
|
+
const projectDir = resolve(this.config.fixturesRoot, this.projectName);
|
|
5178
|
+
if (!existsSync(projectDir)) throw new Error(`project("${this.projectName}"): fixture project not found at ${projectDir}`);
|
|
5179
|
+
cpSync(projectDir, tempDir, { recursive: true });
|
|
5180
|
+
}
|
|
5181
|
+
return tempDir;
|
|
5182
|
+
}
|
|
5183
|
+
async runHttpAction() {
|
|
5184
|
+
if (!this.config.server) throw new Error("HTTP actions require a server adapter (use integration() or e2e())");
|
|
5006
5185
|
let body;
|
|
5007
5186
|
if (this.request.bodyFile) body = JSON.parse(readFileSync(resolve(this.testDir, "requests", this.request.bodyFile), "utf8"));
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5187
|
+
const response = await this.config.server.request(this.request.method, this.request.path, body);
|
|
5188
|
+
return new SpecificationResult({
|
|
5189
|
+
config: this.config,
|
|
5190
|
+
requestInfo: {
|
|
5191
|
+
body,
|
|
5192
|
+
method: this.request.method,
|
|
5193
|
+
path: this.request.path
|
|
5194
|
+
},
|
|
5195
|
+
response,
|
|
5196
|
+
testDir: this.testDir
|
|
5197
|
+
});
|
|
5198
|
+
}
|
|
5199
|
+
async runCliAction(workDir) {
|
|
5200
|
+
if (!this.config.command) throw new Error("CLI actions require a command adapter (use cli())");
|
|
5201
|
+
return new SpecificationResult({
|
|
5202
|
+
commandResult: await this.config.command.exec(this.commandArgs, workDir),
|
|
5203
|
+
config: this.config,
|
|
5204
|
+
testDir: this.testDir,
|
|
5205
|
+
workDir
|
|
5012
5206
|
});
|
|
5013
5207
|
}
|
|
5014
5208
|
};
|
|
@@ -5057,21 +5251,25 @@ function resolveProjectRoot(root) {
|
|
|
5057
5251
|
return resolve(process.cwd(), root);
|
|
5058
5252
|
}
|
|
5059
5253
|
/**
|
|
5254
|
+
* Resolve a CLI command — checks node_modules/.bin, then treats as absolute/PATH.
|
|
5255
|
+
*/
|
|
5256
|
+
function resolveCommand(command, root) {
|
|
5257
|
+
if (isAbsolute(command)) return command;
|
|
5258
|
+
const binPath = resolve(root, "node_modules/.bin", command);
|
|
5259
|
+
if (existsSync(binPath)) return binPath;
|
|
5260
|
+
const cwdBinPath = resolve(process.cwd(), "node_modules/.bin", command);
|
|
5261
|
+
if (existsSync(cwdBinPath)) return cwdBinPath;
|
|
5262
|
+
return command;
|
|
5263
|
+
}
|
|
5264
|
+
/**
|
|
5060
5265
|
* Create an integration specification runner.
|
|
5061
5266
|
* 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
5267
|
*/
|
|
5070
5268
|
async function integration(options) {
|
|
5071
5269
|
const orchestrator = new Orchestrator({
|
|
5072
|
-
services: options.services,
|
|
5073
5270
|
mode: "integration",
|
|
5074
|
-
root: resolveProjectRoot(options.root)
|
|
5271
|
+
root: resolveProjectRoot(options.root),
|
|
5272
|
+
services: options.services
|
|
5075
5273
|
});
|
|
5076
5274
|
await orchestrator.start();
|
|
5077
5275
|
const app = options.app();
|
|
@@ -5089,17 +5287,12 @@ async function integration(options) {
|
|
|
5089
5287
|
/**
|
|
5090
5288
|
* Create an E2E specification runner.
|
|
5091
5289
|
* 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
5290
|
*/
|
|
5098
5291
|
async function e2e(options = {}) {
|
|
5099
5292
|
const orchestrator = new Orchestrator({
|
|
5100
|
-
services: [],
|
|
5101
5293
|
mode: "e2e",
|
|
5102
|
-
root: resolveProjectRoot(options.root)
|
|
5294
|
+
root: resolveProjectRoot(options.root),
|
|
5295
|
+
services: []
|
|
5103
5296
|
});
|
|
5104
5297
|
await orchestrator.startCompose();
|
|
5105
5298
|
const appUrl = orchestrator.getAppUrl();
|
|
@@ -5115,7 +5308,46 @@ async function e2e(options = {}) {
|
|
|
5115
5308
|
runner.orchestrator = orchestrator;
|
|
5116
5309
|
return runner;
|
|
5117
5310
|
}
|
|
5311
|
+
/**
|
|
5312
|
+
* Create a CLI specification runner.
|
|
5313
|
+
* Runs CLI commands against fixture projects. Optionally starts infrastructure.
|
|
5314
|
+
*
|
|
5315
|
+
* @example
|
|
5316
|
+
* export const spec = await cli({
|
|
5317
|
+
* command: resolve(import.meta.dirname, "../../bin/my-cli.sh"),
|
|
5318
|
+
* root: "../fixtures",
|
|
5319
|
+
* });
|
|
5320
|
+
*/
|
|
5321
|
+
async function cli(options) {
|
|
5322
|
+
const root = resolveProjectRoot(options.root);
|
|
5323
|
+
const command = resolveCommand(options.command, root);
|
|
5324
|
+
let orchestrator = null;
|
|
5325
|
+
let database;
|
|
5326
|
+
let databases;
|
|
5327
|
+
if (options.services?.length) {
|
|
5328
|
+
orchestrator = new Orchestrator({
|
|
5329
|
+
mode: "integration",
|
|
5330
|
+
root,
|
|
5331
|
+
services: options.services
|
|
5332
|
+
});
|
|
5333
|
+
await orchestrator.start();
|
|
5334
|
+
database = orchestrator.getDatabase() ?? void 0;
|
|
5335
|
+
const dbMap = orchestrator.getDatabases();
|
|
5336
|
+
databases = dbMap.size > 0 ? dbMap : void 0;
|
|
5337
|
+
}
|
|
5338
|
+
const runner = createSpecificationRunner({
|
|
5339
|
+
command: new ExecAdapter(command),
|
|
5340
|
+
database,
|
|
5341
|
+
databases,
|
|
5342
|
+
fixturesRoot: root
|
|
5343
|
+
});
|
|
5344
|
+
runner.cleanup = async () => {
|
|
5345
|
+
if (orchestrator) await orchestrator.stop();
|
|
5346
|
+
};
|
|
5347
|
+
runner.orchestrator = orchestrator;
|
|
5348
|
+
return runner;
|
|
5349
|
+
}
|
|
5118
5350
|
//#endregion
|
|
5119
|
-
export { FetchAdapter, HonoAdapter, Orchestrator, e2e, integration, mockOf, mockOfDate, normalizeOutput, postgres, redis, stripAnsi };
|
|
5351
|
+
export { ExecAdapter, FetchAdapter, HonoAdapter, Orchestrator, cli, e2e, integration, mockOf, mockOfDate, normalizeOutput, postgres, redis, stripAnsi };
|
|
5120
5352
|
|
|
5121
5353
|
//# sourceMappingURL=index.js.map
|