@vijaypjavvadi/bdd2pw 3.8.1 → 3.9.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/CHANGELOG.md +81 -0
- package/README.md +396 -332
- package/dist/index.js +29 -1
- package/dist/index.js.map +1 -1
- package/dist/llm/index.d.ts +1 -0
- package/dist/llm/index.js +4 -1
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/prompt.js +66 -66
- package/dist/llm/telemetry.d.ts +150 -0
- package/dist/llm/telemetry.js +230 -0
- package/dist/llm/telemetry.js.map +1 -0
- package/dist/types.d.ts +11 -0
- package/package.json +1 -1
- package/templates/heal.ts.tmpl +452 -452
package/README.md
CHANGED
|
@@ -1,332 +1,396 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
##
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
|
293
|
-
|
|
|
294
|
-
|
|
|
295
|
-
|
|
|
296
|
-
|
|
|
297
|
-
| `
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
|
302
|
-
|
|
303
|
-
|
|
|
304
|
-
|
|
|
305
|
-
|
|
|
306
|
-
|
|
|
307
|
-
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
1
|
+
[](https://doi.org/10.5281/zenodo.20450278)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
# bdd2pw — Gherkin `.feature` → Playwright TypeScript scaffold
|
|
5
|
+
|
|
6
|
+
# @vijaypjavvadi/bdd2pw
|
|
7
|
+
|
|
8
|
+
[](https://www.npmjs.com/package/@vijaypjavvadi/bdd2pw)
|
|
9
|
+
[](https://www.npmjs.com/package/@vijaypjavvadi/bdd2pw)
|
|
10
|
+
[](https://www.npmjs.com/package/@vijaypjavvadi/bdd2pw)
|
|
11
|
+
[](https://github.com/javvadivijayprasad/bdd2pw/blob/main/LICENSE)
|
|
12
|
+
[](https://github.com/mxschmitt/awesome-playwright)
|
|
13
|
+
|
|
14
|
+
> Scaffold runnable Playwright TypeScript tests from Gherkin `.feature` files. Auto-detects existing Page Objects, scans live pages via Microsoft Playwright MCP, emits POMs and specs ready for execution. CLI + HTTP service.
|
|
15
|
+
|
|
16
|
+
[](LICENSE)
|
|
17
|
+
[](https://nodejs.org/)
|
|
18
|
+
[](https://www.npmjs.com/package/@vijaypjavvadi/bdd2pw)
|
|
19
|
+
[](./tests)
|
|
20
|
+
[](./src/transformers)
|
|
21
|
+
[](./src/transformers/domains)
|
|
22
|
+
[](https://marketplace.visualstudio.com/items?itemName=vijaypjavvadi.bdd2pw)
|
|
23
|
+
|
|
24
|
+
Most teams writing BDD test cases (via Cucumber `.feature` files, possibly authored by an LLM) face the same gap: the `.feature` describes the test, but **someone still has to write the Page Objects and the Playwright spec by hand**. That's the work `bdd2pw` does for you.
|
|
25
|
+
|
|
26
|
+
Point it at a `.feature` file and a URL. It parses the Gherkin, scans the live page with Chromium, picks the most stable locator for every interactive element, matches each step to a POM method call, and emits a runnable Playwright TypeScript repo — including `playwright.config.ts`, `pages/login.page.ts`, `tests/login.spec.ts`, and a `BDD_REVIEW.md` listing anything a human still needs to look at.
|
|
27
|
+
|
|
28
|
+
## What `bdd2pw` is and isn't (as of v3.8.1)
|
|
29
|
+
|
|
30
|
+
`bdd2pw` is a **deterministic scaffolder with an optional governed LLM fallback**. The output is honest about its limits:
|
|
31
|
+
|
|
32
|
+
- **Specific `.feature` files** — quoted credentials, concrete assertion targets, standard verb forms — convert to **runnable specs with zero hand-edits**. Validated end-to-end against real public sites (`practicetestautomation.com`, `owasp-juice-shop`): every scenario green.
|
|
33
|
+
- **Vague `.feature` files** — "Enter valid username and password and click login button" with no quoted values — get partial coverage. Unmatched steps either route to the LLM fallback (when an Anthropic / OpenAI key is configured) or land as `// TODO` comments + warnings in `BDD_REVIEW.md`.
|
|
34
|
+
- **200+ deterministic rules**, organised across three layers:
|
|
35
|
+
- **API rules** (v3.0+) — `page.request.*` patterns for GET / POST / PUT / DELETE / PATCH, body / header / status assertions.
|
|
36
|
+
- **Visibility rules** (v3.1+) — `<noun> is visible / displayed / shown / appears` intercepts before URL-slug heuristics, so prose like "the user's name or profile indicator is visible in the UI" never gets slugified into a URL regex.
|
|
37
|
+
- **UI + URL rules** (v1.x lineage, refined through v3.7.1) — 30+ rules covering first-person, third-person, no-subject Cucumber dialects + compound input steps.
|
|
38
|
+
- **7 opt-in domain rule packs** (v3.4 + v3.8) — banking, healthcare, insurance, retail, gov, education, telecom. Each adds ~20 industry-specific patterns. Activated via `domains: ["banking"]`; empty by default for byte-stable existing behaviour.
|
|
39
|
+
- **LLM fallback is batched per scenario** (v3.5) — one Anthropic / OpenAI / Gemini call per scenario instead of one per unmatched step. ~75% cost reduction on unmatched-heavy scaffolds. Every prompt goes through the `ai-governance` sidecar's `/sanitize` endpoint (fail-closed).
|
|
40
|
+
- **`updatePom` is append-only by construction.** Re-scanning a page that already has a Page Object adds new locators only. Hand-edited method bodies, custom helper methods, custom imports are all preserved byte-identical.
|
|
41
|
+
- **`--merge` mode** (v3.2) preserves `// bdd2pw:user-block id="..."` sections across regenerations so iterative locator tuning doesn't lose work.
|
|
42
|
+
|
|
43
|
+
> **The pitch.** Run `bdd2pw scaffold` and you get a Playwright TS repo where `npx playwright test` runs against the real site. For specific fixtures, all green. For vague ones, the 60-90% you'd otherwise hand-write is done; you finish the rest — or you let the governed LLM finish them.
|
|
44
|
+
|
|
45
|
+
## What's new in v3.9.0
|
|
46
|
+
|
|
47
|
+
- **NEW** `llmStats: true` writes `<repo>/artefacts/llm-stats.json` with per-call latency, token counts, cache hit rate, and an estimated cost in USD. Finally makes the v3.5 batching ROI measurable per run.
|
|
48
|
+
- Seven domain rule packs (banking, healthcare, insurance, retail, gov, education, telecom) — ~140 industry-specific patterns total.
|
|
49
|
+
- Per-scenario LLM batching cuts Anthropic spend by ~75% on unmatched-heavy scaffolds.
|
|
50
|
+
- `bdd2pw propose-rules` CLI clusters past LLM bindings into draft regex proposals — turning the offline-review pipeline into one command.
|
|
51
|
+
- `diagnostics: true` adds a "Rule trace" block to `BDD_REVIEW.md` showing exactly which rules declined a step and why.
|
|
52
|
+
- `merge: true` preserves user-edited blocks across regenerations.
|
|
53
|
+
- `metaSidecar: true` writes `<spec>.spec.meta.json` describing every step's semantic intent for downstream tools.
|
|
54
|
+
- VS Code extension (`vijaypjavvadi.bdd2pw`) v0.2.0 surfaces all the above as settings + commands.
|
|
55
|
+
|
|
56
|
+
## Where this fits in the platform
|
|
57
|
+
|
|
58
|
+
| Stage | Service | Role |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| 1. Generate | `test-case-generation-service` (FastAPI :4100) | Author `.feature` files from requirements |
|
|
61
|
+
| **1.5. Scaffold** | **`bdd2pw` (this repo) — Express :4300 + CLI** | `.feature` + URL → POM + spec, ready to run |
|
|
62
|
+
| 2. Migrate | [`@vijaypjavvadi/sel2pw`](https://github.com/javvadivijayprasad/sel2pw) (Express :4200) | Legacy Selenium → Playwright |
|
|
63
|
+
| 3. Stabilise | `self-healing-stage-services` (FastAPI :8003) | Heal locators at runtime |
|
|
64
|
+
| 4. Govern | `ai-governance` (Python lib + sidecar :8004) | Sanitise every LLM payload (when v1.1 LLM fallback ships) |
|
|
65
|
+
| Orchestrate | `modern-automation-platform` (Express :3000) | Auth, jobs, UI, artifacts |
|
|
66
|
+
|
|
67
|
+
`bdd2pw` and `sel2pw` are siblings. Both consume **`@vijaypjavvadi/pw-emit`** (the shared emitter library), so the Page Objects produced by one are byte-identical in shape to those produced by the other.
|
|
68
|
+
|
|
69
|
+
## Install
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm install -D @vijaypjavvadi/bdd2pw
|
|
73
|
+
npx playwright install chromium # browser for live page discovery
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Node ≥ 18. Cross-platform (Linux / macOS / Windows). `playwright` is an optional dep — if you don't install browsers, pass `--snapshot-file <path.json>` instead.
|
|
77
|
+
|
|
78
|
+
## Quick start
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Scaffold a runnable Playwright TS project from a .feature file
|
|
82
|
+
npx bdd2pw scaffold path/to/login.feature \
|
|
83
|
+
--url https://your-app.example.com/login \
|
|
84
|
+
--page LoginPage \
|
|
85
|
+
--repo ./my-tests
|
|
86
|
+
|
|
87
|
+
cd ./my-tests
|
|
88
|
+
npm install
|
|
89
|
+
npx playwright test
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
That's it. `./my-tests` now has `pages/login.page.ts`, `tests/login.spec.ts`, `playwright.config.ts`, `package.json`, `tsconfig.json`, `.gitignore`, and `BDD_REVIEW.md`.
|
|
93
|
+
|
|
94
|
+
## LLM fallback (v2.0+)
|
|
95
|
+
|
|
96
|
+
When a Gherkin step doesn't match any of bdd2pw's 30 deterministic rules, you can opt-in to an Anthropic-backed LLM fallback that produces the binding instead of dropping to `// TODO`. Off by default.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Anthropic API key — required when --llm anthropic is set
|
|
100
|
+
export ANTHROPIC_API_KEY=sk-ant-api03-...
|
|
101
|
+
|
|
102
|
+
bdd2pw scaffold ./my.feature \
|
|
103
|
+
--url https://app.example.com \
|
|
104
|
+
--page LoginPage \
|
|
105
|
+
--repo ./out \
|
|
106
|
+
--llm anthropic \
|
|
107
|
+
--governance-url http://localhost:4900
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Every successful LLM-binding is appended to `<repo>/artefacts/candidate-rules.jsonl` so an offline review pipeline can propose new deterministic rules. Auto-write back to `stepMatcher.ts` is deferred to v2.1+ — for v2.0 the LLM is a runtime overlay, never a code generator for the matcher itself.
|
|
111
|
+
|
|
112
|
+
### Governance sanitization (mandatory by default)
|
|
113
|
+
|
|
114
|
+
Per the platform contract, **every prompt passes through the `ai-governance` sidecar's `/sanitize` endpoint** before reaching Anthropic. This scrubs API keys, JWTs, AWS creds, and other secrets that might leak via test data in the `.feature` file. **Fail-closed** — if the sidecar is unreachable, the LLM call is REFUSED and the step falls back to TODO.
|
|
115
|
+
|
|
116
|
+
Two ways to satisfy this:
|
|
117
|
+
|
|
118
|
+
**(a) Internal platform users:** the `ai-governance` service is part of your platform service mesh. Just point bdd2pw at it (`--governance-url http://ai-governance:4900` or wherever).
|
|
119
|
+
|
|
120
|
+
**(b) External users:** run your own sidecar.
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Clone and run the sidecar
|
|
124
|
+
git clone https://github.com/javvadivijayprasad/ai-governance
|
|
125
|
+
cd ai-governance
|
|
126
|
+
python -m venv .venv && .\.venv\Scripts\Activate.ps1 # or `source .venv/bin/activate` on Mac/Linux
|
|
127
|
+
pip install fastapi uvicorn pydantic pyyaml
|
|
128
|
+
PYTHONPATH=src uvicorn service.app:app --port 4900
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Or there's a Docker image once it's published: `docker run -p 4900:4900 ghcr.io/javvadivijayprasad/ai-governance:latest`.
|
|
132
|
+
|
|
133
|
+
**Test-only escape hatch:** `--llm-skip-governance` bypasses the sidecar entirely. Use only when your `.feature` data is synthetic (no real credentials, no PII). For production, **always** keep governance on.
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# UNSAFE for real test data — use only with synthetic fixtures
|
|
137
|
+
bdd2pw scaffold ./my.feature ... --llm anthropic --llm-skip-governance
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Cost + determinism guardrails
|
|
141
|
+
|
|
142
|
+
| Flag | Default | Purpose |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| `--llm-max-calls <n>` | `50` | Hard cap on provider calls per scaffold. Cache hits don't count. |
|
|
145
|
+
| `--llm-cache <path>` | `<repo>/.bdd2pw/llm-cache.sqlite` | SQLite cache keyed by step text + POM signature + model. Same inputs across runs return the same binding — cost goes to zero on re-runs. Pass `:memory:` for one-shot use. |
|
|
146
|
+
| `--llm-model <model>` | `claude-sonnet-4-6` | Override the Anthropic model. |
|
|
147
|
+
|
|
148
|
+
Re-runs of the same `.feature` (after a code edit, retry, etc.) will hit the cache and make zero provider calls. A typical per-scaffold cost on first run: ~$0.005–0.02 USD with Sonnet, depending on how many steps need LLM fallback.
|
|
149
|
+
|
|
150
|
+
### Cloud-jobs deployment recipe
|
|
151
|
+
|
|
152
|
+
If you're running bdd2pw in an automation pipeline (cloud-jobs-template, GitHub Actions, etc.):
|
|
153
|
+
|
|
154
|
+
```yaml
|
|
155
|
+
env:
|
|
156
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} # platform secrets store
|
|
157
|
+
|
|
158
|
+
steps:
|
|
159
|
+
- name: Run scaffold with LLM fallback
|
|
160
|
+
run: |
|
|
161
|
+
bdd2pw scaffold "$FEATURE_FILE" \
|
|
162
|
+
--url "$TARGET_URL" \
|
|
163
|
+
--page "$PAGE_NAME" \
|
|
164
|
+
--repo /work \
|
|
165
|
+
--self-healing \
|
|
166
|
+
--llm anthropic \
|
|
167
|
+
--governance-url http://ai-governance:4900
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Make sure the `ai-governance` sidecar is co-located (k8s sidecar pattern) or reachable on the platform service mesh.
|
|
171
|
+
|
|
172
|
+
## CLI surface — three commands
|
|
173
|
+
|
|
174
|
+
### `scaffold` — generate a fresh repo
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
bdd2pw scaffold <feature> --url <url> --page <Name> --repo <dir> [options]
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Reads the `.feature`, scans the URL with Chromium, picks locators, matches steps, emits the project. Flags:
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
--snapshot-file <path> Use a captured JSON snapshot instead of launching a browser
|
|
184
|
+
--no-discovery Skip page discovery entirely (rule-only probing)
|
|
185
|
+
--storage-state <path> Pre-authenticated storage state JSON
|
|
186
|
+
--headed Show browser during scan
|
|
187
|
+
--templates <dir> Override default project templates
|
|
188
|
+
--dry-run Print plan, write nothing
|
|
189
|
+
--no-validate Skip tsc --noEmit step
|
|
190
|
+
--force Overwrite existing spec files
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### `analyze` — dry-run the matcher
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
bdd2pw analyze <feature> --url <url> [options]
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Same pipeline but writes nothing — prints the parsed feature, the discovered locators, and the planned step bindings as JSON. Useful for "what would scaffold do?" probing.
|
|
200
|
+
|
|
201
|
+
### `update-pom` — merge new locators into an existing POM
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
bdd2pw update-pom --page <Name> --url <url> --repo <dir> [options]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Re-scan the page and **append** any newly-discovered locators to the existing Page Object. Never touches existing fields, methods, or specs. Hand-edited method bodies survive byte-identical.
|
|
208
|
+
|
|
209
|
+
## HTTP service
|
|
210
|
+
|
|
211
|
+
`bdd2pw serve` starts an Express service on `:4300` with the same three commands as REST endpoints. Mirror of the CLI; HTTP is a thin shell.
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
bdd2pw serve --port 4300
|
|
215
|
+
|
|
216
|
+
# In another terminal:
|
|
217
|
+
curl -X POST http://localhost:4300/scaffold \
|
|
218
|
+
-H 'content-type: application/json' \
|
|
219
|
+
-d '{"feature":"/abs/path/to/login.feature","url":"https://...","page":"LoginPage","repo":"unused","options":{"snapshotFile":"/abs/snapshot.json","noValidate":true}}'
|
|
220
|
+
# → 202 Accepted: {"jobId":"01HX...","links":{"self":"/jobs/01HX...","artifact":"/jobs/01HX.../artifact"}}
|
|
221
|
+
|
|
222
|
+
curl http://localhost:4300/jobs/01HX... # poll for completion
|
|
223
|
+
curl -O http://localhost:4300/jobs/01HX.../artifact # download zip
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
| Endpoint | Purpose |
|
|
227
|
+
|---|---|
|
|
228
|
+
| `GET /healthz`, `/version`, `/readyz` | Liveness probes |
|
|
229
|
+
| `POST /scaffold`, `/analyze`, `/update-pom` | Async job — returns `202` + `jobId` |
|
|
230
|
+
| `GET /jobs/:id` | Job status / progress / result |
|
|
231
|
+
| `GET /jobs/:id/artifact` | Stream zip of the scaffolded repo |
|
|
232
|
+
| `GET /jobs/:id/log` | Plain-text dump of warnings + errors |
|
|
233
|
+
|
|
234
|
+
In production, the platform gateway proxies `/api/v1/scaffold/*` to `:4300`. Direct port exposure is local-dev only.
|
|
235
|
+
|
|
236
|
+
## Pipeline
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
.feature file
|
|
240
|
+
│
|
|
241
|
+
▼
|
|
242
|
+
┌──────────────┐
|
|
243
|
+
│ gherkinParser│ @cucumber/gherkin → FeatureIR (scenarios, background, examples)
|
|
244
|
+
└──────┬───────┘
|
|
245
|
+
▼
|
|
246
|
+
┌──────────────┐
|
|
247
|
+
│ repoScanner │ ts-morph → existing pages/*.page.ts → Map<class, IR>
|
|
248
|
+
└──────┬───────┘
|
|
249
|
+
▼
|
|
250
|
+
┌──────────────┐
|
|
251
|
+
│ pomResolver │ CREATE / AUGMENT / REUSE decision
|
|
252
|
+
└──────┬───────┘
|
|
253
|
+
▼
|
|
254
|
+
┌──────────────┐
|
|
255
|
+
│ scanPage │ playwright chromium → DOM walk → ElementIR[]
|
|
256
|
+
│ │ (or --snapshot-file / --no-discovery fallbacks)
|
|
257
|
+
└──────┬───────┘
|
|
258
|
+
▼
|
|
259
|
+
┌──────────────┐
|
|
260
|
+
│ locatorPicker│ getByRole > getByLabel > getByPlaceholder > getByTestId
|
|
261
|
+
│ │ > getByText > css > xpath
|
|
262
|
+
│ │ Status-region special case + dedup by (api, args)
|
|
263
|
+
└──────┬───────┘
|
|
264
|
+
▼
|
|
265
|
+
┌──────────────┐
|
|
266
|
+
│ stepMatcher │ 30 rules — subject-agnostic, dialect-tolerant,
|
|
267
|
+
│ │ compound-input via customBody
|
|
268
|
+
└──────┬───────┘
|
|
269
|
+
▼
|
|
270
|
+
┌──────────────┐
|
|
271
|
+
│ pw-emit │ @vijaypjavvadi/pw-emit → POM TS + spec TS + project scaffold
|
|
272
|
+
└──────┬───────┘
|
|
273
|
+
▼
|
|
274
|
+
┌──────────────┐
|
|
275
|
+
│ tscRunner │ Optional tsc --noEmit → diagnostics into BDD_REVIEW.md
|
|
276
|
+
└──────┬───────┘
|
|
277
|
+
▼
|
|
278
|
+
output/
|
|
279
|
+
pages/<name>.page.ts
|
|
280
|
+
tests/<name>.spec.ts
|
|
281
|
+
playwright.config.ts
|
|
282
|
+
package.json, tsconfig.json, .gitignore
|
|
283
|
+
BDD_REVIEW.md ← warnings + manual TODOs
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## What `bdd2pw` covers
|
|
287
|
+
|
|
288
|
+
### Step matcher rules (14)
|
|
289
|
+
|
|
290
|
+
| # | Pattern | Emits |
|
|
291
|
+
|---|---|---|
|
|
292
|
+
| 1 | `(I/user) am on/navigate to/visit/open <X>` (with or without quoted URL) | `goto()` |
|
|
293
|
+
| 2a | `(I/user) enter "<value>" into <field>` | `<field>.fill("<value>")` |
|
|
294
|
+
| 2b | `(I/user) enter <field> "<value>"` | `<field>.fill("<value>")` |
|
|
295
|
+
| 2c | **Compound:** `(I/user) enter <f1> "<v1>" <f2> "<v2>" ...` | N `.fill()` lines |
|
|
296
|
+
| 3 | `(I/user/-) click/press/tap <X> button/link/icon/tab` | `<field>.click()` (or POM method if defined) |
|
|
297
|
+
| 4 | `(I/user) select "<opt>" from <dropdown>` | `<field>.selectOption(...)` |
|
|
298
|
+
| 5 | `(I/user) check/uncheck <checkbox>` | `<field>.check()` / `.uncheck()` |
|
|
299
|
+
| 6 | `(I/user) (should) see <X>` | `expect(<X>).toBeVisible()` |
|
|
300
|
+
| 7 | `(I/user) should not see <X>` | `expect(<X>).toBeHidden()` |
|
|
301
|
+
| 8 | `(I/user) should see (the/an/a) error message "<X>"` | `expect(<errorField>).toContainText("<X>")` |
|
|
302
|
+
| 9a | `(I/user) should see <X> containing/with text "<Y>"` | `expect(<X>).toContainText("<Y>")` |
|
|
303
|
+
| 9b | `(I/user) should see <X> "<Y>"` (exact equality) | `expect(<X>).toHaveText("<Y>")` |
|
|
304
|
+
| 10 | `(I/user) should remain on <page>` | `expect(page).toHaveURL(/<page>/)` |
|
|
305
|
+
| 11 | `(I/user) (should be/is) redirected to <page>` | `expect(page).toHaveURL(/<page>/)` |
|
|
306
|
+
| 12 | `the <field> field should be of type "<type>"` | `expect(<field>).toHaveAttribute("type", "<type>")` |
|
|
307
|
+
| 13 | `the (current) URL should start with/contain "<X>"` | `expect(page).toHaveURL(/^<X>/)` |
|
|
308
|
+
|
|
309
|
+
### Cucumber features
|
|
310
|
+
|
|
311
|
+
- `Background:` → `test.beforeEach`
|
|
312
|
+
- `Scenario Outline:` + `Examples:` → one `test()` per row, with placeholder substitution
|
|
313
|
+
- `Tags` → emitted as `// @tag` comments above each test
|
|
314
|
+
- Doc strings + data tables — preserved on `StepIR.argument`
|
|
315
|
+
|
|
316
|
+
### Locator priority
|
|
317
|
+
|
|
318
|
+
`getByRole` (with accessible name) > `getByLabel` > `getByPlaceholder` > `getByTestId` > `getByText` > CSS > xpath. **Status regions** (`<div id="error">`, `[role=alert]`, `[class*=notification]`) bypass the visibility filter (they're hidden until triggered) and use their `id` for both field name and locator (text content is volatile, id is stable).
|
|
319
|
+
|
|
320
|
+
## Verification
|
|
321
|
+
|
|
322
|
+
| Check | Status |
|
|
323
|
+
|---|---|
|
|
324
|
+
| `npm run lint` | ✅ clean |
|
|
325
|
+
| `tsc --noEmit` | ✅ clean |
|
|
326
|
+
| `npm test` (vitest) | ✅ **101/101 green** across 10 test files |
|
|
327
|
+
| `practice-test-login` end-to-end vs the live site | ✅ **7/7** scenarios green via `npx playwright test` |
|
|
328
|
+
| `cms-login` (selenium14 dialect) regression | ✅ 12 assertions green, third-person + compound input + `is redirected` |
|
|
329
|
+
| HTTP worker zip download | ✅ end-to-end test verifies real ZIP magic bytes |
|
|
330
|
+
| `update-pom` preserves hand-edited method bodies | ✅ 5 byte-identical-survival assertions |
|
|
331
|
+
|
|
332
|
+
## Roadmap
|
|
333
|
+
|
|
334
|
+
### Shipped (Aug 2025 → May 2026)
|
|
335
|
+
|
|
336
|
+
| Version | Theme | Highlight |
|
|
337
|
+
|---|---|---|
|
|
338
|
+
| v1.0 | Foundation | Gherkin → Playwright TS scaffolding, POM resolver, file-snapshot discovery, HTTP worker service on `:4300`, `update-pom` AST surgery |
|
|
339
|
+
| v1.1 | Self-healing | `--self-healing` flag, `lib/heal.ts` template, JSONL event logging |
|
|
340
|
+
| v2.0 | LLM fallback | Anthropic SDK integration, governance sidecar `/sanitize`, SQLite step-binding cache, opt-in via `--llm anthropic` |
|
|
341
|
+
| v2.2 | Reliability | Promise.race watchdogs, ai-governance fail-closed, structured pino logging end-to-end |
|
|
342
|
+
| v3.0 | API testing | Native `page.request.*` patterns (~17 rules), tag-driven `@api` / `@ui` scenario state injection |
|
|
343
|
+
| v3.1 | TestForge P0+P1 | Visibility-prose intercept, `:root` locator rejection, `testInfo` in test signature, opt-in step hooks + boundary markers |
|
|
344
|
+
| v3.2 | Iteration UX | `playwright.config.ts` end-marker, exact-dep pinning, `*.spec.meta.json` sidecar, JSON scenarios input, `--merge` mode preserving `// bdd2pw:user-block` sections |
|
|
345
|
+
| v3.3 | Hook signature | `fixtures` arg + `status` + try/catch/finally wrapping for `beforeStep` / `afterStep` |
|
|
346
|
+
| v3.4 | Domain packs | Banking / healthcare / insurance opt-in rule packs (~60 new patterns) |
|
|
347
|
+
| v3.5 | LLM batching | One Anthropic call per scenario instead of N — ~75% cost reduction on unmatched-heavy scaffolds |
|
|
348
|
+
| v3.6 | Diagnostics + auto-rules | Rule-trace block in `BDD_REVIEW.md`; new `bdd2pw propose-rules` CLI clustering candidate-rules.jsonl into draft regex |
|
|
349
|
+
| v3.7.1 | Regression fixes | PascalCase className shadow fix; `test.step` wrapping regression-asserted |
|
|
350
|
+
| v3.8.1 | More domain packs | Retail / gov / education / telecom packs added — seven total (~140 industry-specific rules) |
|
|
351
|
+
| **v3.9.0 (current)** | Telemetry | `artefacts/llm-stats.json` sidecar — per-call latency + tokens + cache hit rate + estimated cost. Makes v3.5 batching ROI measurable per scaffold. |
|
|
352
|
+
|
|
353
|
+
### Next 6 months (Jun 2026 → Nov 2026, ~2 releases/month)
|
|
354
|
+
|
|
355
|
+
| Target | Version | Theme | Headline |
|
|
356
|
+
|---|---|---|---|
|
|
357
|
+
| Jun 2026 | **v3.10.0** | OpenAI provider | `LLMClientOptions.provider: "openai"` lands; multi-provider client factory; same governance + cache pipeline. |
|
|
358
|
+
| Jul 2026 | **v3.11.0** | Gemini provider | `LLMClientOptions.provider: "gemini"` lands; full three-provider parity (Anthropic / OpenAI / Gemini). |
|
|
359
|
+
| Jul 2026 | **v3.12.0** | Auto-rules | `bdd2pw apply-proposals --interactive` — walks the human through each v3.6 proposal, validates the regex compiles + matches the sample texts, optionally appends to `stepMatcher.ts`. Closes the propose-rules loop. |
|
|
360
|
+
| Aug 2026 | **v4.0.0** | Modern defaults | Semver-major reset: bump Anthropic default model, retire v2.x deprecated APIs, switch test-signature defaults to current best practice. Migration guide ships alongside. |
|
|
361
|
+
| Aug 2026 | **v4.1.0** | sel2pw merge | sel2pw migrated onto `@vijaypjavvadi/pw-emit` — three packages share one emitter. All future v3.x emitter improvements automatically flow to Selenium users. |
|
|
362
|
+
| Sep 2026 | **v4.2.0** | Domain packs | Three more opt-in packs: **fintech** (KYC, AML, trading desks), **real-estate** (MLS, listings, escrow), **hospitality** (PMS, reservations, OTA). ~60 more rules. |
|
|
363
|
+
| Sep 2026 | **v4.3.0** | API v2 | WebSocket assertion rules, multipart file-upload patterns, GraphQL query / mutation / subscription rules. Extends v3.0's API testing surface. |
|
|
364
|
+
| Oct 2026 | **v4.4.0** | Coverage analyzer | `bdd2pw coverage` CLI: which deterministic rules fired on which features across a fleet, per-pack hit rate, dead-rule report, suggestion to retire unused rules. |
|
|
365
|
+
| Oct 2026 | **v4.5.0** | CI/CD templates | Optional scaffolder output: GitHub Actions / GitLab CI / Azure Pipelines / CircleCI starter workflows wired to run the generated specs. Opt-in via `--ci <provider>`. |
|
|
366
|
+
| Nov 2026 | **v4.6.0** | Mobile dialect | Touch / swipe / scroll-into-view rules + responsive viewport assertions. Reuses the same emitter pipeline; opt-in via `domains: ["mobile"]`. |
|
|
367
|
+
| Nov 2026 | **v4.7.0** | i18n Gherkin | Accept Cucumber-compatible non-English keywords (Spanish, German, French, Portuguese, Japanese, …). Lets bdd2pw scaffold from `.feature` files written in any of the ~70 languages Cucumber supports. |
|
|
368
|
+
|
|
369
|
+
Each release is shaped to be self-contained, ship in ~2 weeks, and keep `domains: []` byte-stable for existing users so the upgrade path stays painless.
|
|
370
|
+
|
|
371
|
+
## Documents
|
|
372
|
+
|
|
373
|
+
| Doc | Purpose |
|
|
374
|
+
|---|---|
|
|
375
|
+
| [`docs/SCOPE.md`](./docs/SCOPE.md) | What's in / out of v1.0, FR/NFR, CLI + HTTP surface, decisions log |
|
|
376
|
+
| [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md) | Component diagram, sequence diagrams, `pw-emit` contract, HTTP API contract, error model |
|
|
377
|
+
| [`docs/PHASE_0_PLAN.md`](./docs/PHASE_0_PLAN.md) | The pw-emit extraction plan (mostly historical now — it shipped) |
|
|
378
|
+
| [`docs/STATUS.md`](./docs/STATUS.md) | Verified state right now — what works, what's pending, what's deferred |
|
|
379
|
+
| [`CHANGELOG.md`](./CHANGELOG.md) | Full version history |
|
|
380
|
+
| [`CONTRIBUTING.md`](./CONTRIBUTING.md) | Local dev, branching, PR conventions |
|
|
381
|
+
|
|
382
|
+
## Examples
|
|
383
|
+
|
|
384
|
+
- [`examples/practice-test-login/`](./examples/practice-test-login/) — first-person dialect, `Scenario Outline + Examples`, security scenarios. Validated 7/7 green against a live public site.
|
|
385
|
+
- [`examples/cms-login/`](./examples/cms-login/) — third-person dialect, compound input, `is redirected`. From a real OSS Selenium codebase.
|
|
386
|
+
## Citation
|
|
387
|
+
|
|
388
|
+
If you use `@vijaypjavvadi/bdd2pw` in academic work, please cite:
|
|
389
|
+
|
|
390
|
+
> Javvadi, V. P. (2026). *@vijaypjavvadi/bdd2pw: Live-DOM Page Object Scaffolding from Gherkin Specifications via the Microsoft Playwright MCP* (Version 3.8.1) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.20450278
|
|
391
|
+
|
|
392
|
+
A machine-readable [`CITATION.cff`](CITATION.cff) file is included in the repository root.
|
|
393
|
+
|
|
394
|
+
## License
|
|
395
|
+
|
|
396
|
+
MIT
|