@cutleryapp/agent 1.0.44 → 1.0.45

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.
@@ -85,9 +85,14 @@ class TestExecutor {
85
85
  const stepAttachment = (testCase.step_attachments || {})[String(i)] || null;
86
86
  console.log(` 📎 Step ${i} attachment: ${stepAttachment ? `YES (${stepAttachment.length} chars)` : 'none'}`);
87
87
  let stepError;
88
- // Dismiss any open overlay (date picker, dropdown, modal) from the previous step
89
- if (i > 0)
88
+ // Dismiss any open overlay (calendar, dropdown, modal) left from the previous step
89
+ if (i > 0) {
90
90
  await page.keyboard.press('Escape').catch(() => { });
91
+ await page.waitForTimeout(80);
92
+ // Click a neutral spot (top-left corner) to blur active element and close popups
93
+ await page.mouse.click(10, 10).catch(() => { });
94
+ await page.waitForTimeout(80);
95
+ }
91
96
  try {
92
97
  // When a reference image is attached, skip MCP strategies entirely and go
93
98
  // straight to the AI multi-field loop so it can scan the form and fill everything.
@@ -387,21 +392,29 @@ class TestExecutor {
387
392
  catch { /* next */ }
388
393
  }
389
394
  }
390
- // 2. Radio / checkbox label click before autocomplete so radio buttons
391
- // are handled in <100ms instead of waiting through autocomplete timeouts
395
+ // 2. Radio / checkbox try before autocomplete so radios resolve in <100ms
392
396
  if (!selHandled) {
393
- try {
394
- await page.locator(`label:has-text("${optionValue}")`).first().click({ timeout: 800 });
395
- selHandled = true;
396
- }
397
- catch { /* not a labelled radio/checkbox */ }
398
- }
399
- if (!selHandled) {
400
- try {
401
- await page.locator(`input[type="radio"][value="${optionValue}" i], input[type="checkbox"][value="${optionValue}" i]`).first().click({ force: true, timeout: 800 });
402
- selHandled = true;
397
+ for (const sel of [
398
+ `label:text-is("${optionValue}")`, // exact case-insensitive
399
+ `label:has-text("${optionValue}")`, // substring match
400
+ `[role="radio"]:has-text("${optionValue}")`,
401
+ `input[type="radio"][value="${optionValue}" i]`,
402
+ `input[type="checkbox"][value="${optionValue}" i]`,
403
+ ]) {
404
+ try {
405
+ const loc = page.locator(sel).first();
406
+ const tag = await loc.evaluate((el) => el.tagName.toLowerCase()).catch(() => 'label');
407
+ if (tag === 'input') {
408
+ await loc.click({ force: true, timeout: 800 });
409
+ }
410
+ else {
411
+ await loc.click({ timeout: 800 });
412
+ }
413
+ selHandled = true;
414
+ break;
415
+ }
416
+ catch { /* try next */ }
403
417
  }
404
- catch { /* not an input with matching value */ }
405
418
  }
406
419
  // 3. React-select / autocomplete typeahead
407
420
  if (!selHandled) {
@@ -1268,11 +1281,15 @@ async function tryFillDate(page, label, value) {
1268
1281
  await page.keyboard.press('Meta+a'); // Mac
1269
1282
  await page.keyboard.type(value, { delay: 40 });
1270
1283
  await page.waitForTimeout(150);
1271
- // Tab out to commit this also closes the calendar
1284
+ // Tab out to commit and close the calendar
1272
1285
  await page.keyboard.press('Tab');
1273
1286
  await page.waitForTimeout(200);
1274
- // If calendar is still open, press Escape
1287
+ // Aggressively close any calendar still open
1275
1288
  await page.keyboard.press('Escape').catch(() => { });
1289
+ await page.waitForTimeout(100);
1290
+ // Click neutral area to ensure calendar/overlay is gone
1291
+ await page.mouse.click(10, 10).catch(() => { });
1292
+ await page.waitForTimeout(150);
1276
1293
  return;
1277
1294
  }
1278
1295
  catch { /* try next */ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cutleryapp/agent",
3
- "version": "1.0.44",
3
+ "version": "1.0.45",
4
4
  "description": "Local agent that connects your machine to the Cutlery QA platform and runs UI tests via Playwright",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {