@vijaypjavvadi/bdd2pw 2.2.4 → 2.2.6

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 CHANGED
@@ -9,6 +9,141 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  _Nothing yet._
11
11
 
12
+ ## [2.2.6] — 2026-05-11
13
+
14
+ ### Fixed — BUG-10 (P2): locator extractor picks framework-internal CSS classes
15
+
16
+ Cloud-job report 2026-05-11 20:08 against `https://preview.owasp-juice.shop`:
17
+ Angular's runtime-managed form-state classes (`.ng-untouched`,
18
+ `.ng-pristine`, `.ng-dirty`) were being picked as both the POM
19
+ field-name source AND the locator CSS selector. The POM emitted
20
+ `ngUntouchedInput = page.locator('.ng-untouched')` and the LLM then
21
+ used `ngUntouchedInput` for "search field has not yet been
22
+ interacted with" preconditions. The assertion failed because:
23
+
24
+ 1. `.ng-untouched` flips to `.ng-touched` the moment focus enters
25
+ the input — locators built on it are flaky by construction.
26
+ 2. Every Angular input shares the same state classes, so the
27
+ selector also fails strict-mode uniqueness.
28
+ 3. The field name itself is misleading — no test author would call
29
+ the search box "ng untouched input".
30
+
31
+ Same class of bug applies to anything prefixed `mat-*` (Angular
32
+ Material), `cdk-*` (CDK overlays / focus traps), `mdc-*` (Material
33
+ Design Components), and `_ngcontent-*` / `_nghost-*` (Angular view
34
+ encapsulation markers).
35
+
36
+ **Fix (two layers in `src/transformers/locatorPicker.ts`):**
37
+
38
+ 1. **Field-name source.** `cssSelectorToName` now skips
39
+ framework-prefix classes when walking a multi-class selector and
40
+ returns the first user-named class instead. For
41
+ `.ng-untouched.search-input` it returns `"search input"`, not
42
+ `"ng untouched"`. If EVERY class on the element is framework-only,
43
+ it returns undefined and the caller falls through to
44
+ `<role|tag>Element` — for an Angular input with no other handles,
45
+ the synthesised field name becomes `inputElement` rather than
46
+ `ngUntouchedInput`.
47
+
48
+ 2. **CSS-fallback gate.** `pickLocator`'s step-6 CSS fallback now
49
+ refuses framework-only selectors via `isFrameworkOnlySelector`.
50
+ When the element has no role / label / placeholder / testId /
51
+ text / xpath and the only CSS handle is something like
52
+ `.ng-untouched.ng-pristine`, we emit a tag-only locator
53
+ (`page.locator("input")`) and flag it `confidence: "fallback"`.
54
+ Tag-only is non-ideal but at least matches a real DOM element
55
+ instead of a transient state class.
56
+
57
+ New exports (both pure, easy to compose into future emitter rules):
58
+ - `isFrameworkClass(cls: string): boolean`
59
+ - `isFrameworkOnlySelector(selector: string | undefined): boolean`
60
+
61
+ Detection covered: `ng-*`, `mat-*`, `cdk-*`, `mdc-*`,
62
+ `_ngcontent-*`, `_nghost-*`. Hyphen-after-prefix is required so we
63
+ don't accidentally flag user-named classes like `nginx-banner` or
64
+ `ngo-button`.
65
+
66
+ ### Tests
67
+
68
+ `tests/unit/locatorPicker.test.ts` — full coverage for BUG-10:
69
+ - `isFrameworkClass` matches every prefix, leaves user classes
70
+ alone (including the deliberate near-misses `nginx-banner`,
71
+ `ngo-button`, `material-card`).
72
+ - `isFrameworkOnlySelector` flags pure framework selectors,
73
+ declines mixed selectors, declines `#id`-bearing selectors, declines
74
+ non-class selectors.
75
+ - `pickLocator` drops a framework-only CSS selector and falls back
76
+ to tag-only.
77
+ - `pickLocator` preserves selectors that have at least one
78
+ user-named class.
79
+ - `synthFieldName` skips framework classes and falls through to
80
+ `<role|tag>Element`.
81
+ - `synthFieldName` picks the user-named class in a mixed selector.
82
+
83
+ ## [2.2.5] — 2026-05-11
84
+
85
+ ### Fixed — BUG-9 (P0): POM field name starting with a digit broke entire spec
86
+
87
+ Cloud-job report 2026-05-11 19:46 against `https://preview.owasp-juice.shop`:
88
+ every test in `tests/r-0-c934-ddf-001.spec.ts` failed with a
89
+ **compile-time** `SyntaxError`, zero tests executed.
90
+
91
+ Root cause: juice-shop renders pagination labels like `"0 of 0"` and
92
+ `"1,500 of 0"` inside status regions. The locator-picker's field-name
93
+ synthesiser routed those through `camelCase`, which produced
94
+ `0Of0`, `1500Of0`, `0,0Of0`. JavaScript identifiers must start with
95
+ a letter / `$` / `_`, never a digit, and cannot contain commas.
96
+
97
+ The emitted POM and spec looked like:
98
+
99
+ this.0Of0 = page.getByText("0 of 0");
100
+ // ^^^ SyntaxError
101
+ await expect(r0c934ddf001.0Of0).toBeVisible();
102
+ // ^^^ SyntaxError
103
+
104
+ This is worse than a runtime failure: there's no triage signal,
105
+ just a hard parse error, and the entire scenario set is skipped.
106
+
107
+ **Fix (defence in depth — three layers):**
108
+
109
+ 1. **Identifier-safe naming helper.** New `toJsIdentifier(s)` in
110
+ `src/utils/naming.ts`. Strips any character not in `[A-Za-z0-9_$]`,
111
+ prefixes digit-leading identifiers with `_`, falls back to
112
+ `_field` for empty input. Pure function, fully unit-tested.
113
+
114
+ 2. **POM emitter.** `synthFieldName` in
115
+ `src/transformers/locatorPicker.ts` runs the post-camelCase result
116
+ through `toJsIdentifier`. Both the main path and the status-region
117
+ special case are covered. So `"0 of 0"` now becomes `_0Of0`,
118
+ `"1,500 of 0"` becomes `_1500Of0`. The POM declares
119
+ `this._0Of0 = page.getByText("0 of 0")` — valid TS.
120
+
121
+ 3. **Binding renderer safety net.** New `sanitizeLocatorReferences(s)`
122
+ in `src/emitters/facade.ts` rewrites `.<digit-leading>` member
123
+ access and `[<digit-leading>]` bracket access to be `_`-prefixed.
124
+ Applied to `assertion.locator`, `pomCall.method`, every
125
+ `pomCall.args` entry, and every line of `customBody`. This catches
126
+ cached LLM bindings from v2.2.4 or earlier that reference the old
127
+ unsanitized name shape, so users don't have to clear their cache
128
+ to benefit from the fix.
129
+
130
+ ### Tests
131
+
132
+ - `tests/unit/naming.test.ts`: full coverage for `toJsIdentifier` —
133
+ pass-through of valid identifiers, digit-prefix path
134
+ (`0Of0`/`1500Of0`/`123`), comma stripping (`0,0Of0`,
135
+ `foo,bar`), arbitrary punctuation, empty-input fallback to
136
+ `_field`.
137
+ - `tests/unit/locatorPicker.test.ts`: end-to-end reproduction of the
138
+ juice-shop pagination case — `{ text: "0 of 0" }` element produces
139
+ fieldName `_0Of0`; `{ text: "1,500 of 0" }` produces `_1500Of0`;
140
+ valid inputs unchanged.
141
+ - `tests/unit/facade.test.ts`: helper coverage for
142
+ `sanitizeLocatorReferences` plus three end-to-end render tests
143
+ (assertion locator / pomCall args / customBody) confirming the
144
+ rewriter fires correctly through the public `emitTestFile` entry
145
+ point.
146
+
12
147
  ## [2.2.4] — 2026-05-11
