@elench/testkit 0.1.17 → 0.1.19
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 +76 -16
- package/bin/testkit.mjs +1 -1
- package/lib/bundler/index.mjs +95 -0
- package/lib/bundler/index.test.mjs +79 -0
- package/lib/cli/args.mjs +57 -0
- package/lib/cli/args.test.mjs +62 -0
- package/lib/cli/index.mjs +114 -0
- package/lib/config/index.mjs +294 -0
- package/lib/config/index.test.mjs +12 -0
- package/lib/config/model.mjs +422 -0
- package/lib/config/model.test.mjs +193 -0
- package/lib/database/fingerprint.mjs +61 -0
- package/lib/database/fingerprint.test.mjs +93 -0
- package/lib/{database.mjs → database/index.mjs} +45 -160
- package/lib/database/naming.mjs +47 -0
- package/lib/database/naming.test.mjs +39 -0
- package/lib/database/state.mjs +52 -0
- package/lib/database/state.test.mjs +66 -0
- package/lib/index.mjs +1 -0
- package/lib/k6/checks.mjs +1 -0
- package/lib/k6/dal-suite.mjs +1 -0
- package/lib/k6/dal.mjs +1 -0
- package/lib/k6/http.mjs +1 -0
- package/lib/k6/index.mjs +30 -0
- package/lib/k6/suite.mjs +1 -0
- package/lib/reporters/playwright.mjs +125 -0
- package/lib/reporters/playwright.test.mjs +73 -0
- package/lib/{runner.mjs → runner/index.mjs} +252 -835
- package/lib/runner/metadata.mjs +55 -0
- package/lib/runner/metadata.test.mjs +52 -0
- package/lib/runner/planning.mjs +270 -0
- package/lib/runner/planning.test.mjs +127 -0
- package/lib/runner/results.mjs +285 -0
- package/lib/runner/results.test.mjs +144 -0
- package/lib/runner/state.mjs +71 -0
- package/lib/runner/state.test.mjs +64 -0
- package/lib/runner/template.mjs +320 -0
- package/lib/runner/template.test.mjs +150 -0
- package/lib/runtime/index.mjs +191 -0
- package/lib/runtime-src/k6/checks.js +39 -0
- package/lib/runtime-src/k6/dal-suite.js +33 -0
- package/lib/runtime-src/k6/dal.js +32 -0
- package/lib/runtime-src/k6/http.js +134 -0
- package/lib/runtime-src/k6/suite.js +55 -0
- package/lib/telemetry/index.mjs +43 -0
- package/lib/timing/index.mjs +73 -0
- package/lib/timing/index.test.mjs +64 -0
- package/package.json +18 -3
- package/infra/neon-down.sh +0 -18
- package/infra/neon-up.sh +0 -124
- package/lib/cli.mjs +0 -132
- package/lib/config.mjs +0 -666
- package/lib/exec.mjs +0 -20
package/lib/cli.mjs
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { cac } from "cac";
|
|
2
|
-
import { loadConfigs, getServiceNames, isSiblingProduct } from "./config.mjs";
|
|
3
|
-
import * as runner from "./runner.mjs";
|
|
4
|
-
|
|
5
|
-
const SUITE_TYPES = new Set(["int", "integration", "e2e", "dal", "load", "all"]);
|
|
6
|
-
const LIFECYCLE = new Set(["status", "destroy"]);
|
|
7
|
-
const RESERVED = new Set([...SUITE_TYPES, ...LIFECYCLE]);
|
|
8
|
-
|
|
9
|
-
export function run() {
|
|
10
|
-
const cli = cac("testkit");
|
|
11
|
-
|
|
12
|
-
cli
|
|
13
|
-
.command("[first] [second] [third]", "Run test suites (int, e2e, dal, all)")
|
|
14
|
-
.option("-s, --suite <name>", "Run specific suite(s)", { default: [] })
|
|
15
|
-
.option("--dir <path>", "Explicit product directory")
|
|
16
|
-
.option("--jobs <n>", "Number of isolated worker stacks for the whole run", {
|
|
17
|
-
default: "1",
|
|
18
|
-
})
|
|
19
|
-
.option("--db-backend <name>", "Database backend override (neon, local)")
|
|
20
|
-
.option("--shard <i/n>", "Run only shard i of n at suite granularity")
|
|
21
|
-
.option("--framework <name>", "Filter by framework (k6, playwright, all)", {
|
|
22
|
-
default: "all",
|
|
23
|
-
})
|
|
24
|
-
.action(async (first, second, third, options) => {
|
|
25
|
-
// Resolve: service filter, suite type, and --dir.
|
|
26
|
-
//
|
|
27
|
-
// From product dir:
|
|
28
|
-
// testkit → all services, all types
|
|
29
|
-
// testkit int -s health → all services, int, health
|
|
30
|
-
// testkit avocado_api int → one service, int
|
|
31
|
-
// testkit avocado_api → one service, all types
|
|
32
|
-
//
|
|
33
|
-
// From workspace root:
|
|
34
|
-
// testkit --dir outreach int → all services, int
|
|
35
|
-
// testkit --dir avocado avocado_api int → one service, int
|
|
36
|
-
//
|
|
37
|
-
// Legacy (sibling dir as first arg):
|
|
38
|
-
// testkit outreach int → --dir outreach, int
|
|
39
|
-
|
|
40
|
-
let service = null;
|
|
41
|
-
let type = null;
|
|
42
|
-
|
|
43
|
-
// If first arg is a sibling dir with a manifest, treat it as --dir
|
|
44
|
-
if (first && !RESERVED.has(first) && !options.dir && isSiblingProduct(first)) {
|
|
45
|
-
options.dir = first;
|
|
46
|
-
first = second;
|
|
47
|
-
second = third;
|
|
48
|
-
third = undefined;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Now resolve service vs type from remaining args
|
|
52
|
-
const serviceNames = new Set(getServiceNames(options.dir));
|
|
53
|
-
|
|
54
|
-
if (first && serviceNames.has(first)) {
|
|
55
|
-
service = first;
|
|
56
|
-
type = second || null;
|
|
57
|
-
} else if (first && RESERVED.has(first)) {
|
|
58
|
-
type = first;
|
|
59
|
-
} else if (first) {
|
|
60
|
-
// Unknown arg — might be a service name that doesn't exist
|
|
61
|
-
throw new Error(
|
|
62
|
-
`Unknown argument "${first}". Expected a service name (${[...serviceNames].join(", ") || "none found"}) ` +
|
|
63
|
-
`or suite type (int, e2e, dal, all).`
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const allConfigs = loadConfigs({ dir: options.dir, dbBackend: options.dbBackend });
|
|
68
|
-
const configs = service
|
|
69
|
-
? allConfigs.filter((config) => config.name === service)
|
|
70
|
-
: allConfigs;
|
|
71
|
-
if (service && configs.length === 0) {
|
|
72
|
-
const available = allConfigs.map((config) => config.name).join(", ");
|
|
73
|
-
throw new Error(`Service "${service}" not found. Available: ${available}`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Lifecycle commands
|
|
77
|
-
if (type === "status" || type === "destroy") {
|
|
78
|
-
for (const config of configs) {
|
|
79
|
-
if (configs.length > 1) console.log(`\n── ${config.name} ──`);
|
|
80
|
-
if (type === "status") runner.showStatus(config);
|
|
81
|
-
else await runner.destroy(config);
|
|
82
|
-
}
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (!["all", "k6", "playwright"].includes(options.framework)) {
|
|
87
|
-
throw new Error(
|
|
88
|
-
`Unknown framework "${options.framework}". Expected one of: all, k6, playwright.`
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const jobs = Number.parseInt(String(options.jobs), 10);
|
|
93
|
-
if (!Number.isInteger(jobs) || jobs <= 0) {
|
|
94
|
-
throw new Error(`Invalid --jobs value "${options.jobs}". Expected a positive integer.`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
let shard = null;
|
|
98
|
-
if (options.shard) {
|
|
99
|
-
const match = String(options.shard).match(/^(\d+)\/(\d+)$/);
|
|
100
|
-
if (!match) {
|
|
101
|
-
throw new Error(
|
|
102
|
-
`Invalid --shard value "${options.shard}". Expected the form "i/n", e.g. 1/3.`
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
const index = Number.parseInt(match[1], 10);
|
|
106
|
-
const total = Number.parseInt(match[2], 10);
|
|
107
|
-
if (index <= 0 || total <= 0 || index > total) {
|
|
108
|
-
throw new Error(
|
|
109
|
-
`Invalid --shard value "${options.shard}". Expected 1 <= i <= n.`
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
shard = { index, total };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const suiteType = type || "all";
|
|
116
|
-
const suiteNames = Array.isArray(options.suite) ? options.suite : [options.suite].filter(Boolean);
|
|
117
|
-
await runner.runAll(
|
|
118
|
-
configs,
|
|
119
|
-
suiteType,
|
|
120
|
-
suiteNames,
|
|
121
|
-
{
|
|
122
|
-
...options,
|
|
123
|
-
jobs,
|
|
124
|
-
shard,
|
|
125
|
-
},
|
|
126
|
-
allConfigs
|
|
127
|
-
);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
cli.help();
|
|
131
|
-
cli.parse();
|
|
132
|
-
}
|