@elench/testkit 0.1.108 → 0.1.109
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 +9 -9
- package/lib/app/doctor.mjs +5 -5
- package/lib/app/typecheck.mjs +6 -5
- package/lib/bundler/index.mjs +134 -7
- package/lib/cli/args.mjs +3 -2
- package/lib/cli/assistant/command-observer.mjs +2 -1
- package/lib/cli/assistant/command-results.mjs +2 -1
- package/lib/cli/assistant/context-pack.mjs +2 -2
- package/lib/cli/assistant/prompt-builder.mjs +2 -2
- package/lib/cli/command-flags.mjs +2 -1
- package/lib/cli/commands/cleanup.mjs +13 -2
- package/lib/cli/commands/discover.mjs +2 -1
- package/lib/cli/commands/run.mjs +3 -2
- package/lib/cli/entrypoint.mjs +3 -1
- package/lib/cli/operations/cleanup/operation.mjs +6 -1
- package/lib/cli/operations/status/operation.mjs +2 -2
- package/lib/cli/renderers/discover/report.mjs +6 -8
- package/lib/cli/renderers/run/failure.mjs +1 -1
- package/lib/cli/renderers/run/text-reporter.mjs +1 -1
- package/lib/cli/renderers/status/text.mjs +101 -1
- package/lib/config/discovery.mjs +10 -1
- package/lib/config-api/index.mjs +2 -2
- package/lib/config-api/next-runtime-tsconfig.mjs +2 -1
- package/lib/coverage/graph-builder.mjs +2 -4
- package/lib/coverage/routing.mjs +1 -1
- package/lib/coverage/shared.mjs +1 -2
- package/lib/discovery/index.d.ts +5 -8
- package/lib/discovery/index.mjs +15 -24
- package/lib/domain/test-types.mjs +44 -0
- package/lib/history/index.d.ts +3 -4
- package/lib/history/index.mjs +6 -14
- package/lib/runner/formatting.mjs +2 -3
- package/lib/runner/maintenance.mjs +136 -35
- package/lib/runner/planning.mjs +1 -1
- package/lib/runner/results.mjs +0 -6
- package/lib/runner/status-model.mjs +520 -0
- package/lib/runner/suite-selection.mjs +20 -11
- package/lib/runner/template-steps.mjs +2 -2
- package/lib/runner/template.mjs +4 -0
- package/lib/ui/index.d.ts +1 -0
- package/lib/ui/index.mjs +1 -0
- package/lib/vitest/index.mjs +2 -1
- package/node_modules/@elench/next-analysis/package.json +1 -1
- package/node_modules/@elench/testkit-bridge/dist/index.js +9 -11
- package/node_modules/@elench/testkit-bridge/dist/index.js.map +1 -1
- package/node_modules/@elench/testkit-bridge/package.json +2 -2
- package/node_modules/@elench/testkit-protocol/dist/index.d.ts +1 -3
- package/node_modules/@elench/testkit-protocol/dist/index.d.ts.map +1 -1
- package/node_modules/@elench/testkit-protocol/dist/index.js +3 -6
- package/node_modules/@elench/testkit-protocol/dist/index.js.map +1 -1
- package/node_modules/@elench/testkit-protocol/package.json +1 -1
- package/node_modules/@elench/ts-analysis/dist/requests.js +1 -1
- package/node_modules/@elench/ts-analysis/package.json +1 -1
- package/package.json +9 -9
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
2
3
|
import {
|
|
3
4
|
cleanupOrphanedLocalInfrastructure,
|
|
4
|
-
collectServiceDatabaseStatus,
|
|
5
5
|
destroyRuntimeDatabase,
|
|
6
6
|
destroyServiceDatabaseCache,
|
|
7
7
|
isDatabaseStateDir,
|
|
8
8
|
} from "../database/index.mjs";
|
|
9
|
-
import { cleanupRuns, formatRunSummary } from "./lifecycle.mjs";
|
|
10
|
-
import { buildRunStatusLines } from "./readiness.mjs";
|
|
9
|
+
import { cleanupRuns, formatRunSummary, isPidRunning, listRunManifests } from "./lifecycle.mjs";
|
|
11
10
|
import { findGraphDirsForService, findRuntimeStateDirs } from "./state.mjs";
|
|
12
|
-
import {
|
|
11
|
+
import { collectCleanupTargets, collectStatusModel } from "./status-model.mjs";
|
|
13
12
|
|
|
14
13
|
export async function destroy(config) {
|
|
15
14
|
await cleanupRuns(config.productDir, { includeActive: true });
|
|
@@ -34,50 +33,152 @@ export async function destroy(config) {
|
|
|
34
33
|
await cleanupOrphanedLocalInfrastructure(config.productDir);
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
export function showStatus(config) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
export function showStatus(config, options = {}) {
|
|
37
|
+
return collectStatusModel(config, options);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function cleanup(productDir, options = {}) {
|
|
41
|
+
const dryRun = Boolean(options.dryRun);
|
|
42
|
+
const allConfigs = options.allConfigs || [];
|
|
43
|
+
const serviceName = options.serviceName || null;
|
|
44
|
+
const cache = normalizeCacheSelection(options.cache);
|
|
45
|
+
const summary = dryRun
|
|
46
|
+
? collectRunCleanupPreview(productDir)
|
|
47
|
+
: await cleanupRuns(productDir, { includeActive: false });
|
|
48
|
+
const targets = collectCleanupTargets(productDir, {
|
|
49
|
+
allConfigs,
|
|
50
|
+
serviceName,
|
|
51
|
+
cache,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const runtimeCleaned = [];
|
|
55
|
+
const bundleCleaned = [];
|
|
56
|
+
const assistantCleaned = [];
|
|
57
|
+
|
|
58
|
+
if (!dryRun) {
|
|
59
|
+
for (const target of targets.runtime) {
|
|
60
|
+
await cleanupRuntimeDir(productDir, target.path);
|
|
61
|
+
runtimeCleaned.push(target);
|
|
62
|
+
}
|
|
63
|
+
for (const target of targets.bundles) {
|
|
64
|
+
fs.rmSync(target.path, { force: true });
|
|
65
|
+
bundleCleaned.push(target);
|
|
49
66
|
}
|
|
50
|
-
for (const
|
|
51
|
-
|
|
52
|
-
|
|
67
|
+
for (const target of targets.assistant) {
|
|
68
|
+
fs.rmSync(target.path, { force: true });
|
|
69
|
+
assistantCleaned.push(target);
|
|
53
70
|
}
|
|
71
|
+
pruneKnownEmptyDirs(productDir);
|
|
54
72
|
}
|
|
55
73
|
|
|
56
|
-
lines
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
74
|
+
const lines = [];
|
|
75
|
+
for (const manifest of summary.cleaned) {
|
|
76
|
+
lines.push(`${dryRun ? "Would clean" : "Cleaned"} stale run ${formatRunSummary(manifest)}`);
|
|
77
|
+
}
|
|
78
|
+
for (const manifest of summary.skippedActive) {
|
|
79
|
+
lines.push(`Active run still present: ${formatRunSummary(manifest)}`);
|
|
80
|
+
}
|
|
81
|
+
for (const target of targets.runtime) {
|
|
82
|
+
lines.push(`${dryRun ? "Would remove" : "Removed"} stale runtime ${target.graph}/${target.runtimeId}`);
|
|
83
|
+
}
|
|
84
|
+
appendBoundedFileCleanupLines(lines, {
|
|
85
|
+
productDir,
|
|
86
|
+
targets: targets.bundles,
|
|
87
|
+
label: "bundle cache file",
|
|
88
|
+
dryRun,
|
|
89
|
+
});
|
|
90
|
+
appendBoundedFileCleanupLines(lines, {
|
|
91
|
+
productDir,
|
|
92
|
+
targets: targets.assistant,
|
|
93
|
+
label: "assistant command result",
|
|
94
|
+
dryRun,
|
|
95
|
+
});
|
|
62
96
|
|
|
63
|
-
|
|
64
|
-
const summary = await cleanupRuns(productDir, { includeActive: false });
|
|
65
|
-
if (summary.cleaned.length === 0 && summary.skippedActive.length === 0) {
|
|
97
|
+
if (lines.length === 0) {
|
|
66
98
|
return {
|
|
67
99
|
...summary,
|
|
100
|
+
dryRun,
|
|
101
|
+
targets,
|
|
102
|
+
runtimeCleaned,
|
|
103
|
+
bundleCleaned,
|
|
104
|
+
assistantCleaned,
|
|
68
105
|
lines: ["No stale runs to clean."],
|
|
69
106
|
};
|
|
70
107
|
}
|
|
71
108
|
|
|
72
|
-
const lines = [];
|
|
73
|
-
for (const manifest of summary.cleaned) {
|
|
74
|
-
lines.push(`Cleaned stale run ${formatRunSummary(manifest)}`);
|
|
75
|
-
}
|
|
76
|
-
for (const manifest of summary.skippedActive) {
|
|
77
|
-
lines.push(`Active run still present: ${formatRunSummary(manifest)}`);
|
|
78
|
-
}
|
|
79
109
|
return {
|
|
80
110
|
...summary,
|
|
111
|
+
dryRun,
|
|
112
|
+
targets,
|
|
113
|
+
runtimeCleaned,
|
|
114
|
+
bundleCleaned,
|
|
115
|
+
assistantCleaned,
|
|
81
116
|
lines,
|
|
82
117
|
};
|
|
83
118
|
}
|
|
119
|
+
|
|
120
|
+
async function cleanupRuntimeDir(productDir, runtimeDir) {
|
|
121
|
+
if (!runtimeDir || !fs.existsSync(runtimeDir)) return;
|
|
122
|
+
const runtimeStateDirs = findRuntimeStateDirs(runtimeDir, isDatabaseStateDir);
|
|
123
|
+
for (const stateDir of runtimeStateDirs) {
|
|
124
|
+
await destroyRuntimeDatabase({ productDir, stateDir });
|
|
125
|
+
}
|
|
126
|
+
fs.rmSync(runtimeDir, { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function normalizeCacheSelection(cache) {
|
|
130
|
+
const values = Array.isArray(cache) ? cache.filter(Boolean).map(String) : [cache].filter(Boolean).map(String);
|
|
131
|
+
if (values.includes("all")) return ["runtime", "bundles", "assistant"];
|
|
132
|
+
return values;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function pruneKnownEmptyDirs(productDir) {
|
|
136
|
+
for (const dir of [
|
|
137
|
+
path.join(productDir, ".testkit", "assistant", "command-results"),
|
|
138
|
+
path.join(productDir, ".testkit", "assistant"),
|
|
139
|
+
path.join(productDir, ".testkit", "_bundles"),
|
|
140
|
+
path.join(productDir, ".testkit", "_graphs"),
|
|
141
|
+
]) {
|
|
142
|
+
pruneEmptyDir(dir);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function pruneEmptyDir(dir) {
|
|
147
|
+
if (!fs.existsSync(dir)) return;
|
|
148
|
+
try {
|
|
149
|
+
if (fs.readdirSync(dir).length === 0) fs.rmSync(dir, { recursive: true, force: true });
|
|
150
|
+
} catch {
|
|
151
|
+
// Best-effort cleanup only.
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function relativeToProduct(productDir, filePath) {
|
|
156
|
+
return path.relative(productDir, filePath).split(path.sep).join("/");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function appendBoundedFileCleanupLines(lines, { productDir, targets, label, dryRun }) {
|
|
160
|
+
if (!targets || targets.length === 0) return;
|
|
161
|
+
const verb = dryRun ? "Would remove" : "Removed";
|
|
162
|
+
lines.push(`${verb} ${targets.length} ${label}${targets.length === 1 ? "" : "s"}.`);
|
|
163
|
+
for (const target of targets.slice(0, 10)) {
|
|
164
|
+
lines.push(` ${relativeToProduct(productDir, target.path)}`);
|
|
165
|
+
}
|
|
166
|
+
if (targets.length > 10) {
|
|
167
|
+
lines.push(` ... ${targets.length - 10} more ${label}${targets.length - 10 === 1 ? "" : "s"}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function collectRunCleanupPreview(productDir) {
|
|
172
|
+
const summary = {
|
|
173
|
+
cleaned: [],
|
|
174
|
+
skippedActive: [],
|
|
175
|
+
};
|
|
176
|
+
for (const manifest of listRunManifests(productDir)) {
|
|
177
|
+
if (isPidRunning(manifest.pid)) {
|
|
178
|
+
summary.skippedActive.push(manifest);
|
|
179
|
+
} else {
|
|
180
|
+
summary.cleaned.push(manifest);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return summary;
|
|
184
|
+
}
|
package/lib/runner/planning.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
suiteSelectionType,
|
|
5
5
|
} from "./suite-selection.mjs";
|
|
6
6
|
|
|
7
|
-
const TYPE_ORDER = ["
|
|
7
|
+
const TYPE_ORDER = ["ui", "e2e", "scenario", "integration", "dal", "load"];
|
|
8
8
|
|
|
9
9
|
export function taskNeedsLocalRuntime(task) {
|
|
10
10
|
return task.type !== "dal";
|
package/lib/runner/results.mjs
CHANGED
|
@@ -263,7 +263,6 @@ function finalizeSuite(suite) {
|
|
|
263
263
|
return {
|
|
264
264
|
name: suite.name,
|
|
265
265
|
type: suite.displayType,
|
|
266
|
-
framework: formatFrameworkForArtifact(suite.framework),
|
|
267
266
|
failed: suite.failedFiles.length > 0,
|
|
268
267
|
fileCount: suite.fileCount,
|
|
269
268
|
completedFileCount: suite.completedFileCount,
|
|
@@ -285,11 +284,6 @@ function normalizePathSeparators(filePath) {
|
|
|
285
284
|
return filePath.split(path.sep).join("/");
|
|
286
285
|
}
|
|
287
286
|
|
|
288
|
-
function formatFrameworkForArtifact(framework) {
|
|
289
|
-
if (framework === "k6") return "default";
|
|
290
|
-
return framework;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
287
|
function normalizeOutcomeStatus(outcome) {
|
|
294
288
|
if (outcome?.status === "not_run") return "not_run";
|
|
295
289
|
if (outcome?.status === "skipped") return "skipped";
|