@elench/testkit 0.1.35 → 0.1.37
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 +20 -0
- package/lib/cli/index.mjs +4 -0
- package/lib/config/index.mjs +116 -0
- package/lib/reporters/playwright.mjs +41 -5
- package/lib/reporters/playwright.test.mjs +83 -0
- package/lib/runner/artifacts.mjs +72 -0
- package/lib/runner/default-runtime-runner.mjs +51 -2
- package/lib/runner/formatting.mjs +36 -4
- package/lib/runner/formatting.test.mjs +49 -0
- package/lib/runner/orchestrator.mjs +9 -2
- package/lib/runner/planning.mjs +55 -4
- package/lib/runner/planning.test.mjs +51 -0
- package/lib/runner/playwright-runner.mjs +2 -1
- package/lib/runner/reporting.mjs +34 -7
- package/lib/runner/reporting.test.mjs +30 -5
- package/lib/runner/results.mjs +61 -14
- package/lib/runner/results.test.mjs +114 -0
- package/lib/runner/selection.mjs +3 -1
- package/lib/runtime/index.d.ts +11 -0
- package/lib/runtime/index.mjs +3 -0
- package/lib/runtime-src/k6/artifacts.js +36 -0
- package/lib/setup/index.d.ts +16 -0
- package/package.json +1 -1
|
@@ -72,6 +72,7 @@ describe("runner results", () => {
|
|
|
72
72
|
status: "failed",
|
|
73
73
|
durationMs: 250,
|
|
74
74
|
error: "boom",
|
|
75
|
+
reason: null,
|
|
75
76
|
},
|
|
76
77
|
]);
|
|
77
78
|
});
|
|
@@ -193,6 +194,119 @@ describe("runner results", () => {
|
|
|
193
194
|
expect(result.totalTaskDurationMs).toBe(3_000);
|
|
194
195
|
});
|
|
195
196
|
|
|
197
|
+
it("counts config-skipped files and runtime-skipped files separately from passed work", () => {
|
|
198
|
+
const trackers = buildServiceTrackers(
|
|
199
|
+
[
|
|
200
|
+
{
|
|
201
|
+
skipped: false,
|
|
202
|
+
config: {
|
|
203
|
+
name: "api",
|
|
204
|
+
testkit: {
|
|
205
|
+
database: {
|
|
206
|
+
selectedBackend: null,
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
suites: [
|
|
211
|
+
{
|
|
212
|
+
name: "billing",
|
|
213
|
+
type: "integration",
|
|
214
|
+
framework: "k6",
|
|
215
|
+
files: ["tests/billing-live.int.testkit.ts"],
|
|
216
|
+
skippedFiles: [
|
|
217
|
+
{
|
|
218
|
+
path: "tests/billing-stubbed.int.testkit.ts",
|
|
219
|
+
reason: "Billing is stubbed",
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
totalFileCount: 2,
|
|
223
|
+
orderIndex: 0,
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
name: "frontend-smoke",
|
|
227
|
+
type: "e2e",
|
|
228
|
+
framework: "playwright",
|
|
229
|
+
files: ["tests/frontend-smoke.pw.testkit.ts"],
|
|
230
|
+
orderIndex: 1,
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
1000
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
recordTaskOutcome(
|
|
239
|
+
trackers,
|
|
240
|
+
{
|
|
241
|
+
serviceName: "api",
|
|
242
|
+
suiteKey: "integration:billing",
|
|
243
|
+
file: "tests/billing-live.int.testkit.ts",
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
failed: false,
|
|
247
|
+
durationMs: 100,
|
|
248
|
+
error: null,
|
|
249
|
+
},
|
|
250
|
+
1100
|
|
251
|
+
);
|
|
252
|
+
recordTaskOutcome(
|
|
253
|
+
trackers,
|
|
254
|
+
{
|
|
255
|
+
serviceName: "api",
|
|
256
|
+
suiteKey: "e2e:frontend-smoke",
|
|
257
|
+
file: "tests/frontend-smoke.pw.testkit.ts",
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
failed: false,
|
|
261
|
+
status: "skipped",
|
|
262
|
+
reason: "Playwright test.skip()",
|
|
263
|
+
durationMs: 50,
|
|
264
|
+
error: null,
|
|
265
|
+
},
|
|
266
|
+
1150
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
const result = finalizeServiceResult(trackers.get("api"), 1000, 1200);
|
|
270
|
+
|
|
271
|
+
expect(result.failed).toBe(false);
|
|
272
|
+
expect(result.completedSuiteCount).toBe(2);
|
|
273
|
+
expect(result.skippedSuiteCount).toBe(1);
|
|
274
|
+
expect(result.totalFileCount).toBe(3);
|
|
275
|
+
expect(result.completedFileCount).toBe(1);
|
|
276
|
+
expect(result.passedFileCount).toBe(1);
|
|
277
|
+
expect(result.failedFileCount).toBe(0);
|
|
278
|
+
expect(result.skippedFileCount).toBe(2);
|
|
279
|
+
expect(result.notRunFileCount).toBe(0);
|
|
280
|
+
expect(result.suites[0].files).toEqual([
|
|
281
|
+
{
|
|
282
|
+
path: "tests/billing-live.int.testkit.ts",
|
|
283
|
+
failed: false,
|
|
284
|
+
status: "passed",
|
|
285
|
+
durationMs: 100,
|
|
286
|
+
error: null,
|
|
287
|
+
reason: null,
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
path: "tests/billing-stubbed.int.testkit.ts",
|
|
291
|
+
failed: false,
|
|
292
|
+
status: "skipped",
|
|
293
|
+
durationMs: 0,
|
|
294
|
+
error: null,
|
|
295
|
+
reason: "Billing is stubbed",
|
|
296
|
+
},
|
|
297
|
+
]);
|
|
298
|
+
expect(result.suites[1].files).toEqual([
|
|
299
|
+
{
|
|
300
|
+
path: "tests/frontend-smoke.pw.testkit.ts",
|
|
301
|
+
failed: false,
|
|
302
|
+
status: "skipped",
|
|
303
|
+
durationMs: 50,
|
|
304
|
+
error: null,
|
|
305
|
+
reason: "Playwright test.skip()",
|
|
306
|
+
},
|
|
307
|
+
]);
|
|
308
|
+
});
|
|
309
|
+
|
|
196
310
|
it("summarizes mixed db backends", () => {
|
|
197
311
|
expect(
|
|
198
312
|
summarizeDbBackend([{ dbBackend: "local" }, { dbBackend: "neon" }])
|
package/lib/runner/selection.mjs
CHANGED
|
@@ -8,7 +8,9 @@ export function findUnmatchedRequestedFiles(
|
|
|
8
8
|
) {
|
|
9
9
|
const matchedFiles = new Set();
|
|
10
10
|
for (const config of configs) {
|
|
11
|
-
const suites = collectSuites(config, typeValues, suiteSelectors, []
|
|
11
|
+
const suites = collectSuites(config, typeValues, suiteSelectors, [], {
|
|
12
|
+
ignoreSkipRules: true,
|
|
13
|
+
});
|
|
12
14
|
for (const suite of suites) {
|
|
13
15
|
for (const file of suite.files) {
|
|
14
16
|
matchedFiles.add(normalizePathSeparators(file));
|
package/lib/runtime/index.d.ts
CHANGED
|
@@ -23,6 +23,12 @@ export interface RuntimeOptions {
|
|
|
23
23
|
thresholds?: Record<string, unknown>;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
export interface RuntimeArtifactOptions {
|
|
27
|
+
contentType?: string;
|
|
28
|
+
kind?: string;
|
|
29
|
+
summary?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
26
32
|
export interface RuntimeEnv {
|
|
27
33
|
BASE: string;
|
|
28
34
|
MACHINE_ID?: string;
|
|
@@ -133,6 +139,11 @@ export declare const http: RuntimeHttpClient;
|
|
|
133
139
|
|
|
134
140
|
export declare function file(data: unknown, filename?: string, contentType?: string): unknown;
|
|
135
141
|
export declare function json<T = unknown>(response: Pick<RuntimeResponse, "body">): T;
|
|
142
|
+
export declare function emitArtifact(
|
|
143
|
+
name: string,
|
|
144
|
+
data: unknown,
|
|
145
|
+
options?: RuntimeArtifactOptions
|
|
146
|
+
): void;
|
|
136
147
|
export declare function contains<T extends Record<string, unknown>>(
|
|
137
148
|
rows: T[],
|
|
138
149
|
field: keyof T | string,
|
package/lib/runtime/index.mjs
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const RUNTIME_ARTIFACT_MARKER = "TESTKIT_ARTIFACT:";
|
|
2
|
+
|
|
3
|
+
export function emitArtifact(name, data, options = {}) {
|
|
4
|
+
const normalizedName = normalizeArtifactName(name);
|
|
5
|
+
const payload = encodeURIComponent(
|
|
6
|
+
JSON.stringify({
|
|
7
|
+
name: normalizedName,
|
|
8
|
+
kind: normalizeOptionalString(options.kind),
|
|
9
|
+
summary: normalizeOptionalString(options.summary),
|
|
10
|
+
contentType: normalizeContentType(options.contentType),
|
|
11
|
+
data,
|
|
12
|
+
emittedAt: new Date().toISOString(),
|
|
13
|
+
})
|
|
14
|
+
);
|
|
15
|
+
console.log(
|
|
16
|
+
`${RUNTIME_ARTIFACT_MARKER}${payload}`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function normalizeArtifactName(name) {
|
|
21
|
+
if (typeof name !== "string" || name.trim().length === 0) {
|
|
22
|
+
throw new Error("emitArtifact(name, data) requires a non-empty artifact name");
|
|
23
|
+
}
|
|
24
|
+
return name.trim();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function normalizeOptionalString(value) {
|
|
28
|
+
if (value === undefined || value === null) return null;
|
|
29
|
+
const normalized = String(value).trim();
|
|
30
|
+
return normalized.length > 0 ? normalized : null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function normalizeContentType(value) {
|
|
34
|
+
const normalized = normalizeOptionalString(value);
|
|
35
|
+
return normalized || "application/json";
|
|
36
|
+
}
|
package/lib/setup/index.d.ts
CHANGED
|
@@ -18,6 +18,21 @@ export interface LifecycleConfig {
|
|
|
18
18
|
testkitCwd?: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
export interface SkipFileRule {
|
|
22
|
+
path: string;
|
|
23
|
+
reason: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface SkipSuiteRule {
|
|
27
|
+
selector: string;
|
|
28
|
+
reason: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SkipConfig {
|
|
32
|
+
files?: SkipFileRule[];
|
|
33
|
+
suites?: SkipSuiteRule[];
|
|
34
|
+
}
|
|
35
|
+
|
|
21
36
|
export interface ServiceConfig {
|
|
22
37
|
database?: LocalDatabaseConfig;
|
|
23
38
|
databaseFrom?: string;
|
|
@@ -38,6 +53,7 @@ export interface ServiceConfig {
|
|
|
38
53
|
};
|
|
39
54
|
migrate?: LifecycleConfig;
|
|
40
55
|
seed?: LifecycleConfig;
|
|
56
|
+
skip?: SkipConfig;
|
|
41
57
|
}
|
|
42
58
|
|
|
43
59
|
export interface TestkitSetup {
|