Skip to content

fix(wdio-browserstack-service): exclude action from a11y command wrapping (SDK-6265)#3

Closed
harshit-browserstack wants to merge 1 commit into
mainfrom
fix/sdk-6265-a11y-action-command-wrapping
Closed

fix(wdio-browserstack-service): exclude action from a11y command wrapping (SDK-6265)#3
harshit-browserstack wants to merge 1 commit into
mainfrom
fix/sdk-6265-a11y-action-command-wrapping

Conversation

@harshit-browserstack

Copy link
Copy Markdown
Owner

What

With @wdio/browserstack-service and accessibility: true, WebdriverIO's Actions API breaks at runtime:

  • browser.action('pointer').move(...)TypeError: browser.action(...).move is not a function
  • browser.keys(Key.Tab)TypeError: keyAction.down is not a function
  • browser.moveTo() fails the same way.

The identical code works with accessibility: false. Reported by RS Components (SDK-6265 / A11Y-11325).

Root cause

The accessibility command wrapper (commandWrapper) is declared async, so it always returns a Promise. It is installed over every command in the server-supplied commandsToWrap list — which includes action. But WebdriverIO's browser.action() is synchronous: it returns a chainable PointerAction/KeyAction builder. Wrapping it in an async function makes browser.action('pointer') resolve to Promise<PointerAction>, so .move()/.down() are undefined. browser.moveTo() and browser.keys() are implemented on top of action(), so both break too. Already-async commands (keys, actions, moveTo) are unaffected.

Fix

Exclude action — the only synchronous chainable command — from a11y wrapping, in both install sites (direct flow accessibility-handler.ts and CLI/gRPC flow accessibilityModule.ts). Accessibility scan coverage is unchanged (already-async commands stay wrapped).

Verification

  • Reproduced the break on WDIO 9 + @wdio/browserstack-service with accessibility: true; control (accessibility: false) passes.
  • Built this exact change from source and ran it on a real BrowserStack accessibility session: the Actions API commands now succeed, the test passes, and the a11y report still generates (far-side session userStatus: passed).

🤖 Generated with Claude Code

…apping (SDK-6265)

The accessibility command wrapper is declared async, so wrapping
WebdriverIO's synchronous `browser.action()` turned its return value into
a Promise — breaking `browser.action(...).move()` / `.down()`, and
therefore `browser.moveTo()` and `browser.keys(Key.Tab)`, which are built
on top of `action()`. With `accessibility: true` users saw
"browser.action(...).move is not a function" / "keyAction.down is not a
function"; the same code works with accessibility disabled.

Exclude `action` (the only synchronous chainable command) from wrapping
in both install sites (direct flow + CLI/gRPC flow). Already-async
commands (`keys`, `actions`, `moveTo`) stay wrapped, so accessibility
scan coverage is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@harshit-browserstack harshit-browserstack force-pushed the fix/sdk-6265-a11y-action-command-wrapping branch from cbb6ed5 to 780e7a0 Compare June 9, 2026 09:08
@harshit-browserstack

Copy link
Copy Markdown
Owner Author

Closing in favour of a backend-side fix: the A11y backend will drop the action entry from the WebdriverIO commandsToWrap list (SDK-6265 / A11Y-11325). That resolves all existing WebdriverIO customers immediately with no SDK upgrade. Keeping the branch (fix/sdk-6265-a11y-action-command-wrapping) around in case we later want the SDK-side guard (refuse to async-wrap synchronous commands) as defense-in-depth.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant