Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
447c4d3
SDK-7414: open the CLI flow for WebdriverIO-cucumber
AdityaHirapara Sep 2, 2026
78a90f2
feat(cli): add WdioCucumberTestFramework and drive it from cucumber's…
AdityaHirapara Sep 2, 2026
7299385
feat(cli): widen cucumber's shared dispatch gates and hook payload
AdityaHirapara Sep 2, 2026
71fa9bb
fix(cli): honour ignoreHooksStatus when marking cucumber sessions
AdityaHirapara Sep 2, 2026
e6596eb
fix(cli): route turboscale marking, hook-failure verdicts, a11y gate …
AdityaHirapara Sep 3, 2026
bdf9cb1
fix(cli): mark the cucumber session failed when a build hook fails wi…
AdityaHirapara Sep 3, 2026
650ca23
fix(cli): fail the cucumber session when any scenario fails, whatever…
AdityaHirapara Sep 4, 2026
28aa160
fix(a11y): decode goog:chromeOptions when it arrives over gRPC
AdityaHirapara Sep 6, 2026
e7f74f5
fix(cli): honour preferScenarioName on the CLI flow, and keep it out …
AdityaHirapara Sep 6, 2026
f1444f6
refactor(a11y): simplify the mocha-only guard on the hook scan gate
AdityaHirapara Sep 8, 2026
7573393
docs(cli): trim the cucumber hook comments in service.ts
AdityaHirapara Sep 8, 2026
ed012cf
refactor(cli): let automateModule own the preferScenarioName rename
AdityaHirapara Sep 8, 2026
a16ef31
docs(cli): drop parity-table references from cucumber comments
AdityaHirapara Sep 9, 2026
f8f5f6a
docs(cli): condense the BEFORE_ALL cascade comment
AdityaHirapara Sep 9, 2026
1382903
fix(cli): send the raw uri in bdd_meta_info.feature.path
AdityaHirapara Sep 9, 2026
e35a3d1
test(cli): name the cucumber framework suite as the main test file
AdityaHirapara Sep 9, 2026
8c550bd
test(cli): drop migration-plan references from test names and labels
AdityaHirapara Sep 9, 2026
17ed99f
fix(cli): relativise bdd_meta_info.feature.path, which 1382903 did not
AdityaHirapara Sep 9, 2026
f45497d
docs(cli): condense the build-level hook comment
AdityaHirapara Sep 9, 2026
f84fc39
fix(cli): status-mark a session even when setSessionName is false
AdityaHirapara Sep 9, 2026
59a03de
fix(cli): register the driver when every product is turned off
AdityaHirapara Sep 9, 2026
31c5cc7
test(cli): merge the driver-registration tests into service.test.ts
AdityaHirapara Sep 9, 2026
8d63e5f
test(cli): fold service.preferScenarioName.cli.test.ts into service.t…
AdityaHirapara Sep 9, 2026
5fd444d
test(cli): fold the automateModule satellites into its main suite
AdityaHirapara Sep 9, 2026
e9f9aaa
Merge branch 'main' into SDK-7414/wdio-cucumber-platformisation
AdityaHirapara Sep 9, 2026
6a73c32
style(test): drop an unnecessary semicolon failing lint
AdityaHirapara Sep 9, 2026
bb7eacf
Merge branch 'main' into SDK-7414/wdio-cucumber-platformisation
AdityaHirapara Sep 11, 2026
343cc78
fix(cli): decouple scenario naming from the status opt-out, and key r…
AdityaHirapara Sep 17, 2026
bc28ca6
test(cli): pin the tag-scan contract, and make the chrome-options dro…
AdityaHirapara Sep 17, 2026
72fbc49
fix(a11y): report only real chrome-options drops, and pin the untouch…
AdityaHirapara Sep 17, 2026
615130a
Merge branch 'main' into SDK-7414/wdio-cucumber-platformisation
AdityaHirapara Sep 17, 2026
6844406
chore(changeset): auto-generate from PR template (minor)
github-actions[bot] Sep 17, 2026
4bf06c3
Merge remote-tracking branch 'origin/main' into SDK-7414/wdio-cucumbe…
AdityaHirapara Sep 21, 2026
ce93d38
fix(cli): report cucumber screenshots on the binary flow (SDK-4177)
AdityaHirapara Sep 21, 2026
7d6fc53
fix(percy): restore Percy capture on WebdriverIO
harshit-browserstack Sep 21, 2026
e016e7d
chore(changeset): auto-generate from PR template (patch)
github-actions[bot] Sep 21, 2026
85708af
fix(percy): route snapshot to @percy/webdriverio; drop the version cap
harshit-browserstack Sep 22, 2026
e9cfe6e
chore(changeset): auto-generate from PR template (patch)
github-actions[bot] Sep 22, 2026
0939a85
fix(percy): type the snapshot fallback stub as async
harshit-browserstack Sep 22, 2026
6aab2ec
fix(observability): report Mocha/Jasmine test tags
kamal-kaur04 Sep 22, 2026
4bc51b5
chore(changeset): auto-generate from PR template (patch)
github-actions[bot] Sep 22, 2026
f8c49f8
fix(observability): address review on Mocha/Jasmine test tags
kamal-kaur04 Sep 23, 2026
356fd77
added changes for release 9.37.0
rounak610 Sep 24, 2026
5bef99e
Merge pull request #214 from browserstack/fix/SDK-7458-mocha-jasmine-…
rounak610 Sep 24, 2026
55017db
Merge pull request #210 from browserstack/fix/sdk-7711-percy-capture
rounak610 Sep 24, 2026
af78134
Merge pull request #191 from browserstack/SDK-7414/wdio-cucumber-plat…
rounak610 Sep 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/pr-191.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@wdio/browserstack-service": minor
---

