Bidi browserstack executor http - #119
Conversation
…TTP/S in BiDi sessions In BiDi sessions, browser.execute() routes over WebSocket directly to the browser, bypassing BrowserStack's HTTP hub, so browserstack_executor: commands fail silently. Overwrite the execute command in BiDi sessions to route executor-prefixed scripts through executeScript (which always uses HTTP/S), leaving all other scripts untouched. Handles single-browser and multiremote setups. Ported from webdriverio/webdriverio#15216. Co-Authored-By: RohanImmanuel <RohanImmanuel@users.noreply.github.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…http fix(browserstack-service): route browserstack_executor commands via HTTP/S in BiDi sessions
|
🔴 SDK PR Review gate is red. Pending:
It turns green once the latest SDK PR Review Agent run reports GTG on the current head commit. A native reviewer approval is separately required by branch protection before merge. |
|
🔴 SDK PR Review gate is red. Pending:
It turns green once the latest SDK PR Review Agent run reports GTG on the current head commit. A native reviewer approval is separately required by branch protection before merge. |
SDK PR Review — 🔴 Fix 2 blocking issuesReviewed Blocking1. The Per SH-12, a feature that cannot run must disable itself loudly and leave the test unaffected — never half-enable. - try {
- if (this._browser.isMultiremote) {
- const multiRemoteBrowser = this._browser as unknown as WebdriverIO.MultiRemoteBrowser
- Object.keys(this._caps).forEach((browserName) => {
- this._routeBidiExecutorToHttp(multiRemoteBrowser.getInstance(browserName))
- })
- } else {
- this._routeBidiExecutorToHttp(this._browser as WebdriverIO.Browser)
- }
- } catch (err) {
- BStackLogger.warn(`Failed to patch execute for BiDi browserstack_executor routing; executor commands may not work in BiDi sessions: ${err}`)
- }
+ const patch = (browser: WebdriverIO.Browser, label?: string) => {
+ try {
+ this._routeBidiExecutorToHttp(browser)
+ } catch (err) {
+ BStackLogger.warn(`Failed to patch execute for BiDi browserstack_executor routing${label ? ` on ${label}` : ''}; executor commands may not work in BiDi sessions: ${err}`)
+ }
+ }
+
+ if (this._browser.isMultiremote) {
+ const multiRemoteBrowser = this._browser as unknown as WebdriverIO.MultiRemoteBrowser
+ Object.keys(this._caps).forEach((browserName) => {
+ patch(multiRemoteBrowser.getInstance(browserName), browserName)
+ })
+ } else {
+ patch(this._browser as WebdriverIO.Browser)
+ }
2. All three new tests are happy-path: single-browser BiDi patch, non-BiDi no-op, and a fully-successful 2-instance multiremote patch. None makes Non-blockingNone. Both findings above survived a falsification pass. Checked and cleared
Per-file confidence
|
|
🔴 SDK PR Review gate is red. Pending:
It turns green once the latest SDK PR Review Agent run reports GTG on the current head commit. A native reviewer approval is separately required by branch protection before merge. |
…nstance The try/catch wrapped the whole multiremote forEach, so a getInstance failure on one instance aborted the loop and left every later instance unpatched — a half-patched session indistinguishable in the logs from a fully-failed one. Wrap each instance's resolve-and-patch individually and name the failing instance in the warning. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
🔴 SDK PR Review gate is red. Pending:
It turns green once the latest SDK PR Review Agent run reports GTG on the current head commit. A native reviewer approval is separately required by branch protection before merge. |
SDK PR Review — ✅ GTGRe-reviewed at Prior findings1. Half-patched multiremote loop — RESOLVED. Confirmed non-cosmetic: reverting 2. Missing throw-path test — RESOLVED. Thunk approach
Non-blocking
CI at this head
Per-file confidence
|
|
🟢 SDK PR Review gate is green — the SDK PR Review Agent has given a GTG for this PR (the A native GitHub reviewer approval is still separately required by branch protection before this PR can merge — this check does not substitute for that. |
1 similar comment
|
🟢 SDK PR Review gate is green — the SDK PR Review Agent has given a GTG for this PR (the A native GitHub reviewer approval is still separately required by branch protection before this PR can merge — this check does not substitute for that. |
What is this about?
In WebDriver BiDi sessions,
browser.execute()is dispatched over the BiDi socket (script.callFunction) instead of the classic W3C/execute/syncHTTP endpoint. BrowserStack'sbrowserstack_executor: {...}commands are interpreted by the hub on that HTTP endpoint, so every executor call the service makes (session name/status, annotations, etc.) is silently swallowed when BiDi is enabled.This PR makes the service route only those executor calls back over HTTP while leaving normal scripts on BiDi:
_routeBidiExecutorToHttp(browser)— no-op unlessbrowser.isBidi. On a BiDi browser itoverwriteCommand('execute', ...), and when the script is a string starting withbrowserstack_executor:it delegates tobrowser.executeScript(script, args)(classic HTTP). Everything else falls through to the originalexecute.before(): applied to each instance viagetInstance(browserName)for multiremote, and to the single browser otherwise.try/catch— a failure logs aBStackLogger.warnand the session continues rather than breaking the user's test run.Unit tests cover: the overwrite routing executor scripts to
executeScriptwhile passing normal scripts (and their args) through to the originalexecute; no overwrite on non-BiDi sessions; and per-instance overwrite in multiremote with no cross-instance leakage.Files touched:
packages/browserstack-service/src/service.ts,packages/browserstack-service/tests/service.test.ts.Related Jira task/s
N/A — no Jira ticket linked. Originates from #118.
Release (mandatory for every PR — required for the
ready-for-reviewlabel)Version bump: (required — tick exactly one)
Release notes type: (optional)
Release notes (customer-facing): (optional but encouraged)
Release notes (internal): (required — engineer-facing; what actually changed / why)
browser.executeis overwritten on BiDi browsers sobrowserstack_executor:scripts are sent viaexecuteScript(classic HTTP/execute/sync) instead of BiDiscript.callFunction, which the hub does not intercept. Non-executor scripts still go through the originalexecute.before()per multiremote instance (getInstance) or to the single browser; skipped entirely whenbrowser.isBidiis false.try/catchwith aBStackLogger.warnso a failure degrades gracefully instead of failing the session.Checklist
PR Validations
Run Tests: Comment RUN_TESTS to trigger sanity tests.