@testmuai/playwright-bindings 0.1.26 → 0.1.27

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.
Files changed (154) hide show
  1. package/dist/actionEngine.d.ts +37 -0
  2. package/dist/actionEngine.d.ts.map +1 -0
  3. package/dist/actionEngine.js +194 -0
  4. package/dist/actionEngine.js.map +1 -0
  5. package/dist/actionSpecs.d.ts +35 -0
  6. package/dist/actionSpecs.d.ts.map +1 -0
  7. package/dist/actionSpecs.js +354 -0
  8. package/dist/actionSpecs.js.map +1 -0
  9. package/dist/capability.d.ts +3 -5
  10. package/dist/capability.d.ts.map +1 -1
  11. package/dist/capability.js +66 -6
  12. package/dist/capability.js.map +1 -1
  13. package/dist/configure.d.ts +16 -0
  14. package/dist/configure.d.ts.map +1 -1
  15. package/dist/configure.js +14 -0
  16. package/dist/configure.js.map +1 -1
  17. package/dist/errors.d.ts +19 -0
  18. package/dist/errors.d.ts.map +1 -1
  19. package/dist/errors.js +29 -0
  20. package/dist/errors.js.map +1 -1
  21. package/dist/healCache.d.ts +28 -0
  22. package/dist/healCache.d.ts.map +1 -0
  23. package/dist/healCache.js +17 -0
  24. package/dist/healCache.js.map +1 -0
  25. package/dist/healPatch.d.ts.map +1 -1
  26. package/dist/healPatch.js +45 -3
  27. package/dist/healPatch.js.map +1 -1
  28. package/dist/helpers/assertion.d.ts.map +1 -1
  29. package/dist/helpers/assertion.js +18 -0
  30. package/dist/helpers/assertion.js.map +1 -1
  31. package/dist/helpers/assertionV3.d.ts +67 -0
  32. package/dist/helpers/assertionV3.d.ts.map +1 -0
  33. package/dist/helpers/assertionV3.js +384 -0
  34. package/dist/helpers/assertionV3.js.map +1 -0
  35. package/dist/helpers/condition.d.ts +84 -0
  36. package/dist/helpers/condition.d.ts.map +1 -0
  37. package/dist/helpers/condition.js +292 -0
  38. package/dist/helpers/condition.js.map +1 -0
  39. package/dist/helpers/cookies.d.ts +12 -0
  40. package/dist/helpers/cookies.d.ts.map +1 -0
  41. package/dist/helpers/cookies.js +66 -0
  42. package/dist/helpers/cookies.js.map +1 -0
  43. package/dist/helpers/coordinateResolver.d.ts +29 -0
  44. package/dist/helpers/coordinateResolver.d.ts.map +1 -0
  45. package/dist/helpers/coordinateResolver.js +118 -0
  46. package/dist/helpers/coordinateResolver.js.map +1 -0
  47. package/dist/helpers/coordinateResolverRead.d.ts +36 -0
  48. package/dist/helpers/coordinateResolverRead.d.ts.map +1 -0
  49. package/dist/helpers/coordinateResolverRead.js +107 -0
  50. package/dist/helpers/coordinateResolverRead.js.map +1 -0
  51. package/dist/helpers/dialog.d.ts +29 -0
  52. package/dist/helpers/dialog.d.ts.map +1 -0
  53. package/dist/helpers/dialog.js +35 -0
  54. package/dist/helpers/dialog.js.map +1 -0
  55. package/dist/helpers/drag.d.ts +36 -1
  56. package/dist/helpers/drag.d.ts.map +1 -1
  57. package/dist/helpers/drag.js +267 -0
  58. package/dist/helpers/drag.js.map +1 -1
  59. package/dist/helpers/executeApi.d.ts +2 -0
  60. package/dist/helpers/executeApi.d.ts.map +1 -1
  61. package/dist/helpers/executeApi.js +30 -10
  62. package/dist/helpers/executeApi.js.map +1 -1
  63. package/dist/helpers/executeJs.d.ts.map +1 -1
  64. package/dist/helpers/executeJs.js +46 -3
  65. package/dist/helpers/executeJs.js.map +1 -1
  66. package/dist/helpers/gesture.d.ts +45 -0
  67. package/dist/helpers/gesture.d.ts.map +1 -0
  68. package/dist/helpers/gesture.js +131 -0
  69. package/dist/helpers/gesture.js.map +1 -0
  70. package/dist/helpers/healCascade.d.ts +57 -0
  71. package/dist/helpers/healCascade.d.ts.map +1 -0
  72. package/dist/helpers/healCascade.js +363 -0
  73. package/dist/helpers/healCascade.js.map +1 -0
  74. package/dist/helpers/png.d.ts +3 -0
  75. package/dist/helpers/png.d.ts.map +1 -0
  76. package/dist/helpers/png.js +18 -0
  77. package/dist/helpers/png.js.map +1 -0
  78. package/dist/helpers/screenshot.d.ts +27 -0
  79. package/dist/helpers/screenshot.d.ts.map +1 -1
  80. package/dist/helpers/screenshot.js +56 -0
  81. package/dist/helpers/screenshot.js.map +1 -1
  82. package/dist/helpers/scrollUntil.d.ts +13 -0
  83. package/dist/helpers/scrollUntil.d.ts.map +1 -0
  84. package/dist/helpers/scrollUntil.js +88 -0
  85. package/dist/helpers/scrollUntil.js.map +1 -0
  86. package/dist/helpers/tabs.d.ts +42 -1
  87. package/dist/helpers/tabs.d.ts.map +1 -1
  88. package/dist/helpers/tabs.js +259 -5
  89. package/dist/helpers/tabs.js.map +1 -1
  90. package/dist/helpers/text.d.ts +15 -0
  91. package/dist/helpers/text.d.ts.map +1 -0
  92. package/dist/helpers/text.js +24 -0
  93. package/dist/helpers/text.js.map +1 -0
  94. package/dist/helpers/textNormalize.d.ts +18 -0
  95. package/dist/helpers/textNormalize.d.ts.map +1 -0
  96. package/dist/helpers/textNormalize.js +39 -0
  97. package/dist/helpers/textNormalize.js.map +1 -0
  98. package/dist/helpers/textualRead.d.ts +37 -0
  99. package/dist/helpers/textualRead.d.ts.map +1 -0
  100. package/dist/helpers/textualRead.js +211 -0
  101. package/dist/helpers/textualRead.js.map +1 -0
  102. package/dist/helpers/vision.d.ts +2 -0
  103. package/dist/helpers/vision.d.ts.map +1 -1
  104. package/dist/helpers/vision.js +11 -0
  105. package/dist/helpers/vision.js.map +1 -1
  106. package/dist/helpers/visionV3.d.ts +38 -0
  107. package/dist/helpers/visionV3.d.ts.map +1 -0
  108. package/dist/helpers/visionV3.js +291 -0
  109. package/dist/helpers/visionV3.js.map +1 -0
  110. package/dist/helpers/wait.d.ts +14 -1
  111. package/dist/helpers/wait.d.ts.map +1 -1
  112. package/dist/helpers/wait.js +25 -0
  113. package/dist/helpers/wait.js.map +1 -1
  114. package/dist/index.d.ts +29 -3
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +23 -4
  117. package/dist/index.js.map +1 -1
  118. package/dist/log.d.ts +4 -1
  119. package/dist/log.d.ts.map +1 -1
  120. package/dist/log.js +8 -3
  121. package/dist/log.js.map +1 -1
  122. package/dist/rankedLocator.d.ts +27 -0
  123. package/dist/rankedLocator.d.ts.map +1 -0
  124. package/dist/rankedLocator.js +85 -0
  125. package/dist/rankedLocator.js.map +1 -0
  126. package/dist/reporters/index.d.ts +2 -0
  127. package/dist/reporters/index.d.ts.map +1 -1
  128. package/dist/reporters/index.js.map +1 -1
  129. package/dist/reporters/lt.d.ts.map +1 -1
  130. package/dist/reporters/lt.js +7 -1
  131. package/dist/reporters/lt.js.map +1 -1
  132. package/dist/routeFailure.d.ts +9 -0
  133. package/dist/routeFailure.d.ts.map +1 -0
  134. package/dist/routeFailure.js +34 -0
  135. package/dist/routeFailure.js.map +1 -0
  136. package/dist/session.d.ts.map +1 -1
  137. package/dist/session.js +21 -0
  138. package/dist/session.js.map +1 -1
  139. package/dist/step.d.ts +10 -0
  140. package/dist/step.d.ts.map +1 -1
  141. package/dist/step.js +14 -1
  142. package/dist/step.js.map +1 -1
  143. package/dist/testConfig.d.ts.map +1 -1
  144. package/dist/testConfig.js +8 -1
  145. package/dist/testConfig.js.map +1 -1
  146. package/dist/vars.d.ts +10 -0
  147. package/dist/vars.d.ts.map +1 -1
  148. package/dist/vars.js +30 -3
  149. package/dist/vars.js.map +1 -1
  150. package/dist/visionLocator.d.ts +53 -0
  151. package/dist/visionLocator.d.ts.map +1 -0
  152. package/dist/visionLocator.js +117 -0
  153. package/dist/visionLocator.js.map +1 -0
  154. package/package.json +2 -2
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Condition classes for test evaluation — the V3 local-eval core.
3
+ *
4
+ * Port of PY testmu/_helpers/condition.py (itself ported from the Selenium
5
+ * binding). Consumed by exported test.js as LIVE OBJECTS — never a
6
+ * stringified repr the binding evals (the V3 PW-JS contract's deliberate
7
+ * divergence; eval under ESM is bundler- and CSP-hostile):
8
+ *
9
+ * const [ok] = await new Condition({
10
+ * conditions: [new ResolvedCondition('{{x}}', PossibleCondition('=='), '5')],
11
+ * connectors: [],
12
+ * }).evaluate();
13
+ *
14
+ * PossibleCondition is a CALLABLE const-object, not a TS enum: Python enums
15
+ * are callable by value, and the generator emits PossibleCondition('==') in
16
+ * both languages — a TS enum cannot keep that emission shape.
17
+ *
18
+ * Day-1 corner cases baked in (skill catalog Top-15):
19
+ * #3 connector fold combines the accumulator with results[i+1];
20
+ * #4 CONTAINS means right-in-left (left is the haystack);
21
+ * unknown operators/connectors THROW — never a silent wrong verdict.
22
+ */
23
+ import { isV3 } from '../configure.js';
24
+ import { normalizeText } from './textNormalize.js';
25
+ import { resolveVar } from '../vars.js';
26
+ // ── Operators ─────────────────────────────────────────────────────────────────
27
+ const POSSIBLE_CONDITION_VALUES = [
28
+ '==', '!=', '>', '<', '>=', '<=',
29
+ 'contains', 'not_contains', 'starts_with', 'ends_with',
30
+ ];
31
+ function possibleConditionFn(raw) {
32
+ const v = raw;
33
+ // No fallback: an unrecognized operator must throw rather than silently
34
+ // defaulting to EQUALS and producing a wrong verdict (PY parity).
35
+ if (!POSSIBLE_CONDITION_VALUES.includes(v)) {
36
+ throw new Error(`'${raw}' is not a valid PossibleCondition`);
37
+ }
38
+ return v;
39
+ }
40
+ export const PossibleCondition = Object.assign(possibleConditionFn, {
41
+ EQUALS: '==', NOT_EQUALS: '!=',
42
+ GREATER_THAN: '>', LESS_THAN: '<',
43
+ GREATER_THAN_OR_EQUALS: '>=', LESS_THAN_OR_EQUALS: '<=',
44
+ CONTAINS: 'contains', NOT_CONTAINS: 'not_contains',
45
+ STARTS_WITH: 'starts_with', ENDS_WITH: 'ends_with',
46
+ });
47
+ function concatenationOperatorFn(raw) {
48
+ const v = raw.toUpperCase();
49
+ if (v !== 'AND' && v !== 'OR') {
50
+ throw new Error(`'${raw}' is not a valid ConcatenationOperator`);
51
+ }
52
+ return v;
53
+ }
54
+ export const ConcatenationOperator = Object.assign(concatenationOperatorFn, { AND: 'AND', OR: 'OR' });
55
+ // ── ResolvedCondition ─────────────────────────────────────────────────────────
56
+ /** A single comparison triple: left_operand op right_operand. */
57
+ export class ResolvedCondition {
58
+ leftOperand;
59
+ operator;
60
+ rightOperand;
61
+ constructor(leftOperand, operator, rightOperand) {
62
+ this.leftOperand = leftOperand;
63
+ this.operator = operator;
64
+ this.rightOperand = rightOperand;
65
+ }
66
+ toDict() {
67
+ return {
68
+ left_operand: this.leftOperand,
69
+ operator: this.operator,
70
+ right_operand: this.rightOperand,
71
+ };
72
+ }
73
+ /** Parse 'left op right' whitespace-delimited string. */
74
+ static fromString(condition) {
75
+ const parts = condition.split(/\s+/).filter(Boolean);
76
+ if (parts.length !== 3) {
77
+ throw new Error(`Cannot parse condition string: ${JSON.stringify(condition)}`);
78
+ }
79
+ const [left, op, right] = parts;
80
+ return new ResolvedCondition(left, PossibleCondition(op), right);
81
+ }
82
+ static fromJson(json) {
83
+ return new ResolvedCondition(json.left_operand ?? '', PossibleCondition(json.operator ?? ''), json.right_operand ?? '');
84
+ }
85
+ toString() {
86
+ return `${this.leftOperand} ${this.operator} ${this.rightOperand}`;
87
+ }
88
+ equals(other) {
89
+ return (other instanceof ResolvedCondition &&
90
+ this.leftOperand === other.leftOperand &&
91
+ this.operator === other.operator &&
92
+ this.rightOperand === other.rightOperand);
93
+ }
94
+ }
95
+ /** Default resolver: the binding's own variable store (async — ATMS/env). */
96
+ const defaultResolver = (template) => resolveVar(template);
97
+ /**
98
+ * Composite condition: ResolvedConditions joined by ConcatenationOperators.
99
+ * `await cond.evaluate()` returns `[boolean, usedVariables]`.
100
+ */
101
+ export class Condition {
102
+ conditions;
103
+ connectors;
104
+ isV3;
105
+ constructor(opts) {
106
+ this.conditions = opts.conditions;
107
+ this.connectors = opts.connectors;
108
+ // V3 mode: text ops are case-insensitive + unicode-folded; AND binds
109
+ // tighter than OR (A OR B AND C == A OR (B AND C)). Resolved from the
110
+ // runtime config when not passed — codegen emits bare Condition({...})
111
+ // with no isV3 arg, so this is what makes those pick up V3 semantics.
112
+ this.isV3 = opts.isV3 ?? isV3();
113
+ }
114
+ // ── Internal helpers ────────────────────────────────────────────────────────
115
+ async resolvePlaceholder(s, variables, getVariableValue) {
116
+ if (getVariableValue) {
117
+ const result = await getVariableValue(s, variables);
118
+ return [result, { [s]: result }];
119
+ }
120
+ const t = s.trim();
121
+ if (t.startsWith('{{') && t.endsWith('}}')) {
122
+ const key = t.slice(2, -2).trim();
123
+ return [this.accessNestedValue(variables, key), { [key]: this.accessNestedValue(variables, key) }];
124
+ }
125
+ if (t.startsWith('${') && t.endsWith('}')) {
126
+ const key = t.slice(2, -1).trim();
127
+ return [this.accessNestedValue(variables, key), { [key]: this.accessNestedValue(variables, key) }];
128
+ }
129
+ return [s, {}]; // not a placeholder
130
+ }
131
+ /** Dotted + bracket-indexed traversal ('api_x.response_body.items[0].id'). */
132
+ accessNestedValue(dump, name) {
133
+ let value = dump;
134
+ for (let key of name.split('.')) {
135
+ while (key.includes('[') && key.includes(']')) {
136
+ const base = key.slice(0, key.indexOf('['));
137
+ const index = parseInt(key.slice(key.indexOf('[') + 1, key.indexOf(']')), 10);
138
+ if (base)
139
+ value = value[base];
140
+ value = value[index];
141
+ key = key.slice(key.indexOf(']') + 1);
142
+ }
143
+ if (key) {
144
+ if (value === null || typeof value !== 'object') {
145
+ throw new Error(`Variable '${name}' not found in variables`);
146
+ }
147
+ if (!(key in value)) {
148
+ throw new Error(`Variable '${name}' not found in variables`);
149
+ }
150
+ value = value[key];
151
+ }
152
+ }
153
+ return value;
154
+ }
155
+ isNumeric(val) {
156
+ if (typeof val === 'number')
157
+ return Number.isFinite(val);
158
+ if (typeof val === 'string') {
159
+ const t = val.trim();
160
+ if (t === '')
161
+ return false;
162
+ return Number.isFinite(Number(t));
163
+ }
164
+ return false;
165
+ }
166
+ toNumeric(val) {
167
+ if (typeof val === 'number')
168
+ return val;
169
+ if (typeof val === 'string') {
170
+ const n = Number(val.trim());
171
+ return Number.isFinite(n) ? n : null;
172
+ }
173
+ return null;
174
+ }
175
+ cleanString(s) {
176
+ if ((s.startsWith('"') && s.endsWith('"')) ||
177
+ (s.startsWith("'") && s.endsWith("'"))) {
178
+ return s.slice(1, -1);
179
+ }
180
+ return s;
181
+ }
182
+ /** Coerce mixed string/number operands before comparing (PY parity). */
183
+ typecast(left, right) {
184
+ const leftIsStr = typeof left === 'string';
185
+ const rightIsStr = typeof right === 'string';
186
+ const leftIsNum = this.isNumeric(left);
187
+ const rightIsNum = this.isNumeric(right);
188
+ if (leftIsNum && rightIsNum) {
189
+ return [this.toNumeric(left), this.toNumeric(right)];
190
+ }
191
+ let l = leftIsStr ? this.cleanString(left) : left;
192
+ let r = rightIsStr ? this.cleanString(right) : right;
193
+ if (leftIsStr && rightIsNum && this.isNumeric(l)) {
194
+ l = this.toNumeric(l);
195
+ }
196
+ else if (rightIsStr && leftIsNum && this.isNumeric(r)) {
197
+ r = this.toNumeric(r);
198
+ }
199
+ return [l, r];
200
+ }
201
+ /** Normalize a text operand for substring/prefix/suffix comparison.
202
+ * V3: accent-fold + case-fold; V4: plain String(). */
203
+ cmp(x) {
204
+ return this.isV3 ? normalizeText(x, { caseInsensitive: true }) : String(x);
205
+ }
206
+ evalCondition(operator, leftOperand, rightOperand) {
207
+ let [left, right] = this.typecast(leftOperand, rightOperand);
208
+ // bool <-> "true"/"false" normalization.
209
+ if (typeof left === 'boolean' && typeof right === 'string') {
210
+ const lowered = right.trim().toLowerCase();
211
+ if (lowered === 'true' || lowered === 'false')
212
+ right = lowered === 'true';
213
+ }
214
+ else if (typeof right === 'boolean' && typeof left === 'string') {
215
+ const lowered = left.trim().toLowerCase();
216
+ if (lowered === 'true' || lowered === 'false')
217
+ left = lowered === 'true';
218
+ }
219
+ switch (operator) {
220
+ case '==': return left === right;
221
+ case '!=': return left !== right;
222
+ case '>': return left > right;
223
+ case '<': return left < right;
224
+ case '>=': return left >= right;
225
+ case '<=': return left <= right;
226
+ // CONTAINS: left is the HAYSTACK (right in left) — corner-case #4.
227
+ case 'contains': return this.cmp(left).includes(this.cmp(right));
228
+ case 'not_contains': return !this.cmp(left).includes(this.cmp(right));
229
+ case 'starts_with': return this.cmp(left).startsWith(this.cmp(right));
230
+ case 'ends_with': return this.cmp(left).endsWith(this.cmp(right));
231
+ default:
232
+ throw new Error(`Unsupported condition: ${String(operator)}`);
233
+ }
234
+ }
235
+ // ── Public API ──────────────────────────────────────────────────────────────
236
+ /**
237
+ * Evaluate all conditions. Returns `[result, usedVariables]`.
238
+ *
239
+ * With no arguments (the emitted-code shape) variables resolve through the
240
+ * binding's own store. Pass an explicit resolver/variables for local eval.
241
+ */
242
+ async evaluate(variables = {}, getVariableValue = defaultResolver) {
243
+ const used = {};
244
+ const results = [];
245
+ for (const condition of this.conditions) {
246
+ const [left, leftUsed] = await this.resolvePlaceholder(condition.leftOperand, variables, getVariableValue);
247
+ const [right, rightUsed] = await this.resolvePlaceholder(condition.rightOperand, variables, getVariableValue);
248
+ results.push(this.evalCondition(condition.operator, left, right));
249
+ Object.assign(used, leftUsed, rightUsed);
250
+ }
251
+ if (this.isV3) {
252
+ // V3 precedence fold: AND binds tighter than OR. Accumulate AND-groups
253
+ // left-to-right; each OR flushes the running group.
254
+ if (results.length === 0)
255
+ return [true, used];
256
+ let current = results[0];
257
+ const orGroups = [];
258
+ this.connectors.forEach((connector, idx) => {
259
+ // Corner-case #3: the operand is results[idx + 1], never results[idx].
260
+ const operand = idx + 1 < results.length ? results[idx + 1] : false;
261
+ if (connector === 'AND')
262
+ current = current && operand;
263
+ else if (connector === 'OR') {
264
+ orGroups.push(current);
265
+ current = operand;
266
+ }
267
+ else
268
+ throw new Error(`Unsupported connector: ${String(connector)}`);
269
+ });
270
+ orGroups.push(current);
271
+ return [orGroups.some(Boolean), used];
272
+ }
273
+ let finalResult = results.length ? results[0] : true;
274
+ this.connectors.forEach((connector, idx) => {
275
+ const operand = results[idx + 1];
276
+ if (connector === 'AND')
277
+ finalResult = finalResult && operand;
278
+ else if (connector === 'OR')
279
+ finalResult = finalResult || operand;
280
+ else
281
+ throw new Error(`Unsupported connector: ${String(connector)}`);
282
+ });
283
+ return [finalResult, used];
284
+ }
285
+ toDict() {
286
+ return {
287
+ connectors: [...this.connectors],
288
+ conditions: this.conditions.map((c) => c.toDict()),
289
+ };
290
+ }
291
+ }
292
+ //# sourceMappingURL=condition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"condition.js","sourceRoot":"","sources":["../../src/helpers/condition.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /** Cookie read with V2 driver_query_script parity (playwright). */
2
+ import type { BrowserContext } from 'playwright';
3
+ /**
4
+ * Read cookies, then narrow by an attribute chain and an optional field.
5
+ *
6
+ * `attributes` entries are either `{index: n}` (array index) or
7
+ * `{<any>: [key]}` / `{<any>: [key, value]}` — a single-element array reads the
8
+ * key, a pair searches for the object whose key equals value.
9
+ * `field` is one of "len" | "keys" | "values", else the narrowed value is returned.
10
+ */
11
+ export declare function getCookies(context: BrowserContext, attributes?: Array<Record<string, unknown>> | null, field?: string): Promise<unknown>;
12
+ //# sourceMappingURL=cookies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/helpers/cookies.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAyBjD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,cAAc,EACvB,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,EAClD,KAAK,SAAK,GACT,OAAO,CAAC,OAAO,CAAC,CAiClB"}
@@ -0,0 +1,66 @@
1
+ import { log } from '../log.js';
2
+ /** Depth-first search for the first object whose `key` equals `value`. */
3
+ function findObjectWithKv(data, key, value) {
4
+ if (Array.isArray(data)) {
5
+ for (const item of data) {
6
+ const found = findObjectWithKv(item, key, value);
7
+ if (found)
8
+ return found;
9
+ }
10
+ return null;
11
+ }
12
+ if (data !== null && typeof data === 'object') {
13
+ const obj = data;
14
+ if (obj[key] === value)
15
+ return obj;
16
+ for (const v of Object.values(obj)) {
17
+ const found = findObjectWithKv(v, key, value);
18
+ if (found)
19
+ return found;
20
+ }
21
+ }
22
+ return null;
23
+ }
24
+ /**
25
+ * Read cookies, then narrow by an attribute chain and an optional field.
26
+ *
27
+ * `attributes` entries are either `{index: n}` (array index) or
28
+ * `{<any>: [key]}` / `{<any>: [key, value]}` — a single-element array reads the
29
+ * key, a pair searches for the object whose key equals value.
30
+ * `field` is one of "len" | "keys" | "values", else the narrowed value is returned.
31
+ */
32
+ export async function getCookies(context, attributes, field = '') {
33
+ const attrs = attributes ?? [];
34
+ log.helper(` [getCookies] attributes=${JSON.stringify(attrs)} field=${JSON.stringify(field)}`);
35
+ let queried = await context.cookies();
36
+ for (const attr of attrs) {
37
+ for (const [key, value] of Object.entries(attr)) {
38
+ if (key === 'index') {
39
+ queried = queried[Number(value)] ?? null;
40
+ continue;
41
+ }
42
+ const query = value;
43
+ if (query.length === 1) {
44
+ const obj = (queried ?? {});
45
+ queried = obj[String(query[0])] ?? '';
46
+ }
47
+ else {
48
+ queried = findObjectWithKv(queried, String(query[0]), query[1]);
49
+ if (queried === null) {
50
+ throw new Error(`Key ${String(query[0])} with value ${String(query[1])} not found in queried content.`);
51
+ }
52
+ }
53
+ }
54
+ }
55
+ if (field === 'len') {
56
+ if (Array.isArray(queried) || typeof queried === 'string')
57
+ return queried.length;
58
+ return Object.keys((queried ?? {})).length;
59
+ }
60
+ if (field === 'keys')
61
+ return Object.keys((queried ?? {}));
62
+ if (field === 'values')
63
+ return Object.values((queried ?? {}));
64
+ return queried;
65
+ }
66
+ //# sourceMappingURL=cookies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookies.js","sourceRoot":"","sources":["../../src/helpers/cookies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Coordinate → element → verified-XPath derivation (design spec §3.1, §4).
3
+ *
4
+ * playwright-ts twin of the PY/Selenium coordinate resolvers. RESOLVER_JS is
5
+ * the CANONICAL tree-shared script — it must stay byte-identical to the
6
+ * selenium-python / playwright-python copies (spec §4.3: edit ALL trees
7
+ * together).
8
+ */
9
+ import type { Page } from 'playwright';
10
+ export declare const RESOLVER_JS = "try {\n var el = document.elementFromPoint(x, y);\n if (!el) { return null; }\n while (el.shadowRoot) {\n var deeper = el.shadowRoot.elementFromPoint(x, y);\n if (!deeper || deeper === el) { break; }\n el = deeper;\n }\n if (el.getRootNode && el.getRootNode() !== document) { return null; }\n var hitTag = el.tagName ? el.tagName.toLowerCase() : '';\n if (hitTag === 'iframe' || hitTag === 'frame' || hitTag === 'canvas' || hitTag === 'video') { return null; }\n\n var INTERACTABLE = 'a, button, input, select, textarea, summary, label, [onclick], [contenteditable], [tabindex]:not([tabindex=\"-1\"]), [role=\"button\"], [role=\"link\"], [role=\"checkbox\"], [role=\"radio\"], [role=\"menuitem\"], [role=\"tab\"], [role=\"option\"], [role=\"switch\"], [role=\"combobox\"], [role=\"textbox\"]';\n if (!(el.matches && el.matches(INTERACTABLE))) {\n var cur = el;\n var hops = 0;\n while (cur && cur !== document.documentElement && hops < 6) {\n cur = cur.parentElement;\n hops += 1;\n if (cur && cur.matches && cur.matches(INTERACTABLE)) { el = cur; break; }\n }\n }\n\n function xpathLiteral(v) {\n if (v.indexOf(\"'\") === -1) { return \"'\" + v + \"'\"; }\n if (v.indexOf('\"') === -1) { return '\"' + v + '\"'; }\n return \"concat('\" + v.split(\"'\").join(\"', \\\"'\\\", '\") + \"')\";\n }\n\n function verifies(xp) {\n try {\n var r = document.evaluate(xp, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n return r.snapshotLength === 1 && r.snapshotItem(0) === el;\n } catch (e) { return false; }\n }\n\n var tag = el.tagName.toLowerCase();\n var candidates = [];\n if (el.id) { candidates.push('//*[@id=' + xpathLiteral(el.id) + ']'); }\n var ATTRS = ['data-testid', 'data-test', 'data-qa', 'name', 'aria-label', 'placeholder', 'title'];\n for (var i = 0; i < ATTRS.length; i++) {\n var av = el.getAttribute(ATTRS[i]);\n if (av) { candidates.push('//' + tag + '[@' + ATTRS[i] + '=' + xpathLiteral(av) + ']'); break; }\n }\n var text = (el.textContent || '').replace(/\\s+/g, ' ').trim();\n if (text && text.length <= 64) {\n candidates.push('//' + tag + '[normalize-space(.)=' + xpathLiteral(text) + ']');\n }\n var parts = [];\n var node = el;\n while (node && node.nodeType === 1) {\n var name = node.tagName.toLowerCase();\n var idx = 1;\n var sib = node.previousElementSibling;\n while (sib) {\n if (sib.tagName === node.tagName) { idx += 1; }\n sib = sib.previousElementSibling;\n }\n parts.unshift(name + '[' + idx + ']');\n node = node.parentElement;\n }\n candidates.push('/' + parts.join('/'));\n\n for (var c = 0; c < candidates.length; c++) {\n if (verifies(candidates[c])) {\n return { xpath: candidates[c], tag: tag, id: el.id || '', text: text.slice(0, 80) };\n }\n }\n return null;\n} catch (e) {\n return null;\n}\n";
11
+ /** A self-verified, document-rooted XPath for the element under a point. */
12
+ export interface ResolvedTarget {
13
+ xpath: string;
14
+ meta: {
15
+ tag: string;
16
+ id: string;
17
+ text: string;
18
+ };
19
+ }
20
+ /**
21
+ * Resolve viewport-CSS (x, y) to a verified XPath, or null.
22
+ *
23
+ * null ALWAYS means "use the coordinate fallback" (shadow-DOM hit, iframe
24
+ * hit, no node, verification failure, or any JS error). Never throws — a
25
+ * derivation failure must never break a heal that would have succeeded via
26
+ * the coord runner (spec §3.1).
27
+ */
28
+ export declare function resolveCoordinate(page: Page, x: number, y: number): Promise<ResolvedTarget | null>;
29
+ //# sourceMappingURL=coordinateResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinateResolver.d.ts","sourceRoot":"","sources":["../../src/helpers/coordinateResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,eAAO,MAAM,WAAW,s1FAyEvB,CAAC;AAWF,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,IAAI,EACV,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,GACR,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAyBhC"}
@@ -0,0 +1,118 @@
1
+ import { log } from '../log.js';
2
+ // === CANONICAL_RESOLVER_JS_START === (edit ALL trees together; spec §4.3)
3
+ export const RESOLVER_JS = `\
4
+ try {
5
+ var el = document.elementFromPoint(x, y);
6
+ if (!el) { return null; }
7
+ while (el.shadowRoot) {
8
+ var deeper = el.shadowRoot.elementFromPoint(x, y);
9
+ if (!deeper || deeper === el) { break; }
10
+ el = deeper;
11
+ }
12
+ if (el.getRootNode && el.getRootNode() !== document) { return null; }
13
+ var hitTag = el.tagName ? el.tagName.toLowerCase() : '';
14
+ if (hitTag === 'iframe' || hitTag === 'frame' || hitTag === 'canvas' || hitTag === 'video') { return null; }
15
+
16
+ var INTERACTABLE = 'a, button, input, select, textarea, summary, label, [onclick], [contenteditable], [tabindex]:not([tabindex="-1"]), [role="button"], [role="link"], [role="checkbox"], [role="radio"], [role="menuitem"], [role="tab"], [role="option"], [role="switch"], [role="combobox"], [role="textbox"]';
17
+ if (!(el.matches && el.matches(INTERACTABLE))) {
18
+ var cur = el;
19
+ var hops = 0;
20
+ while (cur && cur !== document.documentElement && hops < 6) {
21
+ cur = cur.parentElement;
22
+ hops += 1;
23
+ if (cur && cur.matches && cur.matches(INTERACTABLE)) { el = cur; break; }
24
+ }
25
+ }
26
+
27
+ function xpathLiteral(v) {
28
+ if (v.indexOf("'") === -1) { return "'" + v + "'"; }
29
+ if (v.indexOf('"') === -1) { return '"' + v + '"'; }
30
+ return "concat('" + v.split("'").join("', \\"'\\", '") + "')";
31
+ }
32
+
33
+ function verifies(xp) {
34
+ try {
35
+ var r = document.evaluate(xp, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
36
+ return r.snapshotLength === 1 && r.snapshotItem(0) === el;
37
+ } catch (e) { return false; }
38
+ }
39
+
40
+ var tag = el.tagName.toLowerCase();
41
+ var candidates = [];
42
+ if (el.id) { candidates.push('//*[@id=' + xpathLiteral(el.id) + ']'); }
43
+ var ATTRS = ['data-testid', 'data-test', 'data-qa', 'name', 'aria-label', 'placeholder', 'title'];
44
+ for (var i = 0; i < ATTRS.length; i++) {
45
+ var av = el.getAttribute(ATTRS[i]);
46
+ if (av) { candidates.push('//' + tag + '[@' + ATTRS[i] + '=' + xpathLiteral(av) + ']'); break; }
47
+ }
48
+ var text = (el.textContent || '').replace(/\\s+/g, ' ').trim();
49
+ if (text && text.length <= 64) {
50
+ candidates.push('//' + tag + '[normalize-space(.)=' + xpathLiteral(text) + ']');
51
+ }
52
+ var parts = [];
53
+ var node = el;
54
+ while (node && node.nodeType === 1) {
55
+ var name = node.tagName.toLowerCase();
56
+ var idx = 1;
57
+ var sib = node.previousElementSibling;
58
+ while (sib) {
59
+ if (sib.tagName === node.tagName) { idx += 1; }
60
+ sib = sib.previousElementSibling;
61
+ }
62
+ parts.unshift(name + '[' + idx + ']');
63
+ node = node.parentElement;
64
+ }
65
+ candidates.push('/' + parts.join('/'));
66
+
67
+ for (var c = 0; c < candidates.length; c++) {
68
+ if (verifies(candidates[c])) {
69
+ return { xpath: candidates[c], tag: tag, id: el.id || '', text: text.slice(0, 80) };
70
+ }
71
+ }
72
+ return null;
73
+ } catch (e) {
74
+ return null;
75
+ }
76
+ `;
77
+ // === CANONICAL_RESOLVER_JS_END ===
78
+ // Built via the Function constructor (browser-executed by Playwright, which
79
+ // serializes fn.toString() over the wire) — the grid CDP relay returns
80
+ // undefined for STRING page-functions, so a plain string wrap never runs.
81
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
82
+ const WRAPPED_FN = new Function('args', 'const [x, y] = args;\n' + RESOLVER_JS);
83
+ /**
84
+ * Resolve viewport-CSS (x, y) to a verified XPath, or null.
85
+ *
86
+ * null ALWAYS means "use the coordinate fallback" (shadow-DOM hit, iframe
87
+ * hit, no node, verification failure, or any JS error). Never throws — a
88
+ * derivation failure must never break a heal that would have succeeded via
89
+ * the coord runner (spec §3.1).
90
+ */
91
+ export async function resolveCoordinate(page, x, y) {
92
+ let raw;
93
+ try {
94
+ raw = await page.evaluate(WRAPPED_FN, [Math.trunc(x), Math.trunc(y)]);
95
+ }
96
+ catch (exc) {
97
+ log.helper(` [resolver] derived_xpath=None reason=js-error: ${String(exc)}`);
98
+ return null;
99
+ }
100
+ if (raw === null || typeof raw !== 'object') {
101
+ log.helper(' [resolver] derived_xpath=None reason=no-node-or-bail');
102
+ return null;
103
+ }
104
+ const obj = raw;
105
+ const xpath = obj['xpath'];
106
+ if (typeof xpath !== 'string' || !xpath) {
107
+ log.helper(' [resolver] derived_xpath=None reason=verify-failed');
108
+ return null;
109
+ }
110
+ const meta = {
111
+ tag: String(obj['tag'] ?? ''),
112
+ id: String(obj['id'] ?? ''),
113
+ text: String(obj['text'] ?? ''),
114
+ };
115
+ log.helper(` [resolver] derived_xpath=${xpath} meta=${JSON.stringify(meta)}`);
116
+ return { xpath, meta };
117
+ }
118
+ //# sourceMappingURL=coordinateResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinateResolver.js","sourceRoot":"","sources":["../../src/helpers/coordinateResolver.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyE1B,CAAC;AACF,oCAAoC;AAEpC,4EAA4E;AAC5E,uEAAuE;AACvE,0EAA0E;AAC1E,8DAA8D;AAC9D,MAAM,UAAU,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,wBAAwB,GAAG,WAAW,CAElE,CAAC;AAQb;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAU,EACV,CAAS,EACT,CAAS;IAET,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAmB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAU,CAAC,CAAC;IAC1F,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,MAAM,CAAC,sDAAsD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5C,GAAG,CAAC,MAAM,CAAC,0DAA0D,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,GAA8B,CAAC;IAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;QACxC,GAAG,CAAC,MAAM,CAAC,wDAAwD,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG;QACX,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;KAChC,CAAC;IACF,GAAG,CAAC,MAAM,CAAC,gCAAgC,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Read-tuned coordinate → element → verified-XPath (textual_query read path).
3
+ *
4
+ * playwright-ts read twin of PY _coordinate_resolver_read.py / selenium's
5
+ * READ_RESOLVER_JS. READ_RESOLVER_JS is CANONICAL and byte-shared across all
6
+ * three trees (spec §4.3: edit ALL trees together).
7
+ *
8
+ * Key difference from coordinateResolver.ts / RESOLVER_JS:
9
+ * The interactable ancestor up-walk (INTERACTABLE selector + 6-hop
10
+ * parentElement loop) is OMITTED, and img is a bail tag. `el` stays the
11
+ * exact elementFromPoint hit, so non-inherited CSS (background-color) is
12
+ * read from the correct box, not a climbed a/button/[role] ancestor.
13
+ */
14
+ import type { Page } from 'playwright';
15
+ export declare const READ_RESOLVER_JS = "try {\n var el = document.elementFromPoint(x, y);\n if (!el) { return null; }\n while (el.shadowRoot) {\n var deeper = el.shadowRoot.elementFromPoint(x, y);\n if (!deeper || deeper === el) { break; }\n el = deeper;\n }\n if (el.getRootNode && el.getRootNode() !== document) { return null; }\n var hitTag = el.tagName ? el.tagName.toLowerCase() : '';\n if (hitTag === 'iframe' || hitTag === 'frame' || hitTag === 'canvas' || hitTag === 'video' || hitTag === 'img') { return null; }\n\n // *** NO interactable up-walk here (the ONLY structural difference from\n // RESOLVER_JS): the read must stay on the exact direct hit so non-inherited\n // CSS (background-color) is read off the correct box. ***\n\n function xpathLiteral(v) {\n if (v.indexOf(\"'\") === -1) { return \"'\" + v + \"'\"; }\n if (v.indexOf('\"') === -1) { return '\"' + v + '\"'; }\n return \"concat('\" + v.split(\"'\").join(\"', \\\"'\\\", '\") + \"')\";\n }\n function verifies(xp) {\n try {\n var r = document.evaluate(xp, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n return r.snapshotLength === 1 && r.snapshotItem(0) === el;\n } catch (e) { return false; }\n }\n var tag = el.tagName.toLowerCase();\n var candidates = [];\n if (el.id) { candidates.push('//*[@id=' + xpathLiteral(el.id) + ']'); }\n var ATTRS = ['data-testid', 'data-test', 'data-qa', 'name', 'aria-label', 'placeholder', 'title'];\n for (var i = 0; i < ATTRS.length; i++) {\n var av = el.getAttribute(ATTRS[i]);\n if (av) { candidates.push('//' + tag + '[@' + ATTRS[i] + '=' + xpathLiteral(av) + ']'); break; }\n }\n var text = (el.textContent || '').replace(/\\s+/g, ' ').trim();\n if (text && text.length <= 64) {\n candidates.push('//' + tag + '[normalize-space(.)=' + xpathLiteral(text) + ']');\n }\n var parts = [];\n var node = el;\n while (node && node.nodeType === 1) {\n var name = node.tagName.toLowerCase();\n var idx = 1;\n var sib = node.previousElementSibling;\n while (sib) { if (sib.tagName === node.tagName) { idx += 1; } sib = sib.previousElementSibling; }\n parts.unshift(name + '[' + idx + ']');\n node = node.parentElement;\n }\n candidates.push('/' + parts.join('/'));\n for (var c = 0; c < candidates.length; c++) {\n if (verifies(candidates[c])) {\n return { xpath: candidates[c], tag: tag, id: el.id || '', text: text.slice(0, 80) };\n }\n }\n return null;\n} catch (e) {\n return null;\n}\n";
16
+ /** A self-verified, document-rooted XPath for the element under a point (read path). */
17
+ export interface ResolvedRead {
18
+ xpath: string;
19
+ meta: {
20
+ tag: string;
21
+ id: string;
22
+ text: string;
23
+ };
24
+ }
25
+ /**
26
+ * Resolve viewport-CSS (x, y) to a verified XPath for READING, or null.
27
+ *
28
+ * Identical no-throw contract to resolveCoordinate but uses READ_RESOLVER_JS
29
+ * (no interactable up-walk), so the derived xpath is the EXACT direct hit —
30
+ * correct for non-interactable nodes and non-inherited CSS (background-color).
31
+ *
32
+ * null ALWAYS means "use the server fallback" (shadow-DOM hit, iframe hit,
33
+ * canvas/video/img hit, no node, verification failure, or any JS error).
34
+ */
35
+ export declare function resolveCoordinateRead(page: Page, x: number, y: number): Promise<ResolvedRead | null>;
36
+ //# sourceMappingURL=coordinateResolverRead.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinateResolverRead.d.ts","sourceRoot":"","sources":["../../src/helpers/coordinateResolverRead.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,eAAO,MAAM,gBAAgB,m7EA4D5B,CAAC;AAWF,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,IAAI,EACV,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,GACR,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAyB9B"}