- WebdriverIO + CucumberJS now runs on the BrowserStack CLI flow, the same path Mocha already uses. Reporting, accessibility, Percy and session naming behave as before — no config change is needed.
- Fixed: sessions were left unmarked pass/fail when setSessionName: false was set. Naming and status are independent options again.
- Fixed: the accessibility extension was not applied on non-BrowserStack infrastructure, leaving scans empty on otherwise green runs.
8 changes: 8 additions & 0 deletions .changeset/pr-210.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@wdio/browserstack-service": patch
---

- Fixed Percy capture on WebdriverIO. Runs with `percy: true` logged "Unsupported driver for percy" and produced no screenshots, while the tests themselves continued to pass.
- Fixed Percy web snapshots, which previously captured nothing on WebdriverIO.
- Percy errors are now logged instead of failing the test. Set `PERCY_RAISE_ERROR=true` to fail the build on Percy errors instead.
- Added Percy documentation to the README, including how to use a Percy web project alongside this service.
5 changes: 5 additions & 0 deletions .changeset/pr-214.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@wdio/browserstack-service": patch
---

- Fixed test tags not being reported to Test Observability for Mocha and Jasmine. Tags written as `@tag` tokens in suite or test titles are now sent with each test.
37 changes: 31 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions packages/browserstack-service/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# @wdio/browserstack-service

## 9.37.0

### Minor Changes

- 6844406: - WebdriverIO + CucumberJS now runs on the BrowserStack CLI flow, the same path Mocha already uses. Reporting, accessibility, Percy and session naming behave as before — no config change is needed.
- Fixed: sessions were left unmarked pass/fail when setSessionName: false was set. Naming and status are independent options again.
- Fixed: the accessibility extension was not applied on non-BrowserStack infrastructure, leaving scans empty on otherwise green runs.

### Patch Changes

- 4bc51b5: - Fixed test tags not being reported to Test Observability for Mocha and Jasmine. Tags written as `@tag` tokens in suite or test titles are now sent with each test.
- e9cfe6e: - Fixed Percy capture on WebdriverIO. Runs with `percy: true` logged "Unsupported driver for percy" and produced no screenshots, while the tests themselves continued to pass.
- Fixed Percy web snapshots, which previously captured nothing on WebdriverIO.
- Percy errors are now logged instead of failing the test. Set `PERCY_RAISE_ERROR=true` to fail the build on Percy errors instead.
- Added Percy documentation to the README, including how to use a Percy web project alongside this service.

## 9.36.2

### Patch Changes
Expand Down
34 changes: 34 additions & 0 deletions packages/browserstack-service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,40 @@ Automatically set the BrowserStack Automate session status (passed/failed).
Type: `Boolean`<br />
Default: `true`

