@elench/testkit 0.1.44 → 0.1.46
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
CHANGED
|
@@ -161,12 +161,35 @@ If `reporting.knownFailuresFile` is configured, `testkit` enriches
|
|
|
161
161
|
- per-file `triage` metadata (issue, classification, description)
|
|
162
162
|
- top-level `triageSummary` counts for known vs untriaged failures
|
|
163
163
|
|
|
164
|
+
Known-failure entry authoring uses this contract:
|
|
165
|
+
|
|
166
|
+
- `title`
|
|
167
|
+
- exact issue-tracker title for the linked issue
|
|
168
|
+
- shared issues may reuse the same title across multiple local entries
|
|
169
|
+
- `description`
|
|
170
|
+
- product-local bug slice or route-family summary
|
|
171
|
+
- this is where file-specific nuance belongs
|
|
172
|
+
- `whyFailing`
|
|
173
|
+
- underlying technical cause of the failure
|
|
174
|
+
|
|
164
175
|
If `reporting.issueValidation` is also configured, `testkit` validates known-failure
|
|
165
176
|
issue references against GitHub and adds top-level `knownFailuresIssueValidation`
|
|
166
177
|
data to the run/status artifacts. The most important stale-triage signal is:
|
|
167
178
|
|
|
168
179
|
- a known-failure test still fails, but the linked GitHub issue is closed
|
|
169
180
|
|
|
181
|
+
In `mode: "error"`, exact GitHub metadata drift is also treated as a validation
|
|
182
|
+
failure:
|
|
183
|
+
|
|
184
|
+
- title does not match the linked issue title
|
|
185
|
+
- local open/closed state does not match the linked issue state
|
|
186
|
+
|
|
187
|
+
Reproduction warnings are execution-aware:
|
|
188
|
+
|
|
189
|
+
- `failed` means the known failure reproduced
|
|
190
|
+
- `passed` means the matched test executed and did not reproduce
|
|
191
|
+
- `skipped` and `not_run` do not count as reproduction evidence
|
|
192
|
+
|
|
170
193
|
## Authoring
|
|
171
194
|
|
|
172
195
|
HTTP suites:
|
|
@@ -125,7 +125,7 @@ export async function validateKnownFailureIssues({
|
|
|
125
125
|
|
|
126
126
|
const summary = buildIssueValidationSummary(entries, globalFindings);
|
|
127
127
|
return {
|
|
128
|
-
schemaVersion:
|
|
128
|
+
schemaVersion: 2,
|
|
129
129
|
provider: "github",
|
|
130
130
|
mode: normalizedConfig.mode,
|
|
131
131
|
checkedAt: new Date(now).toISOString(),
|
|
@@ -363,7 +363,15 @@ function collectObservedKnownFailureEntries(document, runArtifact, statusArtifac
|
|
|
363
363
|
const observed = checks.get(entry.id) || createObservedCheck(entry);
|
|
364
364
|
observed.matchedTests += 1;
|
|
365
365
|
if (test.status === "failed") {
|
|
366
|
+
observed.executedTests += 1;
|
|
366
367
|
observed.failedTests += 1;
|
|
368
|
+
} else if (test.status === "passed") {
|
|
369
|
+
observed.executedTests += 1;
|
|
370
|
+
observed.passedTests += 1;
|
|
371
|
+
} else if (test.status === "skipped") {
|
|
372
|
+
observed.skippedTests += 1;
|
|
373
|
+
} else if (test.status === "not_run") {
|
|
374
|
+
observed.notRunTests += 1;
|
|
367
375
|
}
|
|
368
376
|
checks.set(entry.id, observed);
|
|
369
377
|
}
|
|
@@ -399,7 +407,11 @@ function createObservedCheck(entry) {
|
|
|
399
407
|
return {
|
|
400
408
|
id: entry.id,
|
|
401
409
|
matchedTests: 0,
|
|
410
|
+
executedTests: 0,
|
|
411
|
+
passedTests: 0,
|
|
402
412
|
failedTests: 0,
|
|
413
|
+
skippedTests: 0,
|
|
414
|
+
notRunTests: 0,
|
|
403
415
|
};
|
|
404
416
|
}
|
|
405
417
|
|
|
@@ -436,7 +448,7 @@ function buildIssueValidationEntry({ entry, observed, issueData }) {
|
|
|
436
448
|
if (issueData?.exists && issueData.title && issueData.title !== entry.title) {
|
|
437
449
|
findings.push({
|
|
438
450
|
code: "title_mismatch",
|
|
439
|
-
severity: "
|
|
451
|
+
severity: "error",
|
|
440
452
|
message: `Known failure ${entry.id} title does not match issue #${entry.issue.number}`,
|
|
441
453
|
});
|
|
442
454
|
}
|
|
@@ -444,7 +456,7 @@ function buildIssueValidationEntry({ entry, observed, issueData }) {
|
|
|
444
456
|
if (issueData?.exists && normalizedIssueState && normalizedIssueState !== entry.state) {
|
|
445
457
|
findings.push({
|
|
446
458
|
code: "state_mismatch",
|
|
447
|
-
severity: "
|
|
459
|
+
severity: "error",
|
|
448
460
|
message: `Known failure ${entry.id} state ${entry.state} does not match issue #${entry.issue.number} state ${normalizedIssueState}`,
|
|
449
461
|
});
|
|
450
462
|
}
|
|
@@ -457,7 +469,12 @@ function buildIssueValidationEntry({ entry, observed, issueData }) {
|
|
|
457
469
|
});
|
|
458
470
|
}
|
|
459
471
|
|
|
460
|
-
if (
|
|
472
|
+
if (
|
|
473
|
+
issueData?.exists &&
|
|
474
|
+
observed.executedTests > 0 &&
|
|
475
|
+
observed.failedTests === 0 &&
|
|
476
|
+
observed.passedTests > 0
|
|
477
|
+
) {
|
|
461
478
|
if (normalizedIssueState === "open") {
|
|
462
479
|
findings.push({
|
|
463
480
|
code: "open_not_reproduced",
|
|
@@ -479,7 +496,11 @@ function buildIssueValidationEntry({ entry, observed, issueData }) {
|
|
|
479
496
|
issue: entry.issue,
|
|
480
497
|
observed: {
|
|
481
498
|
matchedTests: observed.matchedTests,
|
|
499
|
+
executedTests: observed.executedTests,
|
|
500
|
+
passedTests: observed.passedTests,
|
|
482
501
|
failedTests: observed.failedTests,
|
|
502
|
+
skippedTests: observed.skippedTests,
|
|
503
|
+
notRunTests: observed.notRunTests,
|
|
483
504
|
reproduced: observed.failedTests > 0,
|
|
484
505
|
},
|
|
485
506
|
github: issueData
|
|
@@ -510,8 +531,23 @@ function resolveIssueValidationStatus(issueData, observed, findings) {
|
|
|
510
531
|
const normalizedState = normalizeIssueState(issueData.state);
|
|
511
532
|
if (observed.failedTests > 0 && normalizedState === "closed") return "closed_but_failing";
|
|
512
533
|
if (observed.failedTests > 0 && normalizedState === "open") return "open_and_failing";
|
|
513
|
-
if (observed.
|
|
514
|
-
if (
|
|
534
|
+
if (observed.executedTests === 0 && observed.matchedTests > 0) return "not_executed";
|
|
535
|
+
if (
|
|
536
|
+
observed.executedTests > 0 &&
|
|
537
|
+
observed.failedTests === 0 &&
|
|
538
|
+
observed.passedTests > 0 &&
|
|
539
|
+
normalizedState === "open"
|
|
540
|
+
) {
|
|
541
|
+
return "open_not_reproduced";
|
|
542
|
+
}
|
|
543
|
+
if (
|
|
544
|
+
observed.executedTests > 0 &&
|
|
545
|
+
observed.failedTests === 0 &&
|
|
546
|
+
observed.passedTests > 0 &&
|
|
547
|
+
normalizedState === "closed"
|
|
548
|
+
) {
|
|
549
|
+
return "closed_not_reproduced";
|
|
550
|
+
}
|
|
515
551
|
if (findings.length > 0) return "metadata_mismatch";
|
|
516
552
|
return "not_observed";
|
|
517
553
|
}
|
|
@@ -25,7 +25,7 @@ describe("known failures GitHub validation", () => {
|
|
|
25
25
|
expect(parseGitHubRepoSlug("https://gitlab.com/acme/repo.git")).toBe(null);
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
it("
|
|
28
|
+
it("fails validation for title/state drift and closed issues that still reproduce", async () => {
|
|
29
29
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-gh-issues-"));
|
|
30
30
|
tempDirs.push(tempDir);
|
|
31
31
|
const document = normalizeKnownFailuresDocument({
|
|
@@ -98,11 +98,114 @@ describe("known failures GitHub validation", () => {
|
|
|
98
98
|
|
|
99
99
|
expect(result.summary.byCode.closed_but_failing).toBe(1);
|
|
100
100
|
expect(result.summary.byCode.title_mismatch).toBe(1);
|
|
101
|
+
expect(result.summary.byCode.state_mismatch).toBe(1);
|
|
101
102
|
expect(result.summary.errors).toBeGreaterThan(0);
|
|
102
103
|
expect(result.entries[0].status).toBe("closed_but_failing");
|
|
103
104
|
expect(shouldFailKnownFailureIssueValidation(result)).toBe(true);
|
|
104
105
|
});
|
|
105
106
|
|
|
107
|
+
it("allows multiple local entries to share one issue title while keeping distinct descriptions", async () => {
|
|
108
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-gh-shared-title-"));
|
|
109
|
+
tempDirs.push(tempDir);
|
|
110
|
+
const document = normalizeKnownFailuresDocument({
|
|
111
|
+
schemaVersion: 1,
|
|
112
|
+
issueRepo: "acme/repo",
|
|
113
|
+
entries: [
|
|
114
|
+
{
|
|
115
|
+
id: "route-a-invalid-uuid",
|
|
116
|
+
title: "UUID path params reach Postgres and return 500 instead of 400",
|
|
117
|
+
classification: "product_bug",
|
|
118
|
+
state: "open",
|
|
119
|
+
issue: {
|
|
120
|
+
repo: "acme/repo",
|
|
121
|
+
number: 77,
|
|
122
|
+
url: "https://github.com/acme/repo/issues/77",
|
|
123
|
+
},
|
|
124
|
+
description: "Route A leaks Postgres UUID parse errors on malformed ids.",
|
|
125
|
+
whyFailing: "Route A is missing UUID param validation.",
|
|
126
|
+
lastReviewedAt: "2026-04-27",
|
|
127
|
+
matches: [
|
|
128
|
+
{
|
|
129
|
+
service: "api",
|
|
130
|
+
type: "int",
|
|
131
|
+
path: "src/api/routes/__testkit__/route-a.int.testkit.ts",
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: "route-b-invalid-uuid",
|
|
137
|
+
title: "UUID path params reach Postgres and return 500 instead of 400",
|
|
138
|
+
classification: "product_bug",
|
|
139
|
+
state: "open",
|
|
140
|
+
issue: {
|
|
141
|
+
repo: "acme/repo",
|
|
142
|
+
number: 77,
|
|
143
|
+
url: "https://github.com/acme/repo/issues/77",
|
|
144
|
+
},
|
|
145
|
+
description: "Route B leaks Postgres UUID parse errors on malformed ids.",
|
|
146
|
+
whyFailing: "Route B is missing UUID param validation.",
|
|
147
|
+
lastReviewedAt: "2026-04-27",
|
|
148
|
+
matches: [
|
|
149
|
+
{
|
|
150
|
+
service: "api",
|
|
151
|
+
type: "int",
|
|
152
|
+
path: "src/api/routes/__testkit__/route-b.int.testkit.ts",
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const result = await validateKnownFailureIssues({
|
|
160
|
+
productDir: tempDir,
|
|
161
|
+
document,
|
|
162
|
+
statusArtifact: {
|
|
163
|
+
tests: [
|
|
164
|
+
{
|
|
165
|
+
service: "api",
|
|
166
|
+
type: "int",
|
|
167
|
+
path: "src/api/routes/__testkit__/route-a.int.testkit.ts",
|
|
168
|
+
status: "failed",
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
service: "api",
|
|
172
|
+
type: "int",
|
|
173
|
+
path: "src/api/routes/__testkit__/route-b.int.testkit.ts",
|
|
174
|
+
status: "failed",
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
config: {
|
|
179
|
+
provider: "github",
|
|
180
|
+
mode: "error",
|
|
181
|
+
},
|
|
182
|
+
transport: {
|
|
183
|
+
async fetchRepoIssues(repo, numbers) {
|
|
184
|
+
const map = new Map();
|
|
185
|
+
map.set(numbers[0], {
|
|
186
|
+
repo,
|
|
187
|
+
number: numbers[0],
|
|
188
|
+
exists: true,
|
|
189
|
+
title: "UUID path params reach Postgres and return 500 instead of 400",
|
|
190
|
+
state: "OPEN",
|
|
191
|
+
url: `https://github.com/${repo}/issues/${numbers[0]}`,
|
|
192
|
+
checkedAt: "2026-04-27T00:00:00.000Z",
|
|
193
|
+
source: "github",
|
|
194
|
+
});
|
|
195
|
+
return map;
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
expect(result.summary.byCode.title_mismatch).toBeUndefined();
|
|
201
|
+
expect(result.summary.errors).toBe(0);
|
|
202
|
+
expect(result.entries).toHaveLength(2);
|
|
203
|
+
expect(result.entries[0].findings).toEqual([]);
|
|
204
|
+
expect(result.entries[1].findings).toEqual([]);
|
|
205
|
+
expect(result.entries[0].status).toBe("open_and_failing");
|
|
206
|
+
expect(result.entries[1].status).toBe("open_and_failing");
|
|
207
|
+
});
|
|
208
|
+
|
|
106
209
|
it("warns when an open issue is not reproduced", async () => {
|
|
107
210
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-gh-open-"));
|
|
108
211
|
tempDirs.push(tempDir);
|
|
@@ -176,6 +279,196 @@ describe("known failures GitHub validation", () => {
|
|
|
176
279
|
expect(result.summary.errors).toBe(0);
|
|
177
280
|
expect(result.summary.warnings).toBeGreaterThan(0);
|
|
178
281
|
expect(shouldFailKnownFailureIssueValidation(result)).toBe(false);
|
|
282
|
+
expect(result.entries[0].observed).toMatchObject({
|
|
283
|
+
matchedTests: 1,
|
|
284
|
+
executedTests: 1,
|
|
285
|
+
passedTests: 1,
|
|
286
|
+
failedTests: 0,
|
|
287
|
+
skippedTests: 0,
|
|
288
|
+
notRunTests: 0,
|
|
289
|
+
reproduced: false,
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it("does not treat skipped or not_run files as not reproduced", async () => {
|
|
294
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-gh-not-executed-"));
|
|
295
|
+
tempDirs.push(tempDir);
|
|
296
|
+
const document = normalizeKnownFailuresDocument({
|
|
297
|
+
schemaVersion: 1,
|
|
298
|
+
issueRepo: "acme/repo",
|
|
299
|
+
entries: [
|
|
300
|
+
{
|
|
301
|
+
id: "bad-message",
|
|
302
|
+
title: "Bad message bug",
|
|
303
|
+
classification: "product_bug",
|
|
304
|
+
state: "open",
|
|
305
|
+
issue: {
|
|
306
|
+
repo: "acme/repo",
|
|
307
|
+
number: 12,
|
|
308
|
+
url: "https://github.com/acme/repo/issues/12",
|
|
309
|
+
},
|
|
310
|
+
description: "Wrong message",
|
|
311
|
+
whyFailing: "Payload is wrong",
|
|
312
|
+
lastReviewedAt: "2026-04-27",
|
|
313
|
+
matches: [
|
|
314
|
+
{
|
|
315
|
+
service: "api",
|
|
316
|
+
type: "int",
|
|
317
|
+
path: "src/api/routes/__testkit__/failing.int.testkit.ts",
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
service: "api",
|
|
321
|
+
type: "int",
|
|
322
|
+
path: "src/api/routes/__testkit__/blocked.int.testkit.ts",
|
|
323
|
+
},
|
|
324
|
+
],
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
const result = await validateKnownFailureIssues({
|
|
330
|
+
productDir: tempDir,
|
|
331
|
+
document,
|
|
332
|
+
statusArtifact: {
|
|
333
|
+
tests: [
|
|
334
|
+
{
|
|
335
|
+
service: "api",
|
|
336
|
+
type: "int",
|
|
337
|
+
path: "src/api/routes/__testkit__/failing.int.testkit.ts",
|
|
338
|
+
status: "skipped",
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
service: "api",
|
|
342
|
+
type: "int",
|
|
343
|
+
path: "src/api/routes/__testkit__/blocked.int.testkit.ts",
|
|
344
|
+
status: "not_run",
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
},
|
|
348
|
+
config: {
|
|
349
|
+
provider: "github",
|
|
350
|
+
mode: "warn",
|
|
351
|
+
},
|
|
352
|
+
transport: {
|
|
353
|
+
async fetchRepoIssues(repo, numbers) {
|
|
354
|
+
const map = new Map();
|
|
355
|
+
map.set(numbers[0], {
|
|
356
|
+
repo,
|
|
357
|
+
number: numbers[0],
|
|
358
|
+
exists: true,
|
|
359
|
+
title: "Bad message bug",
|
|
360
|
+
state: "OPEN",
|
|
361
|
+
url: `https://github.com/${repo}/issues/${numbers[0]}`,
|
|
362
|
+
checkedAt: "2026-04-27T00:00:00.000Z",
|
|
363
|
+
source: "github",
|
|
364
|
+
});
|
|
365
|
+
return map;
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
expect(result.summary.byCode.open_not_reproduced).toBeUndefined();
|
|
371
|
+
expect(result.entries[0].findings).toEqual([]);
|
|
372
|
+
expect(result.entries[0].status).toBe("not_executed");
|
|
373
|
+
expect(result.entries[0].observed).toMatchObject({
|
|
374
|
+
matchedTests: 2,
|
|
375
|
+
executedTests: 0,
|
|
376
|
+
passedTests: 0,
|
|
377
|
+
failedTests: 0,
|
|
378
|
+
skippedTests: 1,
|
|
379
|
+
notRunTests: 1,
|
|
380
|
+
reproduced: false,
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it("still treats mixed passed and skipped execution as not reproduced", async () => {
|
|
385
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-gh-mixed-execution-"));
|
|
386
|
+
tempDirs.push(tempDir);
|
|
387
|
+
const document = normalizeKnownFailuresDocument({
|
|
388
|
+
schemaVersion: 1,
|
|
389
|
+
issueRepo: "acme/repo",
|
|
390
|
+
entries: [
|
|
391
|
+
{
|
|
392
|
+
id: "bad-message",
|
|
393
|
+
title: "Bad message bug",
|
|
394
|
+
classification: "product_bug",
|
|
395
|
+
state: "open",
|
|
396
|
+
issue: {
|
|
397
|
+
repo: "acme/repo",
|
|
398
|
+
number: 12,
|
|
399
|
+
url: "https://github.com/acme/repo/issues/12",
|
|
400
|
+
},
|
|
401
|
+
description: "Wrong message",
|
|
402
|
+
whyFailing: "Payload is wrong",
|
|
403
|
+
lastReviewedAt: "2026-04-27",
|
|
404
|
+
matches: [
|
|
405
|
+
{
|
|
406
|
+
service: "api",
|
|
407
|
+
type: "int",
|
|
408
|
+
path: "src/api/routes/__testkit__/passed.int.testkit.ts",
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
service: "api",
|
|
412
|
+
type: "int",
|
|
413
|
+
path: "src/api/routes/__testkit__/skipped.int.testkit.ts",
|
|
414
|
+
},
|
|
415
|
+
],
|
|
416
|
+
},
|
|
417
|
+
],
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
const result = await validateKnownFailureIssues({
|
|
421
|
+
productDir: tempDir,
|
|
422
|
+
document,
|
|
423
|
+
statusArtifact: {
|
|
424
|
+
tests: [
|
|
425
|
+
{
|
|
426
|
+
service: "api",
|
|
427
|
+
type: "int",
|
|
428
|
+
path: "src/api/routes/__testkit__/passed.int.testkit.ts",
|
|
429
|
+
status: "passed",
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
service: "api",
|
|
433
|
+
type: "int",
|
|
434
|
+
path: "src/api/routes/__testkit__/skipped.int.testkit.ts",
|
|
435
|
+
status: "skipped",
|
|
436
|
+
},
|
|
437
|
+
],
|
|
438
|
+
},
|
|
439
|
+
config: {
|
|
440
|
+
provider: "github",
|
|
441
|
+
mode: "warn",
|
|
442
|
+
},
|
|
443
|
+
transport: {
|
|
444
|
+
async fetchRepoIssues(repo, numbers) {
|
|
445
|
+
const map = new Map();
|
|
446
|
+
map.set(numbers[0], {
|
|
447
|
+
repo,
|
|
448
|
+
number: numbers[0],
|
|
449
|
+
exists: true,
|
|
450
|
+
title: "Bad message bug",
|
|
451
|
+
state: "OPEN",
|
|
452
|
+
url: `https://github.com/${repo}/issues/${numbers[0]}`,
|
|
453
|
+
checkedAt: "2026-04-27T00:00:00.000Z",
|
|
454
|
+
source: "github",
|
|
455
|
+
});
|
|
456
|
+
return map;
|
|
457
|
+
},
|
|
458
|
+
},
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
expect(result.summary.byCode.open_not_reproduced).toBe(1);
|
|
462
|
+
expect(result.entries[0].status).toBe("open_not_reproduced");
|
|
463
|
+
expect(result.entries[0].observed).toMatchObject({
|
|
464
|
+
matchedTests: 2,
|
|
465
|
+
executedTests: 1,
|
|
466
|
+
passedTests: 1,
|
|
467
|
+
failedTests: 0,
|
|
468
|
+
skippedTests: 1,
|
|
469
|
+
notRunTests: 0,
|
|
470
|
+
reproduced: false,
|
|
471
|
+
});
|
|
179
472
|
});
|
|
180
473
|
|
|
181
474
|
it("falls back to warning when validation is unavailable", async () => {
|
|
@@ -23,11 +23,14 @@ export interface KnownFailureMatch {
|
|
|
23
23
|
|
|
24
24
|
export interface KnownFailureEntry {
|
|
25
25
|
id: string;
|
|
26
|
+
/** Exact issue-tracker title for the linked issue. */
|
|
26
27
|
title: string;
|
|
27
28
|
classification: KnownFailureClassification;
|
|
28
29
|
state: KnownFailureState;
|
|
29
30
|
issue: KnownFailureIssueRef;
|
|
31
|
+
/** Product-local bug slice or route-family summary. */
|
|
30
32
|
description: string;
|
|
33
|
+
/** Underlying technical cause of the failure. */
|
|
31
34
|
whyFailing: string;
|
|
32
35
|
lastReviewedAt: string;
|
|
33
36
|
matches: KnownFailureMatch[];
|
|
@@ -69,7 +72,11 @@ export interface KnownFailureIssueValidationEntry {
|
|
|
69
72
|
issue: KnownFailureIssueRef;
|
|
70
73
|
observed: {
|
|
71
74
|
matchedTests: number;
|
|
75
|
+
executedTests: number;
|
|
76
|
+
passedTests: number;
|
|
72
77
|
failedTests: number;
|
|
78
|
+
skippedTests: number;
|
|
79
|
+
notRunTests: number;
|
|
73
80
|
reproduced: boolean;
|
|
74
81
|
};
|
|
75
82
|
github: {
|
|
@@ -85,7 +92,7 @@ export interface KnownFailureIssueValidationEntry {
|
|
|
85
92
|
}
|
|
86
93
|
|
|
87
94
|
export interface KnownFailureIssueValidationResult {
|
|
88
|
-
schemaVersion:
|
|
95
|
+
schemaVersion: 2;
|
|
89
96
|
provider: "github";
|
|
90
97
|
mode: "off" | "warn" | "error";
|
|
91
98
|
checkedAt: string;
|
package/lib/runner/reporting.mjs
CHANGED
|
@@ -78,7 +78,7 @@ export function buildStatusArtifact({
|
|
|
78
78
|
scope.serviceFilter === null;
|
|
79
79
|
|
|
80
80
|
return {
|
|
81
|
-
schemaVersion:
|
|
81
|
+
schemaVersion: 6,
|
|
82
82
|
source: "testkit",
|
|
83
83
|
notice: "Generated file. Do not edit manually.",
|
|
84
84
|
product: {
|
|
@@ -127,7 +127,7 @@ export function buildRunArtifact({
|
|
|
127
127
|
const dbBackend = summarizeDbBackend(results);
|
|
128
128
|
|
|
129
129
|
return {
|
|
130
|
-
schemaVersion:
|
|
130
|
+
schemaVersion: 6,
|
|
131
131
|
source: "testkit",
|
|
132
132
|
generatedAt: new Date(finishedAt).toISOString(),
|
|
133
133
|
product: {
|
|
@@ -78,7 +78,7 @@ describe("runner reporting", () => {
|
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
expect(artifact.product.name).toBe("my-product");
|
|
81
|
-
expect(artifact.schemaVersion).toBe(
|
|
81
|
+
expect(artifact.schemaVersion).toBe(6);
|
|
82
82
|
expect(artifact.run).toMatchObject({
|
|
83
83
|
workers: 2,
|
|
84
84
|
fileTimeoutSeconds: 60,
|
|
@@ -149,7 +149,7 @@ describe("runner reporting", () => {
|
|
|
149
149
|
});
|
|
150
150
|
|
|
151
151
|
expect(status).toEqual({
|
|
152
|
-
schemaVersion:
|
|
152
|
+
schemaVersion: 6,
|
|
153
153
|
source: "testkit",
|
|
154
154
|
notice: "Generated file. Do not edit manually.",
|
|
155
155
|
product: {
|