@elench/testkit 0.1.52 → 0.1.53
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/README.md +14 -0
- package/bin/testkit.mjs +4 -6
- package/lib/cli/command-helpers.mjs +170 -0
- package/lib/cli/commands/artifacts.mjs +45 -0
- package/lib/cli/commands/cleanup.mjs +15 -0
- package/lib/cli/commands/db/snapshot/capture.mjs +22 -0
- package/lib/cli/commands/destroy.mjs +15 -0
- package/lib/cli/commands/known-failures/render.mjs +19 -0
- package/lib/cli/commands/known-failures/validate.mjs +20 -0
- package/lib/cli/commands/logs.mjs +47 -0
- package/lib/cli/commands/run.mjs +23 -0
- package/lib/cli/commands/show.mjs +47 -0
- package/lib/cli/commands/status.mjs +15 -0
- package/lib/cli/commands/watch.mjs +23 -0
- package/lib/cli/entrypoint.mjs +83 -0
- package/lib/cli/index.mjs +6 -116
- package/lib/cli/presentation/run-reporter.mjs +91 -0
- package/lib/cli/tui/watch-app.mjs +104 -0
- package/lib/cli/viewer.mjs +163 -0
- package/lib/runner/artifacts.mjs +35 -0
- package/lib/runner/default-runtime-runner.mjs +44 -10
- package/lib/runner/formatting.mjs +97 -0
- package/lib/runner/formatting.test.mjs +4 -6
- package/lib/runner/logs.mjs +72 -0
- package/lib/runner/orchestrator.mjs +41 -19
- package/lib/runner/playwright-runner.mjs +15 -7
- package/lib/runner/processes.mjs +9 -11
- package/lib/runner/reporting.mjs +5 -1
- package/lib/runner/reporting.test.mjs +4 -1
- package/lib/runner/runtime-contexts.mjs +7 -3
- package/lib/runner/runtime-manager.mjs +8 -2
- package/lib/runner/runtime-preparation.mjs +9 -4
- package/lib/runner/services.mjs +25 -8
- package/lib/runner/template-steps.mjs +4 -3
- package/lib/runner/worker-loop.mjs +8 -7
- package/lib/toolchains/index.mjs +6 -3
- package/package.json +11 -3
package/lib/runner/services.mjs
CHANGED
|
@@ -6,16 +6,16 @@ import {
|
|
|
6
6
|
} from "../toolchains/index.mjs";
|
|
7
7
|
import { buildExecutionEnv, numericPortFromUrl } from "./template.mjs";
|
|
8
8
|
import { DEFAULT_READY_TIMEOUT_MS, assertLocalServicePortsAvailable, isPortInUse, waitForReady } from "./readiness.mjs";
|
|
9
|
-
import {
|
|
9
|
+
import { captureOutput, killChildProcess, startDetachedCommand, stopChildProcess, sleep } from "./processes.mjs";
|
|
10
10
|
import { readDatabaseUrl } from "./state-io.mjs";
|
|
11
11
|
|
|
12
|
-
export async function startLocalServices(runtimeConfigs, lifecycle) {
|
|
12
|
+
export async function startLocalServices(runtimeConfigs, lifecycle, options = {}) {
|
|
13
13
|
const started = [];
|
|
14
14
|
|
|
15
15
|
try {
|
|
16
16
|
for (const config of runtimeConfigs) {
|
|
17
17
|
if (!config.testkit.local) continue;
|
|
18
|
-
const proc = await startLocalService(config, lifecycle);
|
|
18
|
+
const proc = await startLocalService(config, lifecycle, options);
|
|
19
19
|
started.push(proc);
|
|
20
20
|
}
|
|
21
21
|
} catch (error) {
|
|
@@ -26,10 +26,10 @@ export async function startLocalServices(runtimeConfigs, lifecycle) {
|
|
|
26
26
|
return started;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export async function startLocalService(config, lifecycle) {
|
|
29
|
+
export async function startLocalService(config, lifecycle, options = {}) {
|
|
30
30
|
const cwd = resolveServiceCwd(config.productDir, config.testkit.local.cwd);
|
|
31
31
|
const resolvedToolchain = await resolveConfiguredToolchain(config);
|
|
32
|
-
await announceResolvedToolchain(config, resolvedToolchain);
|
|
32
|
+
await announceResolvedToolchain(config, resolvedToolchain, options.reporter);
|
|
33
33
|
const env = applyToolchainEnv(
|
|
34
34
|
buildExecutionEnv(config, config.testkit.local.env, process.env),
|
|
35
35
|
resolvedToolchain
|
|
@@ -46,12 +46,29 @@ export async function startLocalService(config, lifecycle) {
|
|
|
46
46
|
|
|
47
47
|
await assertLocalServicePortsAvailable(config, isPortInUse);
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
options.reporter?.localServiceStarting?.(config, config.testkit.local.start);
|
|
50
50
|
const child = startDetachedCommand(config.testkit.local.start, cwd, env);
|
|
51
|
+
const logRecord = options.logRegistry?.ensureServiceLogRecord(config);
|
|
52
|
+
const liveWriter =
|
|
53
|
+
options.reporter?.outputMode === "debug"
|
|
54
|
+
? (line) => options.reporter.writeDebugLine?.(line)
|
|
55
|
+
: null;
|
|
51
56
|
|
|
52
57
|
const outputDrains = [
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
captureOutput(child.stdout, {
|
|
59
|
+
livePrefix: `[${config.runtimeLabel}:${config.name}]`,
|
|
60
|
+
liveWriter,
|
|
61
|
+
onLine(line) {
|
|
62
|
+
if (logRecord) options.logRegistry.append(logRecord, "stdout", line);
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
captureOutput(child.stderr, {
|
|
66
|
+
livePrefix: `[${config.runtimeLabel}:${config.name}]`,
|
|
67
|
+
liveWriter,
|
|
68
|
+
onLine(line) {
|
|
69
|
+
if (logRecord) options.logRegistry.append(logRecord, "stderr", line);
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
55
72
|
];
|
|
56
73
|
lifecycle.registerService(config, child, cwd, () => {
|
|
57
74
|
killChildProcess(child, "SIGTERM");
|
|
@@ -23,14 +23,15 @@ const MODULE_RUNNER_ENTRY = path.join(
|
|
|
23
23
|
"template-step-module-runner.mjs"
|
|
24
24
|
);
|
|
25
25
|
|
|
26
|
-
export async function runConfiguredSteps({ config, steps = [], env, labelPrefix }) {
|
|
26
|
+
export async function runConfiguredSteps({ config, steps = [], env, labelPrefix, reporter = null }) {
|
|
27
27
|
if (steps.length === 0) return;
|
|
28
28
|
const resolvedToolchain = await resolveConfiguredToolchain(config);
|
|
29
|
-
await announceResolvedToolchain(config, resolvedToolchain);
|
|
29
|
+
await announceResolvedToolchain(config, resolvedToolchain, reporter);
|
|
30
30
|
|
|
31
31
|
for (const [index, step] of steps.entries()) {
|
|
32
32
|
const label = `${labelPrefix}:${config.name}:${index + 1}`;
|
|
33
|
-
|
|
33
|
+
if (reporter?.phaseStarted) reporter.phaseStarted(label);
|
|
34
|
+
else console.log(`\n── ${label} ──`);
|
|
34
35
|
await runConfiguredStep(config, step, env, resolvedToolchain);
|
|
35
36
|
}
|
|
36
37
|
}
|
|
@@ -23,10 +23,10 @@ export async function runWorker(
|
|
|
23
23
|
lifecycle,
|
|
24
24
|
claimNextTask,
|
|
25
25
|
recordTaskOutcome,
|
|
26
|
-
recordGraphError
|
|
26
|
+
recordGraphError,
|
|
27
|
+
reporter = null
|
|
27
28
|
) {
|
|
28
29
|
const startedAt = Date.now();
|
|
29
|
-
console.log(`\n══ worker ${worker.workerId} ══`);
|
|
30
30
|
const errors = [];
|
|
31
31
|
|
|
32
32
|
try {
|
|
@@ -69,8 +69,9 @@ export async function runWorker(
|
|
|
69
69
|
}
|
|
70
70
|
worker.currentGraphKey = task.graphKey;
|
|
71
71
|
lease = await runtimeManager.acquire(task);
|
|
72
|
-
const outcome = await runTask(lease.context, task, lifecycle, lease);
|
|
72
|
+
const outcome = await runTask(lease.context, task, lifecycle, lease, reporter);
|
|
73
73
|
recordTaskOutcome(trackers, outcome.task, outcome);
|
|
74
|
+
reporter?.taskFinished?.(outcome.task, outcome);
|
|
74
75
|
timingUpdates.push({
|
|
75
76
|
key: outcome.task.timingKey,
|
|
76
77
|
durationMs: outcome.durationMs,
|
|
@@ -100,20 +101,20 @@ export async function runWorker(
|
|
|
100
101
|
};
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
async function runTask(context, task, lifecycle, lease) {
|
|
104
|
+
async function runTask(context, task, lifecycle, lease, reporter = null) {
|
|
104
105
|
const targetConfig = context.configByName.get(task.targetName);
|
|
105
106
|
if (!targetConfig) {
|
|
106
107
|
throw new Error(`Runtime instance is missing target config "${task.targetName}"`);
|
|
107
108
|
}
|
|
108
109
|
|
|
109
110
|
if (task.framework === "playwright") {
|
|
110
|
-
return runPlaywrightTask(targetConfig, task, lifecycle, lease);
|
|
111
|
+
return runPlaywrightTask(targetConfig, task, lifecycle, lease, reporter);
|
|
111
112
|
}
|
|
112
113
|
if (task.type === "dal") {
|
|
113
|
-
return runDalTask(targetConfig, task, lifecycle, lease);
|
|
114
|
+
return runDalTask(targetConfig, task, lifecycle, lease, reporter);
|
|
114
115
|
}
|
|
115
116
|
if (task.framework === "k6" && HTTP_K6_TYPES.has(task.type)) {
|
|
116
|
-
return runHttpK6Task(targetConfig, task, lifecycle, lease);
|
|
117
|
+
return runHttpK6Task(targetConfig, task, lifecycle, lease, reporter);
|
|
117
118
|
}
|
|
118
119
|
|
|
119
120
|
throw new Error(
|
package/lib/toolchains/index.mjs
CHANGED
|
@@ -84,12 +84,15 @@ export async function resolveConfiguredToolchain(config, options = {}) {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
export async function announceResolvedToolchain(config, resolvedToolchain) {
|
|
87
|
+
export async function announceResolvedToolchain(config, resolvedToolchain, reporter = null) {
|
|
88
88
|
if (!resolvedToolchain || announcedToolchains.has(config)) return;
|
|
89
89
|
announcedToolchains.add(config);
|
|
90
|
+
if (reporter?.toolchainResolved) {
|
|
91
|
+
reporter.toolchainResolved(config, resolvedToolchain);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
90
94
|
console.log(
|
|
91
|
-
`[testkit] ${config.runtimeLabel || config.name}:${config.name} toolchain `
|
|
92
|
-
`${resolvedToolchain.summary}`
|
|
95
|
+
`[testkit] ${config.runtimeLabel || config.name}:${config.name} toolchain ${resolvedToolchain.summary}`
|
|
93
96
|
);
|
|
94
97
|
}
|
|
95
98
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elench/testkit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.53",
|
|
4
4
|
"description": "CLI for discovering and running local HTTP, DAL, and Playwright test suites",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -26,6 +26,12 @@
|
|
|
26
26
|
"bin": {
|
|
27
27
|
"testkit": "bin/testkit.mjs"
|
|
28
28
|
},
|
|
29
|
+
"oclif": {
|
|
30
|
+
"bin": "testkit",
|
|
31
|
+
"commands": "./lib/cli/commands",
|
|
32
|
+
"default": "run",
|
|
33
|
+
"topicSeparator": " "
|
|
34
|
+
},
|
|
29
35
|
"scripts": {
|
|
30
36
|
"test": "vitest run",
|
|
31
37
|
"test:unit": "vitest run lib",
|
|
@@ -42,9 +48,11 @@
|
|
|
42
48
|
"vitest": "^3.2.4"
|
|
43
49
|
},
|
|
44
50
|
"dependencies": {
|
|
45
|
-
"
|
|
51
|
+
"@oclif/core": "^4.10.6",
|
|
46
52
|
"esbuild": "^0.25.11",
|
|
47
|
-
"execa": "^9.5.0"
|
|
53
|
+
"execa": "^9.5.0",
|
|
54
|
+
"ink": "^7.0.1",
|
|
55
|
+
"react": "^19.2.5"
|
|
48
56
|
},
|
|
49
57
|
"engines": {
|
|
50
58
|
"node": ">=18"
|