### percy

Enable Percy visual testing.

Type: `Boolean`<br />
Default: `false` — except for App Automate runs, where Percy is enabled automatically when `percy` is left unset and `app` is provided.

This service runs Percy in **Percy on Automate** mode: it provisions the Percy project for you and captures screenshots server-side from the Automate session. Use `percyCaptureMode` to control when captures happen — no code changes are needed.

**Percy web projects.** This service provisions a Percy on Automate project; it does not create web-type Percy projects. To use a Percy **web** project with WebdriverIO, leave `percy` unset in the service options and drive Percy yourself:

```bash
PERCY_TOKEN=<your web project token> npx percy exec -- npx wdio run wdio.conf.js
```

calling [`@percy/webdriverio`](https://github.com/percy/percy-webdriverio)'s `percySnapshot` in your specs. BrowserStack Automate and Test Observability continue to work through this service alongside it.

> Pin `@percy/webdriverio` below `3.3.3` — that release omits a file its entry point requires and fails to load.

### percyCaptureMode

When to capture Percy screenshots automatically.

Type: `String`<br />
Default: `auto`

* `auto` — capture on clicks, screenshots, actions and input changes
* `click` — capture on clicks only
* `screenshot` — capture on screenshot commands only
* `testcase` — capture once at the end of each test
* `manual` — never capture automatically

Your Percy project's own capture-mode setting takes precedence over this option when one is configured.

### buildIdentifier

**buildIdentifier** is a unique id to differentiate every execution that gets appended to buildName. Choose your buildIdentifier format from the available expressions:
Expand Down
13 changes: 7 additions & 6 deletions packages/browserstack-service/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@wdio/browserstack-service",
"version": "9.36.2",
"version": "9.37.0",
"description": "WebdriverIO service for better Browserstack integration",
"author": "BrowserStack <support@browserstack.com>",
"homepage": "https://github.com/browserstack/wdio-browserstack-service",
Expand Down Expand Up @@ -58,7 +58,11 @@
"@grpc/grpc-js": "~1.13.5",
"@percy/appium-app": "^2.0.9",
"@percy/selenium-webdriver": "^2.2.2",
"@percy/webdriverio": ">=3.3.0 <3.3.3",
"@types/gitconfiglocal": "^2.0.1",
"@wdio/logger": "^9.0.0",
"@wdio/reporter": "^9.0.0",
"@wdio/types": "^9.0.0",
"browserstack-local": "^1.5.1",
"chalk": "^5.3.0",
"csv-writer": "^1.6.0",
Expand All @@ -68,12 +72,9 @@
"tar": "^7.5.11",
"undici": "^6.24.0",
"uuid": "^11.1.0",
"webdriverio": "^9.0.0",
"winston-transport": "^4.5.0",
"yauzl": "^3.4.0",
"@wdio/logger": "^9.0.0",
"@wdio/reporter": "^9.0.0",
"@wdio/types": "^9.0.0",
"webdriverio": "^9.0.0"
"yauzl": "^3.4.0"
},
"peerDependencies": {
"@wdio/cli": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
Expand Down
59 changes: 48 additions & 11 deletions packages/browserstack-service/src/Percy/PercySDK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,56 @@ const tryRequire = function (pkg: string, fallback: unknown) {
return (mod as { default: unknown }).default
}
return mod
} catch {
} catch (err) {
PercyLogger.debug(`Percy: could not load ${pkg} - ${(err as Error)?.message}`)
return fallback
}
}

const percySnapshot = tryRequire('@percy/selenium-webdriver', null)

/*
Percy ships two disjoint web SDKs, and the correct one depends on the driver, not the
product. percySnapshot from @percy/selenium-webdriver drives the browser through Selenium
client APIs - executeScript(script) with a single argument, By, switchTo() - none of which
a WebdriverIO browser provides, so it captures nothing and swallows the failure. The
WebdriverIO-native port lives in @percy/webdriverio and is what `snapshot` binds to.

percyScreenshot (Percy on Automate) deliberately stays on @percy/selenium-webdriver: it is
driver-agnostic - it reads session metadata and posts, capturing server-side - and carries
an explicit wdio branch in its DriverMetadata.
*/
const percyWebdriverioSnapshot = tryRequire('@percy/webdriverio', null)