13
148
 
14
149
  ### Fixed — BUG-7: empty `expect()` for URL assertions (regression from 2.2.3)
@@ -9,6 +9,24 @@
9
9
  */
10
10
  import { type EmitResult } from "@vijaypjavvadi/pw-emit";
11
11
  import type { PageObjectIR, StepBinding } from "../types";
12
+ /**
13
+ * v2.2.5 — BUG-9 safety net.
14
+ *
15
+ * If a cached LLM binding from v2.2.4 or earlier references a POM field
16
+ * whose name starts with a digit (e.g. `r0c934ddf001.0Of0` from
17
+ * juice-shop's "0 of 0" pagination label), we rewrite the
18
+ * digit-leading segment to be `_`-prefixed so the spec parses.
19
+ *
20
+ * The v2.2.5 field-name synthesiser already prevents new bindings from
21
+ * having this shape, but cached entries persist across versions until
22
+ * explicitly cleared.
23
+ *
24
+ * Patterns rewritten:
25
+ * `foo.0Of0` → `foo._0Of0` // member access onto digit
26
+ * `foo[0Of0]` → `foo[_0Of0]` // computed-property identifier
27
+ * `foo.0,0Of0` → `foo._0_0Of0` // commas → underscore
28
+ */
29
+ export declare function sanitizeLocatorReferences(s: string): string;
12
30
  export declare class EmitterConsistencyError extends Error {
13
31
  constructor(message: string);
14
32
  }
