@cutleryapp/agent 1.0.39 → 1.0.40

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.
@@ -334,36 +334,37 @@ class TestExecutor {
334
334
  const optionValue = selMatch[1].trim();
335
335
  const fieldLabel = selMatch[2].trim();
336
336
  let selHandled = false;
337
- // Try native <select>
337
+ // 1. Native <select> — fastest for actual <select> elements
338
338
  try {
339
339
  const fieldLoc = page.getByLabel(new RegExp(fieldLabel, 'i')).first();
340
340
  await fieldLoc.selectOption({ label: optionValue }, { timeout: 800 });
341
341
  selHandled = true;
342
342
  }
343
343
  catch { /* not a native select */ }
344
- // Try React-select / autocomplete typeahead
345
- if (!selHandled) {
346
- selHandled = await tryAutocomplete(page, fieldLabel, optionValue);
347
- }
348
- // Try clicking a visible option in an already-open dropdown
344
+ // 2. Radio / checkbox label click — do this BEFORE autocomplete so radio buttons
345
+ // are handled in <100ms instead of waiting through autocomplete timeouts
349
346
  if (!selHandled) {
350
347
  try {
351
- await page.locator(`[role="option"]:has-text("${optionValue}"), [class*="option"]:has-text("${optionValue}")`).first().click({ timeout: 1500 });
348
+ await page.locator(`label:has-text("${optionValue}")`).first().click({ timeout: 800 });
352
349
  selHandled = true;
353
350
  }
354
- catch { /* try checkbox */ }
351
+ catch { /* not a labelled radio/checkbox */ }
355
352
  }
356
- // Checkbox / radio fallback — label click or direct input click
357
353
  if (!selHandled) {
358
354
  try {
359
- await page.locator(`label:has-text("${optionValue}")`).first().click({ timeout: 2000 });
355
+ await page.locator(`input[type="radio"][value="${optionValue}" i], input[type="checkbox"][value="${optionValue}" i]`).first().click({ force: true, timeout: 800 });
360
356
  selHandled = true;
361
357
  }
362
- catch { /* try input by value */ }
358
+ catch { /* not an input with matching value */ }
363
359
  }
360
+ // 3. React-select / autocomplete typeahead
361
+ if (!selHandled) {
362
+ selHandled = await tryAutocomplete(page, fieldLabel, optionValue);
363
+ }
364
+ // 4. Already-open dropdown option
364
365
  if (!selHandled) {
365
366
  try {
366
- await page.locator(`input[type="radio"][value="${optionValue}" i], input[type="checkbox"][value="${optionValue}" i]`).first().click({ force: true, timeout: 2000 });
367
+ await page.locator(`[role="option"]:has-text("${optionValue}"), [class*="option"]:has-text("${optionValue}")`).first().click({ timeout: 1000 });
367
368
  selHandled = true;
368
369
  }
369
370
  catch { /* fall to AI */ }
@@ -978,12 +979,17 @@ async function tryAutocomplete(page, fieldLabel, value) {
978
979
  for (const loc of inputLocators) {
979
980
  try {
980
981
  const input = loc.first();
981
- // Skip wrapper divs getByLabel can return the React-select container div
982
+ // Skip wrapper divs and non-text inputs (radio/checkbox handled by label click above)
982
983
  const tag = await input.evaluate((el) => el.tagName.toLowerCase()).catch(() => '');
983
984
  if (tag && !['input', 'textarea'].includes(tag))
984
985
  continue;
985
- await input.waitFor({ state: 'visible', timeout: 1500 });
986
- await input.click({ timeout: 1500 });
986
+ if (tag === 'input') {
987
+ const inputType = await input.evaluate((el) => el.type || '').catch(() => '');
988
+ if (['radio', 'checkbox', 'submit', 'button', 'file', 'hidden'].includes(inputType))
989
+ continue;
990
+ }
991
+ await input.waitFor({ state: 'visible', timeout: 500 });
992
+ await input.click({ timeout: 500 });
987
993
  await input.fill('');
988
994
  await input.type(value, { delay: 30 });
989
995
  await page.waitForTimeout(350);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cutleryapp/agent",
3
- "version": "1.0.39",
3
+ "version": "1.0.40",
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": {