executable-stories-formatters 0.9.0 → 0.11.0
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 +35 -0
- package/dist/adapters.d.cts +1 -1
- package/dist/adapters.d.ts +1 -1
- package/dist/cli.js +1437 -126
- package/dist/cli.js.map +1 -1
- package/dist/{index-it3Pkmqv.d.cts → index-DF16Xl5i.d.cts} +9 -0
- package/dist/{index-it3Pkmqv.d.ts → index-DF16Xl5i.d.ts} +9 -0
- package/dist/index.cjs +613 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +240 -7
- package/dist/index.d.ts +240 -7
- package/dist/index.js +602 -54
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/schemas/behavior-manifest-v1.json +65 -0
- package/schemas/examples/dotnet.json +84 -20
- package/schemas/examples/go.json +77 -20
- package/schemas/examples/junit5.json +84 -20
- package/schemas/examples/pytest.json +92 -20
- package/schemas/examples/rust.json +84 -20
- package/schemas/raw-run.schema.json +19 -0
- package/schemas/scenario-index-v1.json +88 -0
- package/schemas/story-report-v1.json +22 -0
|
@@ -11,7 +11,12 @@
|
|
|
11
11
|
{
|
|
12
12
|
"externalId": "tests/auth/test_login.py::test_successful_login",
|
|
13
13
|
"title": "Successful login with valid credentials",
|
|
14
|
-
"titlePath": [
|
|
14
|
+
"titlePath": [
|
|
15
|
+
"tests",
|
|
16
|
+
"auth",
|
|
17
|
+
"test_login",
|
|
18
|
+
"Successful login with valid credentials"
|
|
19
|
+
],
|
|
15
20
|
"sourceFile": "tests/auth/test_login.py",
|
|
16
21
|
"sourceLine": 15,
|
|
17
22
|
"status": "pass",
|
|
@@ -19,15 +24,39 @@
|
|
|
19
24
|
"story": {
|
|
20
25
|
"scenario": "Successful login with valid credentials",
|
|
21
26
|
"steps": [
|
|
22
|
-
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
{
|
|
28
|
+
"keyword": "Given",
|
|
29
|
+
"text": "a registered user with email 'alice@example.com'"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"keyword": "When",
|
|
33
|
+
"text": "the user submits login with valid credentials"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"keyword": "Then",
|
|
37
|
+
"text": "the response status is 200"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"keyword": "And",
|
|
41
|
+
"text": "a JWT token is returned"
|
|
42
|
+
}
|
|
26
43
|
],
|
|
27
|
-
"tags": [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
44
|
+
"tags": [
|
|
45
|
+
"smoke",
|
|
46
|
+
"auth"
|
|
47
|
+
],
|
|
48
|
+
"tickets": [
|
|
49
|
+
"AUTH-101"
|
|
50
|
+
],
|
|
51
|
+
"suitePath": [
|
|
52
|
+
"tests",
|
|
53
|
+
"auth",
|
|
54
|
+
"test_login"
|
|
55
|
+
],
|
|
56
|
+
"sourceOrder": 0,
|
|
57
|
+
"covers": [
|
|
58
|
+
"src/auth/login.*"
|
|
59
|
+
]
|
|
31
60
|
},
|
|
32
61
|
"meta": {
|
|
33
62
|
"framework": "pytest",
|
|
@@ -37,7 +66,13 @@
|
|
|
37
66
|
{
|
|
38
67
|
"externalId": "tests/auth/test_login.py::TestLoginValidation::test_invalid_password",
|
|
39
68
|
"title": "Login with invalid password shows error",
|
|
40
|
-
"titlePath": [
|
|
69
|
+
"titlePath": [
|
|
70
|
+
"tests",
|
|
71
|
+
"auth",
|
|
72
|
+
"test_login",
|
|
73
|
+
"TestLoginValidation",
|
|
74
|
+
"Login with invalid password shows error"
|
|
75
|
+
],
|
|
41
76
|
"sourceFile": "tests/auth/test_login.py",
|
|
42
77
|
"sourceLine": 42,
|
|
43
78
|
"status": "fail",
|
|
@@ -54,7 +89,12 @@
|
|
|
54
89
|
{
|
|
55
90
|
"externalId": "tests/auth/test_login.py::test_login_rate_limiting",
|
|
56
91
|
"title": "Login is rate-limited after 5 failed attempts",
|
|
57
|
-
"titlePath": [
|
|
92
|
+
"titlePath": [
|
|
93
|
+
"tests",
|
|
94
|
+
"auth",
|
|
95
|
+
"test_login",
|
|
96
|
+
"Login is rate-limited after 5 failed attempts"
|
|
97
|
+
],
|
|
58
98
|
"sourceFile": "tests/auth/test_login.py",
|
|
59
99
|
"sourceLine": 68,
|
|
60
100
|
"status": "skip",
|
|
@@ -68,7 +108,12 @@
|
|
|
68
108
|
{
|
|
69
109
|
"externalId": "tests/cart/test_checkout.py::test_checkout_flow",
|
|
70
110
|
"title": "Complete checkout with credit card",
|
|
71
|
-
"titlePath": [
|
|
111
|
+
"titlePath": [
|
|
112
|
+
"tests",
|
|
113
|
+
"cart",
|
|
114
|
+
"test_checkout",
|
|
115
|
+
"Complete checkout with credit card"
|
|
116
|
+
],
|
|
72
117
|
"sourceFile": "tests/cart/test_checkout.py",
|
|
73
118
|
"sourceLine": 10,
|
|
74
119
|
"status": "pass",
|
|
@@ -76,14 +121,36 @@
|
|
|
76
121
|
"story": {
|
|
77
122
|
"scenario": "Complete checkout with credit card",
|
|
78
123
|
"steps": [
|
|
79
|
-
{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
124
|
+
{
|
|
125
|
+
"keyword": "Given",
|
|
126
|
+
"text": "a cart with 2 items totaling $59.98"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"keyword": "When",
|
|
130
|
+
"text": "the user submits payment with a test credit card"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"keyword": "Then",
|
|
134
|
+
"text": "the order is confirmed"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"keyword": "And",
|
|
138
|
+
"text": "a confirmation email is queued"
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
"tags": [
|
|
142
|
+
"checkout",
|
|
143
|
+
"payments",
|
|
144
|
+
"e2e"
|
|
145
|
+
],
|
|
146
|
+
"tickets": [
|
|
147
|
+
"SHOP-200"
|
|
148
|
+
],
|
|
149
|
+
"suitePath": [
|
|
150
|
+
"tests",
|
|
151
|
+
"cart",
|
|
152
|
+
"test_checkout"
|
|
83
153
|
],
|
|
84
|
-
"tags": ["checkout", "payments", "e2e"],
|
|
85
|
-
"tickets": ["SHOP-200"],
|
|
86
|
-
"suitePath": ["tests", "cart", "test_checkout"],
|
|
87
154
|
"sourceOrder": 0
|
|
88
155
|
},
|
|
89
156
|
"meta": {
|
|
@@ -94,7 +161,12 @@
|
|
|
94
161
|
{
|
|
95
162
|
"externalId": "tests/cart/test_checkout.py::test_empty_cart_checkout",
|
|
96
163
|
"title": "Cannot checkout with an empty cart",
|
|
97
|
-
"titlePath": [
|
|
164
|
+
"titlePath": [
|
|
165
|
+
"tests",
|
|
166
|
+
"cart",
|
|
167
|
+
"test_checkout",
|
|
168
|
+
"Cannot checkout with an empty cart"
|
|
169
|
+
],
|
|
98
170
|
"sourceFile": "tests/cart/test_checkout.py",
|
|
99
171
|
"sourceLine": 55,
|
|
100
172
|
"status": "pass",
|
|
@@ -11,7 +11,11 @@
|
|
|
11
11
|
{
|
|
12
12
|
"externalId": "crate::auth::tests::test_successful_login",
|
|
13
13
|
"title": "Successful login with valid credentials",
|
|
14
|
-
"titlePath": [
|
|
14
|
+
"titlePath": [
|
|
15
|
+
"auth",
|
|
16
|
+
"tests",
|
|
17
|
+
"Successful login with valid credentials"
|
|
18
|
+
],
|
|
15
19
|
"sourceFile": "src/auth.rs",
|
|
16
20
|
"sourceLine": 120,
|
|
17
21
|
"status": "pass",
|
|
@@ -19,15 +23,38 @@
|
|
|
19
23
|
"story": {
|
|
20
24
|
"scenario": "Successful login with valid credentials",
|
|
21
25
|
"steps": [
|
|
22
|
-
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
{
|
|
27
|
+
"keyword": "Given",
|
|
28
|
+
"text": "a registered user with email 'alice@example.com'"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"keyword": "When",
|
|
32
|
+
"text": "the user submits login with valid credentials"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"keyword": "Then",
|
|
36
|
+
"text": "the response status is 200"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"keyword": "And",
|
|
40
|
+
"text": "a JWT token is returned"
|
|
41
|
+
}
|
|
26
42
|
],
|
|
27
|
-
"tags": [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
43
|
+
"tags": [
|
|
44
|
+
"smoke",
|
|
45
|
+
"auth"
|
|
46
|
+
],
|
|
47
|
+
"tickets": [
|
|
48
|
+
"AUTH-101"
|
|
49
|
+
],
|
|
50
|
+
"suitePath": [
|
|
51
|
+
"auth",
|
|
52
|
+
"tests"
|
|
53
|
+
],
|
|
54
|
+
"sourceOrder": 0,
|
|
55
|
+
"covers": [
|
|
56
|
+
"src/auth/login.*"
|
|
57
|
+
]
|
|
31
58
|
},
|
|
32
59
|
"meta": {
|
|
33
60
|
"framework": "rust",
|
|
@@ -37,7 +64,11 @@
|
|
|
37
64
|
{
|
|
38
65
|
"externalId": "crate::auth::tests::test_login_invalid_password",
|
|
39
66
|
"title": "Login with invalid password returns 401",
|
|
40
|
-
"titlePath": [
|
|
67
|
+
"titlePath": [
|
|
68
|
+
"auth",
|
|
69
|
+
"tests",
|
|
70
|
+
"Login with invalid password returns 401"
|
|
71
|
+
],
|
|
41
72
|
"sourceFile": "src/auth.rs",
|
|
42
73
|
"sourceLine": 145,
|
|
43
74
|
"status": "fail",
|
|
@@ -54,7 +85,11 @@
|
|
|
54
85
|
{
|
|
55
86
|
"externalId": "crate::auth::tests::test_login_rate_limiting",
|
|
56
87
|
"title": "Login is rate-limited after 5 failed attempts",
|
|
57
|
-
"titlePath": [
|
|
88
|
+
"titlePath": [
|
|
89
|
+
"auth",
|
|
90
|
+
"tests",
|
|
91
|
+
"Login is rate-limited after 5 failed attempts"
|
|
92
|
+
],
|
|
58
93
|
"sourceFile": "src/auth.rs",
|
|
59
94
|
"sourceLine": 170,
|
|
60
95
|
"status": "skip",
|
|
@@ -68,7 +103,11 @@
|
|
|
68
103
|
{
|
|
69
104
|
"externalId": "crate::cart::tests::test_complete_checkout",
|
|
70
105
|
"title": "Complete checkout with credit card",
|
|
71
|
-
"titlePath": [
|
|
106
|
+
"titlePath": [
|
|
107
|
+
"cart",
|
|
108
|
+
"tests",
|
|
109
|
+
"Complete checkout with credit card"
|
|
110
|
+
],
|
|
72
111
|
"sourceFile": "src/cart.rs",
|
|
73
112
|
"sourceLine": 88,
|
|
74
113
|
"status": "pass",
|
|
@@ -76,14 +115,35 @@
|
|
|
76
115
|
"story": {
|
|
77
116
|
"scenario": "Complete checkout with credit card",
|
|
78
117
|
"steps": [
|
|
79
|
-
{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
118
|
+
{
|
|
119
|
+
"keyword": "Given",
|
|
120
|
+
"text": "a cart with 2 items totaling $59.98"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"keyword": "When",
|
|
124
|
+
"text": "the user submits payment with a test credit card"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"keyword": "Then",
|
|
128
|
+
"text": "the order is confirmed"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"keyword": "And",
|
|
132
|
+
"text": "a confirmation email is queued"
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
"tags": [
|
|
136
|
+
"checkout",
|
|
137
|
+
"payments",
|
|
138
|
+
"e2e"
|
|
139
|
+
],
|
|
140
|
+
"tickets": [
|
|
141
|
+
"SHOP-200"
|
|
142
|
+
],
|
|
143
|
+
"suitePath": [
|
|
144
|
+
"cart",
|
|
145
|
+
"tests"
|
|
83
146
|
],
|
|
84
|
-
"tags": ["checkout", "payments", "e2e"],
|
|
85
|
-
"tickets": ["SHOP-200"],
|
|
86
|
-
"suitePath": ["cart", "tests"],
|
|
87
147
|
"sourceOrder": 0
|
|
88
148
|
},
|
|
89
149
|
"meta": {
|
|
@@ -94,7 +154,11 @@
|
|
|
94
154
|
{
|
|
95
155
|
"externalId": "crate::cart::tests::test_empty_cart_checkout",
|
|
96
156
|
"title": "Cannot checkout with an empty cart",
|
|
97
|
-
"titlePath": [
|
|
157
|
+
"titlePath": [
|
|
158
|
+
"cart",
|
|
159
|
+
"tests",
|
|
160
|
+
"Cannot checkout with an empty cart"
|
|
161
|
+
],
|
|
98
162
|
"sourceFile": "src/cart.rs",
|
|
99
163
|
"sourceLine": 115,
|
|
100
164
|
"status": "pass",
|
|
@@ -198,6 +198,11 @@
|
|
|
198
198
|
"type": "integer",
|
|
199
199
|
"minimum": 0,
|
|
200
200
|
"description": "Order in which the story was defined in source (for stable sorting)."
|
|
201
|
+
},
|
|
202
|
+
"otelSpans": {
|
|
203
|
+
"type": "array",
|
|
204
|
+
"items": { "type": "object" },
|
|
205
|
+
"description": "OpenTelemetry spans captured for this scenario (from autotel), used to render a trace waterfall."
|
|
201
206
|
}
|
|
202
207
|
},
|
|
203
208
|
"required": ["scenario"],
|
|
@@ -386,6 +391,20 @@
|
|
|
386
391
|
"required": ["kind", "path", "phase"],
|
|
387
392
|
"additionalProperties": false
|
|
388
393
|
},
|
|
394
|
+
{
|
|
395
|
+
"type": "object",
|
|
396
|
+
"description": "Video reference with optional caption and poster image.",
|
|
397
|
+
"properties": {
|
|
398
|
+
"kind": { "const": "video" },
|
|
399
|
+
"path": { "type": "string" },
|
|
400
|
+
"caption": { "type": "string" },
|
|
401
|
+
"poster": { "type": "string" },
|
|
402
|
+
"phase": { "$ref": "#/$defs/DocPhase" },
|
|
403
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/DocEntry" }, "description": "Nested child doc entries for grouping." }
|
|
404
|
+
},
|
|
405
|
+
"required": ["kind", "path", "phase"],
|
|
406
|
+
"additionalProperties": false
|
|
407
|
+
},
|
|
389
408
|
{
|
|
390
409
|
"type": "object",
|
|
391
410
|
"description": "Custom documentation entry with arbitrary data.",
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://executable-stories.dev/schemas/scenario-index-v1.json",
|
|
4
|
+
"title": "Executable Stories Scenario Index v1",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["schemaVersion", "runId", "generatedAtMs", "summary", "scenarios"],
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"schemaVersion": { "const": "1.0" },
|
|
10
|
+
"runId": { "type": "string" },
|
|
11
|
+
"generatedAtMs": { "type": "number" },
|
|
12
|
+
"summary": { "$ref": "#/$defs/summary" },
|
|
13
|
+
"scenarios": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"items": { "$ref": "#/$defs/scenario" }
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"$defs": {
|
|
19
|
+
"status": { "enum": ["passed", "failed", "skipped", "pending"] },
|
|
20
|
+
"summary": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"required": ["total", "passed", "failed", "skipped", "pending", "durationMs"],
|
|
23
|
+
"additionalProperties": false,
|
|
24
|
+
"properties": {
|
|
25
|
+
"total": { "type": "number" },
|
|
26
|
+
"passed": { "type": "number" },
|
|
27
|
+
"failed": { "type": "number" },
|
|
28
|
+
"skipped": { "type": "number" },
|
|
29
|
+
"pending": { "type": "number" },
|
|
30
|
+
"durationMs": { "type": "number" }
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"scenario": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"required": ["id", "title", "status", "feature", "sourceFile", "tags", "tickets", "covers", "durationMs", "steps", "docKinds"],
|
|
36
|
+
"additionalProperties": false,
|
|
37
|
+
"properties": {
|
|
38
|
+
"id": { "type": "string" },
|
|
39
|
+
"title": { "type": "string" },
|
|
40
|
+
"status": { "$ref": "#/$defs/status" },
|
|
41
|
+
"feature": { "type": "string" },
|
|
42
|
+
"sourceFile": { "type": "string" },
|
|
43
|
+
"sourceLine": { "type": "number" },
|
|
44
|
+
"tags": { "type": "array", "items": { "type": "string" } },
|
|
45
|
+
"covers": { "type": "array", "items": { "type": "string" } },
|
|
46
|
+
"tickets": {
|
|
47
|
+
"type": "array",
|
|
48
|
+
"items": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"required": ["id"],
|
|
51
|
+
"additionalProperties": false,
|
|
52
|
+
"properties": {
|
|
53
|
+
"id": { "type": "string" },
|
|
54
|
+
"url": { "type": "string" }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"durationMs": { "type": "number" },
|
|
59
|
+
"steps": { "type": "array", "items": { "$ref": "#/$defs/step" } },
|
|
60
|
+
"docKinds": { "type": "array", "items": { "type": "string" } },
|
|
61
|
+
"error": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"required": ["message"],
|
|
64
|
+
"additionalProperties": false,
|
|
65
|
+
"properties": {
|
|
66
|
+
"message": { "type": "string" },
|
|
67
|
+
"stack": { "type": "string" }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"step": {
|
|
73
|
+
"type": "object",
|
|
74
|
+
"required": ["id", "index", "keyword", "text", "status", "durationMs", "docKinds"],
|
|
75
|
+
"additionalProperties": false,
|
|
76
|
+
"properties": {
|
|
77
|
+
"id": { "type": "string" },
|
|
78
|
+
"index": { "type": "number" },
|
|
79
|
+
"keyword": { "enum": ["Given", "When", "Then", "And", "But"] },
|
|
80
|
+
"text": { "type": "string" },
|
|
81
|
+
"status": { "$ref": "#/$defs/status" },
|
|
82
|
+
"durationMs": { "type": "number" },
|
|
83
|
+
"errorMessage": { "type": "string" },
|
|
84
|
+
"docKinds": { "type": "array", "items": { "type": "string" } }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -131,6 +131,11 @@
|
|
|
131
131
|
"type": "array",
|
|
132
132
|
"items": { "$ref": "#/$defs/Ticket" }
|
|
133
133
|
},
|
|
134
|
+
"covers": {
|
|
135
|
+
"type": "array",
|
|
136
|
+
"items": { "type": "string" },
|
|
137
|
+
"description": "Product-code paths/globs this scenario exercises."
|
|
138
|
+
},
|
|
134
139
|
"sourceLine": { "type": "integer", "minimum": 1 },
|
|
135
140
|
"errorMessage": { "type": "string" },
|
|
136
141
|
"errorStack": { "type": "string" },
|
|
@@ -247,6 +252,7 @@
|
|
|
247
252
|
{ "$ref": "#/$defs/DocSection" },
|
|
248
253
|
{ "$ref": "#/$defs/DocMermaid" },
|
|
249
254
|
{ "$ref": "#/$defs/DocScreenshot" },
|
|
255
|
+
{ "$ref": "#/$defs/DocVideo" },
|
|
250
256
|
{ "$ref": "#/$defs/DocCustom" }
|
|
251
257
|
]
|
|
252
258
|
},
|
|
@@ -391,6 +397,22 @@
|
|
|
391
397
|
"required": ["kind", "path", "phase"],
|
|
392
398
|
"additionalProperties": false
|
|
393
399
|
},
|
|
400
|
+
"DocVideo": {
|
|
401
|
+
"type": "object",
|
|
402
|
+
"properties": {
|
|
403
|
+
"kind": { "const": "video" },
|
|
404
|
+
"path": { "type": "string" },
|
|
405
|
+
"caption": { "type": "string" },
|
|
406
|
+
"poster": { "type": "string" },
|
|
407
|
+
"phase": { "$ref": "#/$defs/DocPhase" },
|
|
408
|
+
"children": {
|
|
409
|
+
"type": "array",
|
|
410
|
+
"items": { "$ref": "#/$defs/DocEntry" }
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
"required": ["kind", "path", "phase"],
|
|
414
|
+
"additionalProperties": false
|
|
415
|
+
},
|
|
394
416
|
"DocCustom": {
|
|
395
417
|
"type": "object",
|
|
396
418
|
"properties": {
|