@sungen/driver-ui 3.2.21 → 3.2.22-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sungen/driver-ui",
3
- "version": "3.2.21",
3
+ "version": "3.2.22-beta.2",
4
4
  "description": "Sungen UI capability (Playwright) — step patterns, viewpoint gate, and phase hooks. Plugs into @sun-asterisk/sungen via the capability SPI.",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -13,7 +13,7 @@
13
13
  "author": "eqe team (engineer & quality) — Sun Asterisk",
14
14
  "license": "MIT",
15
15
  "dependencies": {
16
- "@sun-asterisk/sungen": "3.2.21"
16
+ "@sun-asterisk/sungen": "3.2.22-beta.2"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "@playwright/test": "^1.57.0"
@@ -125,8 +125,15 @@ export const capturePatterns: StepPattern[] = [
125
125
  selectorRef: step.selectorRef,
126
126
  childRef: step.childRef,
127
127
  stepCounter: sc,
128
- // Render the child RELATIVE to each container row via locator.hbs's parentLocator branch.
129
- child: { ...child, parentLocator: `__cards_${sc}.nth(__i_${sc})` },
128
+ // C4 — plain variable NAMES only, no built locator expression. `.nth()` is a
129
+ // Playwright-only method; baking it into a string here (as the driver-agnostic
130
+ // pattern layer) leaked into the Appium output. Each adapter's own
131
+ // all-contain-element template composes its own per-index child chain
132
+ // (Playwright: `{{containerVar}}.nth({{containerIndexVar}})`; Appium:
133
+ // `{{containerVar}}[{{containerIndexVar}}]`).
134
+ containerVar: `__cards_${sc}`,
135
+ containerIndexVar: `__i_${sc}`,
136
+ child,
130
137
  },
131
138
  comment: `Assert all ${step.selectorRef} contain [${step.childRef}]`,
132
139
  };
@@ -561,7 +561,7 @@ export const interactionPatterns: StepPattern[] = [
561
561
  if (!allRefs || allRefs.length < 2) {
562
562
  return {
563
563
  templateName: 'drag-action',
564
- data: { strategy: 'text', value: step.selectorRef, targetLocator: 'page.locator(\'TODO\')' },
564
+ data: { strategy: 'text', value: step.selectorRef, targetStrategy: 'locator', targetValue: 'TODO' },
565
565
  comment: `Drag ${step.selectorRef} (missing target)`,
566
566
  };
567
567
  }
@@ -571,30 +571,20 @@ export const interactionPatterns: StepPattern[] = [
571
571
  const sourceResolved = context.selectorResolver.resolveSelector(sourceRef, undefined, step.elementType, step.nth);
572
572
  const targetResolved = context.selectorResolver.resolveSelector(targetRef, undefined, undefined, 0);
573
573
 
574
- // Build target locator expression from resolved selector
575
- let targetLocator: string;
576
- switch (targetResolved.strategy) {
577
- case 'role':
578
- targetLocator = targetResolved.name
579
- ? `page.getByRole('${targetResolved.role}', { name: '${targetResolved.name}' })`
580
- : `page.getByRole('${targetResolved.role}')`;
581
- break;
582
- case 'testid':
583
- targetLocator = `page.getByTestId('${targetResolved.value}')`;
584
- break;
585
- case 'text':
586
- targetLocator = `page.getByText('${targetResolved.value}')`;
587
- break;
588
- case 'locator':
589
- targetLocator = `page.locator('${targetResolved.value}')`;
590
- break;
591
- default:
592
- targetLocator = `page.getByText('${targetRef}')`;
593
- }
594
-
574
+ // C3 — pass the resolved TARGET selector FIELDS, not a built Playwright locator string.
575
+ // Each adapter's own drag-action template renders the target locator for its own
576
+ // framework (Playwright: page.getByRole/getByText/...; Appium: an accessibility-id/xpath
577
+ // $() lookup — it already consumes this exact shape).
595
578
  return {
596
579
  templateName: 'drag-action',
597
- data: { ...sourceResolved, targetLocator },
580
+ data: {
581
+ ...sourceResolved,
582
+ targetStrategy: targetResolved.strategy,
583
+ targetValue: targetResolved.value,
584
+ targetName: targetResolved.name,
585
+ targetRole: targetResolved.role,
586
+ targetRef,
587
+ },
598
588
  comment: `Drag ${sourceRef} to ${targetRef}`,
599
589
  };
600
590
  },
@@ -113,6 +113,40 @@ export const tablePatterns: StepPattern[] = [
113
113
  priority: 16,
114
114
  },
115
115
 
116
+ // "User see [Result Row] row with {{n}}" — COUNT of matching rows (#575 field report).
117
+ // Every doc layer (Pattern 5, the gherkin-syntax skill's "# 7. Count") promises this
118
+ // form counts, and authors write it meaning a count ("40 results after load-more") —
119
+ // but it fell through to see-with-variable and compiled to toHaveText('40') against
120
+ // the row's ENTIRE text: a test that can essentially never pass, emitted silently.
121
+ // The value decides: a numeric base value is a count; any other value keeps the text
122
+ // semantics (asserting a row's full text equals a bare number is no real intent).
123
+ // `row in [Table] table with` (row scope/exists) and `is hidden` stay untouched.
124
+ {
125
+ name: 'row-count',
126
+ matcher: (step) => {
127
+ return step.elementType === 'row' &&
128
+ /\brow\s+with\b/i.test(step.text) &&
129
+ !!step.dataRef && !!step.selectorRef &&
130
+ !/\bin\b.*\btable\b/i.test(step.text) &&
131
+ !/\bis\s+hidden\b/i.test(step.text);
132
+ },
133
+ resolver: (step, context) => {
134
+ // Decide by the BASE literal (runtime mode returns an opaque marker from resolveData).
135
+ const base = context.dataResolver.peekBaseValue?.(step.dataRef!, context.featureName);
136
+ if (base === undefined || !/^\d+$/.test(String(base).trim())) return null as any; // not numeric → fall through to text semantics
137
+ const resolved = context.selectorResolver.resolveSelector(
138
+ step.selectorRef!, context.featureName, 'row', step.nth
139
+ );
140
+ const count = context.dataResolver.resolveData(step.dataRef!, context.featureName);
141
+ return {
142
+ templateName: 'count-assertion',
143
+ data: { ...resolved, expectedCount: count },
144
+ comment: `Assert ${step.selectorRef} row count is ${count}`,
145
+ };
146
+ },
147
+ priority: 18, // above see-with-variable (14) — the count reading wins for numeric values
148
+ },
149
+
116
150
  // "User see [Ref] row in [Table] table with {{value}}" — row exists (enters row scope)
117
151
  {
118
152
  name: 'table-row-exists',