@futdevpro/dynamo-e2e 1.18.18 → 1.18.22
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/CHANGELOG.md +63 -0
- package/bin/dye2e.js +85 -1
- package/build/_modules/coverage/_collections/coverage-catalog.util.d.ts +22 -0
- package/build/_modules/coverage/_collections/coverage-catalog.util.d.ts.map +1 -0
- package/build/_modules/coverage/_collections/coverage-catalog.util.js +217 -0
- package/build/_modules/coverage/_collections/coverage-catalog.util.js.map +1 -0
- package/build/_modules/coverage/_models/coverage-catalog.interface.d.ts +75 -0
- package/build/_modules/coverage/_models/coverage-catalog.interface.d.ts.map +1 -0
- package/build/_modules/coverage/_models/coverage-catalog.interface.js +8 -0
- package/build/_modules/coverage/_models/coverage-catalog.interface.js.map +1 -0
- package/build/_modules/coverage/index.d.ts +3 -0
- package/build/_modules/coverage/index.d.ts.map +1 -0
- package/build/_modules/coverage/index.js +20 -0
- package/build/_modules/coverage/index.js.map +1 -0
- package/build/_modules/generators/_collections/cli-runner.util.d.ts.map +1 -1
- package/build/_modules/generators/_collections/cli-runner.util.js +20 -1
- package/build/_modules/generators/_collections/cli-runner.util.js.map +1 -1
- package/build/_modules/runtime/_collections/journey-context.util.d.ts +72 -0
- package/build/_modules/runtime/_collections/journey-context.util.d.ts.map +1 -0
- package/build/_modules/runtime/_collections/journey-context.util.js +137 -0
- package/build/_modules/runtime/_collections/journey-context.util.js.map +1 -0
- package/build/_modules/runtime/_models/journey-context.interface.d.ts +31 -0
- package/build/_modules/runtime/_models/journey-context.interface.d.ts.map +1 -0
- package/build/_modules/runtime/_models/journey-context.interface.js +3 -0
- package/build/_modules/runtime/_models/journey-context.interface.js.map +1 -0
- package/build/_modules/runtime/index.d.ts +2 -0
- package/build/_modules/runtime/index.d.ts.map +1 -1
- package/build/_modules/runtime/index.js +2 -0
- package/build/_modules/runtime/index.js.map +1 -1
- package/build/_modules/vqa/_collections/constants/vqa-standard-viewports.const.d.ts +1 -1
- package/build/_modules/vqa/_collections/constants/vqa-standard-viewports.const.js +1 -1
- package/build/_modules/vqa/_collections/index.d.ts +1 -0
- package/build/_modules/vqa/_collections/index.d.ts.map +1 -1
- package/build/_modules/vqa/_collections/index.js +1 -0
- package/build/_modules/vqa/_collections/index.js.map +1 -1
- package/build/_modules/vqa/_collections/utils/review-gate.util.d.ts +36 -0
- package/build/_modules/vqa/_collections/utils/review-gate.util.d.ts.map +1 -0
- package/build/_modules/vqa/_collections/utils/review-gate.util.js +232 -0
- package/build/_modules/vqa/_collections/utils/review-gate.util.js.map +1 -0
- package/build/_modules/vqa/_models/interfaces/index.d.ts +1 -0
- package/build/_modules/vqa/_models/interfaces/index.d.ts.map +1 -1
- package/build/_modules/vqa/_models/interfaces/index.js +1 -0
- package/build/_modules/vqa/_models/interfaces/index.js.map +1 -1
- package/build/_modules/vqa/_models/interfaces/review-gate.interface.d.ts +55 -0
- package/build/_modules/vqa/_models/interfaces/review-gate.interface.d.ts.map +1 -0
- package/build/_modules/vqa/_models/interfaces/review-gate.interface.js +3 -0
- package/build/_modules/vqa/_models/interfaces/review-gate.interface.js.map +1 -0
- package/build/_modules/vqa/generators/ai-agent-readme.template.js +8 -8
- package/build/_modules/vqa/generators/capture-spec.generator.js +1 -1
- package/build/_modules/vqa/generators/review-bundle.generator.d.ts +16 -4
- package/build/_modules/vqa/generators/review-bundle.generator.d.ts.map +1 -1
- package/build/_modules/vqa/generators/review-bundle.generator.js +31 -5
- package/build/_modules/vqa/generators/review-bundle.generator.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -1
- package/build/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,69 @@
|
|
|
3
3
|
Minden release a `dynamo-e2e-foundation` HYPERPLAN MP-N ütemezést követi.
|
|
4
4
|
Verzióformátum: `MM.mm.p` (két-számjegyes major-minor, Dynamo-konvenció).
|
|
5
5
|
|
|
6
|
+
## [01.18.22] — 2026-09-25 — Coverage catalog ↔ evidence validator (BFR-FSMED-006)
|
|
7
|
+
|
|
8
|
+
- ⚠️ The first 01.18.22 CI run failed the COVERAGE gate (functions 61%, gate 75%) — not a test failure: the runnable-capture
|
|
9
|
+
spec's `playwright test --list` child loaded the whole package through Playwright's loader, and c8 merged it as ~150
|
|
10
|
+
never-called functions. The child's `NODE_V8_COVERAGE` now goes to a discard dir (deleting the variable is not enough
|
|
11
|
+
on Windows — measured); functions back to 90%.
|
|
12
|
+
|
|
13
|
+
- Added `DyE2E_validateCoverageCatalog({ featureCatalogPath, journeyCatalogPath, discoveredTestIds?, featureIdPrefix?,
|
|
14
|
+
journeyIdPrefix? })`, `DyE2E_writeCoverageReport(report, path)` and `DyE2E_discoverTestIds({ roots, idPattern })`
|
|
15
|
+
(root export), plus `dye2e validate-coverage-catalog --features --journeys [--scan --id-pattern] [--report]
|
|
16
|
+
[--require-complete]` (exit 0 ok · 1 findings, or not complete in release mode · 2 usage).
|
|
17
|
+
- Checks, with stable `COV-*` codes: an EMPTY or unreadable catalog is never green (`COV-ZERO-DENOMINATOR`,
|
|
18
|
+
`COV-CATALOG-UNREADABLE`) · duplicate / invalid entries · feature ↔ journey links BOTH ways (`COV-LINK-UNKNOWN`,
|
|
19
|
+
`COV-LINK-ONE-WAY`) · `covered` needs evidence, anything else needs `missingEvidence` · evidence files exist and each
|
|
20
|
+
claimed id is in them, with the layer prefix; journey evidence never counts as feature evidence · with discovered
|
|
21
|
+
ids: claimed-but-absent (`COV-EVIDENCE-ID-UNDISCOVERED`) and present-but-unclaimed (`COV-EVIDENCE-ORPHAN`).
|
|
22
|
+
- The report (`schema: dye2e-coverage-report/1`) keeps the feature and the journey denominators SEPARATE, each split
|
|
23
|
+
into covered / red / pending ids, plus the orphan / undiscovered ids; `releaseReady` only when valid, both
|
|
24
|
+
denominators > 0 and every entry covered. Project-specific rules (requirement mapping, variants …) stay project-side.
|
|
25
|
+
|
|
26
|
+
## [01.18.21] — 2026-09-25 — VQA aggregate review gate (BFR-FSMED-015, part 3)
|
|
27
|
+
|
|
28
|
+
- ⚠️ **01.18.19 and 01.18.20 were never published on their own:** the CI queue coalesced the quick successive pushes
|
|
29
|
+
into one run — their content (journey context, runnable capture) is published in 01.18.21.
|
|
30
|
+
|
|
31
|
+
- Added `DyE2E_VQA_ReviewGate_Util.verify({ bundlePath, findingsPath?, humanReviewPath?, failOn? })` and the CLI
|
|
32
|
+
`dye2e verify-review-bundle --bundle <path> [--findings] [--human-review] [--report <json>] [--fail-on a,b]`
|
|
33
|
+
(exit 0 pass · 1 fail · 2 usage): manifest + captured evidence + finding-set + human-review marker ⇒ ONE release
|
|
34
|
+
verdict with stable codes and a JSON report (`schema: dye2e-vqa-review-gate/1`).
|
|
35
|
+
- Categories (`--fail-on`, default all): `missing` (`VQA-GATE-EVIDENCE-MISSING`, `-FINDINGS-MISSING`) · `orphan`
|
|
36
|
+
(`-EVIDENCE-ORPHAN`: evidence for an undeclared state / viewport) · `invalid` (`-FINDING-INVALID` schema,
|
|
37
|
+
`-FINDING-FOREIGN` other feature / state / viewport, `-FINDING-REF-MISSING` evidence ref not in the bundle) ·
|
|
38
|
+
`blocker` / `high` (`-FINDING-OPEN-BLOCKER` / `-HIGH`; closed = verified / ignored / accepted-risk) · `human-review`
|
|
39
|
+
(`-HUMAN-REVIEW-MISSING` / `-INVALID` / `-REJECTED`; marker `{ reviewer, reviewedAt, verdict }`). A missing /
|
|
40
|
+
unreadable manifest always fails. Issues outside `--fail-on` are still reported (`blocking: false`); an unknown
|
|
41
|
+
`--fail-on` category is a usage error, not a silently weaker gate.
|
|
42
|
+
- The bundle README told the reviewer to reference `screenshots/…` / `dom-snapshots/…`, which the capture never
|
|
43
|
+
writes — it now names the real `states/<stateId>/<viewport>-<orientation>/` files (the gate checks refs exist).
|
|
44
|
+
|
|
45
|
+
## [01.18.20] — 2026-09-25 — Runnable VQA capture (BFR-FSMED-015, part 2)
|
|
46
|
+
|
|
47
|
+
- The review bundle now holds `capture.spec.ts` (was `capture-spec.ts`, which no Playwright `testMatch` picks up) AND
|
|
48
|
+
its own `playwright.config.ts` (`testDir: '.'`, `testMatch: 'capture.spec.ts'`): the bundle lives outside the
|
|
49
|
+
project's `testDir`, so even a correctly named spec gave "No tests found" with the project config.
|
|
50
|
+
- The run command is `DyE2E_VQA_ReviewBundle_Generator.captureCommand(bundlePath)` —
|
|
51
|
+
`VQA_OUT_DIR="<bundle>" npx playwright test --config "<bundle>/playwright.config.ts"`; `dye2e generate-review-bundle`
|
|
52
|
+
prints exactly this. Proven by a spec that runs `playwright test --config … --list` on a generated bundle
|
|
53
|
+
(4 tests discovered) and by running the CLI's printed command.
|
|
54
|
+
- The generated spec imports from `@futdevpro/dynamo-e2e` (root) instead of the `/vqa` subpath, so it resolves under
|
|
55
|
+
`moduleResolution: node` as well; a spec compiles the generated files with `strict` + `moduleResolution: node`.
|
|
56
|
+
- Docs: `vqa-announcement.md` and `vqa-cicd-step-template.md` use the new command (the template's `VQA_OUT_DIR` now
|
|
57
|
+
points at the bundle itself, so the artifacts land where `verifyBundleArtifacts` looks).
|
|
58
|
+
|
|
59
|
+
## [01.18.19] — 2026-09-25 — Journey context + cleanup registry (BFR-FSMED-007)
|
|
60
|
+
|
|
61
|
+
- Added `DyE2E_JourneyContext<TState>` to `/runtime`: typed state handoff between journey steps (`step(name, fn)` merges
|
|
62
|
+
the returned patch; `handoff(patch)`; `require(key)` fails with the key and the completed steps named instead of
|
|
63
|
+
calling an API with `undefined`) and a cleanup registry (`registerCleanup(label, fn)` → `runCleanup()`: LIFO, every
|
|
64
|
+
cleanup isolated, idempotent, and it THROWS naming the leaked labels when any cleanup failed — a leaked entity is a
|
|
65
|
+
red journey, never a silent one). A failed step is recorded and later steps refuse to run; the cleanups still run.
|
|
66
|
+
- `DyE2E_useJourney(test, { name, initialState })`: serial mode + `afterAll → runCleanup()` for a Playwright
|
|
67
|
+
`describe`. The cleanup runs after the test-scoped fixtures are disposed — it must use its own client.
|
|
68
|
+
|
|
6
69
|
## [01.18.18] — 2026-09-25 — Capability-scoped global setup (BFR-FSMED-017)
|
|
7
70
|
|
|
8
71
|
- `DyE2E_getGlobalSetup` new options: `failOnMissingEnv` (the missing `requiredEnvVars` become FATAL, named in the
|
package/bin/dye2e.js
CHANGED
|
@@ -354,7 +354,7 @@ function main() {
|
|
|
354
354
|
process.stdout.write(' runId: ' + result.runId + '\n');
|
|
355
355
|
process.stdout.write(' files: ' + result.files.length + '\n');
|
|
356
356
|
process.stdout.write('\n next: cd to the project + run\n');
|
|
357
|
-
process.stdout.write('
|
|
357
|
+
process.stdout.write(' ' + DyE2E_VQA_ReviewBundle_Generator.captureCommand(result.bundlePath) + '\n');
|
|
358
358
|
process.exit(0);
|
|
359
359
|
}
|
|
360
360
|
|
|
@@ -437,6 +437,90 @@ function main() {
|
|
|
437
437
|
process.exit(0);
|
|
438
438
|
}
|
|
439
439
|
|
|
440
|
+
if (parsed.command === 'verify-review-bundle') {
|
|
441
|
+
// BFR-FSMED-015 (3. resz) — aggregate release gate: exit 0 = pass, 1 = fail, 2 = usage / unknown category
|
|
442
|
+
const { DyE2E_VQA_ReviewGate_Util } = require('../build/_modules/vqa/_collections/utils/review-gate.util');
|
|
443
|
+
const bundleP = parsed.flags.bundle;
|
|
444
|
+
if (!bundleP) {
|
|
445
|
+
process.stderr.write('[dye2e] error: --bundle <path> required\n');
|
|
446
|
+
process.exit(2);
|
|
447
|
+
}
|
|
448
|
+
let failOn;
|
|
449
|
+
try {
|
|
450
|
+
failOn = DyE2E_VQA_ReviewGate_Util.parseFailOn(parsed.flags['fail-on']);
|
|
451
|
+
} catch (e) {
|
|
452
|
+
process.stderr.write('[dye2e] error: ' + e.message + '\n');
|
|
453
|
+
process.exit(2);
|
|
454
|
+
}
|
|
455
|
+
const report = DyE2E_VQA_ReviewGate_Util.verify({
|
|
456
|
+
bundlePath: path.resolve(process.cwd(), bundleP),
|
|
457
|
+
findingsPath: parsed.flags.findings ? path.resolve(process.cwd(), parsed.flags.findings) : undefined,
|
|
458
|
+
humanReviewPath: parsed.flags['human-review'] ? path.resolve(process.cwd(), parsed.flags['human-review']) : undefined,
|
|
459
|
+
failOn: failOn,
|
|
460
|
+
});
|
|
461
|
+
if (parsed.flags.report) {
|
|
462
|
+
const reportPath = path.resolve(process.cwd(), parsed.flags.report);
|
|
463
|
+
fs.mkdirSync(path.dirname(reportPath), { recursive: true });
|
|
464
|
+
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
465
|
+
}
|
|
466
|
+
process.stdout.write((report.verdict === 'pass' ? '✓' : '✗') + ' review gate: ' + report.verdict.toUpperCase() +
|
|
467
|
+
' (' + report.featureId + ', ' + report.findingsTotal + ' findings, fail-on: ' + report.failOn.join(',') + ')\n');
|
|
468
|
+
for (const issue of report.issues) {
|
|
469
|
+
process.stdout.write(' ' + (issue.blocking ? '✗' : '·') + ' ' + issue.code + (issue.ref ? ' [' + issue.ref + ']' : '') +
|
|
470
|
+
' — ' + issue.message + '\n');
|
|
471
|
+
}
|
|
472
|
+
process.exit(report.verdict === 'pass' ? 0 : 1);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (parsed.command === 'validate-coverage-catalog') {
|
|
476
|
+
// BFR-FSMED-006 — catalog <-> evidence validator: exit 0 ok, 1 findings (or not complete with --require-complete), 2 usage
|
|
477
|
+
const cov = require('../build/_modules/coverage/_collections/coverage-catalog.util');
|
|
478
|
+
const featuresP = parsed.flags.features;
|
|
479
|
+
const journeysP = parsed.flags.journeys;
|
|
480
|
+
if (!featuresP || !journeysP) {
|
|
481
|
+
process.stderr.write('[dye2e] error: --features <path> and --journeys <path> required\n');
|
|
482
|
+
process.exit(2);
|
|
483
|
+
}
|
|
484
|
+
let discovered;
|
|
485
|
+
if (parsed.flags.scan) {
|
|
486
|
+
if (!parsed.flags['id-pattern']) {
|
|
487
|
+
process.stderr.write('[dye2e] error: --scan needs --id-pattern <regex>\n');
|
|
488
|
+
process.exit(2);
|
|
489
|
+
}
|
|
490
|
+
let idPattern;
|
|
491
|
+
try {
|
|
492
|
+
idPattern = new RegExp(parsed.flags['id-pattern'], 'g');
|
|
493
|
+
} catch (e) {
|
|
494
|
+
process.stderr.write('[dye2e] error: invalid --id-pattern: ' + e.message + '\n');
|
|
495
|
+
process.exit(2);
|
|
496
|
+
}
|
|
497
|
+
discovered = cov.DyE2E_discoverTestIds({
|
|
498
|
+
roots: String(parsed.flags.scan).split(',').map((r) => path.resolve(process.cwd(), r.trim())),
|
|
499
|
+
idPattern: idPattern,
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
const report = cov.DyE2E_validateCoverageCatalog({
|
|
503
|
+
featureCatalogPath: path.resolve(process.cwd(), featuresP),
|
|
504
|
+
journeyCatalogPath: path.resolve(process.cwd(), journeysP),
|
|
505
|
+
discoveredTestIds: discovered,
|
|
506
|
+
featureIdPrefix: parsed.flags['feature-prefix'],
|
|
507
|
+
journeyIdPrefix: parsed.flags['journey-prefix'],
|
|
508
|
+
});
|
|
509
|
+
if (parsed.flags.report) {
|
|
510
|
+
cov.DyE2E_writeCoverageReport(report, path.resolve(process.cwd(), parsed.flags.report));
|
|
511
|
+
}
|
|
512
|
+
const layer = (name, l) => name + ' ' + l.covered.length + '/' + l.denominator + ' covered (red ' + l.red.length +
|
|
513
|
+
', pending ' + l.pending.length + ')';
|
|
514
|
+
process.stdout.write('[dye2e coverage] ' + layer('features', report.features) + '; ' + layer('journeys', report.journeys) +
|
|
515
|
+
'; orphan ' + report.orphanEvidenceIds.length + '; findings ' + report.findings.length +
|
|
516
|
+
'; releaseReady=' + report.releaseReady + '\n');
|
|
517
|
+
for (const f of report.findings) {
|
|
518
|
+
process.stdout.write(' ✗ ' + f.code + ' [' + f.ref + '] — ' + f.message + '\n');
|
|
519
|
+
}
|
|
520
|
+
const requireComplete = parsed.flags['require-complete'] !== undefined;
|
|
521
|
+
process.exit(!report.structurallyValid || (requireComplete && !report.releaseReady) ? 1 : 0);
|
|
522
|
+
}
|
|
523
|
+
|
|
440
524
|
process.stderr.write(`[dye2e] unknown command: ${parsed.command}\n`);
|
|
441
525
|
process.stderr.write(DyE2E_CliRunner_Util.helpText());
|
|
442
526
|
process.exit(2);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DyE2E_CoverageCatalog_Options, DyE2E_CoverageReport_Interface } from '../_models/coverage-catalog.interface';
|
|
2
|
+
/**
|
|
3
|
+
* BFR-FSMED-006 — two-way feature / journey catalog ↔ test-evidence validator + coverage report.
|
|
4
|
+
*
|
|
5
|
+
* Findings (stable codes): `COV-CATALOG-UNREADABLE` · `COV-ZERO-DENOMINATOR` (an EMPTY catalog is never green) ·
|
|
6
|
+
* `COV-DUPLICATE-ID` · `COV-ENTRY-INVALID` · `COV-LINK-UNKNOWN` / `COV-LINK-ONE-WAY` (feature ↔ journey both ways) ·
|
|
7
|
+
* `COV-STATUS-COVERED-WITHOUT-EVIDENCE` · `COV-MISSING-EVIDENCE-UNEXPLAINED` · `COV-EVIDENCE-FILE-MISSING` ·
|
|
8
|
+
* `COV-EVIDENCE-ID-NOT-IN-FILE` · `COV-EVIDENCE-ID-PREFIX` · `COV-JOURNEY-EVIDENCE-AS-FEATURE` ·
|
|
9
|
+
* with discovered ids: `COV-EVIDENCE-ID-UNDISCOVERED` · `COV-EVIDENCE-ORPHAN`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function DyE2E_validateCoverageCatalog(options: DyE2E_CoverageCatalog_Options): DyE2E_CoverageReport_Interface;
|
|
12
|
+
/** Writes the report as JSON (creating the folder). */
|
|
13
|
+
export declare function DyE2E_writeCoverageReport(report: DyE2E_CoverageReport_Interface, reportPath: string): void;
|
|
14
|
+
/**
|
|
15
|
+
* Collects the test ids that really exist: every `idPattern` match in the `*.spec.ts` / `*.test.ts` files under
|
|
16
|
+
* `roots` (the ids live in the test titles). Sorted, unique.
|
|
17
|
+
*/
|
|
18
|
+
export declare function DyE2E_discoverTestIds(set: {
|
|
19
|
+
roots: string[];
|
|
20
|
+
idPattern: RegExp;
|
|
21
|
+
}): string[];
|
|
22
|
+
//# sourceMappingURL=coverage-catalog.util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage-catalog.util.d.ts","sourceRoot":"","sources":["../../../../src/_modules/coverage/_collections/coverage-catalog.util.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,6BAA6B,EAI7B,8BAA8B,EAC/B,MAAM,uCAAuC,CAAC;AAW/C;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,6BAA6B,GAAG,8BAA8B,CAgEpH;AAED,uDAAuD;AACvD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,8BAA8B,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAG1G;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,EAAE,CAqB3F"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.DyE2E_validateCoverageCatalog = DyE2E_validateCoverageCatalog;
|
|
27
|
+
exports.DyE2E_writeCoverageReport = DyE2E_writeCoverageReport;
|
|
28
|
+
exports.DyE2E_discoverTestIds = DyE2E_discoverTestIds;
|
|
29
|
+
const fs = __importStar(require("fs"));
|
|
30
|
+
const path = __importStar(require("path"));
|
|
31
|
+
/**
|
|
32
|
+
* BFR-FSMED-006 — two-way feature / journey catalog ↔ test-evidence validator + coverage report.
|
|
33
|
+
*
|
|
34
|
+
* Findings (stable codes): `COV-CATALOG-UNREADABLE` · `COV-ZERO-DENOMINATOR` (an EMPTY catalog is never green) ·
|
|
35
|
+
* `COV-DUPLICATE-ID` · `COV-ENTRY-INVALID` · `COV-LINK-UNKNOWN` / `COV-LINK-ONE-WAY` (feature ↔ journey both ways) ·
|
|
36
|
+
* `COV-STATUS-COVERED-WITHOUT-EVIDENCE` · `COV-MISSING-EVIDENCE-UNEXPLAINED` · `COV-EVIDENCE-FILE-MISSING` ·
|
|
37
|
+
* `COV-EVIDENCE-ID-NOT-IN-FILE` · `COV-EVIDENCE-ID-PREFIX` · `COV-JOURNEY-EVIDENCE-AS-FEATURE` ·
|
|
38
|
+
* with discovered ids: `COV-EVIDENCE-ID-UNDISCOVERED` · `COV-EVIDENCE-ORPHAN`.
|
|
39
|
+
*/
|
|
40
|
+
function DyE2E_validateCoverageCatalog(options) {
|
|
41
|
+
const findings = [];
|
|
42
|
+
const add = (code, ref, message) => {
|
|
43
|
+
findings.push({ code: code, ref: ref, message: message });
|
|
44
|
+
};
|
|
45
|
+
const features = readEntries(options.featureCatalogPath, 'features', add);
|
|
46
|
+
const journeys = readEntries(options.journeyCatalogPath, 'journeys', add);
|
|
47
|
+
const featureLayer = {
|
|
48
|
+
name: 'feature',
|
|
49
|
+
idOf: (entry) => entry.featureId ?? '',
|
|
50
|
+
linksOf: (entry) => entry.journeyIds ?? [],
|
|
51
|
+
catalogPath: options.featureCatalogPath,
|
|
52
|
+
idPrefix: options.featureIdPrefix,
|
|
53
|
+
};
|
|
54
|
+
const journeyLayer = {
|
|
55
|
+
name: 'journey',
|
|
56
|
+
idOf: (entry) => entry.journeyId ?? '',
|
|
57
|
+
linksOf: (entry) => entry.featureIds ?? [],
|
|
58
|
+
catalogPath: options.journeyCatalogPath,
|
|
59
|
+
idPrefix: options.journeyIdPrefix,
|
|
60
|
+
};
|
|
61
|
+
validateLayer(featureLayer, features, journeyLayer, journeys, options, add);
|
|
62
|
+
validateLayer(journeyLayer, journeys, featureLayer, features, options, add);
|
|
63
|
+
// Two-way evidence discovery: claimed-but-absent ids and present-but-unclaimed (orphan) ids
|
|
64
|
+
const claimed = [...features, ...journeys]
|
|
65
|
+
.flatMap((entry) => entry.evidenceTestIds ?? []);
|
|
66
|
+
let orphanEvidenceIds = [];
|
|
67
|
+
let undiscoveredEvidenceIds = [];
|
|
68
|
+
if (options.discoveredTestIds) {
|
|
69
|
+
const discovered = new Set(options.discoveredTestIds);
|
|
70
|
+
const claimedSet = new Set(claimed);
|
|
71
|
+
undiscoveredEvidenceIds = [...claimedSet].filter((id) => !discovered.has(id)).sort();
|
|
72
|
+
orphanEvidenceIds = [...discovered].filter((id) => !claimedSet.has(id)).sort();
|
|
73
|
+
undiscoveredEvidenceIds.forEach((id) => add('COV-EVIDENCE-ID-UNDISCOVERED', id, `claimed evidence id '${id}' does not exist among the discovered tests`));
|
|
74
|
+
orphanEvidenceIds.forEach((id) => add('COV-EVIDENCE-ORPHAN', id, `test id '${id}' exists but no catalog entry claims it`));
|
|
75
|
+
}
|
|
76
|
+
const featureReport = layerReport(features, featureLayer);
|
|
77
|
+
const journeyReport = layerReport(journeys, journeyLayer);
|
|
78
|
+
const structurallyValid = !findings.length;
|
|
79
|
+
return {
|
|
80
|
+
schema: 'dye2e-coverage-report/1',
|
|
81
|
+
generatedAt: new Date().toISOString(),
|
|
82
|
+
features: featureReport,
|
|
83
|
+
journeys: journeyReport,
|
|
84
|
+
orphanEvidenceIds: orphanEvidenceIds,
|
|
85
|
+
undiscoveredEvidenceIds: undiscoveredEvidenceIds,
|
|
86
|
+
structurallyValid: structurallyValid,
|
|
87
|
+
releaseReady: structurallyValid
|
|
88
|
+
&& featureReport.denominator > 0 && journeyReport.denominator > 0
|
|
89
|
+
&& featureReport.covered.length === featureReport.denominator
|
|
90
|
+
&& journeyReport.covered.length === journeyReport.denominator,
|
|
91
|
+
findings: findings,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** Writes the report as JSON (creating the folder). */
|
|
95
|
+
function DyE2E_writeCoverageReport(report, reportPath) {
|
|
96
|
+
fs.mkdirSync(path.dirname(reportPath), { recursive: true });
|
|
97
|
+
fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Collects the test ids that really exist: every `idPattern` match in the `*.spec.ts` / `*.test.ts` files under
|
|
101
|
+
* `roots` (the ids live in the test titles). Sorted, unique.
|
|
102
|
+
*/
|
|
103
|
+
function DyE2E_discoverTestIds(set) {
|
|
104
|
+
const flags = set.idPattern.flags.includes('g') ? set.idPattern.flags : `${set.idPattern.flags}g`;
|
|
105
|
+
const pattern = new RegExp(set.idPattern.source, flags);
|
|
106
|
+
const ids = new Set();
|
|
107
|
+
const walk = (dir) => {
|
|
108
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
109
|
+
const full = path.join(dir, entry.name);
|
|
110
|
+
if (entry.isDirectory() && entry.name !== 'node_modules') {
|
|
111
|
+
walk(full);
|
|
112
|
+
}
|
|
113
|
+
else if (entry.isFile() && /\.(spec|test)\.[cm]?[jt]s$/.test(entry.name)) {
|
|
114
|
+
for (const match of fs.readFileSync(full, 'utf-8').matchAll(pattern)) {
|
|
115
|
+
ids.add(match[0]);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
set.roots.filter((root) => fs.existsSync(root)).forEach(walk);
|
|
121
|
+
return [...ids].sort();
|
|
122
|
+
}
|
|
123
|
+
/** Reads `features` / `journeys` from a catalog file; an unreadable file is a finding (never an empty-but-green list). */
|
|
124
|
+
function readEntries(catalogPath, key, add) {
|
|
125
|
+
try {
|
|
126
|
+
const catalog = JSON.parse(fs.readFileSync(catalogPath, 'utf-8'));
|
|
127
|
+
const entries = catalog?.[key];
|
|
128
|
+
if (!Array.isArray(entries)) {
|
|
129
|
+
throw new Error(`"${key}" array missing`);
|
|
130
|
+
}
|
|
131
|
+
return entries;
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
add('COV-CATALOG-UNREADABLE', catalogPath, `${key} catalog unreadable: ${err instanceof Error ? err.message : String(err)}`);
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/** Validates one layer against the other (links both ways) and its own evidence. */
|
|
139
|
+
function validateLayer(layer, entries, other, otherEntries, options, add) {
|
|
140
|
+
if (!entries.length) {
|
|
141
|
+
add('COV-ZERO-DENOMINATOR', layer.catalogPath, `the ${layer.name} catalog is empty — an empty catalog is never covered`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const seen = new Set();
|
|
145
|
+
const otherById = new Map(otherEntries
|
|
146
|
+
.map((entry) => [other.idOf(entry), entry]));
|
|
147
|
+
entries.forEach((entry, index) => {
|
|
148
|
+
const id = layer.idOf(entry);
|
|
149
|
+
const ref = id || `${layer.name}s[${index}]`;
|
|
150
|
+
if (!id || !Array.isArray(entry.evidenceTestIds) || !Array.isArray(entry.evidenceFiles)
|
|
151
|
+
|| typeof entry.coverageStatus !== 'string' || !entry.coverageStatus) {
|
|
152
|
+
add('COV-ENTRY-INVALID', ref, `${layer.name} needs ${layer.name}Id, evidenceTestIds[], evidenceFiles[] and a coverageStatus`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (seen.has(id)) {
|
|
156
|
+
add('COV-DUPLICATE-ID', id, `duplicate ${layer.name} id '${id}'`);
|
|
157
|
+
}
|
|
158
|
+
seen.add(id);
|
|
159
|
+
// Feature ↔ journey links, both ways
|
|
160
|
+
layer.linksOf(entry).forEach((linkedId) => {
|
|
161
|
+
const linked = otherById.get(linkedId);
|
|
162
|
+
if (!linked) {
|
|
163
|
+
add('COV-LINK-UNKNOWN', id, `${layer.name} '${id}' links an unknown ${other.name} '${linkedId}'`);
|
|
164
|
+
}
|
|
165
|
+
else if (!other.linksOf(linked).includes(id)) {
|
|
166
|
+
add('COV-LINK-ONE-WAY', id, `${other.name} '${linkedId}' does not link back to ${layer.name} '${id}'`);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
// Status ↔ evidence consistency
|
|
170
|
+
if (entry.coverageStatus === 'covered' && (!entry.evidenceTestIds.length || !entry.evidenceFiles.length)) {
|
|
171
|
+
add('COV-STATUS-COVERED-WITHOUT-EVIDENCE', id, `'${id}' is covered without evidenceTestIds / evidenceFiles`);
|
|
172
|
+
}
|
|
173
|
+
if (entry.coverageStatus !== 'covered' && !entry.missingEvidence?.trim()) {
|
|
174
|
+
add('COV-MISSING-EVIDENCE-UNEXPLAINED', id, `'${id}' is ${entry.coverageStatus} but missingEvidence is empty`);
|
|
175
|
+
}
|
|
176
|
+
validateEvidence(layer, entry, id, options, add);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
/** Evidence files exist; every claimed id appears in them, carries the layer prefix and stays in its layer. */
|
|
180
|
+
function validateEvidence(layer, entry, id, options, add) {
|
|
181
|
+
const catalogDir = path.dirname(layer.catalogPath);
|
|
182
|
+
const sources = [];
|
|
183
|
+
entry.evidenceFiles.forEach((file) => {
|
|
184
|
+
const absolute = path.resolve(catalogDir, file);
|
|
185
|
+
if (fs.existsSync(absolute)) {
|
|
186
|
+
sources.push(fs.readFileSync(absolute, 'utf-8'));
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
add('COV-EVIDENCE-FILE-MISSING', id, `evidence file does not exist: ${file}`);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
entry.evidenceTestIds.forEach((testId) => {
|
|
193
|
+
if (layer.idPrefix && !testId.startsWith(layer.idPrefix)) {
|
|
194
|
+
add('COV-EVIDENCE-ID-PREFIX', id, `evidence id '${testId}' must start with '${layer.idPrefix}'`);
|
|
195
|
+
}
|
|
196
|
+
// A journey test proves the journey layer — it can never be counted as per-feature evidence
|
|
197
|
+
if (layer.name === 'feature' && options.journeyIdPrefix && testId.startsWith(options.journeyIdPrefix)) {
|
|
198
|
+
add('COV-JOURNEY-EVIDENCE-AS-FEATURE', id, `journey evidence '${testId}' cannot count as feature evidence`);
|
|
199
|
+
}
|
|
200
|
+
if (!sources.some((source) => source.includes(testId))) {
|
|
201
|
+
add('COV-EVIDENCE-ID-NOT-IN-FILE', id, `evidence id '${testId}' is not in the declared evidence files`);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
/** Splits a layer's entries into covered / red / pending (ids). */
|
|
206
|
+
function layerReport(entries, layer) {
|
|
207
|
+
const ids = (status) => entries
|
|
208
|
+
.filter((entry) => status(entry.coverageStatus))
|
|
209
|
+
.map(layer.idOf);
|
|
210
|
+
return {
|
|
211
|
+
denominator: entries.length,
|
|
212
|
+
covered: ids((status) => status === 'covered'),
|
|
213
|
+
red: ids((status) => status === 'red'),
|
|
214
|
+
pending: ids((status) => status !== 'covered' && status !== 'red'),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=coverage-catalog.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage-catalog.util.js","sourceRoot":"","sources":["../../../../src/_modules/coverage/_collections/coverage-catalog.util.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BFR-FSMED-006 — the generic coverage-catalog schema (the common core of the fleet's feature / journey catalogs).
|
|
3
|
+
* Projects may carry more fields (requirement ids, sub-plans, variants …) — the validator ignores what it does not know,
|
|
4
|
+
* and the project keeps its own extra checks on top.
|
|
5
|
+
*/
|
|
6
|
+
/** One catalog entry (a feature or a journey). */
|
|
7
|
+
export interface DyE2E_CoverageCatalogEntry_Interface {
|
|
8
|
+
/** Feature: `featureId`; journey: `journeyId` — the validator reads whichever the layer uses. */
|
|
9
|
+
featureId?: string;
|
|
10
|
+
journeyId?: string;
|
|
11
|
+
title: string;
|
|
12
|
+
/** Feature → the journeys it takes part in; journey → the features it crosses (checked BOTH ways). */
|
|
13
|
+
journeyIds?: string[];
|
|
14
|
+
featureIds?: string[];
|
|
15
|
+
/** The test ids that prove this entry (they must appear in `evidenceFiles` and, if given, among the discovered ids). */
|
|
16
|
+
evidenceTestIds: string[];
|
|
17
|
+
/** Spec files holding the evidence, relative to the catalog file. */
|
|
18
|
+
evidenceFiles: string[];
|
|
19
|
+
/** `covered` (proven), `red` (evidence exists, but failing), anything else = pending (not proven yet). */
|
|
20
|
+
coverageStatus: string;
|
|
21
|
+
/** Required for every non-`covered` entry: what is missing. */
|
|
22
|
+
missingEvidence?: string;
|
|
23
|
+
}
|
|
24
|
+
/** A catalog file: `{ features: [] }` or `{ journeys: [] }` (extra top-level fields are allowed). */
|
|
25
|
+
export interface DyE2E_CoverageCatalog_Interface {
|
|
26
|
+
features?: DyE2E_CoverageCatalogEntry_Interface[];
|
|
27
|
+
journeys?: DyE2E_CoverageCatalogEntry_Interface[];
|
|
28
|
+
}
|
|
29
|
+
/** A validator finding — the `code` is stable (machine key), the message is for the human. */
|
|
30
|
+
export interface DyE2E_CoverageFinding_Interface {
|
|
31
|
+
code: string;
|
|
32
|
+
/** The entry id (or catalog) the finding is about. */
|
|
33
|
+
ref: string;
|
|
34
|
+
message: string;
|
|
35
|
+
}
|
|
36
|
+
/** Per-layer coverage (feature and journey are reported SEPARATELY — they are different denominators). */
|
|
37
|
+
export interface DyE2E_CoverageLayerReport_Interface {
|
|
38
|
+
denominator: number;
|
|
39
|
+
covered: string[];
|
|
40
|
+
red: string[];
|
|
41
|
+
pending: string[];
|
|
42
|
+
}
|
|
43
|
+
/** The coverage report (`DyE2E_writeCoverageReport` writes it as JSON). */
|
|
44
|
+
export interface DyE2E_CoverageReport_Interface {
|
|
45
|
+
schema: 'dye2e-coverage-report/1';
|
|
46
|
+
generatedAt: string;
|
|
47
|
+
features: DyE2E_CoverageLayerReport_Interface;
|
|
48
|
+
journeys: DyE2E_CoverageLayerReport_Interface;
|
|
49
|
+
/** Discovered test ids that no catalog entry claims (only when discovered ids were given). */
|
|
50
|
+
orphanEvidenceIds: string[];
|
|
51
|
+
/** Catalog evidence ids the discovery did not find (only when discovered ids were given). */
|
|
52
|
+
undiscoveredEvidenceIds: string[];
|
|
53
|
+
/** `true` when there is no finding. */
|
|
54
|
+
structurallyValid: boolean;
|
|
55
|
+
/** `true` only when structurally valid, both denominators are > 0 and EVERY entry is `covered`. */
|
|
56
|
+
releaseReady: boolean;
|
|
57
|
+
findings: DyE2E_CoverageFinding_Interface[];
|
|
58
|
+
}
|
|
59
|
+
/** The validator input. */
|
|
60
|
+
export interface DyE2E_CoverageCatalog_Options {
|
|
61
|
+
/** The feature catalog file (JSON with `features: []`). */
|
|
62
|
+
featureCatalogPath: string;
|
|
63
|
+
/** The journey catalog file (JSON with `journeys: []`). */
|
|
64
|
+
journeyCatalogPath: string;
|
|
65
|
+
/**
|
|
66
|
+
* The test ids that really exist (e.g. `DyE2E_discoverTestIds`). When given, the check is two-way: a claimed id
|
|
67
|
+
* that does not exist, and an existing id nobody claims (orphan), are both findings.
|
|
68
|
+
*/
|
|
69
|
+
discoveredTestIds?: string[];
|
|
70
|
+
/** Required prefix of feature evidence ids (e.g. `SMD-E2E-`). */
|
|
71
|
+
featureIdPrefix?: string;
|
|
72
|
+
/** Required prefix of journey evidence ids (e.g. `SMD-E2E-J-`); such ids may NOT count as feature evidence. */
|
|
73
|
+
journeyIdPrefix?: string;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=coverage-catalog.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage-catalog.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/coverage/_models/coverage-catalog.interface.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,kDAAkD;AAClD,MAAM,WAAW,oCAAoC;IACnD,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,sGAAsG;IACtG,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,wHAAwH;IACxH,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,qEAAqE;IACrE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,0GAA0G;IAC1G,cAAc,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qGAAqG;AACrG,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,EAAE,oCAAoC,EAAE,CAAC;IAClD,QAAQ,CAAC,EAAE,oCAAoC,EAAE,CAAC;CACnD;AAED,8FAA8F;AAC9F,MAAM,WAAW,+BAA+B;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,0GAA0G;AAC1G,MAAM,WAAW,mCAAmC;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,2EAA2E;AAC3E,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,yBAAyB,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,mCAAmC,CAAC;IAC9C,QAAQ,EAAE,mCAAmC,CAAC;IAC9C,8FAA8F;IAC9F,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,6FAA6F;IAC7F,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,uCAAuC;IACvC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,mGAAmG;IACnG,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,+BAA+B,EAAE,CAAC;CAC7C;AAED,2BAA2B;AAC3B,MAAM,WAAW,6BAA6B;IAC5C,2DAA2D;IAC3D,kBAAkB,EAAE,MAAM,CAAC;IAC3B,2DAA2D;IAC3D,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+GAA+G;IAC/G,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* BFR-FSMED-006 — the generic coverage-catalog schema (the common core of the fleet's feature / journey catalogs).
|
|
4
|
+
* Projects may carry more fields (requirement ids, sub-plans, variants …) — the validator ignores what it does not know,
|
|
5
|
+
* and the project keeps its own extra checks on top.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
//# sourceMappingURL=coverage-catalog.interface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage-catalog.interface.js","sourceRoot":"","sources":["../../../../src/_modules/coverage/_models/coverage-catalog.interface.ts"],"names":[],"mappings":";AAAA;;;;GAIG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/_modules/coverage/index.ts"],"names":[],"mappings":"AACA,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// BFR-FSMED-006 — feature / journey coverage catalog ↔ evidence validator + coverage report.
|
|
18
|
+
__exportStar(require("./_collections/coverage-catalog.util"), exports);
|
|
19
|
+
__exportStar(require("./_models/coverage-catalog.interface"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/_modules/coverage/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6FAA6F;AAC7F,uEAAqD;AACrD,uEAAqD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-runner.util.d.ts","sourceRoot":"","sources":["../../../../src/_modules/generators/_collections/cli-runner.util.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,qBAAa,oBAAoB;IAE/B,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE;IAsBpF,MAAM,CAAC,QAAQ,IAAI,MAAM;
|
|
1
|
+
{"version":3,"file":"cli-runner.util.d.ts","sourceRoot":"","sources":["../../../../src/_modules/generators/_collections/cli-runner.util.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,qBAAa,oBAAoB;IAE/B,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE;IAsBpF,MAAM,CAAC,QAAQ,IAAI,MAAM;IA4HzB;;;OAGG;IACH,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IA0D/C;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE;QAAE,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;QAAC,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;KAAE,GAAG;QAC9H,YAAY,EAAE,OAAO,CAAC;QACtB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,mBAAmB,EAAE,OAAO,CAAC;QAC7B,SAAS,EAAE,OAAO,CAAC;QACnB,aAAa,EAAE,OAAO,CAAC;QACvB,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB;IA2CD,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAI3C;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM;IAuB9D;;;OAGG;IACH,MAAM,CAAC,WAAW,CAChB,OAAO,EAAE,qBAAqB,GAAG,yBAAyB,GAAG,mBAAmB,EAChF,UAAU,EAAE,MAAM,GACjB,MAAM;CAaV"}
|
|
@@ -49,6 +49,7 @@ Commands:
|
|
|
49
49
|
diff Compare two CWV reports → regression analysis
|
|
50
50
|
info Show registered field-types + CLI capabilities
|
|
51
51
|
schema Print JSON Schema for a config type
|
|
52
|
+
validate-coverage-catalog Feature / journey catalog <-> test evidence (both ways) -> coverage report
|
|
52
53
|
validate-config Validate a config file against its JSON Schema
|
|
53
54
|
preset List built-in configs, or print one (--name)
|
|
54
55
|
version Print package version
|
|
@@ -57,9 +58,10 @@ Commands:
|
|
|
57
58
|
Visual QA (/vqa) commands:
|
|
58
59
|
validate-manifest Validate a VQA state-manifest JSON
|
|
59
60
|
validate-finding Validate a VQA finding JSON
|
|
60
|
-
generate-review-bundle Manifest -> review bundle (capture
|
|
61
|
+
generate-review-bundle Manifest -> review bundle (capture.spec.ts + its playwright.config.ts, README, summary)
|
|
61
62
|
generate-comparison-bundle Before/after capture sets -> comparison bundle
|
|
62
63
|
bundle-summary Print an existing bundle's summary.md
|
|
64
|
+
verify-review-bundle Aggregate release gate: evidence + findings + human review -> pass / fail + JSON
|
|
63
65
|
|
|
64
66
|
QA commands:
|
|
65
67
|
notification-sweep Login pages -> wrong-password submit -> notification / banner / leak matrix
|
|
@@ -78,6 +80,16 @@ Flags (notification-sweep):
|
|
|
78
80
|
--fail-on-leak Exit 1 if any page shows a raw technical leak
|
|
79
81
|
--executable-path <exe> Chromium to launch (or DYE2E_CHROMIUM_EXECUTABLE_PATH)
|
|
80
82
|
|
|
83
|
+
Flags (validate-coverage-catalog):
|
|
84
|
+
--features <path> Feature catalog JSON ({ features: [] }) (required)
|
|
85
|
+
--journeys <path> Journey catalog JSON ({ journeys: [] }) (required)
|
|
86
|
+
--scan <dir,..> Spec roots to discover the real test ids in (two-way check: undiscovered + orphan)
|
|
87
|
+
--id-pattern <regex> Test-id pattern for --scan (e.g. SMD-E2E-[A-Z0-9-]+)
|
|
88
|
+
--feature-prefix <p> Required feature evidence-id prefix
|
|
89
|
+
--journey-prefix <p> Journey evidence-id prefix (never counts as feature evidence)
|
|
90
|
+
--report <path> Write the JSON coverage report
|
|
91
|
+
--require-complete Exit 1 unless EVERY feature and journey is covered (release mode)
|
|
92
|
+
|
|
81
93
|
Flags (preset):
|
|
82
94
|
--name <preset> Print this preset as JSON (omit to list all)
|
|
83
95
|
|
|
@@ -98,6 +110,13 @@ Flags (generate-comparison-bundle):
|
|
|
98
110
|
Flags (bundle-summary):
|
|
99
111
|
--bundle <path> Bundle dir containing manifest.json + summary.md
|
|
100
112
|
|
|
113
|
+
Flags (verify-review-bundle):
|
|
114
|
+
--bundle <path> Review bundle dir (required)
|
|
115
|
+
--findings <path> Finding-set JSON (default: <bundle>/findings/findings.json)
|
|
116
|
+
--human-review <path> { reviewer, reviewedAt, verdict } (default: <bundle>/human-review.json)
|
|
117
|
+
--report <path> Write the JSON gate report here
|
|
118
|
+
--fail-on <a,b> missing,orphan,invalid,blocker,high,human-review (default: all)
|
|
119
|
+
|
|
101
120
|
Flags (generate-form-suite):
|
|
102
121
|
--config <path> Path to JSON config (formSettings, formRoute, ...)
|
|
103
122
|
--out <path> Output spec.ts path
|