Fix: SDK-7075 honour BROWSERSTACK_LOCAL / BROWSERSTACK_LOCAL_IDENTIFIER in the WDIO service - #151
Open
shivam5643 wants to merge 2 commits into
Open
Fix: SDK-7075 honour BROWSERSTACK_LOCAL / BROWSERSTACK_LOCAL_IDENTIFIER in the WDIO service#151shivam5643 wants to merge 2 commits into
shivam5643 wants to merge 2 commits into
Conversation
…OCAL_IDENTIFIER (SDK-7075) The service resolved BrowserStack Local purely from the `wdio.conf.js` service options, so the SDK-wide `BROWSERSTACK_LOCAL` / `BROWSERSTACK_LOCAL_IDENTIFIER` env vars were silently dropped: no tunnel was launched and no `local` / `localIdentifier` capability reached the session, leaving every session with `isLocalEnabled: false`. Add `normalizeLocalEnvVariables()` and call it from the launcher constructor alongside the existing `normalizeTestReporting*` normalizers. The env var wins over `wdio.conf.js`, matching `updateConfigWithEnvVars` in browserstack-binary and `getObservabilityUser` / `getObservabilityKey` here. An identifier on its own still does not enable Local, mirroring `getLocalConfig()` in the binary. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
shivam5643
requested review from
dandonarahul2002 and
kamal-kaur04
and removed request for
a team
August 17, 2026 11:16
Contributor
|
🔴 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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is this about?
@wdio/browserstack-servicenever readBROWSERSTACK_LOCAL/BROWSERSTACK_LOCAL_IDENTIFIER. Withboth exported and no
browserstackLocalkey inwdio.conf.js, no tunnel was launched and thesession capabilities carried zero local-related keys —
isLocalEnabled: false, andcaps['localIdentifier']raisedKeyError. This makes the service honour the two env vars that arethe SDK-wide contract every other BrowserStack SDK already respects.
Root cause
BrowserstackLauncherService.onPrepareresolves Local purely from the service options: it gatesthe entire Local path on
this._options.browserstackLocal(src/launcher.ts:520) and takes thetunnel identifier from
this._options.opts.localIdentifier(:532). Nothing in the package everread either env var — a
grepfor both names acrosspackages/browserstack-service/src/returnedzero hits on
v8and onmain. So with the env vars exported and nobrowserstackLocalin theconfig,
onPreparetook thebrowserstackLocal is not enabled - skipping...early return: notunnel, and neither
_updateCaps(capabilities, 'local')nor_updateCaps(capabilities, 'localIdentifier', …)ever ran.These env vars are not a WDIO invention —
browserstack-binary'sEnvCapsMappingmapsbrowserstackLocal → BROWSERSTACK_LOCALandlocalIdentifier → BROWSERSTACK_LOCAL_IDENTIFIER(
core/config/env.js:12-13), which is why the sibling wrapper cases on the other SDKs pass. Everyother SDK routes config resolution through the binary; this service does its own resolution in the
non-CLI path and never implemented the env layer.
Fix
One normalization at the single point where the options are first seen — the launcher constructor,
beside the existing
normalizeTestReportingConfig()/normalizeTestReportingEnvVariables()callsthat do exactly this job. The tunnel-start and
_updateCapscode is untouched, so the env-var pathand the config path converge immediately and cannot drift.
packages/browserstack-service/src/util.tsnormalizeLocalEnvVariables()— maps the two env vars onto_options.browserstackLocal/_options.opts.localIdentifierpackages/browserstack-service/src/launcher.tsBrowserStackConfig.getInstance()(4 lines)packages/browserstack-service/src/constants.tsBROWSERSTACK_LOCAL,BROWSERSTACK_LOCAL_IDENTIFIERenv-var name constantspackages/browserstack-service/tests/launcher.test.tsdescribe, env cleared inbeforeEach/afterEach).changeset/sdk-7075-honour-local-env-vars-v8.mdTwo deliberate behavioural decisions, both regression-guarded by tests:
wdio.conf.js— the same direction as the binary'supdateConfigWithEnvVars(
core/config/index.js:168) and asgetObservabilityUser/getObservabilityKey/getObservabilityProjectin this very file.BROWSERSTACK_LOCALonly,mirroring the binary's
getLocalConfig()(core/config/index.js:693), so a staleBROWSERSTACK_LOCAL_IDENTIFIERleft in a CI environment stays inert.Related Jira task/s
Release (mandatory for every PR — required for the
ready-for-reviewlabel)Version bump:
Release notes type:
Release notes (customer-facing):
BROWSERSTACK_LOCALandBROWSERSTACK_LOCAL_IDENTIFIERbeing ignored. Both env vars now configure BrowserStack Local — the tunnel is launched and thelocal/localIdentifiercapabilities reach the session — matching the other BrowserStack SDKs.Release notes (internal):
normalizeLocalEnvVariables()(util.ts) mapsBROWSERSTACK_LOCAL→_options.browserstackLocalandBROWSERSTACK_LOCAL_IDENTIFIER→_options.opts.localIdentifier, called from theBrowserstackLauncherServiceconstructor beforeBrowserStackConfig.getInstance(). Previously the non-CLI path read Local only fromwdio.conf.js, soonPrepareearly-returned and no tunnel orlocal/localIdentifiercaps were produced. Env takes precedence over the config; an identifier alone does not enable Local.Proof
End-to-end against real BrowserStack sessions
Built this branch,
npm packed it, installed the tarball into the reproduction project and ran itunder the original failure conditions: node 16.19.0, WDIO v8, service 8.50.0,
services: [["browserstack", {"testReporting": "true"}]](nobrowserstackLocalkey anywhere),with
BROWSERSTACK_LOCAL=trueandBROWSERSTACK_LOCAL_IDENTIFIER=local_identifier_qoknmqexported.Build: https://automate.browserstack.com/builds/71c8aac5d40fd2f6c82dbae7be0d3abf5056d64b
isLocalEnabledFalseTrueinputCapabilitieslocalIdentifierKeyErrorlocal_identifier_qoknmqlocalcapabilityTrue(asbrowserstack.local)localVersion(tunnel actually ran)8.9BStackAutomation regression coverage
./run_tests.sh tests/{automate,app_automate}/wdio_cucumber/wdio_cucumber_wrapper/test_*wdio_cucumber_wrapper_env_vars.py(fromrun_test.sample.sh,--language wdio --agent_install True --node_version_agent 16.19.0 --wdio_versions v8)SDK-7075_uncomment_testcasesnake_caseauth params, skipped by the fixture for the unrelated open ticket SDK-4942 — pre-existing.test_app_automate_local_identifier, which indexedcaps['localIdentifier']strictly while App Automate surfaces the identifier only asbrowserstack.localIdentifier. The fix-verify caps prove the SDK is correct and the tunnel ran (browserstack.local=True,browserstack.localIdentifier=local_identifier_VfJEXk,browserstack.tunnelIdentifier=local_identifier_VfJEXk,localVersion=8.9) — the assertion read a key that never exists. Corrected in the companion PR, still falsifiable (pre-fix those caps had 26 keys and zero local/tunnel keys).Companion PR — coverage must land with the fix
browserstack/BStackAutomation#80300 — uncomments the three tests (both wrapper files go from
1 live / 2 commented to 3 live / 0 commented) and corrects the strict assertion above. Merging this
fix without it would leave the coverage switched off.
Unit tests
npm test(inpackages/browserstack-service)launcher.test.ts= 122 casesnormalizeLocalEnvVariables()call disabled,launcher.test.tsgoes to7 failed / 115 passed — the 9 new cases genuinely exercise the change. The 2 that pass either
way are the deliberate regression guards (config still honoured with no env var set; identifier
alone must not enable Local).
bstack:optionsand flattenedbrowserstack.*), the identifieractually reaching the Local binary (
mockStartargs), both override directions(
BROWSERSTACK_LOCAL=trueoverbrowserstackLocal: falseand=falseover: true), andBROWSERSTACK_LOCAL_IDENTIFIERoveropts.localIdentifier.npm run build(buf generate +tsc -p tsconfig.prod.json) andtsc --noEmitboth clean.Blast radius
_options.browserstackLocalis read at exactly one site insrc/(launcher.ts:520);opts.localIdentifieris consumed only at:532-533.localnorlocalIdentifieris inNOT_ALLOWED_KEYS_IN_CAPS(constants.ts:50), so_removeCliOnlyCapabilityOptionscannot strip the new caps.onPreparereturns before the Local block (launcher.ts:516-518) and the binary resolves the same two env vars itself — consistent either way, so neither code path is left behind.!isUndefined(process.env[…]), andisUndefined()treats''as unset, so an exported-but-empty var cannot silently disable a config-enabled tunnel.Deliberately out of scope
BROWSERSTACK_BUILD_IDENTIFIERis also missing from the caps, but it is not the same code path:_handleBuildIdentifier(launcher.ts:1064) already branches onprocess.env.BROWSERSTACK_BUILD_NAMEand deletes
buildIdentifierfrom the caps when it is set, so feeding the identifier in from theenv would fight that rule. Needs its own ticket. Same for
BROWSERSTACK_PROJECT_NAME/BROWSERSTACK_BUILD_NAME— the passingtest_project_namecase does not prove those env vars work,because the fixture writes them into
test.conf.jsand exports them with the same values, so theassertion passes off the config.
main) has the identical gap —git grepfor either env var onorigin/mainreturns nothing. This branch targets
v8only, per the repo's rule (v8 →v8, v9 →main) andbecause the ticket and all three reproductions are on v8. The port to
mainis a one-to-onecherry-pick of this commit and should be raised alongside — please don't let the release lines
drift.
Checklist
Review Checklist
process.envreads + property assignment only, so no try/catch is warrantedconstants.tsbeside the existingBROWSERSTACK_*constantssdk-anti-patterns.md) — incl. §2 hardcoded config, §23 parallel-path drift, §26 unreachable fallbacksPR Validations
Run Tests: Comment RUN_TESTS to trigger sanity tests.
Wiki
knowledge/infra-issues/harness-unsatisfiable-assertion-v1.md— the App Automatecaps['localIdentifier']strict-index case, corrected in the companion PRknowledge/infra-issues/uncomment-scaffolding-v1.md(Variant C checked and absent; Variant D — the reason the coverage ships in the companion PR rather than a follow-up)knowledge/conventions/exit-code-is-not-proof.md(why the unit tests were re-run with the fix disabled instead of trusting a green suite)knowledge/conventions/handoff-bundle-format.mdknowledge/conventions/uncomment-branch-resolution.mdHandoff bundle
BStackAutomation/SDK/api/.github/docs/handoff/SDK-7075/handoff.md— the original reproduction (three independent runs, all on service 8.50.0)fix-notes.md— root cause + files changed + local verificationfix-verify.log— test output on this fix branch