fix(extension): reject selectOption when no option matches

HS
4d ago
+58-2

why

When none of the requested values match an option, locator.selectOption() deselects every option. A single <select> then falls back to its first option, and a multi-select is cleared. input and change still fire, and the call resolves with that first option's value as if it had been chosen:

// <select id="size"><option value="s">Small</option><option value="m" selected>Medium</option></select>
await page.locator("#size").selectOption("Extra Large"); // resolves ["s"], select now shows "Small"

The same path backs act()'s selectOptionFromDropdown. A model value that is slightly off (a typo, or a label that doesn't match exactly) silently submits the wrong choice, and act() reports success. #2953 works around this with a snapshot read-back ("selectOption reports success even when nothing matched"). The Playwright migration guide lists selectOption() as "Same names", and Playwright throws in this case.

what changed

  • selectElementOptions returns null without touching the selection when values were requested but no option matches them. selectOption([]) still clears a multi-select.
  • Locator.selectOption throws Failed to select option (no option matches [...]) for selector: ... on that null. act() already logs and rethrows selection errors.
  • Added an integration test covering a single select and a multi-select: the call rejects, the selection is unchanged, and no change event fires.
  • Patch changeset for the extension and both SDKs.

test plan

  • pnpm exec vitest run -c vitest.integration.config.ts packages/sdk-ts/tests/integration/locatorSelectOption.test.ts: the new test fails before the fix (promise resolved "[ 's' ]" instead of rejecting). After the fix, 11/11 pass.
  • just check passes.
  • pnpm --filter ./packages/extension test:unit: 1054 passed. pnpm --filter ./packages/sdk-ts test:unit: 579 passed.
  • pnpm --filter ./packages/sdk-ts test:browser: 25 passed, 18 skipped. Only rpcClientExtensionSmoke fails, and it fails on main too (path contains a space).
  • Python SDK pytest: 1052 passed, 5 skipped.

Summary by cubic

Rejects locator.selectOption() when no option matches the requested values, instead of silently resetting the <select> to its first option (or clearing a multi-select) and reporting success.

Previously, a single <select> fell back to its first option and the call resolved as if that option was chosen, so a typo or slightly-off label could submit the wrong choice. Now the call throws, the current selection is left unchanged, and no input or change events fire. This aligns the behavior with Playwright, which throws in this case.

Bug Fixes

  • selectElementOptions returns null without touching the selection when values were requested but none match; selectOption([]) still clears a multi-select.
  • Locator.selectOption throws Failed to select option (no option matches [...]).
  • Added integration tests covering single and multi-selects: the call rejects, the selection is unchanged, and no change event fires.
  • Patch changeset for the extension and both SDKs.