@anselmdk/feature-spec-md 0.1.0 → 0.1.1-rc.2
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 +57 -7
- package/SPEC_FORMAT.md +175 -35
- package/dist/cli.js +169 -29
- 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 +14 -0
- package/dist/reportTemplate.d.ts.map +1 -0
- package/dist/reportTemplate.js +154 -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/specDocuments.d.ts +72 -0
- package/dist/specDocuments.d.ts.map +1 -0
- package/dist/specDocuments.js +414 -0
- package/dist/specDocuments.js.map +1 -0
- package/dist/testImplementationReport.d.ts +31 -0
- package/dist/testImplementationReport.d.ts.map +1 -0
- package/dist/testImplementationReport.js +88 -0
- package/dist/testImplementationReport.js.map +1 -0
- package/dist/types.d.ts +142 -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 +20 -4
package/README.md
CHANGED
|
@@ -1,26 +1,37 @@
|
|
|
1
1
|
# feature-spec-md
|
|
2
2
|
|
|
3
|
-
Markdown feature specs with stable rule and scenario IDs, validation, coverage checks, and generated reports.
|
|
3
|
+
Markdown feature specs with stable model, rule, and scenario IDs, validation, coverage checks, and generated reports.
|
|
4
4
|
|
|
5
5
|
The goal is simple:
|
|
6
6
|
|
|
7
7
|
```txt
|
|
8
|
-
human-readable feature
|
|
8
|
+
human-readable model + feature specs
|
|
9
9
|
→ exact executable tests
|
|
10
10
|
→ generated coverage report
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
The handwritten
|
|
13
|
+
The handwritten specs stay clean. Shared domain language lives in `*.model.md` files. User-facing capabilities live in `*.feature.md` files with rules and scenarios. Test mapping is derived from stable IDs instead of being written manually in the spec.
|
|
14
14
|
|
|
15
15
|
## Format
|
|
16
16
|
|
|
17
|
-
Feature
|
|
17
|
+
Feature Spec Markdown uses ordinary Markdown files:
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
```txt
|
|
20
|
+
*.model.md
|
|
21
|
+
*.feature.md
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Model files use:
|
|
20
25
|
|
|
21
26
|
- frontmatter for metadata
|
|
22
|
-
- `##
|
|
23
|
-
- `## Rules` for
|
|
27
|
+
- `## Model` for shared domain vocabulary
|
|
28
|
+
- optional `## Rules` for global invariants
|
|
29
|
+
|
|
30
|
+
Feature files use:
|
|
31
|
+
|
|
32
|
+
- frontmatter for metadata
|
|
33
|
+
- optional `model` or `models` references
|
|
34
|
+
- `## Rules` for durable product truths
|
|
24
35
|
- `## Scenarios` for Given / When / Then examples
|
|
25
36
|
|
|
26
37
|
See `SPEC_FORMAT.md` and `examples/account-access.feature.md`.
|
|
@@ -30,7 +41,30 @@ See `SPEC_FORMAT.md` and `examples/account-access.feature.md`.
|
|
|
30
41
|
```bash
|
|
31
42
|
npm install
|
|
32
43
|
npm run dev -- check --specs "examples/**/*.feature.md" --tests "tests/**/*.test.ts" --require-scenario-coverage=false
|
|
44
|
+
npm run dev -- coverage --specs "specs/**/*.feature.md" --tests "tests/**/*.spec.ts"
|
|
33
45
|
npm run dev -- report --specs "examples/**/*.feature.md" --tests "tests/**/*.test.ts"
|
|
46
|
+
npm run dev -- report --specs "examples/**/*.feature.md" --tests "tests/**/*.test.ts" --screenshots "test-results/spec-report/screenshots-*.json"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The `coverage` command prints a simple terminal report that groups feature
|
|
50
|
+
specs by whether all, some, or none of their scenarios have matching test
|
|
51
|
+
references. Use `--fail-on-missing` when missing scenario tests should fail CI.
|
|
52
|
+
|
|
53
|
+
Playwright screenshot evidence can be shown in the report by passing one or
|
|
54
|
+
more screenshot manifest JSON files. Each screenshot should point at the spec
|
|
55
|
+
file and line it proves:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"screenshots": [
|
|
60
|
+
{
|
|
61
|
+
"specPath": "specs/account-access.feature.md",
|
|
62
|
+
"line": 24,
|
|
63
|
+
"path": "screenshots/account-s001-line-24.png",
|
|
64
|
+
"title": "ACCOUNT-S001:24 Given a registered person is on the sign-in page"
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
34
68
|
```
|
|
35
69
|
|
|
36
70
|
## Library API
|
|
@@ -52,3 +86,19 @@ npm test
|
|
|
52
86
|
npm run typecheck
|
|
53
87
|
npm run build
|
|
54
88
|
```
|
|
89
|
+
|
|
90
|
+
## Releases
|
|
91
|
+
|
|
92
|
+
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.
|
|
93
|
+
|
|
94
|
+
Release candidates are published manually from GitHub Actions:
|
|
95
|
+
|
|
96
|
+
1. Open the `Publish RC to npm` workflow.
|
|
97
|
+
2. Run the workflow from `main`.
|
|
98
|
+
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.
|
|
99
|
+
|
|
100
|
+
Install the latest release candidate with:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm install @anselmdk/feature-spec-md@rc
|
|
104
|
+
```
|
package/SPEC_FORMAT.md
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
# Feature Spec Markdown format
|
|
2
2
|
|
|
3
|
-
Feature Spec Markdown is a lightweight convention for readable, testable
|
|
3
|
+
Feature Spec Markdown is a lightweight convention for readable, testable specifications.
|
|
4
4
|
|
|
5
|
-
It
|
|
5
|
+
It uses ordinary Markdown and stable IDs instead of a dedicated executable specification language.
|
|
6
6
|
|
|
7
|
-
## File
|
|
7
|
+
## File types
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The format has four document types:
|
|
10
10
|
|
|
11
11
|
```txt
|
|
12
|
+
*.model.md
|
|
12
13
|
*.feature.md
|
|
14
|
+
*.stack.md
|
|
15
|
+
*.design.md
|
|
13
16
|
```
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
```
|
|
18
|
+
- `*.model.md` defines shared domain vocabulary.
|
|
19
|
+
- `*.feature.md` defines user-facing behavior with rules and scenarios.
|
|
20
|
+
- `*.stack.md` defines technical platform choices.
|
|
21
|
+
- `*.design.md` defines product, UI, and interaction design direction.
|
|
20
22
|
|
|
21
23
|
## Frontmatter
|
|
22
24
|
|
|
@@ -24,9 +26,10 @@ Every file starts with YAML-like frontmatter:
|
|
|
24
26
|
|
|
25
27
|
```md
|
|
26
28
|
---
|
|
27
|
-
id:
|
|
28
|
-
title:
|
|
29
|
+
id: KANBAN-CARD-AUTHORING
|
|
30
|
+
title: Card authoring
|
|
29
31
|
status: draft
|
|
32
|
+
model: KANBAN
|
|
30
33
|
---
|
|
31
34
|
```
|
|
32
35
|
|
|
@@ -39,48 +42,75 @@ Optional fields:
|
|
|
39
42
|
|
|
40
43
|
- `status`: `draft`, `active`, or `deprecated`
|
|
41
44
|
- `owner`
|
|
45
|
+
- `model`: a single referenced model id, for feature and design files
|
|
46
|
+
- `models`: comma-separated referenced model ids, for feature and design files
|
|
47
|
+
|
|
48
|
+
## Purpose
|
|
42
49
|
|
|
43
|
-
|
|
50
|
+
Every model, feature, stack, and design file MUST include a short `## Purpose` section.
|
|
51
|
+
|
|
52
|
+
Purpose explains the document boundary and intent. It SHOULD be one or two short paragraphs and SHOULD NOT contain rules, scenarios, implementation details, or roadmap notes.
|
|
53
|
+
|
|
54
|
+
## Model files
|
|
55
|
+
|
|
56
|
+
Model files use the `.model.md` suffix.
|
|
57
|
+
|
|
58
|
+
Required sections:
|
|
44
59
|
|
|
45
60
|
```md
|
|
46
|
-
#
|
|
61
|
+
# Kanban model
|
|
47
62
|
|
|
48
63
|
## Purpose
|
|
49
64
|
|
|
50
|
-
##
|
|
51
|
-
|
|
52
|
-
## Scenarios
|
|
65
|
+
## Model
|
|
53
66
|
```
|
|
54
67
|
|
|
68
|
+
Optional sections:
|
|
69
|
+
|
|
70
|
+
```md
|
|
55
71
|
## Rules
|
|
72
|
+
```
|
|
56
73
|
|
|
57
|
-
|
|
74
|
+
Model items use stable `-M001` IDs:
|
|
58
75
|
|
|
59
76
|
```md
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
### KANBAN-M001: Card
|
|
78
|
+
|
|
79
|
+
A card represents one work item on the board.
|
|
63
80
|
```
|
|
64
81
|
|
|
65
|
-
|
|
82
|
+
Model rules use stable `-R001` IDs and should describe global invariants for the domain vocabulary.
|
|
83
|
+
|
|
84
|
+
## Feature files
|
|
85
|
+
|
|
86
|
+
Feature files use the `.feature.md` suffix.
|
|
87
|
+
|
|
88
|
+
Required sections:
|
|
89
|
+
|
|
90
|
+
```md
|
|
91
|
+
# Card authoring
|
|
92
|
+
|
|
93
|
+
## Purpose
|
|
66
94
|
|
|
67
|
-
|
|
68
|
-
- `MUST NOT`
|
|
69
|
-
- `SHOULD`
|
|
70
|
-
- `SHOULD NOT`
|
|
71
|
-
- `MAY`
|
|
72
|
-
- `OPTIONAL`
|
|
95
|
+
## Rules
|
|
73
96
|
|
|
74
97
|
## Scenarios
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Rules use stable `-R001` IDs:
|
|
101
|
+
|
|
102
|
+
```md
|
|
103
|
+
- KANBAN-CARD-AUTHORING-R001: A new card MUST start in the To do column.
|
|
104
|
+
```
|
|
75
105
|
|
|
76
|
-
Scenarios
|
|
106
|
+
Scenarios use stable `-S001` IDs and Given / When / Then steps:
|
|
77
107
|
|
|
78
108
|
```md
|
|
79
|
-
###
|
|
109
|
+
### KANBAN-CARD-AUTHORING-S001: User creates a card
|
|
80
110
|
|
|
81
|
-
Given
|
|
82
|
-
When they
|
|
83
|
-
Then
|
|
111
|
+
Given the user is on the board
|
|
112
|
+
When they create a card with the title "Write release notes"
|
|
113
|
+
Then the card "Write release notes" is visible in the To do column
|
|
84
114
|
```
|
|
85
115
|
|
|
86
116
|
Allowed step keywords:
|
|
@@ -91,14 +121,124 @@ Allowed step keywords:
|
|
|
91
121
|
- `And`
|
|
92
122
|
- `But`
|
|
93
123
|
|
|
124
|
+
## Stack files
|
|
125
|
+
|
|
126
|
+
Stack files use the `.stack.md` suffix.
|
|
127
|
+
|
|
128
|
+
A stack file defines technical platform choices and the reasoning behind them.
|
|
129
|
+
|
|
130
|
+
Required sections:
|
|
131
|
+
|
|
132
|
+
```md
|
|
133
|
+
# Kanban tech stack
|
|
134
|
+
|
|
135
|
+
## Purpose
|
|
136
|
+
|
|
137
|
+
## Stack
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Optional sections:
|
|
141
|
+
|
|
142
|
+
```md
|
|
143
|
+
## Context
|
|
144
|
+
|
|
145
|
+
## Rationale
|
|
146
|
+
|
|
147
|
+
## Consequences
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Example:
|
|
151
|
+
|
|
152
|
+
```md
|
|
153
|
+
---
|
|
154
|
+
id: KANBAN-STACK
|
|
155
|
+
title: Kanban tech stack
|
|
156
|
+
status: draft
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
# Kanban tech stack
|
|
160
|
+
|
|
161
|
+
## Purpose
|
|
162
|
+
|
|
163
|
+
Define the initial technical stack for implementing the Kanban board.
|
|
164
|
+
|
|
165
|
+
## Stack
|
|
166
|
+
|
|
167
|
+
| Area | Choice |
|
|
168
|
+
| -------- | ---------- |
|
|
169
|
+
| Frontend | React |
|
|
170
|
+
| Language | TypeScript |
|
|
171
|
+
| Testing | Playwright |
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Design files
|
|
175
|
+
|
|
176
|
+
Design files use the `.design.md` suffix.
|
|
177
|
+
|
|
178
|
+
A design file defines product, UI, layout, visual, and interaction direction.
|
|
179
|
+
|
|
180
|
+
Required sections:
|
|
181
|
+
|
|
182
|
+
```md
|
|
183
|
+
# Kanban board design
|
|
184
|
+
|
|
185
|
+
## Purpose
|
|
186
|
+
|
|
187
|
+
## Design
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Optional sections:
|
|
191
|
+
|
|
192
|
+
```md
|
|
193
|
+
## Principles
|
|
194
|
+
|
|
195
|
+
## Layout
|
|
196
|
+
|
|
197
|
+
## Interaction
|
|
198
|
+
|
|
199
|
+
## Visual style
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Example:
|
|
203
|
+
|
|
204
|
+
```md
|
|
205
|
+
---
|
|
206
|
+
id: KANBAN-DESIGN
|
|
207
|
+
title: Kanban board design
|
|
208
|
+
status: draft
|
|
209
|
+
model: KANBAN
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
# Kanban board design
|
|
213
|
+
|
|
214
|
+
## Purpose
|
|
215
|
+
|
|
216
|
+
Define the visual and interaction design direction for the Kanban board.
|
|
217
|
+
|
|
218
|
+
## Design
|
|
219
|
+
|
|
220
|
+
The board should feel lightweight, immediate, and calm.
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Splitting guidance
|
|
224
|
+
|
|
225
|
+
Split model files by coherent domain vocabulary, ownership, or lifecycle.
|
|
226
|
+
|
|
227
|
+
Feature files SHOULD be split by user capability.
|
|
228
|
+
|
|
229
|
+
Use stack files for broad technical choices such as framework, language, testing, persistence, and deployment.
|
|
230
|
+
|
|
231
|
+
Use design files for product/UI direction such as layout, interaction, visual style, and design principles.
|
|
232
|
+
|
|
94
233
|
## Test coverage convention
|
|
95
234
|
|
|
96
|
-
|
|
235
|
+
Spec files do not contain test mappings.
|
|
97
236
|
|
|
98
|
-
Tests reference rule and scenario IDs in test titles, tags, annotations, comments, or metadata.
|
|
237
|
+
Tests reference model item, rule, and scenario IDs in test titles, tags, annotations, comments, or metadata.
|
|
99
238
|
|
|
100
|
-
Generated tooling can
|
|
239
|
+
Generated tooling can answer:
|
|
101
240
|
|
|
241
|
+
- Which model items are referenced?
|
|
102
242
|
- Which scenarios have tests?
|
|
103
243
|
- Which rules have executable coverage?
|
|
104
244
|
- Which tests reference deleted or unknown spec IDs?
|
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import { collectSpecScreenshots, renderHtmlReport, writeTextFile, } from "./index.js";
|
|
5
|
+
import { checkSpecDocuments } from "./specDocuments.js";
|
|
6
|
+
import { buildSpecImplementationReport, formatSpecImplementationReport, } from "./testImplementationReport.js";
|
|
7
|
+
const defaultSpecPattern = "specs/**/*.model.md,specs/**/*.feature.md,specs/**/*.stack.md,specs/**/*.design.md";
|
|
6
8
|
const defaultTestPattern = "tests/**/*.spec.ts";
|
|
7
9
|
main().catch((error) => {
|
|
8
10
|
console.error(error instanceof Error ? error.message : error);
|
|
@@ -15,44 +17,78 @@ async function main() {
|
|
|
15
17
|
return runCheck(options);
|
|
16
18
|
if (command === "report")
|
|
17
19
|
return runReport(options);
|
|
20
|
+
if (command === "coverage")
|
|
21
|
+
return runCoverage(options);
|
|
18
22
|
if (command === "init")
|
|
19
23
|
return runInit(options);
|
|
20
24
|
printHelp();
|
|
21
25
|
process.exit(command === "help" || command === "--help" || command === "-h" ? 0 : 1);
|
|
22
26
|
}
|
|
23
27
|
async function runCheck(options) {
|
|
24
|
-
const result = await
|
|
28
|
+
const result = await checkSpecDocuments({
|
|
25
29
|
specs: optionList(options.specs, defaultSpecPattern),
|
|
26
30
|
tests: options.tests === "" ? [] : optionList(options.tests, defaultTestPattern),
|
|
31
|
+
requireModelCoverage: options["require-model-coverage"] === "true",
|
|
27
32
|
requireRuleCoverage: options["require-rule-coverage"] === "true",
|
|
28
33
|
requireScenarioCoverage: options["require-scenario-coverage"] !== "false",
|
|
29
34
|
});
|
|
30
35
|
printIssues([...result.validationIssues, ...result.coverageIssues]);
|
|
31
36
|
if (!result.ok)
|
|
32
37
|
process.exit(1);
|
|
33
|
-
const
|
|
34
|
-
const ruleCount = result.
|
|
35
|
-
|
|
38
|
+
const modelItemCount = result.models.reduce((sum, spec) => sum + spec.modelItems.length, 0);
|
|
39
|
+
const ruleCount = result.documents.reduce((sum, spec) => sum + spec.rules.length, 0);
|
|
40
|
+
const scenarioCount = result.features.reduce((sum, spec) => sum + spec.scenarios.length, 0);
|
|
41
|
+
console.log(`Spec check passed: ${result.models.length} model(s), ${result.features.length} feature(s), ${result.stacks.length} stack(s), ${result.designs.length} design(s), ${modelItemCount} model item(s), ${ruleCount} rule(s), ${scenarioCount} scenario(s).`);
|
|
42
|
+
}
|
|
43
|
+
async function runCoverage(options) {
|
|
44
|
+
const result = await checkSpecDocuments({
|
|
45
|
+
specs: optionList(options.specs, defaultSpecPattern),
|
|
46
|
+
tests: options.tests === "" ? [] : optionList(options.tests, defaultTestPattern),
|
|
47
|
+
requireModelCoverage: false,
|
|
48
|
+
requireRuleCoverage: false,
|
|
49
|
+
requireScenarioCoverage: false,
|
|
50
|
+
});
|
|
51
|
+
printIssues(result.coverageIssues);
|
|
52
|
+
if (!result.coverage) {
|
|
53
|
+
console.log("Spec test implementation report");
|
|
54
|
+
console.log("");
|
|
55
|
+
console.log("No tests were scanned. Pass --tests or omit --tests to use the default tests/**/*.spec.ts pattern.");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const report = buildSpecImplementationReport(result.features, result.coverage);
|
|
59
|
+
console.log(formatSpecImplementationReport(report));
|
|
60
|
+
if (options["fail-on-missing"] === "true" && report.missingScenarios > 0) {
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
36
63
|
}
|
|
37
64
|
async function runReport(options) {
|
|
38
|
-
const result = await
|
|
65
|
+
const result = await checkSpecDocuments({
|
|
39
66
|
specs: optionList(options.specs, defaultSpecPattern),
|
|
40
67
|
tests: options.tests === "" ? [] : optionList(options.tests, defaultTestPattern),
|
|
68
|
+
requireModelCoverage: options["require-model-coverage"] === "true",
|
|
41
69
|
requireRuleCoverage: options["require-rule-coverage"] === "true",
|
|
42
70
|
requireScenarioCoverage: false,
|
|
43
71
|
});
|
|
44
72
|
const out = options.out ?? "test-results/feature-spec-report/index.html";
|
|
45
|
-
|
|
73
|
+
const screenshots = options.screenshots
|
|
74
|
+
? await collectSpecScreenshots(optionList(options.screenshots, ""))
|
|
75
|
+
: [];
|
|
76
|
+
await writeTextFile(out, renderHtmlReport(result.features, {
|
|
77
|
+
models: result.models,
|
|
78
|
+
stacks: result.stacks,
|
|
79
|
+
designs: result.designs,
|
|
46
80
|
coverage: result.coverage,
|
|
81
|
+
screenshots,
|
|
47
82
|
validationIssues: [...result.validationIssues, ...result.coverageIssues],
|
|
48
83
|
}));
|
|
49
84
|
console.log(`Feature spec report written to ${out}`);
|
|
50
85
|
}
|
|
51
86
|
async function runInit(options) {
|
|
52
87
|
const dir = options.dir ?? "specs";
|
|
53
|
-
const
|
|
88
|
+
const kind = options.kind ?? "feature";
|
|
89
|
+
const target = path.join(dir, fileNameForKind(kind));
|
|
54
90
|
await mkdir(dir, { recursive: true });
|
|
55
|
-
await writeFile(target,
|
|
91
|
+
await writeFile(target, exampleForKind(kind), "utf8");
|
|
56
92
|
console.log(`Created ${target}`);
|
|
57
93
|
}
|
|
58
94
|
function parseArgs(args) {
|
|
@@ -77,11 +113,16 @@ function parseArgs(args) {
|
|
|
77
113
|
return options;
|
|
78
114
|
}
|
|
79
115
|
function optionList(value, fallback) {
|
|
80
|
-
return (value ?? fallback)
|
|
116
|
+
return (value ?? fallback)
|
|
117
|
+
.split(",")
|
|
118
|
+
.map((item) => item.trim())
|
|
119
|
+
.filter(Boolean);
|
|
81
120
|
}
|
|
82
121
|
function printIssues(issues) {
|
|
83
122
|
for (const issue of issues) {
|
|
84
|
-
const location = issue.filePath
|
|
123
|
+
const location = issue.filePath
|
|
124
|
+
? `${issue.filePath}${issue.line ? `:${issue.line}` : ""}`
|
|
125
|
+
: "";
|
|
85
126
|
console.error(`${issue.severity.toUpperCase()} ${issue.code}${location ? ` ${location}` : ""}: ${issue.message}`);
|
|
86
127
|
}
|
|
87
128
|
}
|
|
@@ -89,20 +130,61 @@ function printHelp() {
|
|
|
89
130
|
console.log(`feature-spec-md
|
|
90
131
|
|
|
91
132
|
Usage:
|
|
92
|
-
feature-spec-md init [--dir specs]
|
|
93
|
-
feature-spec-md check [--specs "specs/**/*.feature.md"] [--tests "tests/**/*.spec.ts"]
|
|
94
|
-
feature-spec-md
|
|
133
|
+
feature-spec-md init [--kind feature|model|stack|design] [--dir specs]
|
|
134
|
+
feature-spec-md check [--specs "specs/**/*.model.md,specs/**/*.feature.md,specs/**/*.stack.md,specs/**/*.design.md"] [--tests "tests/**/*.spec.ts"]
|
|
135
|
+
feature-spec-md coverage [--specs "specs/**/*.feature.md"] [--tests "tests/**/*.spec.ts"] [--fail-on-missing]
|
|
136
|
+
feature-spec-md report [--specs "specs/**/*.model.md,specs/**/*.feature.md,specs/**/*.stack.md,specs/**/*.design.md"] [--tests "tests/**/*.spec.ts"] [--screenshots "test-results/spec-report/screenshots.json"] [--out test-results/feature-spec-report/index.html]
|
|
95
137
|
|
|
96
138
|
Options:
|
|
139
|
+
--require-model-coverage Fail when model items have no matching test references.
|
|
97
140
|
--require-rule-coverage Fail when rules have no matching test references.
|
|
98
141
|
--require-scenario-coverage Defaults to true for check. Use --require-scenario-coverage=false to disable.
|
|
142
|
+
--fail-on-missing Exit with status 1 when coverage finds missing scenario tests.
|
|
143
|
+
--screenshots Screenshot manifest JSON glob for report evidence.
|
|
99
144
|
--tests "" Disable test coverage lookup.
|
|
100
145
|
`);
|
|
101
146
|
}
|
|
102
|
-
|
|
147
|
+
function fileNameForKind(kind) {
|
|
148
|
+
if (kind === "model")
|
|
149
|
+
return "example.model.md";
|
|
150
|
+
if (kind === "stack")
|
|
151
|
+
return "example.stack.md";
|
|
152
|
+
if (kind === "design")
|
|
153
|
+
return "example.design.md";
|
|
154
|
+
return "account-access.feature.md";
|
|
155
|
+
}
|
|
156
|
+
function exampleForKind(kind) {
|
|
157
|
+
if (kind === "model")
|
|
158
|
+
return exampleModel;
|
|
159
|
+
if (kind === "stack")
|
|
160
|
+
return exampleStack;
|
|
161
|
+
if (kind === "design")
|
|
162
|
+
return exampleDesign;
|
|
163
|
+
return exampleFeature;
|
|
164
|
+
}
|
|
165
|
+
const exampleModel = `---
|
|
103
166
|
id: ACCOUNT
|
|
167
|
+
title: Account model
|
|
168
|
+
status: draft
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
# Account model
|
|
172
|
+
|
|
173
|
+
## Purpose
|
|
174
|
+
|
|
175
|
+
Define the shared account concepts used by account access features.
|
|
176
|
+
|
|
177
|
+
## Model
|
|
178
|
+
|
|
179
|
+
### ACCOUNT-M001: Account
|
|
180
|
+
|
|
181
|
+
An account represents one registered person.
|
|
182
|
+
`;
|
|
183
|
+
const exampleFeature = `---
|
|
184
|
+
id: ACCOUNT-ACCESS
|
|
104
185
|
title: Account access
|
|
105
186
|
status: draft
|
|
187
|
+
model: ACCOUNT
|
|
106
188
|
---
|
|
107
189
|
|
|
108
190
|
# Account access
|
|
@@ -113,24 +195,82 @@ People can access their own account after proving their identity.
|
|
|
113
195
|
|
|
114
196
|
## Rules
|
|
115
197
|
|
|
116
|
-
- ACCOUNT-R001: A person MUST prove control of a registered email address before accessing an account.
|
|
117
|
-
- ACCOUNT-R002: The system MUST NOT reveal whether an unknown email address belongs to an account.
|
|
118
|
-
- ACCOUNT-R003: A signed-in person SHOULD be returned to the page they originally requested.
|
|
198
|
+
- ACCOUNT-ACCESS-R001: A person MUST prove control of a registered email address before accessing an account.
|
|
199
|
+
- ACCOUNT-ACCESS-R002: The system MUST NOT reveal whether an unknown email address belongs to an account.
|
|
119
200
|
|
|
120
201
|
## Scenarios
|
|
121
202
|
|
|
122
|
-
### ACCOUNT-S001: Registered person signs in
|
|
203
|
+
### ACCOUNT-ACCESS-S001: Registered person signs in
|
|
204
|
+
|
|
205
|
+
Given a registered person is on the sign-in page
|
|
206
|
+
When they request and open a valid sign-in link
|
|
207
|
+
Then they are signed in
|
|
208
|
+
`;
|
|
209
|
+
const exampleStack = `---
|
|
210
|
+
id: ACCOUNT-STACK
|
|
211
|
+
title: Account stack
|
|
212
|
+
status: draft
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
# Account stack
|
|
216
|
+
|
|
217
|
+
## Purpose
|
|
218
|
+
|
|
219
|
+
Define the initial technical stack for the account access demo.
|
|
220
|
+
|
|
221
|
+
## Context
|
|
222
|
+
|
|
223
|
+
The demo is a small browser-based application with automated tests.
|
|
224
|
+
|
|
225
|
+
## Stack
|
|
226
|
+
|
|
227
|
+
| Area | Choice |
|
|
228
|
+
|---|---|
|
|
229
|
+
| Frontend | React |
|
|
230
|
+
| Language | TypeScript |
|
|
231
|
+
| Testing | Playwright |
|
|
232
|
+
|
|
233
|
+
## Rationale
|
|
234
|
+
|
|
235
|
+
React, TypeScript, and Playwright fit the interaction-heavy UI and scenario-based testing style.
|
|
236
|
+
|
|
237
|
+
## Consequences
|
|
238
|
+
|
|
239
|
+
The stack is optimized for a browser UI and static deployment.
|
|
240
|
+
`;
|
|
241
|
+
const exampleDesign = `---
|
|
242
|
+
id: ACCOUNT-DESIGN
|
|
243
|
+
title: Account design
|
|
244
|
+
status: draft
|
|
245
|
+
model: ACCOUNT
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
# Account design
|
|
249
|
+
|
|
250
|
+
## Purpose
|
|
251
|
+
|
|
252
|
+
Define the initial interaction and visual design direction for account access.
|
|
253
|
+
|
|
254
|
+
## Design
|
|
255
|
+
|
|
256
|
+
The account access flow should feel simple, calm, and direct.
|
|
257
|
+
|
|
258
|
+
## Principles
|
|
259
|
+
|
|
260
|
+
- Keep the sign-in flow short.
|
|
261
|
+
- Avoid revealing whether an email address exists.
|
|
262
|
+
- Make recovery states easy to understand.
|
|
263
|
+
|
|
264
|
+
## Layout
|
|
265
|
+
|
|
266
|
+
The sign-in page uses one primary form and one primary action.
|
|
267
|
+
|
|
268
|
+
## Interaction
|
|
123
269
|
|
|
124
|
-
|
|
125
|
-
When they request and open a valid sign-in link
|
|
126
|
-
Then they are signed in
|
|
127
|
-
And they are returned to the page they originally requested
|
|
270
|
+
Validation messages appear near the field they describe.
|
|
128
271
|
|
|
129
|
-
|
|
272
|
+
## Visual style
|
|
130
273
|
|
|
131
|
-
|
|
132
|
-
When they request a sign-in link
|
|
133
|
-
Then the response says to check their email
|
|
134
|
-
And the response does not reveal whether the email address is registered
|
|
274
|
+
Use a clean, low-distraction visual style.
|
|
135
275
|
`;
|
|
136
276
|
//# sourceMappingURL=cli.js.map
|
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"}
|