@anselmdk/feature-spec-md 0.1.0 → 0.1.1
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 +34 -0
- package/SPEC_FORMAT.md +5 -0
- package/dist/cli.js +14 -4
- package/dist/cli.js.map +1 -1
- package/dist/filePatterns.d.ts +5 -0
- package/dist/filePatterns.d.ts.map +1 -0
- package/dist/filePatterns.js +24 -0
- package/dist/filePatterns.js.map +1 -0
- package/dist/html.d.ts +2 -0
- package/dist/html.d.ts.map +1 -0
- package/dist/html.js +9 -0
- package/dist/html.js.map +1 -0
- package/dist/index.d.ts +14 -69
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +95 -43
- package/dist/index.js.map +1 -1
- package/dist/playwright.d.ts +45 -0
- package/dist/playwright.d.ts.map +1 -0
- package/dist/playwright.js +109 -0
- package/dist/playwright.js.map +1 -0
- package/dist/reportTemplate.d.ts +11 -0
- package/dist/reportTemplate.d.ts.map +1 -0
- package/dist/reportTemplate.js +124 -0
- package/dist/reportTemplate.js.map +1 -0
- package/dist/screenshots.d.ts +6 -0
- package/dist/screenshots.d.ts.map +1 -0
- package/dist/screenshots.js +49 -0
- package/dist/screenshots.js.map +1 -0
- package/dist/types.d.ts +81 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +15 -3
package/README.md
CHANGED
|
@@ -31,6 +31,24 @@ See `SPEC_FORMAT.md` and `examples/account-access.feature.md`.
|
|
|
31
31
|
npm install
|
|
32
32
|
npm run dev -- check --specs "examples/**/*.feature.md" --tests "tests/**/*.test.ts" --require-scenario-coverage=false
|
|
33
33
|
npm run dev -- report --specs "examples/**/*.feature.md" --tests "tests/**/*.test.ts"
|
|
34
|
+
npm run dev -- report --specs "examples/**/*.feature.md" --tests "tests/**/*.test.ts" --screenshots "test-results/spec-report/screenshots-*.json"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Playwright screenshot evidence can be shown in the report by passing one or
|
|
38
|
+
more screenshot manifest JSON files. Each screenshot should point at the spec
|
|
39
|
+
file and line it proves:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"screenshots": [
|
|
44
|
+
{
|
|
45
|
+
"specPath": "specs/account-access.feature.md",
|
|
46
|
+
"line": 24,
|
|
47
|
+
"path": "screenshots/account-s001-line-24.png",
|
|
48
|
+
"title": "ACCOUNT-S001:24 Given a registered person is on the sign-in page"
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
34
52
|
```
|
|
35
53
|
|
|
36
54
|
## Library API
|
|
@@ -52,3 +70,19 @@ npm test
|
|
|
52
70
|
npm run typecheck
|
|
53
71
|
npm run build
|
|
54
72
|
```
|
|
73
|
+
|
|
74
|
+
## Releases
|
|
75
|
+
|
|
76
|
+
Stable releases are published to npm by the `Publish to npm` GitHub Actions workflow when a `v*` tag is pushed, or when the workflow is run manually.
|
|
77
|
+
|
|
78
|
+
Release candidates are published manually from GitHub Actions:
|
|
79
|
+
|
|
80
|
+
1. Open the `Publish RC to npm` workflow.
|
|
81
|
+
2. Run the workflow from `main`.
|
|
82
|
+
3. The workflow verifies the package, creates a prerelease version using the current package version and GitHub run number, and publishes it with the npm `rc` dist-tag.
|
|
83
|
+
|
|
84
|
+
Install the latest release candidate with:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npm install @anselmdk/feature-spec-md@rc
|
|
88
|
+
```
|
package/SPEC_FORMAT.md
CHANGED
|
@@ -103,3 +103,8 @@ Generated tooling can then answer:
|
|
|
103
103
|
- Which rules have executable coverage?
|
|
104
104
|
- Which tests reference deleted or unknown spec IDs?
|
|
105
105
|
- Which visible flows have screenshots, traces, or other evidence?
|
|
106
|
+
|
|
107
|
+
For Playwright tests, capture one screenshot for each scenario step line in the
|
|
108
|
+
spec. Report manifests associate each screenshot with the exact spec file and
|
|
109
|
+
line number, so the HTML report can display the evidence beside the
|
|
110
|
+
Given / When / Then / And line it proves.
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { checkFeatureSpecs, renderHtmlReport, writeTextFile } from "./index.js";
|
|
4
|
+
import { checkFeatureSpecs, collectSpecScreenshots, renderHtmlReport, writeTextFile, } from "./index.js";
|
|
5
5
|
const defaultSpecPattern = "specs/**/*.feature.md";
|
|
6
6
|
const defaultTestPattern = "tests/**/*.spec.ts";
|
|
7
7
|
main().catch((error) => {
|
|
@@ -42,8 +42,12 @@ async function runReport(options) {
|
|
|
42
42
|
requireScenarioCoverage: false,
|
|
43
43
|
});
|
|
44
44
|
const out = options.out ?? "test-results/feature-spec-report/index.html";
|
|
45
|
+
const screenshots = options.screenshots
|
|
46
|
+
? await collectSpecScreenshots(optionList(options.screenshots, ""))
|
|
47
|
+
: [];
|
|
45
48
|
await writeTextFile(out, renderHtmlReport(result.specs, {
|
|
46
49
|
coverage: result.coverage,
|
|
50
|
+
screenshots,
|
|
47
51
|
validationIssues: [...result.validationIssues, ...result.coverageIssues],
|
|
48
52
|
}));
|
|
49
53
|
console.log(`Feature spec report written to ${out}`);
|
|
@@ -77,11 +81,16 @@ function parseArgs(args) {
|
|
|
77
81
|
return options;
|
|
78
82
|
}
|
|
79
83
|
function optionList(value, fallback) {
|
|
80
|
-
return (value ?? fallback)
|
|
84
|
+
return (value ?? fallback)
|
|
85
|
+
.split(",")
|
|
86
|
+
.map((item) => item.trim())
|
|
87
|
+
.filter(Boolean);
|
|
81
88
|
}
|
|
82
89
|
function printIssues(issues) {
|
|
83
90
|
for (const issue of issues) {
|
|
84
|
-
const location = issue.filePath
|
|
91
|
+
const location = issue.filePath
|
|
92
|
+
? `${issue.filePath}${issue.line ? `:${issue.line}` : ""}`
|
|
93
|
+
: "";
|
|
85
94
|
console.error(`${issue.severity.toUpperCase()} ${issue.code}${location ? ` ${location}` : ""}: ${issue.message}`);
|
|
86
95
|
}
|
|
87
96
|
}
|
|
@@ -91,11 +100,12 @@ function printHelp() {
|
|
|
91
100
|
Usage:
|
|
92
101
|
feature-spec-md init [--dir specs]
|
|
93
102
|
feature-spec-md check [--specs "specs/**/*.feature.md"] [--tests "tests/**/*.spec.ts"]
|
|
94
|
-
feature-spec-md report [--specs "specs/**/*.feature.md"] [--tests "tests/**/*.spec.ts"] [--out test-results/feature-spec-report/index.html]
|
|
103
|
+
feature-spec-md report [--specs "specs/**/*.feature.md"] [--tests "tests/**/*.spec.ts"] [--screenshots "test-results/spec-report/screenshots.json"] [--out test-results/feature-spec-report/index.html]
|
|
95
104
|
|
|
96
105
|
Options:
|
|
97
106
|
--require-rule-coverage Fail when rules have no matching test references.
|
|
98
107
|
--require-scenario-coverage Defaults to true for check. Use --require-scenario-coverage=false to disable.
|
|
108
|
+
--screenshots Screenshot manifest JSON glob for report evidence.
|
|
99
109
|
--tests "" Disable test coverage lookup.
|
|
100
110
|
`);
|
|
101
111
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Expand user-provided source globs while ignoring generated directories. */
|
|
2
|
+
export declare function expandFilePatterns(patterns: string[]): Promise<string[]>;
|
|
3
|
+
/** Expand report artifact globs, including files under `test-results`. */
|
|
4
|
+
export declare function expandArtifactPatterns(patterns: string[]): Promise<string[]>;
|
|
5
|
+
//# sourceMappingURL=filePatterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filePatterns.d.ts","sourceRoot":"","sources":["../src/filePatterns.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,qBAO1D;AAED,0EAA0E;AAC1E,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,qBAE9D"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { glob } from "node:fs/promises";
|
|
2
|
+
/** Expand user-provided source globs while ignoring generated directories. */
|
|
3
|
+
export async function expandFilePatterns(patterns) {
|
|
4
|
+
return expandPatterns(patterns, [
|
|
5
|
+
"node_modules/**",
|
|
6
|
+
".git/**",
|
|
7
|
+
"dist/**",
|
|
8
|
+
"test-results/**",
|
|
9
|
+
]);
|
|
10
|
+
}
|
|
11
|
+
/** Expand report artifact globs, including files under `test-results`. */
|
|
12
|
+
export async function expandArtifactPatterns(patterns) {
|
|
13
|
+
return expandPatterns(patterns, ["node_modules/**", ".git/**", "dist/**"]);
|
|
14
|
+
}
|
|
15
|
+
async function expandPatterns(patterns, exclude) {
|
|
16
|
+
const files = new Set();
|
|
17
|
+
for (const pattern of patterns) {
|
|
18
|
+
for await (const file of glob(pattern, { exclude })) {
|
|
19
|
+
files.add(file);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return Array.from(files).sort();
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=filePatterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filePatterns.js","sourceRoot":"","sources":["../src/filePatterns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAkB;IACzD,OAAO,cAAc,CAAC,QAAQ,EAAE;QAC9B,iBAAiB;QACjB,SAAS;QACT,SAAS;QACT,iBAAiB;KAClB,CAAC,CAAC;AACL,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,QAAkB;IAC7D,OAAO,cAAc,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,QAAkB,EAAE,OAAiB;IACjE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;YACpD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;AAClC,CAAC"}
|
package/dist/html.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AAAA,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,UAOjC"}
|
package/dist/html.js
ADDED
package/dist/html.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.js","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,IAAI,CAAC,KAAa;IAChC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC;SACxB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,77 +1,28 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
scenarios: FeatureScenario[];
|
|
8
|
-
source: string;
|
|
9
|
-
};
|
|
10
|
-
export type FeatureFrontmatter = {
|
|
11
|
-
id: string;
|
|
12
|
-
title: string;
|
|
13
|
-
status?: "draft" | "active" | "deprecated";
|
|
14
|
-
owner?: string;
|
|
15
|
-
};
|
|
16
|
-
export type FeatureRule = {
|
|
17
|
-
id: string;
|
|
18
|
-
text: string;
|
|
19
|
-
keyword?: RuleKeyword;
|
|
20
|
-
strength: "required" | "recommended" | "optional" | "unspecified";
|
|
21
|
-
line: number;
|
|
22
|
-
};
|
|
23
|
-
export type FeatureScenario = {
|
|
24
|
-
id: string;
|
|
25
|
-
title: string;
|
|
26
|
-
line: number;
|
|
27
|
-
steps: Array<{
|
|
28
|
-
keyword: StepKeyword;
|
|
29
|
-
text: string;
|
|
30
|
-
line: number;
|
|
31
|
-
}>;
|
|
32
|
-
};
|
|
33
|
-
export type RuleKeyword = "MUST" | "MUST NOT" | "SHOULD" | "SHOULD NOT" | "MAY" | "OPTIONAL";
|
|
34
|
-
export type StepKeyword = "Given" | "When" | "Then" | "And" | "But";
|
|
35
|
-
export type ValidationIssue = {
|
|
36
|
-
code: string;
|
|
37
|
-
severity: "error" | "warning";
|
|
38
|
-
message: string;
|
|
39
|
-
filePath?: string;
|
|
40
|
-
line?: number;
|
|
41
|
-
};
|
|
42
|
-
export type TestReference = {
|
|
43
|
-
id: string;
|
|
44
|
-
filePath: string;
|
|
45
|
-
line: number;
|
|
46
|
-
kind: "scenario" | "rule";
|
|
47
|
-
source: "title" | "tag" | "covers" | "annotation" | "free-text";
|
|
48
|
-
};
|
|
49
|
-
export type CoverageItem = {
|
|
50
|
-
id: string;
|
|
51
|
-
title?: string;
|
|
52
|
-
filePath?: string;
|
|
53
|
-
line?: number;
|
|
54
|
-
covered: boolean;
|
|
55
|
-
references: TestReference[];
|
|
56
|
-
};
|
|
57
|
-
export type CoverageSummary = {
|
|
58
|
-
scenarioCoverage: CoverageItem[];
|
|
59
|
-
ruleCoverage: CoverageItem[];
|
|
60
|
-
orphanScenarioReferences: TestReference[];
|
|
61
|
-
orphanRuleReferences: TestReference[];
|
|
62
|
-
};
|
|
1
|
+
export { expandFilePatterns } from "./filePatterns.js";
|
|
2
|
+
export { renderHtmlReport } from "./reportTemplate.js";
|
|
3
|
+
export { collectSpecScreenshots } from "./screenshots.js";
|
|
4
|
+
export type { CoverageItem, CoverageSummary, FeatureFrontmatter, FeatureRule, FeatureScenario, FeatureSpec, FeatureStep, RuleKeyword, SpecScreenshot, StepKeyword, TestReference, ValidationIssue, } from "./types.js";
|
|
5
|
+
import type { CoverageSummary, FeatureSpec, TestReference, ValidationIssue } from "./types.js";
|
|
6
|
+
/** Parse one feature spec Markdown document into structured metadata, rules, and scenarios. */
|
|
63
7
|
export declare function parseFeatureSpec(source: string, options?: {
|
|
64
8
|
filePath?: string;
|
|
65
9
|
}): FeatureSpec;
|
|
10
|
+
/** Validate spec structure, ID prefixes, duplicate IDs, and required sections. */
|
|
66
11
|
export declare function validateFeatureSpec(spec: FeatureSpec): ValidationIssue[];
|
|
12
|
+
/** Find rule and scenario IDs referenced by one test source file. */
|
|
67
13
|
export declare function parseTestReferences(source: string, filePath?: string): TestReference[];
|
|
14
|
+
/** Expand test file globs and collect all rule and scenario references from them. */
|
|
68
15
|
export declare function collectTestReferences(patterns: string[]): Promise<TestReference[]>;
|
|
16
|
+
/** Build rule and scenario coverage from parsed specs and collected test references. */
|
|
69
17
|
export declare function buildCoverageSummary(specs: FeatureSpec[], references: TestReference[]): CoverageSummary;
|
|
18
|
+
/** Validate coverage expectations and orphaned references. */
|
|
70
19
|
export declare function validateCoverage(coverage: CoverageSummary, options?: {
|
|
71
20
|
requireRuleCoverage?: boolean;
|
|
72
21
|
requireScenarioCoverage?: boolean;
|
|
73
22
|
}): ValidationIssue[];
|
|
23
|
+
/** Load and parse all feature specs matching the provided globs. */
|
|
74
24
|
export declare function loadFeatureSpecs(patterns: string[]): Promise<FeatureSpec[]>;
|
|
25
|
+
/** Run spec validation and optional test coverage validation in one call. */
|
|
75
26
|
export declare function checkFeatureSpecs(options: {
|
|
76
27
|
specs: string[];
|
|
77
28
|
tests?: string[];
|
|
@@ -84,12 +35,6 @@ export declare function checkFeatureSpecs(options: {
|
|
|
84
35
|
coverageIssues: ValidationIssue[];
|
|
85
36
|
ok: boolean;
|
|
86
37
|
}>;
|
|
87
|
-
|
|
88
|
-
coverage?: CoverageSummary;
|
|
89
|
-
validationIssues?: ValidationIssue[];
|
|
90
|
-
title?: string;
|
|
91
|
-
generatedAt?: string;
|
|
92
|
-
}): string;
|
|
38
|
+
/** Write text content to a path, creating the parent directory when needed. */
|
|
93
39
|
export declare function writeTextFile(filePath: string, content: string): Promise<void>;
|
|
94
|
-
export declare function expandFilePatterns(patterns: string[]): Promise<string[]>;
|
|
95
40
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,YAAY,EACV,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,WAAW,EACX,WAAW,EACX,WAAW,EACX,cAAc,EACd,WAAW,EACX,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAEV,eAAe,EAIf,WAAW,EAGX,aAAa,EACb,eAAe,EAChB,MAAM,YAAY,CAAC;AAapB,+FAA+F;AAC/F,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,WAAW,CAuCb;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG,eAAe,EAAE,CA2GxE;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,QAAQ,SAAa,GACpB,aAAa,EAAE,CAyBjB;AAED,qFAAqF;AACrF,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,4BAM7D;AAED,wFAAwF;AACxF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,EAAE,EACpB,UAAU,EAAE,aAAa,EAAE,GAC1B,eAAe,CAkCjB;AAED,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,eAAe,EACzB,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;CAC9B,qBAmDP;AAED,oEAAoE;AACpE,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,0BAQxD;AAED,6EAA6E;AAC7E,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;;;;;;GAsBA;AAED,+EAA+E;AAC/E,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,iBAGpE"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { expandFilePatterns } from "./filePatterns.js";
|
|
4
|
+
export { expandFilePatterns } from "./filePatterns.js";
|
|
5
|
+
export { renderHtmlReport } from "./reportTemplate.js";
|
|
6
|
+
export { collectSpecScreenshots } from "./screenshots.js";
|
|
3
7
|
const scenarioIdPattern = /\b[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*-S\d{3}\b/g;
|
|
4
8
|
const ruleIdPattern = /\b[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*-R\d{3}\b/g;
|
|
5
|
-
const ruleKeywords = [
|
|
9
|
+
const ruleKeywords = [
|
|
10
|
+
"MUST NOT",
|
|
11
|
+
"SHOULD NOT",
|
|
12
|
+
"MUST",
|
|
13
|
+
"SHOULD",
|
|
14
|
+
"MAY",
|
|
15
|
+
"OPTIONAL",
|
|
16
|
+
];
|
|
17
|
+
/** Parse one feature spec Markdown document into structured metadata, rules, and scenarios. */
|
|
6
18
|
export function parseFeatureSpec(source, options = {}) {
|
|
7
19
|
const filePath = options.filePath ?? "<inline>";
|
|
8
20
|
const normalized = source.replace(/\r\n/g, "\n");
|
|
@@ -23,13 +35,17 @@ export function parseFeatureSpec(source, options = {}) {
|
|
|
23
35
|
return {
|
|
24
36
|
filePath,
|
|
25
37
|
frontmatter: frontmatter,
|
|
26
|
-
title: lines
|
|
38
|
+
title: lines
|
|
39
|
+
.find((line) => line.startsWith("# "))
|
|
40
|
+
?.replace(/^#\s+/, "")
|
|
41
|
+
.trim() ?? frontmatter.title,
|
|
27
42
|
purpose: sectionText(lines, "Purpose").trim(),
|
|
28
43
|
rules: parseRules(lines, bodyStartLine),
|
|
29
44
|
scenarios: parseScenarios(lines, bodyStartLine),
|
|
30
45
|
source,
|
|
31
46
|
};
|
|
32
47
|
}
|
|
48
|
+
/** Validate spec structure, ID prefixes, duplicate IDs, and required sections. */
|
|
33
49
|
export function validateFeatureSpec(spec) {
|
|
34
50
|
const issues = [];
|
|
35
51
|
const seen = new Map();
|
|
@@ -67,6 +83,7 @@ export function validateFeatureSpec(spec) {
|
|
|
67
83
|
}
|
|
68
84
|
return issues;
|
|
69
85
|
}
|
|
86
|
+
/** Find rule and scenario IDs referenced by one test source file. */
|
|
70
87
|
export function parseTestReferences(source, filePath = "<inline>") {
|
|
71
88
|
const lines = source.split(/\r?\n/);
|
|
72
89
|
const refs = [];
|
|
@@ -90,6 +107,7 @@ export function parseTestReferences(source, filePath = "<inline>") {
|
|
|
90
107
|
}
|
|
91
108
|
return dedupe(refs);
|
|
92
109
|
}
|
|
110
|
+
/** Expand test file globs and collect all rule and scenario references from them. */
|
|
93
111
|
export async function collectTestReferences(patterns) {
|
|
94
112
|
const refs = [];
|
|
95
113
|
for (const file of await expandFilePatterns(patterns)) {
|
|
@@ -97,6 +115,7 @@ export async function collectTestReferences(patterns) {
|
|
|
97
115
|
}
|
|
98
116
|
return refs;
|
|
99
117
|
}
|
|
118
|
+
/** Build rule and scenario coverage from parsed specs and collected test references. */
|
|
100
119
|
export function buildCoverageSummary(specs, references) {
|
|
101
120
|
const scenarios = new Map(specs.flatMap((spec) => spec.scenarios.map((scenario) => [scenario.id, { spec, scenario }])));
|
|
102
121
|
const rules = new Map(specs.flatMap((spec) => spec.rules.map((rule) => [rule.id, { spec, rule }])));
|
|
@@ -109,26 +128,52 @@ export function buildCoverageSummary(specs, references) {
|
|
|
109
128
|
orphanRuleReferences: ruleRefs.filter((ref) => !rules.has(ref.id)),
|
|
110
129
|
};
|
|
111
130
|
}
|
|
131
|
+
/** Validate coverage expectations and orphaned references. */
|
|
112
132
|
export function validateCoverage(coverage, options = {}) {
|
|
113
133
|
const issues = [];
|
|
114
134
|
if (options.requireScenarioCoverage ?? true) {
|
|
115
135
|
for (const item of coverage.scenarioCoverage.filter((item) => !item.covered)) {
|
|
116
|
-
issues.push({
|
|
136
|
+
issues.push({
|
|
137
|
+
code: "missing-scenario-coverage",
|
|
138
|
+
severity: "error",
|
|
139
|
+
message: `Scenario "${item.id}" has no matching test reference.`,
|
|
140
|
+
filePath: item.filePath,
|
|
141
|
+
line: item.line,
|
|
142
|
+
});
|
|
117
143
|
}
|
|
118
144
|
}
|
|
119
145
|
if (options.requireRuleCoverage ?? false) {
|
|
120
146
|
for (const item of coverage.ruleCoverage.filter((item) => !item.covered)) {
|
|
121
|
-
issues.push({
|
|
147
|
+
issues.push({
|
|
148
|
+
code: "missing-rule-coverage",
|
|
149
|
+
severity: "error",
|
|
150
|
+
message: `Rule "${item.id}" has no matching test reference.`,
|
|
151
|
+
filePath: item.filePath,
|
|
152
|
+
line: item.line,
|
|
153
|
+
});
|
|
122
154
|
}
|
|
123
155
|
}
|
|
124
156
|
for (const ref of coverage.orphanScenarioReferences) {
|
|
125
|
-
issues.push({
|
|
157
|
+
issues.push({
|
|
158
|
+
code: "orphan-scenario-reference",
|
|
159
|
+
severity: "error",
|
|
160
|
+
message: `Test references unknown scenario "${ref.id}".`,
|
|
161
|
+
filePath: ref.filePath,
|
|
162
|
+
line: ref.line,
|
|
163
|
+
});
|
|
126
164
|
}
|
|
127
165
|
for (const ref of coverage.orphanRuleReferences) {
|
|
128
|
-
issues.push({
|
|
166
|
+
issues.push({
|
|
167
|
+
code: "orphan-rule-reference",
|
|
168
|
+
severity: "error",
|
|
169
|
+
message: `Test references unknown rule "${ref.id}".`,
|
|
170
|
+
filePath: ref.filePath,
|
|
171
|
+
line: ref.line,
|
|
172
|
+
});
|
|
129
173
|
}
|
|
130
174
|
return issues;
|
|
131
175
|
}
|
|
176
|
+
/** Load and parse all feature specs matching the provided globs. */
|
|
132
177
|
export async function loadFeatureSpecs(patterns) {
|
|
133
178
|
const specs = [];
|
|
134
179
|
for (const file of await expandFilePatterns(patterns)) {
|
|
@@ -136,11 +181,19 @@ export async function loadFeatureSpecs(patterns) {
|
|
|
136
181
|
}
|
|
137
182
|
return specs;
|
|
138
183
|
}
|
|
184
|
+
/** Run spec validation and optional test coverage validation in one call. */
|
|
139
185
|
export async function checkFeatureSpecs(options) {
|
|
140
186
|
const specs = await loadFeatureSpecs(options.specs);
|
|
141
187
|
const validationIssues = specs.flatMap(validateFeatureSpec);
|
|
142
|
-
const coverage = options.tests?.length
|
|
143
|
-
|
|
188
|
+
const coverage = options.tests?.length
|
|
189
|
+
? buildCoverageSummary(specs, await collectTestReferences(options.tests))
|
|
190
|
+
: undefined;
|
|
191
|
+
const coverageIssues = coverage
|
|
192
|
+
? validateCoverage(coverage, {
|
|
193
|
+
requireRuleCoverage: options.requireRuleCoverage,
|
|
194
|
+
requireScenarioCoverage: options.requireScenarioCoverage,
|
|
195
|
+
})
|
|
196
|
+
: [];
|
|
144
197
|
return {
|
|
145
198
|
specs,
|
|
146
199
|
validationIssues,
|
|
@@ -149,30 +202,20 @@ export async function checkFeatureSpecs(options) {
|
|
|
149
202
|
ok: ![...validationIssues, ...coverageIssues].some((i) => i.severity === "error"),
|
|
150
203
|
};
|
|
151
204
|
}
|
|
152
|
-
|
|
153
|
-
const title = options.title ?? "Feature Spec Report";
|
|
154
|
-
const issues = options.validationIssues ?? [];
|
|
155
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${html(title)}</title><style>body{font-family:system-ui,sans-serif;max-width:1100px;margin:0 auto;padding:40px 24px}.panel{border:1px solid #ddd;border-radius:16px;padding:20px;margin:18px 0}.ok{color:#1a7f37}.missing,.error{color:#cf222e}.warning{color:#9a6700}.badge{border:1px solid #ddd;border-radius:999px;padding:2px 8px;font-size:12px}</style></head><body><h1>${html(title)}</h1><p>Generated ${html(options.generatedAt ?? new Date().toISOString())}.</p>${renderIssues(issues)}${specs.map((spec) => renderSpec(spec, options.coverage)).join("")}</body></html>`;
|
|
156
|
-
}
|
|
205
|
+
/** Write text content to a path, creating the parent directory when needed. */
|
|
157
206
|
export async function writeTextFile(filePath, content) {
|
|
158
207
|
await mkdir(path.dirname(filePath), { recursive: true });
|
|
159
208
|
await writeFile(filePath, content, "utf8");
|
|
160
209
|
}
|
|
161
|
-
export async function expandFilePatterns(patterns) {
|
|
162
|
-
const files = new Set();
|
|
163
|
-
for (const pattern of patterns) {
|
|
164
|
-
for await (const file of glob(pattern, { exclude: ["node_modules/**", ".git/**", "dist/**", "test-results/**"] })) {
|
|
165
|
-
files.add(file);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return Array.from(files).sort();
|
|
169
|
-
}
|
|
170
210
|
function parseFrontmatter(source) {
|
|
171
211
|
const data = {};
|
|
172
212
|
for (const line of source.split("\n")) {
|
|
173
213
|
const match = line.match(/^([A-Za-z][A-Za-z0-9_-]*):\s*(.*)$/);
|
|
174
214
|
if (match)
|
|
175
|
-
data[match[1]] = match[2]
|
|
215
|
+
data[match[1]] = match[2]
|
|
216
|
+
.replace(/^[']|[']$/g, "")
|
|
217
|
+
.replace(/^["]|["]$/g, "")
|
|
218
|
+
.trim();
|
|
176
219
|
}
|
|
177
220
|
return data;
|
|
178
221
|
}
|
|
@@ -203,7 +246,13 @@ function parseRules(lines, bodyStartLine) {
|
|
|
203
246
|
if (!match)
|
|
204
247
|
continue;
|
|
205
248
|
const keyword = ruleKeywords.find((kw) => match[2].toUpperCase().includes(kw));
|
|
206
|
-
rules.push({
|
|
249
|
+
rules.push({
|
|
250
|
+
id: match[1],
|
|
251
|
+
text: match[2].trim(),
|
|
252
|
+
keyword,
|
|
253
|
+
strength: strength(keyword),
|
|
254
|
+
line: bodyStartLine + i,
|
|
255
|
+
});
|
|
207
256
|
}
|
|
208
257
|
return rules;
|
|
209
258
|
}
|
|
@@ -219,9 +268,18 @@ function parseScenarios(lines, bodyStartLine) {
|
|
|
219
268
|
break;
|
|
220
269
|
const step = lines[j].trim().match(/^(Given|When|Then|And|But)\s+(.+)$/);
|
|
221
270
|
if (step)
|
|
222
|
-
steps.push({
|
|
271
|
+
steps.push({
|
|
272
|
+
keyword: step[1],
|
|
273
|
+
text: step[2].trim(),
|
|
274
|
+
line: bodyStartLine + j,
|
|
275
|
+
});
|
|
223
276
|
}
|
|
224
|
-
scenarios.push({
|
|
277
|
+
scenarios.push({
|
|
278
|
+
id: match[1],
|
|
279
|
+
title: match[2].trim(),
|
|
280
|
+
line: bodyStartLine + i,
|
|
281
|
+
steps,
|
|
282
|
+
});
|
|
225
283
|
}
|
|
226
284
|
return scenarios;
|
|
227
285
|
}
|
|
@@ -245,7 +303,14 @@ function registerId(spec, issues, seen, id, line) {
|
|
|
245
303
|
}
|
|
246
304
|
function item(id, title, filePath, line, refs) {
|
|
247
305
|
const references = refs.filter((ref) => ref.id === id);
|
|
248
|
-
return {
|
|
306
|
+
return {
|
|
307
|
+
id,
|
|
308
|
+
title,
|
|
309
|
+
filePath,
|
|
310
|
+
line,
|
|
311
|
+
references,
|
|
312
|
+
covered: references.length > 0,
|
|
313
|
+
};
|
|
249
314
|
}
|
|
250
315
|
function lineForOffset(lines, offset) {
|
|
251
316
|
let consumed = 0;
|
|
@@ -261,7 +326,8 @@ function sourceForMatch(source, offset) {
|
|
|
261
326
|
const context = source.slice(Math.max(0, offset - 80), offset + 80);
|
|
262
327
|
if (/covers\s*:\s*\[[^\]]*$/.test(before))
|
|
263
328
|
return "covers";
|
|
264
|
-
if (/tag\s*:\s*\[[^\]]*$/.test(before) ||
|
|
329
|
+
if (/tag\s*:\s*\[[^\]]*$/.test(before) ||
|
|
330
|
+
/@/.test(source.slice(Math.max(0, offset - 2), offset + 2)))
|
|
265
331
|
return "tag";
|
|
266
332
|
if (/annotation/.test(context))
|
|
267
333
|
return "annotation";
|
|
@@ -279,18 +345,4 @@ function dedupe(refs) {
|
|
|
279
345
|
return true;
|
|
280
346
|
});
|
|
281
347
|
}
|
|
282
|
-
function renderIssues(issues) {
|
|
283
|
-
if (!issues.length)
|
|
284
|
-
return `<section class="panel"><h2>Validation</h2><p class="ok">No validation issues found.</p></section>`;
|
|
285
|
-
return `<section class="panel"><h2>Validation</h2><ul>${issues.map((i) => `<li class="${i.severity}"><code>${html(`${i.filePath ?? ""}${i.line ? `:${i.line}` : ""}`)}</code> ${html(i.message)}</li>`).join("")}</ul></section>`;
|
|
286
|
-
}
|
|
287
|
-
function renderSpec(spec, coverage) {
|
|
288
|
-
return `<section class="panel"><p><span class="badge">${html(spec.frontmatter.status ?? "draft")}</span></p><h2>${html(spec.frontmatter.id)} ${html(spec.title)}</h2><p>${html(spec.purpose)}</p><h3>Rules</h3><ul>${spec.rules.map((r) => `<li><code>${html(r.id)}</code>: ${html(r.text)} ${coverageBadge(coverage?.ruleCoverage.find((i) => i.id === r.id)?.covered)}</li>`).join("")}</ul><h3>Scenarios</h3>${spec.scenarios.map((s) => `<article class="panel"><h4><code>${html(s.id)}</code>: ${html(s.title)} ${coverageBadge(coverage?.scenarioCoverage.find((i) => i.id === s.id)?.covered)}</h4>${s.steps.map((step) => `<p><strong>${html(step.keyword)}</strong> ${html(step.text)}</p>`).join("")}</article>`).join("")}</section>`;
|
|
289
|
-
}
|
|
290
|
-
function coverageBadge(covered) {
|
|
291
|
-
return covered === undefined ? "" : covered ? `<span class="badge ok">covered</span>` : `<span class="badge missing">missing coverage</span>`;
|
|
292
|
-
}
|
|
293
|
-
function html(value) {
|
|
294
|
-
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
295
|
-
}
|
|
296
348
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { StepKeyword } from "./types.js";
|
|
2
|
+
export type SpecEvidenceStep = {
|
|
3
|
+
scenarioId: string;
|
|
4
|
+
specPath: string;
|
|
5
|
+
line: number;
|
|
6
|
+
keyword: StepKeyword;
|
|
7
|
+
text: string;
|
|
8
|
+
};
|
|
9
|
+
export type SpecEvidenceScreenshot = {
|
|
10
|
+
specPath: string;
|
|
11
|
+
line: number;
|
|
12
|
+
path: string;
|
|
13
|
+
title: string;
|
|
14
|
+
testPath: string;
|
|
15
|
+
};
|
|
16
|
+
export type PlaywrightSpecEvidenceOptions = {
|
|
17
|
+
specs: string[];
|
|
18
|
+
reportDir?: string;
|
|
19
|
+
screenshotsDirName?: string;
|
|
20
|
+
cwd?: string;
|
|
21
|
+
};
|
|
22
|
+
export type PlaywrightPageLike = {
|
|
23
|
+
screenshot(options: {
|
|
24
|
+
fullPage?: boolean;
|
|
25
|
+
path: string;
|
|
26
|
+
}): Promise<unknown>;
|
|
27
|
+
};
|
|
28
|
+
export type PlaywrightTestInfoLike = {
|
|
29
|
+
attach(name: string, options: {
|
|
30
|
+
contentType: string;
|
|
31
|
+
path: string;
|
|
32
|
+
}): Promise<unknown>;
|
|
33
|
+
file: string;
|
|
34
|
+
workerIndex: number;
|
|
35
|
+
};
|
|
36
|
+
export type PlaywrightTestLike = {
|
|
37
|
+
step<T>(title: string, body: () => Promise<T>): Promise<T>;
|
|
38
|
+
};
|
|
39
|
+
/** Create a Playwright helper that captures screenshot evidence for spec step lines. */
|
|
40
|
+
export declare function createPlaywrightSpecEvidence(test: PlaywrightTestLike, options: PlaywrightSpecEvidenceOptions): {
|
|
41
|
+
specStep(page: PlaywrightPageLike, testInfo: PlaywrightTestInfoLike, scenarioId: string, stepText: string, body: () => Promise<void>): Promise<void>;
|
|
42
|
+
};
|
|
43
|
+
/** Parse spec files and return all scenario step lines addressable by Playwright tests. */
|
|
44
|
+
export declare function loadSpecSteps(patterns: string[], cwd?: string): Promise<SpecEvidenceStep[]>;
|
|
45
|
+
//# sourceMappingURL=playwright.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright.d.ts","sourceRoot":"","sources":["../src/playwright.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7E,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,CACJ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAC7C,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC5D,CAAC;AAEF,wFAAwF;AACxF,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,6BAA6B;mBAc5B,kBAAkB,YACd,sBAAsB,cACpB,MAAM,YACR,MAAM,QACV,MAAM,OAAO,CAAC,IAAI,CAAC;EAiB9B;AAED,2FAA2F;AAC3F,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,GAAG,SAAgB,+BAuC1E"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { expandFilePatterns } from "./filePatterns.js";
|
|
4
|
+
/** Create a Playwright helper that captures screenshot evidence for spec step lines. */
|
|
5
|
+
export function createPlaywrightSpecEvidence(test, options) {
|
|
6
|
+
const cwd = options.cwd ?? process.cwd();
|
|
7
|
+
const reportDir = path.resolve(cwd, options.reportDir ?? "test-results/spec-report");
|
|
8
|
+
const screenshotsDirName = options.screenshotsDirName ?? "screenshots";
|
|
9
|
+
const screenshotDir = path.join(reportDir, screenshotsDirName);
|
|
10
|
+
const stepsPromise = loadSpecSteps(options.specs, cwd);
|
|
11
|
+
const entriesByWorker = new Map();
|
|
12
|
+
return {
|
|
13
|
+
async specStep(page, testInfo, scenarioId, stepText, body) {
|
|
14
|
+
const step = await findSpecStep(stepsPromise, scenarioId, stepText);
|
|
15
|
+
await test.step(`${step.keyword} ${step.text}`, async () => {
|
|
16
|
+
await body();
|
|
17
|
+
await captureStepScreenshot({
|
|
18
|
+
entriesByWorker,
|
|
19
|
+
page,
|
|
20
|
+
reportDir,
|
|
21
|
+
screenshotDir,
|
|
22
|
+
screenshotsDirName,
|
|
23
|
+
step,
|
|
24
|
+
testInfo,
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** Parse spec files and return all scenario step lines addressable by Playwright tests. */
|
|
31
|
+
export async function loadSpecSteps(patterns, cwd = process.cwd()) {
|
|
32
|
+
const previousCwd = process.cwd();
|
|
33
|
+
const steps = [];
|
|
34
|
+
try {
|
|
35
|
+
process.chdir(cwd);
|
|
36
|
+
for (const specPath of await expandFilePatterns(patterns)) {
|
|
37
|
+
const source = await readFile(path.resolve(cwd, specPath), "utf8");
|
|
38
|
+
let scenarioId = "";
|
|
39
|
+
for (const [index, line] of source
|
|
40
|
+
.replace(/\r\n/g, "\n")
|
|
41
|
+
.split("\n")
|
|
42
|
+
.entries()) {
|
|
43
|
+
const scenario = line.match(/^###\s+([A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*-S\d{3}):/);
|
|
44
|
+
if (scenario) {
|
|
45
|
+
scenarioId = scenario[1];
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const step = line.trim().match(/^(Given|When|Then|And|But)\s+(.+)$/);
|
|
49
|
+
if (scenarioId && step) {
|
|
50
|
+
steps.push({
|
|
51
|
+
scenarioId,
|
|
52
|
+
specPath,
|
|
53
|
+
line: index + 1,
|
|
54
|
+
keyword: step[1],
|
|
55
|
+
text: step[2].trim(),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
process.chdir(previousCwd);
|
|
63
|
+
}
|
|
64
|
+
return steps;
|
|
65
|
+
}
|
|
66
|
+
async function findSpecStep(stepsPromise, scenarioId, stepText) {
|
|
67
|
+
const steps = await stepsPromise;
|
|
68
|
+
const normalizedStepText = stepText.replace(/^(Given|When|Then|And|But)\s+/, "");
|
|
69
|
+
const step = steps.find((candidate) => candidate.scenarioId === scenarioId &&
|
|
70
|
+
candidate.text === normalizedStepText);
|
|
71
|
+
if (!step) {
|
|
72
|
+
throw new Error(`No spec step found for ${scenarioId}: ${stepText}`);
|
|
73
|
+
}
|
|
74
|
+
return step;
|
|
75
|
+
}
|
|
76
|
+
async function captureStepScreenshot(options) {
|
|
77
|
+
await mkdir(options.screenshotDir, { recursive: true });
|
|
78
|
+
const fileName = `${options.step.scenarioId}-line-${options.step.line}-${slug(options.step.text)}.png`;
|
|
79
|
+
const screenshotPath = path.join(options.screenshotDir, fileName);
|
|
80
|
+
const relativePath = `${options.screenshotsDirName}/${fileName}`;
|
|
81
|
+
const title = `${options.step.scenarioId}:${options.step.line} ${options.step.keyword} ${options.step.text}`;
|
|
82
|
+
await options.page.screenshot({ fullPage: true, path: screenshotPath });
|
|
83
|
+
await options.testInfo.attach(title, {
|
|
84
|
+
contentType: "image/png",
|
|
85
|
+
path: screenshotPath,
|
|
86
|
+
});
|
|
87
|
+
const entries = options.entriesByWorker.get(options.testInfo.workerIndex) ?? [];
|
|
88
|
+
entries.push({
|
|
89
|
+
specPath: options.step.specPath,
|
|
90
|
+
line: options.step.line,
|
|
91
|
+
path: relativePath,
|
|
92
|
+
title,
|
|
93
|
+
testPath: options.testInfo.file,
|
|
94
|
+
});
|
|
95
|
+
options.entriesByWorker.set(options.testInfo.workerIndex, entries);
|
|
96
|
+
await writeWorkerManifest(options.reportDir, options.testInfo.workerIndex, entries);
|
|
97
|
+
}
|
|
98
|
+
async function writeWorkerManifest(reportDir, workerIndex, screenshots) {
|
|
99
|
+
await mkdir(reportDir, { recursive: true });
|
|
100
|
+
await writeFile(path.join(reportDir, `screenshots-${workerIndex}.json`), JSON.stringify({ screenshots }, null, 2), "utf8");
|
|
101
|
+
}
|
|
102
|
+
function slug(value) {
|
|
103
|
+
return value
|
|
104
|
+
.toLowerCase()
|
|
105
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
106
|
+
.replace(/^-|-$/g, "")
|
|
107
|
+
.slice(0, 72);
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=playwright.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright.js","sourceRoot":"","sources":["../src/playwright.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CoverageSummary, FeatureSpec, SpecScreenshot, ValidationIssue } from "./types.js";
|
|
2
|
+
export type ReportOptions = {
|
|
3
|
+
coverage?: CoverageSummary;
|
|
4
|
+
screenshots?: SpecScreenshot[];
|
|
5
|
+
validationIssues?: ValidationIssue[];
|
|
6
|
+
title?: string;
|
|
7
|
+
generatedAt?: string;
|
|
8
|
+
};
|
|
9
|
+
/** Render a complete self-contained feature spec report as HTML. */
|
|
10
|
+
export declare function renderHtmlReport(specs: FeatureSpec[], options?: ReportOptions): string;
|
|
11
|
+
//# sourceMappingURL=reportTemplate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reportTemplate.d.ts","sourceRoot":"","sources":["../src/reportTemplate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,eAAe,EACf,WAAW,EAEX,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,oEAAoE;AACpE,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,WAAW,EAAE,EACpB,OAAO,GAAE,aAAkB,UAoC5B"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { html } from "./html.js";
|
|
2
|
+
import { screenshotKey } from "./screenshots.js";
|
|
3
|
+
/** Render a complete self-contained feature spec report as HTML. */
|
|
4
|
+
export function renderHtmlReport(specs, options = {}) {
|
|
5
|
+
const title = options.title ?? "Feature Spec Report";
|
|
6
|
+
const issues = options.validationIssues ?? [];
|
|
7
|
+
const screenshots = options.screenshots ?? [];
|
|
8
|
+
return `<!doctype html>
|
|
9
|
+
<html lang="en">
|
|
10
|
+
<head>
|
|
11
|
+
<meta charset="utf-8">
|
|
12
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
13
|
+
<title>${html(title)}</title>
|
|
14
|
+
<style>
|
|
15
|
+
body{font-family:system-ui,sans-serif;max-width:1180px;margin:0 auto;padding:40px 24px;color:#1f2328}
|
|
16
|
+
.panel{border:1px solid #d0d7de;border-radius:8px;padding:20px;margin:18px 0}
|
|
17
|
+
.ok{color:#1a7f37}.missing,.error{color:#cf222e}.warning{color:#9a6700}
|
|
18
|
+
.badge{border:1px solid #d0d7de;border-radius:999px;padding:2px 8px;font-size:12px;white-space:nowrap}
|
|
19
|
+
.feature-header{display:flex;gap:12px;align-items:center;justify-content:space-between}
|
|
20
|
+
.scenario{border:1px solid #d0d7de;border-radius:8px;margin:12px 0;background:#fff}
|
|
21
|
+
.scenario summary{cursor:pointer;padding:14px 16px;font-weight:600}
|
|
22
|
+
.scenario-body{padding:0 16px 16px}
|
|
23
|
+
.step{border-left:3px solid #d0d7de;margin:12px 0;padding:2px 0 2px 12px}
|
|
24
|
+
.step p{margin:8px 0}
|
|
25
|
+
.screenshots{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px;margin:10px 0 14px}
|
|
26
|
+
.screenshot{border:1px solid #d0d7de;border-radius:8px;overflow:hidden;background:#f6f8fa}
|
|
27
|
+
.screenshot img{display:block;width:100%;height:auto}
|
|
28
|
+
.screenshot figcaption{font-size:12px;padding:8px;color:#57606a}
|
|
29
|
+
</style>
|
|
30
|
+
</head>
|
|
31
|
+
<body>
|
|
32
|
+
<h1>${html(title)}</h1>
|
|
33
|
+
<p>Generated ${html(options.generatedAt ?? new Date().toISOString())}.</p>
|
|
34
|
+
${renderIssues(issues)}
|
|
35
|
+
${specs.map((spec) => renderSpec(spec, options.coverage, screenshots)).join("\n")}
|
|
36
|
+
</body>
|
|
37
|
+
</html>`;
|
|
38
|
+
}
|
|
39
|
+
function renderIssues(issues) {
|
|
40
|
+
if (!issues.length) {
|
|
41
|
+
return `<section class="panel"><h2>Validation</h2><p class="ok">No validation issues found.</p></section>`;
|
|
42
|
+
}
|
|
43
|
+
return `<section class="panel"><h2>Validation</h2><ul>${issues
|
|
44
|
+
.map((issue) => `<li class="${issue.severity}"><code>${html(`${issue.filePath ?? ""}${issue.line ? `:${issue.line}` : ""}`)}</code> ${html(issue.message)}</li>`)
|
|
45
|
+
.join("")}</ul></section>`;
|
|
46
|
+
}
|
|
47
|
+
function renderSpec(spec, coverage, screenshots = []) {
|
|
48
|
+
const screenshotsByLine = groupScreenshotsByLine(screenshots);
|
|
49
|
+
const ruleCoverage = coverage?.ruleCoverage ?? [];
|
|
50
|
+
const scenarioCoverage = coverage?.scenarioCoverage ?? [];
|
|
51
|
+
return `<section class="panel">
|
|
52
|
+
<div class="feature-header">
|
|
53
|
+
<h2>${html(spec.frontmatter.id)} ${html(spec.title)}</h2>
|
|
54
|
+
<span class="badge">${html(spec.frontmatter.status ?? "draft")}</span>
|
|
55
|
+
</div>
|
|
56
|
+
<p>${html(spec.purpose)}</p>
|
|
57
|
+
<h3>Rules</h3>
|
|
58
|
+
<ul>${spec.rules
|
|
59
|
+
.map((rule) => {
|
|
60
|
+
const item = ruleCoverage.find((coverageItem) => coverageItem.id === rule.id);
|
|
61
|
+
return `<li><code>${html(rule.id)}</code>: ${html(rule.text)} ${coverageBadge(item?.covered, ruleScenarioShortIds(item, scenarioCoverage))}</li>`;
|
|
62
|
+
})
|
|
63
|
+
.join("")}</ul>
|
|
64
|
+
<h3>Scenarios</h3>
|
|
65
|
+
${spec.scenarios
|
|
66
|
+
.map((scenario) => {
|
|
67
|
+
const screenshotCount = scenario.steps.reduce((count, step) => count +
|
|
68
|
+
(screenshotsByLine.get(screenshotKey(spec.filePath, step.line))
|
|
69
|
+
?.length ?? 0), 0);
|
|
70
|
+
return `<details class="scenario">
|
|
71
|
+
<summary><code>${html(scenario.id)}</code>: ${html(scenario.title)} ${coverageBadge(scenarioCoverage.find((item) => item.id === scenario.id)?.covered)} <span class="badge">${screenshotCount} screenshot${screenshotCount === 1 ? "" : "s"}</span></summary>
|
|
72
|
+
<div class="scenario-body">${scenario.steps.map((step) => renderStep(spec, step, screenshotsByLine)).join("")}</div>
|
|
73
|
+
</details>`;
|
|
74
|
+
})
|
|
75
|
+
.join("\n")}
|
|
76
|
+
</section>`;
|
|
77
|
+
}
|
|
78
|
+
function renderStep(spec, step, screenshotsByLine) {
|
|
79
|
+
const screenshots = screenshotsByLine.get(screenshotKey(spec.filePath, step.line)) ?? [];
|
|
80
|
+
const evidenceBadge = screenshots.length
|
|
81
|
+
? `<span class="badge ok">${screenshots.length} screenshot${screenshots.length === 1 ? "" : "s"}</span>`
|
|
82
|
+
: `<span class="badge missing">missing screenshot</span>`;
|
|
83
|
+
return `<div class="step"><p><strong>${html(step.keyword)}</strong> ${html(step.text)} <span class="badge">line ${step.line}</span> ${evidenceBadge}</p>${renderScreenshots(screenshots)}</div>`;
|
|
84
|
+
}
|
|
85
|
+
function renderScreenshots(screenshots) {
|
|
86
|
+
if (!screenshots.length)
|
|
87
|
+
return "";
|
|
88
|
+
return `<div class="screenshots">${screenshots
|
|
89
|
+
.map((screenshot) => `<figure class="screenshot"><img src="${html(screenshot.path)}" alt="${html(screenshot.title ?? `Screenshot for ${screenshot.specPath}:${screenshot.line}`)}"><figcaption>${html(screenshot.title ?? `${screenshot.specPath}:${screenshot.line}`)}</figcaption></figure>`)
|
|
90
|
+
.join("")}</div>`;
|
|
91
|
+
}
|
|
92
|
+
function coverageBadge(covered, suffixes = []) {
|
|
93
|
+
return covered === undefined
|
|
94
|
+
? ""
|
|
95
|
+
: covered
|
|
96
|
+
? `<span class="badge ok">covered${suffixes.length ? ` ${suffixes.map(html).join(" ")}` : ""}</span>`
|
|
97
|
+
: `<span class="badge missing">missing coverage</span>`;
|
|
98
|
+
}
|
|
99
|
+
function ruleScenarioShortIds(ruleCoverage, scenarioCoverage) {
|
|
100
|
+
if (!ruleCoverage?.covered)
|
|
101
|
+
return [];
|
|
102
|
+
const scenarioIds = new Set();
|
|
103
|
+
for (const ruleReference of ruleCoverage.references) {
|
|
104
|
+
for (const scenario of scenarioCoverage) {
|
|
105
|
+
const coversRule = scenario.references.some((scenarioReference) => scenarioReference.filePath === ruleReference.filePath &&
|
|
106
|
+
scenarioReference.line === ruleReference.line);
|
|
107
|
+
if (coversRule)
|
|
108
|
+
scenarioIds.add(shortScenarioId(scenario.id));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return Array.from(scenarioIds).sort();
|
|
112
|
+
}
|
|
113
|
+
function shortScenarioId(id) {
|
|
114
|
+
return id.match(/-(S\d{3})$/)?.[1] ?? id;
|
|
115
|
+
}
|
|
116
|
+
function groupScreenshotsByLine(screenshots) {
|
|
117
|
+
const grouped = new Map();
|
|
118
|
+
for (const screenshot of screenshots) {
|
|
119
|
+
const key = screenshotKey(screenshot.specPath, screenshot.line);
|
|
120
|
+
grouped.set(key, [...(grouped.get(key) ?? []), screenshot]);
|
|
121
|
+
}
|
|
122
|
+
return grouped;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=reportTemplate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reportTemplate.js","sourceRoot":"","sources":["../src/reportTemplate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SpecScreenshot } from "./types.js";
|
|
2
|
+
/** Load screenshot evidence manifests and normalize entries for report rendering. */
|
|
3
|
+
export declare function collectSpecScreenshots(patterns: string[]): Promise<SpecScreenshot[]>;
|
|
4
|
+
export declare function screenshotKey(filePath: string, line: number): string;
|
|
5
|
+
export declare function normalizeFilePath(filePath: string): string;
|
|
6
|
+
//# sourceMappingURL=screenshots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshots.d.ts","sourceRoot":"","sources":["../src/screenshots.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,qFAAqF;AACrF,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,6BAgB9D;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAE3D;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,UAEjD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { expandArtifactPatterns } from "./filePatterns.js";
|
|
3
|
+
/** Load screenshot evidence manifests and normalize entries for report rendering. */
|
|
4
|
+
export async function collectSpecScreenshots(patterns) {
|
|
5
|
+
const screenshots = [];
|
|
6
|
+
for (const file of await expandArtifactPatterns(patterns)) {
|
|
7
|
+
const parsed = JSON.parse(await readFile(file, "utf8"));
|
|
8
|
+
const entries = Array.isArray(parsed)
|
|
9
|
+
? parsed
|
|
10
|
+
: isRecord(parsed) && Array.isArray(parsed.screenshots)
|
|
11
|
+
? parsed.screenshots
|
|
12
|
+
: [];
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
const screenshot = normalizeScreenshot(entry);
|
|
15
|
+
if (screenshot)
|
|
16
|
+
screenshots.push(screenshot);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return screenshots;
|
|
20
|
+
}
|
|
21
|
+
export function screenshotKey(filePath, line) {
|
|
22
|
+
return `${normalizeFilePath(filePath)}:${line}`;
|
|
23
|
+
}
|
|
24
|
+
export function normalizeFilePath(filePath) {
|
|
25
|
+
return filePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
26
|
+
}
|
|
27
|
+
function normalizeScreenshot(value) {
|
|
28
|
+
if (!isRecord(value))
|
|
29
|
+
return null;
|
|
30
|
+
const specPath = value.specPath;
|
|
31
|
+
const line = value.line;
|
|
32
|
+
const imagePath = value.path ?? value.imagePath;
|
|
33
|
+
if (typeof specPath !== "string" ||
|
|
34
|
+
typeof line !== "number" ||
|
|
35
|
+
typeof imagePath !== "string") {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
specPath: normalizeFilePath(specPath),
|
|
40
|
+
line,
|
|
41
|
+
path: imagePath,
|
|
42
|
+
title: typeof value.title === "string" ? value.title : undefined,
|
|
43
|
+
testPath: typeof value.testPath === "string" ? value.testPath : undefined,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function isRecord(value) {
|
|
47
|
+
return typeof value === "object" && value !== null;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=screenshots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshots.js","sourceRoot":"","sources":["../src/screenshots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAG3D,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,QAAkB;IAC7D,MAAM,WAAW,GAAqB,EAAE,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,MAAM,sBAAsB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAY,CAAC;QACnE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YACnC,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC;gBACrD,CAAC,CAAC,MAAM,CAAC,WAAW;gBACpB,CAAC,CAAC,EAAE,CAAC;QAET,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,UAAU,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAC9C,IAAI,UAAU;gBAAE,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,IAAY;IAC1D,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc;IACzC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAChC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC;IAChD,IACE,OAAO,QAAQ,KAAK,QAAQ;QAC5B,OAAO,IAAI,KAAK,QAAQ;QACxB,OAAO,SAAS,KAAK,QAAQ,EAC7B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC;QACrC,IAAI;QACJ,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;QAChE,QAAQ,EAAE,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;KAC1E,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/** Parsed contents of one `*.feature.md` file. */
|
|
2
|
+
export type FeatureSpec = {
|
|
3
|
+
filePath: string;
|
|
4
|
+
frontmatter: FeatureFrontmatter;
|
|
5
|
+
title: string;
|
|
6
|
+
purpose: string;
|
|
7
|
+
rules: FeatureRule[];
|
|
8
|
+
scenarios: FeatureScenario[];
|
|
9
|
+
source: string;
|
|
10
|
+
};
|
|
11
|
+
/** Frontmatter fields supported by the feature spec format. */
|
|
12
|
+
export type FeatureFrontmatter = {
|
|
13
|
+
id: string;
|
|
14
|
+
title: string;
|
|
15
|
+
status?: "draft" | "active" | "deprecated";
|
|
16
|
+
owner?: string;
|
|
17
|
+
};
|
|
18
|
+
/** A business rule declared in the `## Rules` section. */
|
|
19
|
+
export type FeatureRule = {
|
|
20
|
+
id: string;
|
|
21
|
+
text: string;
|
|
22
|
+
keyword?: RuleKeyword;
|
|
23
|
+
strength: "required" | "recommended" | "optional" | "unspecified";
|
|
24
|
+
line: number;
|
|
25
|
+
};
|
|
26
|
+
/** A concrete example declared in the `## Scenarios` section. */
|
|
27
|
+
export type FeatureScenario = {
|
|
28
|
+
id: string;
|
|
29
|
+
title: string;
|
|
30
|
+
line: number;
|
|
31
|
+
steps: FeatureStep[];
|
|
32
|
+
};
|
|
33
|
+
/** A single Given / When / Then style step inside a scenario. */
|
|
34
|
+
export type FeatureStep = {
|
|
35
|
+
keyword: StepKeyword;
|
|
36
|
+
text: string;
|
|
37
|
+
line: number;
|
|
38
|
+
};
|
|
39
|
+
export type RuleKeyword = "MUST" | "MUST NOT" | "SHOULD" | "SHOULD NOT" | "MAY" | "OPTIONAL";
|
|
40
|
+
export type StepKeyword = "Given" | "When" | "Then" | "And" | "But";
|
|
41
|
+
/** Validation problem found in a spec, test reference, or report input. */
|
|
42
|
+
export type ValidationIssue = {
|
|
43
|
+
code: string;
|
|
44
|
+
severity: "error" | "warning";
|
|
45
|
+
message: string;
|
|
46
|
+
filePath?: string;
|
|
47
|
+
line?: number;
|
|
48
|
+
};
|
|
49
|
+
/** A rule or scenario ID found in executable tests. */
|
|
50
|
+
export type TestReference = {
|
|
51
|
+
id: string;
|
|
52
|
+
filePath: string;
|
|
53
|
+
line: number;
|
|
54
|
+
kind: "scenario" | "rule";
|
|
55
|
+
source: "title" | "tag" | "covers" | "annotation" | "free-text";
|
|
56
|
+
};
|
|
57
|
+
/** Coverage state for one expected rule or scenario. */
|
|
58
|
+
export type CoverageItem = {
|
|
59
|
+
id: string;
|
|
60
|
+
title?: string;
|
|
61
|
+
filePath?: string;
|
|
62
|
+
line?: number;
|
|
63
|
+
covered: boolean;
|
|
64
|
+
references: TestReference[];
|
|
65
|
+
};
|
|
66
|
+
/** Complete test coverage mapping for a set of feature specs. */
|
|
67
|
+
export type CoverageSummary = {
|
|
68
|
+
scenarioCoverage: CoverageItem[];
|
|
69
|
+
ruleCoverage: CoverageItem[];
|
|
70
|
+
orphanScenarioReferences: TestReference[];
|
|
71
|
+
orphanRuleReferences: TestReference[];
|
|
72
|
+
};
|
|
73
|
+
/** Screenshot evidence associated with an exact spec line. */
|
|
74
|
+
export type SpecScreenshot = {
|
|
75
|
+
specPath: string;
|
|
76
|
+
line: number;
|
|
77
|
+
path: string;
|
|
78
|
+
title?: string;
|
|
79
|
+
testPath?: string;
|
|
80
|
+
};
|
|
81
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anselmdk/feature-spec-md",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Markdown feature specs with rule/scenario IDs, validation, coverage checks, and generated reports.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./playwright": {
|
|
15
|
+
"types": "./dist/playwright.d.ts",
|
|
16
|
+
"import": "./dist/playwright.js"
|
|
13
17
|
}
|
|
14
18
|
},
|
|
15
19
|
"files": [
|
|
@@ -27,9 +31,15 @@
|
|
|
27
31
|
"build": "tsc -p tsconfig.build.json",
|
|
28
32
|
"prepare": "npm run build",
|
|
29
33
|
"dev": "tsx src/cli.ts",
|
|
30
|
-
"
|
|
34
|
+
"spec": "tsx src/cli.ts check",
|
|
35
|
+
"spec:init": "tsx src/cli.ts init",
|
|
36
|
+
"spec:report": "tsx src/cli.ts report",
|
|
37
|
+
"format": "prettier --write .",
|
|
38
|
+
"check:example": "tsx src/cli.ts check --specs examples/**/*.feature.md --require-scenario-coverage=false",
|
|
31
39
|
"report:example": "tsx src/cli.ts report --specs examples/**/*.feature.md --tests tests/**/*.test.ts --out test-results/feature-spec-report/index.html",
|
|
32
|
-
"test": "
|
|
40
|
+
"test": "npm run test:unit && npm run test:playwright",
|
|
41
|
+
"test:unit": "tsx --test tests/**/*.test.ts",
|
|
42
|
+
"test:playwright": "playwright install chromium && playwright test",
|
|
33
43
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
34
44
|
"verify": "npm run typecheck && npm test && npm run build && npm run check:example"
|
|
35
45
|
},
|
|
@@ -43,7 +53,9 @@
|
|
|
43
53
|
],
|
|
44
54
|
"license": "MIT",
|
|
45
55
|
"devDependencies": {
|
|
56
|
+
"@playwright/test": "^1.60.0",
|
|
46
57
|
"@types/node": "^25.3.2",
|
|
58
|
+
"prettier": "^3.8.4",
|
|
47
59
|
"tsx": "^4.21.0",
|
|
48
60
|
"typescript": "^5.9.3"
|
|
49
61
|
}
|