@@ -10,11 +10,43 @@
10
10
  */
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.EmitterConsistencyError = void 0;
13
+ exports.sanitizeLocatorReferences = sanitizeLocatorReferences;
13
14
  exports.emitPageObject = emitPageObject;
14
15
  exports.emitTestFile = emitTestFile;
15
16
  const pw_emit_1 = require("@vijaypjavvadi/pw-emit");
16
17
  const naming_1 = require("../utils/naming");
17
18
  const commentSafe_1 = require("../utils/commentSafe");
19
+ /**
20
+ * v2.2.5 — BUG-9 safety net.
21
+ *
22
+ * If a cached LLM binding from v2.2.4 or earlier references a POM field
23
+ * whose name starts with a digit (e.g. `r0c934ddf001.0Of0` from
24
+ * juice-shop's "0 of 0" pagination label), we rewrite the
25
+ * digit-leading segment to be `_`-prefixed so the spec parses.
26
+ *
27
+ * The v2.2.5 field-name synthesiser already prevents new bindings from
28
+ * having this shape, but cached entries persist across versions until
29
+ * explicitly cleared.
30
+ *
31
+ * Patterns rewritten:
32
+ * `foo.0Of0` → `foo._0Of0` // member access onto digit
33
+ * `foo[0Of0]` → `foo[_0Of0]` // computed-property identifier
34
+ * `foo.0,0Of0` → `foo._0_0Of0` // commas → underscore
35
+ */
36
+ function sanitizeLocatorReferences(s) {
37
+ if (!s)
38
+ return s;
39
+ // 1. `.<digit>` → `._<digit>` for member access
40
+ let out = s.replace(/(\.)([0-9][A-Za-z0-9_$,]*)/g, (_, dot, ident) => {
41
+ return dot + "_" + ident.replace(/,/g, "_");
42
+ });
43
+ // 2. Strip stray commas from identifier-shaped runs after a dot we
44
+ // already prefixed (handled above) and from bracket-property names.
45
+ out = out.replace(/\[([0-9][A-Za-z0-9_$,]*)\]/g, (_, ident) => {
46
+ return "[_" + ident.replace(/,/g, "_") + "]";
47
+ });
48
+ return out;
49
+ }
18
50
  class EmitterConsistencyError extends Error {
19
51
  constructor(message) {
20
52
  super(message);
@@ -123,12 +155,18 @@ function bindingsToBody(bindings, prelude = []) {
123
155
  lines.push(`await test.step(${labelLit}, async () => {`);
124
156
  if (b.customBody) {
125
157
  // Compound step — body has multiple statements pre-rendered.
126
- for (const line of b.customBody.split("\n"))
158
+ // v2.2.5 — sanitize digit-leading POM references that may have been
159
+ // cached from older bdd2pw versions.
160
+ const safeBody = sanitizeLocatorReferences(b.customBody);
161
+ for (const line of safeBody.split("\n"))
127
162
  lines.push(` ${line}`);
128
163
  }
129
164
  else if (b.pomCall) {
130
- const args = b.pomCall.args.join(", ");
131
- lines.push(` await ${b.pomCall.page}.${b.pomCall.method}(${args});`);
165
+ const args = b.pomCall.args
166
+ .map((a) => sanitizeLocatorReferences(a))
167
+ .join(", ");
168
+ const method = sanitizeLocatorReferences(b.pomCall.method);
169
+ lines.push(` await ${b.pomCall.page}.${method}(${args});`);
132
170
  }
133
171
  else if (b.assertion) {
134
172
  const expected = b.assertion.expected !== undefined ? b.assertion.expected : "";
@@ -140,7 +178,9 @@ function bindingsToBody(bindings, prelude = []) {
140
178
  // async ({ page }) => ...) when the locator is empty/whitespace.
141
179
  const rawLocator = b.assertion.locator;
142
180
  const trimmedLocator = (rawLocator == null ? "" : String(rawLocator)).trim();
143
- const renderedLocator = trimmedLocator === "" ? "page" : trimmedLocator;
181
+ // v2.2.5 — rewrite `.0Of0` → `._0Of0` for cached bindings.
182
+ const safeLocator = sanitizeLocatorReferences(trimmedLocator);
183
+ const renderedLocator = safeLocator === "" ? "page" : safeLocator;
144
184
  lines.push(` await expect(${renderedLocator}).${b.assertion.matcher}(${expected});`);
145
185
  }
146
186
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"facade.js","sourceRoot":"","sources":["../../src/emitters/facade.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"facade.js","sourceRoot":"","sources":["../../src/emitters/facade.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,18 @@ import type { ElementIR, LocatorChoice } from "../types";
16
16
  * candidate locator, we fall down the chain.
17
17
  */
18
18
  export declare function pickLocator(element: ElementIR, allElements: ElementIR[]): LocatorChoice;
19
+ /** True when `cls` looks like a framework-internal class. */
20
+ export declare function isFrameworkClass(cls: string): boolean;
21
+ /**
22
+ * True when `selector` reduces to *only* framework-internal classes
23
+ * (e.g. `.ng-untouched.ng-pristine`). Such selectors are unstable
24
+ * runtime markers and must not be used as Playwright locators.
25
+ *
26
+ * Selectors with at least one non-framework class
27
+ * (`.ng-untouched.search-input`) are NOT flagged — the non-framework
28
+ * class can still drive a useful locator.
29
+ */
30
+ export declare function isFrameworkOnlySelector(selector: string | undefined): boolean;
19
31
  /**
20
32
  * Dedupe a list of locator choices.
21
33
  *
@@ -12,6 +12,8 @@
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.pickLocator = pickLocator;
15
+ exports.isFrameworkClass = isFrameworkClass;
16
+ exports.isFrameworkOnlySelector = isFrameworkOnlySelector;
15
17
  exports.dedupeLocators = dedupeLocators;
16
18
  const naming_1 = require("../utils/naming");
17
19
  /**
@@ -85,8 +87,12 @@ function pickLocator(element, allElements) {
85
87
  confidence: rivals.length === 0 ? "unique" : "ambiguous",
86
88
  };
87
89
  }
88
- // 6. CSS selector
89
- if (element.cssSelector) {
90
+ // 6. CSS selector — but reject framework-only class selectors
91
+ // (Angular's `.ng-untouched`, Material's `.mat-form-field`, etc.).
92
+ // These are runtime state markers that change as the user
93
+ // interacts with the page, so locators built on them are flaky.
94
+ // See BUG-10 / v2.2.6.
95
+ if (element.cssSelector && !isFrameworkOnlySelector(element.cssSelector)) {
90
96
  return {
91
97
  api: "locator",
92
98
  args: JSON.stringify(element.cssSelector),
@@ -105,7 +111,12 @@ function pickLocator(element, allElements) {
105
111
  confidence: "fallback",
106
112
  };
107
113
  }
108
- // Nothing usable — emit a tag-only locator and flag as fallback
114
+ // Nothing usable — emit a tag-only locator and flag as fallback.
115
+ // v2.2.6 — if we got here because the only CSS selector was
116
+ // framework-internal (and there was no role / label / placeholder /
117
+ // testId / text / xpath), the tag-only fallback is the least-bad
118
+ // option. It at least matches a visible DOM element rather than a
119
+ // transient state class.
109
120
  return {
110
121
  api: "locator",
111
122
  args: JSON.stringify(element.tag),
@@ -127,6 +138,68 @@ function pickLocator(element, allElements) {
127
138
  * `notificationBanner`) is what a test author would write by hand.
128
139
  */
129
140
  const STATUS_REGION_RE = /(error|alert|message|warning|success|notification|status)/i;
141
+ /**
142
+ * v2.2.6 — BUG-10. CSS class prefixes that frameworks generate at runtime
143
+ * for their own bookkeeping (form-state, view-encapsulation, theming,
144
+ * etc.). These classes:
145
+ *
146
+ * - Change at runtime (`.ng-untouched` → `.ng-touched` the moment the
147
+ * user types), so selecting by them gives flaky locators.
148
+ * - Are not user-facing — no test author would write
149
+ * `await expect(page.locator('.ng-untouched')).toBeVisible()` by hand.
150
+ * - Mass-collide across the DOM (every Angular input has the same
151
+ * state classes), so locator-by-class is non-unique anyway.
152
+ *
153
+ * Covered prefixes:
154
+ * - `ng-*` Angular core (ng-untouched, ng-pristine, ng-dirty, …)
155
+ * - `mat-*` Angular Material
156
+ * - `cdk-*` Angular CDK (overlay, focus-trap, etc.)
157
+ * - `mdc-*` Material Design Components (web)
158
+ * - `_ngcontent-*` Angular view encapsulation attribute-like classes
159
+ * - `_nghost-*` Angular view encapsulation host markers
160
+ *
161
+ * Hyphen is required after the prefix so we don't accidentally exclude
162
+ * legitimate classes like `ngo-button` (user-named) or `cdkit` (rare but
163
+ * possible). The `_ngcontent-` / `_nghost-` patterns are handled with an
164
+ * explicit underscore prefix.
165
+ */
166
+ const FRAMEWORK_CLASS_RE = /^(?:ng-|mat-|cdk-|mdc-|_ngcontent-|_nghost-)/i;
167
+ /** True when `cls` looks like a framework-internal class. */
168
+ function isFrameworkClass(cls) {
169
+ return FRAMEWORK_CLASS_RE.test(cls);
170
+ }
171
+ /**
172
+ * Extract all bare class names from a CSS selector. Tolerant of compound
173
+ * selectors like `div.foo.bar#main` (returns `["foo", "bar"]`).
174
+ */
175
+ function extractClasses(selector) {
176
+ const out = [];
177
+ const re = /\.([a-zA-Z_][\w-]*)/g;
178
+ let m;
179
+ while ((m = re.exec(selector)) !== null)
180
+ out.push(m[1]);
181
+ return out;
182
+ }
183
+ /**
184
+ * True when `selector` reduces to *only* framework-internal classes
185
+ * (e.g. `.ng-untouched.ng-pristine`). Such selectors are unstable
186
+ * runtime markers and must not be used as Playwright locators.
187
+ *
188
+ * Selectors with at least one non-framework class
189
+ * (`.ng-untouched.search-input`) are NOT flagged — the non-framework
190
+ * class can still drive a useful locator.
191
+ */
192
+ function isFrameworkOnlySelector(selector) {
193
+ if (!selector)
194
+ return false;
195
+ // If there's an #id, we can't claim "framework only" — id is independent.
196
+ if (/#[a-zA-Z][\w-]*/.test(selector))
197
+ return false;
198
+ const classes = extractClasses(selector);
199
+ if (classes.length === 0)
200
+ return false; // not a class-based selector
201
+ return classes.every(isFrameworkClass);
202
+ }
130
203
  /**
131
204
  * Synthesise a camelCase TS field name for an element.
132
205
  *
@@ -151,7 +224,7 @@ function synthFieldName(element) {
151
224
  const idDerived = cssSelectorToName(element.cssSelector);
152
225
  if (idDerived && STATUS_REGION_RE.test(idDerived)) {
153
226
  const cleaned = idDerived.replace(/[^a-zA-Z0-9 ]/g, " ").trim();
154
- return (0, naming_1.camelCase)(cleaned) || "errorRegion";
227
+ return (0, naming_1.toJsIdentifier)((0, naming_1.camelCase)(cleaned) || "errorRegion");
155
228
  }
156
229
  const baseName = element.name ??
157
230
  element.label ??
@@ -166,14 +239,32 @@ function synthFieldName(element) {
166
239
  if (suffix && !fieldName.toLowerCase().endsWith(suffix.toLowerCase())) {
167
240
  fieldName += suffix;
168
241
  }
169
- return fieldName;
242
+ // v2.2.5 — BUG-9 guard: ensure the name is a valid JS identifier.
243
+ // `camelCase("0 of 0")` returns "0Of0", which is not a legal
244
+ // identifier and breaks the .spec.ts parse. Prefix digit-leading
245
+ // names with `_` and strip any stray punctuation that survived
246
+ // upstream normalisation (commas, etc.).
247
+ return (0, naming_1.toJsIdentifier)(fieldName);
170
248
  }
171
249
  /**
172
250
  * Best-effort name extraction from a CSS selector. Handles common shapes:
173
- * #username → "username"
174
- * .foo-bar → "foo bar"
175
- * div#main → "main"
176
- * a.wp-block-btn → "wp block btn"
251
+ * #username → "username"
252
+ * .foo-bar → "foo bar"
253
+ * div#main → "main"
254
+ * a.wp-block-btn → "wp block btn"
255
+ * input.ng-untouched.search-input → "search input" (v2.2.6)
256
+ *
257
+ * v2.2.6 — BUG-10. When the selector has multiple classes, skip
258
+ * framework-internal classes (`ng-*`, `mat-*`, `cdk-*`, `mdc-*`,
259
+ * `_ngcontent-*`, `_nghost-*`) and pick the first user-named class.
260
+ * Without this filter, juice-shop's `.ng-untouched.search-input` gets
261
+ * named "ng untouched" → `ngUntouchedInput`, which is a flaky state
262
+ * locator and a confusing field name.
263
+ *
264
+ * If EVERY class is framework-internal, returns undefined so the caller
265
+ * falls through to `<role|tag>Element` rather than naming the field
266
+ * after a transient state class.
267
+ *
177
268
  * Returns undefined for selectors with no usable id/class.
178
269
  */
179
270
  function cssSelectorToName(selector) {
@@ -183,9 +274,14 @@ function cssSelectorToName(selector) {
183
274
  const idMatch = selector.match(/#([a-zA-Z][\w-]*)/);
184
275
  if (idMatch)
185
276
  return idMatch[1].replace(/-/g, " ");
186
- const classMatch = selector.match(/\.([a-zA-Z][\w-]*)/);
187
- if (classMatch)
188
- return classMatch[1].replace(/-/g, " ");
277
+ // Walk all classes, return the first non-framework one.
278
+ const classes = extractClasses(selector);
279
+ for (const cls of classes) {
280
+ if (!isFrameworkClass(cls))
281
+ return cls.replace(/-/g, " ");
282
+ }
283
+ // All classes were framework-internal — fall through to the caller's
284
+ // next priority (typically `<role|tag>Element`).
189
285
  return undefined;
190
286
  }
191
287
  function roleToSuffix(role, tag) {
@@ -1 +1 @@
1
- {"version":3,"file":"locatorPicker.js","sourceRoot":"","sources":["../../src/transformers/locatorPicker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"locatorPicker.js","sourceRoot":"","sources":["../../src/transformers/locatorPicker.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,26 @@
7
7
  export declare function pascalCase(input: string): string;
8
8
  /** Convert any case to camelCase. */
9
9
  export declare function camelCase(input: string): string;
10
+ /**
11
+ * v2.2.5 — coerce an arbitrary string into a valid TypeScript / JavaScript
12
+ * identifier. Used by the POM field-name synthesiser so we never emit
13
+ * code like `this.0Of0 = ...` (juice-shop pagination labels: "0 of 0",
14
+ * "1 - 50 of 0") which makes the .spec.ts file refuse to parse.
15
+ *
16
+ * Rules:
17
+ * 1. Strip any character that isn't `[A-Za-z0-9_$]`. Commas, hyphens,
18
+ * backticks, quotes, whitespace etc. all go.
19
+ * 2. If what remains starts with a digit, prefix with a single `_`.
20
+ * JS identifier production: `IdentifierStart` = letter | `$` | `_`.
21
+ * 3. If the result is empty, return a stable fallback "_field" so the
22
+ * caller never has to handle empty-string corner cases.
23
+ *
24
+ * Reserved-word avoidance is intentionally NOT handled here: at the
25
+ * field-access site `obj.class` is fine (only top-level identifiers are
26
+ * reserved). If we later add free-standing identifier emission (e.g. let
27
+ * <name> = ...), revisit.
28
+ */
29
+ export declare function toJsIdentifier(input: string): string;
10
30
  /** Convert any case to kebab-case. */
11
31
  export declare function kebabCase(input: string): string;
12
32
  /** Convert any case to snake_case. */
@@ -7,6 +7,7 @@
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.pascalCase = pascalCase;
9
9
  exports.camelCase = camelCase;
10
+ exports.toJsIdentifier = toJsIdentifier;
10
11
  exports.kebabCase = kebabCase;
11
12
  exports.snakeCase = snakeCase;
12
13
  exports.pageObjectFileStem = pageObjectFileStem;
@@ -22,6 +23,31 @@ function camelCase(input) {
22
23
  const pascal = pascalCase(input);
23
24
  return pascal.charAt(0).toLowerCase() + pascal.slice(1);
24
25
  }
26
+ /**
27
+ * v2.2.5 — coerce an arbitrary string into a valid TypeScript / JavaScript
28
+ * identifier. Used by the POM field-name synthesiser so we never emit
29
+ * code like `this.0Of0 = ...` (juice-shop pagination labels: "0 of 0",
30
+ * "1 - 50 of 0") which makes the .spec.ts file refuse to parse.
31
+ *
32
+ * Rules:
33
+ * 1. Strip any character that isn't `[A-Za-z0-9_$]`. Commas, hyphens,
34
+ * backticks, quotes, whitespace etc. all go.
35
+ * 2. If what remains starts with a digit, prefix with a single `_`.
36
+ * JS identifier production: `IdentifierStart` = letter | `$` | `_`.
37
+ * 3. If the result is empty, return a stable fallback "_field" so the
38
+ * caller never has to handle empty-string corner cases.
39
+ *
40
+ * Reserved-word avoidance is intentionally NOT handled here: at the
41
+ * field-access site `obj.class` is fine (only top-level identifiers are
42
+ * reserved). If we later add free-standing identifier emission (e.g. let
43
+ * <name> = ...), revisit.
44
+ */
45
+ function toJsIdentifier(input) {
46
+ let s = input.replace(/[^A-Za-z0-9_$]/g, "");
47
+ if (s.length > 0 && /^[0-9]/.test(s))
48
+ s = "_" + s;
49
+ return s || "_field";
50
+ }
25
51
  /** Convert any case to kebab-case. */
26
52
  function kebabCase(input) {
27
53
  return splitWords(input).map((w) => w.toLowerCase()).join("-");
@@ -1 +1 @@
1
- {"version":3,"file":"naming.js","sourceRoot":"","sources":["../../src/utils/naming.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAGH,gCAIC;AAGD,8BAGC;AAGD,8BAEC;AAGD,8BAEC;AAMD,gDAGC;AAMD,oCAEC;AAtCD,sCAAsC;AACtC,SAAgB,UAAU,CAAC,KAAa;IACtC,OAAO,UAAU,CAAC,KAAK,CAAC;SACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAChE,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,qCAAqC;AACrC,SAAgB,SAAS,CAAC,KAAa;IACrC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,sCAAsC;AACtC,SAAgB,SAAS,CAAC,KAAa;IACrC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC;AAED,sCAAsC;AACtC,SAAgB,SAAS,CAAC,KAAa;IACrC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB,CAAC,SAAiB;IAClD,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACjD,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAAC,WAAmB;IAC9C,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC;AAC1C,CAAC;AAED,sEAAsE;AACtE,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC;SACzB,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC;SACnC,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC;SACzC,IAAI,EAAE;SACN,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"naming.js","sourceRoot":"","sources":["../../src/utils/naming.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAGH,gCAIC;AAGD,8BAGC;AAqBD,wCAIC;AAGD,8BAEC;AAGD,8BAEC;AAMD,gDAGC;AAMD,oCAEC;AA/DD,sCAAsC;AACtC,SAAgB,UAAU,CAAC,KAAa;IACtC,OAAO,UAAU,CAAC,KAAK,CAAC;SACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAChE,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,qCAAqC;AACrC,SAAgB,SAAS,CAAC,KAAa;IACrC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,cAAc,CAAC,KAAa;IAC1C,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;IAC7C,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,QAAQ,CAAC;AACvB,CAAC;AAED,sCAAsC;AACtC,SAAgB,SAAS,CAAC,KAAa;IACrC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC;AAED,sCAAsC;AACtC,SAAgB,SAAS,CAAC,KAAa;IACrC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB,CAAC,SAAiB;IAClD,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACjD,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAAC,WAAmB;IAC9C,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC;AAC1C,CAAC;AAED,sEAAsE;AACtE,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC;SACzB,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC;SACnC,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC;SACzC,IAAI,EAAE;SACN,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vijaypjavvadi/bdd2pw",
3
- "version": "2.2.4",
3
+ "version": "2.2.6",
4
4
  "description": "Scaffold runnable Playwright TypeScript tests from Gherkin .feature files. Detects existing Page Objects, scans live pages via Microsoft Playwright MCP, emits POMs + specs, ready for execution. CLI + HTTP service. Optional governed LLM fallback (Anthropic / OpenAI / Gemini).",
5
5
  "bin": {
6
6
  "bdd2pw": "dist/cli.js"