const webSnapshot = percyWebdriverioSnapshot || percySnapshot

const percyAppScreenshot = tryRequire('@percy/appium-app', {})

/*
Percy's SDKs raise their misuse guards - percySnapshot against a Percy-on-Automate build,
percyScreenshot against anything else - before their own try/catch, so those rejections
reach the caller. Every PercySDK entry point is publicly exported, so an unguarded one
fails the user's test rather than their visual coverage. PERCY_RAISE_ERROR is Percy's own
opt-in for the opposite behaviour and is honoured.
*/
const runPercy = async (label: string, call: () => unknown) => {
try {
return await call()
} catch (err) {
if (process.env.PERCY_RAISE_ERROR === 'true') {
throw err
}
PercyLogger.error(`Percy ${label} failed: ${(err as Error)?.message}`)
}
}

/* eslint-disable @typescript-eslint/no-unused-vars */
let snapshotHandler = (...args: unknown[]) => {
let snapshotHandler = async (...args: unknown[]): Promise<unknown> => {
PercyLogger.error('Unsupported driver for percy')
return undefined
}
if (percySnapshot) {
snapshotHandler = (browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser, snapshotName: string, options?: { [key: string]: unknown }) => {
if (webSnapshot) {
snapshotHandler = async (browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser, snapshotName: string, options?: { [key: string]: unknown }) => {
if (process.env.PERCY_SNAPSHOT === 'true') {
let { name, uuid } = InsightsHandler.currentTest
if (isUndefined(name)) {
Expand All @@ -38,7 +73,7 @@ if (percySnapshot) {
...options,
testCase: name || ''
}
return percySnapshot(browser, snapshotName, options)
return await runPercy(`snapshot "${snapshotName}"`, () => webSnapshot(browser, snapshotName, options))
}
}
}
Expand Down Expand Up @@ -75,23 +110,25 @@ const screenshotHelper = (type: string, driverOrName: WebdriverIO.Browser | Webd
}

/* eslint-disable @typescript-eslint/no-unused-vars */
let screenshotHandler = async (...args: unknown[]) => {
let screenshotHandler = async (...args: unknown[]): Promise<unknown> => {
PercyLogger.error('Unsupported driver for percy')
return undefined
}
if (percySnapshot && percySnapshot.percyScreenshot) {
screenshotHandler = (browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | string, screenshotName?: string | { [key: string]: unknown }, options?: { [key: string]: unknown }) => {
return screenshotHelper('web', browser, screenshotName, options)
screenshotHandler = async (browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | string, screenshotName?: string | { [key: string]: unknown }, options?: { [key: string]: unknown }) => {
return await runPercy('screenshot', () => screenshotHelper('web', browser, screenshotName, options))
}
}
export const screenshot = screenshotHandler

/* eslint-disable @typescript-eslint/no-unused-vars */
let screenshotAppHandler = async (...args: unknown[]) => {
let screenshotAppHandler = async (...args: unknown[]): Promise<unknown> => {
PercyLogger.error('Unsupported driver for percy')
return undefined
}
if (percyAppScreenshot) {
screenshotAppHandler = (driverOrName: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | string, nameOrOptions?: string | { [key: string]: unknown }, options?: { [key: string]: unknown }) => {
return screenshotHelper('app', driverOrName, nameOrOptions, options)
screenshotAppHandler = async (driverOrName: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | string, nameOrOptions?: string | { [key: string]: unknown }, options?: { [key: string]: unknown }) => {
return await runPercy('app screenshot', () => screenshotHelper('app', driverOrName, nameOrOptions, options))
}
}
export const screenshotApp = screenshotAppHandler
2 changes: 1 addition & 1 deletion packages/browserstack-service/src/cli/cliUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const CLI_DOWNLOAD_TMP_SUFFIX = '.zip'
export class CLIUtils {
static automationFrameworkDetail = {}
static testFrameworkDetail = {}
static CLISupportedFrameworks = ['mocha']
static CLISupportedFrameworks = ['mocha', 'cucumber']

static isDevelopmentEnv() {
return process.env.BROWSERSTACK_CLI_ENV === 'development'
Expand Down
Loading
Loading