Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8199e0b
feat(v8): route framework: 'cucumber' to the CLI/binary flow
AdityaHirapara Sep 10, 2026
f738561
feat(v8): report cucumber scenarios and hooks through the CLI framewo…
AdityaHirapara Sep 10, 2026
9633a1e
feat(cli): widen cucumber's shared dispatch gates, hook-log attributi…
Sep 10, 2026
73d4916
fix(cli): register the Automate session even when setSessionName is f…
Sep 10, 2026
09276cc
fix(cli): register the driver without a TestHub product, and contain …
Sep 10, 2026
cbbb425
fix(cli): emit cucumber's feature-start before the session-name REST …
AdityaHirapara Sep 15, 2026
2ae72ed
fix(cli): apply sessionNameFormat on the CLI flow
AdityaHirapara Sep 17, 2026
3d71cc0
refactor(cli): keep all session naming inside automateModule
AdityaHirapara Sep 17, 2026
78c0e54
Merge remote-tracking branch 'origin/v8' into SDK-7606/wdio-cucumber-…
AdityaHirapara Sep 18, 2026
7e631ec
chore(changeset): auto-generate from PR template (minor)
github-actions[bot] Sep 18, 2026
00d7681
refactor(cli): move the preferScenarioName rename into automateModule
AdityaHirapara Sep 18, 2026
da33da5
Merge remote-tracking branch 'origin/SDK-7606/wdio-cucumber-platformi…
AdityaHirapara Sep 18, 2026
7d82e6c
test(cucumber): cover the CLI dispatch branches in service.ts
AdityaHirapara Sep 20, 2026
4444852
fix(cucumber): restore the preferScenarioName rename and split outlin…
AdityaHirapara Sep 23, 2026
4adaae4
fix(cucumber): seed the scenario uuid so CLI screenshots are attributed
AdityaHirapara Sep 23, 2026
3595271
fix: strip preferScenarioName from outgoing capabilities on the CLI flow
AdityaHirapara Sep 23, 2026
3cdbfec
fix: strip the remaining SDK-only session-name options from capabilities
AdityaHirapara Sep 24, 2026
0827727
fix(cucumber): send the bdd meta feature path cwd-relative
AdityaHirapara Sep 24, 2026
6ab845c
fix(cucumber): relativise the feature path in the skip-cascade meta b…
AdityaHirapara 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-207.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@wdio/browserstack-service": minor
---

- Cucumber tests on WebdriverIO now report through the BrowserStack CLI, matching the behaviour of Mocha.
- Fixed `sessionNameFormat` being ignored, so custom session names now apply on the CLI flow.
- Fixed Observability losing a feature's file path when a session-name update failed.
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 @@ -39,7 +39,7 @@ import APIUtils from './apiUtils.js'
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
13 changes: 12 additions & 1 deletion packages/browserstack-service/src/cli/eventDispatcher.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import util from 'node:util'

import { BStackLogger } from './cliLogger.js'

/**
* EventDispatcher - Singleton class for event handling
*/
Expand Down Expand Up @@ -42,7 +46,14 @@ class EventDispatcher {
async notifyObserver(event: string, args: unknown) {
if (this.observers[event]) {
for (const callback of this.observers[event]) {
await callback(args)
// Per-observer boundary. Without it one product module's failure aborts the loop,
// so every module registered after it silently stops receiving that state, and the
// exception escapes into whatever framework hook raised it.
try {
await callback(args)
} catch (error) {
BStackLogger.error(`notifyObserver: observer failed for ${event}, continuing: ${util.format(error)}`)
}
}
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const TestFrameworkConstants = {
KEY_EVENT_STARTED_AT : 'event_started_at',
KEY_EVENT_ENDED_AT : 'event_ended_at',
KEY_HOOK_ID : 'hook_id',
KEY_HOOK_STATE : 'hook_state',
KEY_HOOK_RESULT : 'hook_result',
KEY_HOOK_LOGS : 'hook_logs',
KEY_HOOK_NAME : 'hook_name',
Expand Down

Large diffs are not rendered by default.

15 changes: 12 additions & 3 deletions packages/browserstack-service/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { BROWSERSTACK_ACCESSIBILITY, BROWSERSTACK_OBSERVABILITY, BROWSERSTACK_TE
import type { Options } from '@wdio/types'
import TestOpsConfig from '../testOps/testOpsConfig.js'
import WdioMochaTestFramework from './frameworks/wdioMochaTestFramework.js'
import WdioCucumberTestFramework from './frameworks/wdioCucumberTestFramework.js'
import type TestFramework from './frameworks/testFramework.js'
import WdioAutomationFramework from './frameworks/wdioAutomationFramework.js'
import WebdriverIOModule from './modules/webdriverIOModule.js'
import AccessibilityModule from './modules/accessibilityModule.js'
Expand Down Expand Up @@ -44,7 +46,7 @@ export class BrowserstackCLI {
isChildConnected = false
binSessionId: string | null = null
modules: Record<string, BaseModule> = {}
testFramework: WdioMochaTestFramework|null = null
testFramework: TestFramework|null = null
cliParams: Record<string, string> | null = null
automationFramework: WdioAutomationFramework|null = null
SDK_CLI_BIN_PATH: string | null = null
Expand Down Expand Up @@ -134,7 +136,7 @@ export class BrowserstackCLI {
this.setupAutomationFramework()

this.modules[WebdriverIOModule.MODULE_NAME] = new WebdriverIOModule()
this.modules[AutomateModule.MODULE_NAME] = new AutomateModule(this.browserstackConfig as Options.Testrunner)
this.modules[AutomateModule.MODULE_NAME] = new AutomateModule(this.browserstackConfig as Options.Testrunner, this.options as Record<string, any>)

if (startBinResponse.testhub) {
this.logBuildStartErrors(startBinResponse.testhub)
Expand Down Expand Up @@ -488,8 +490,15 @@ export class BrowserstackCLI {
*/
setupTestFramework() {
const testFrameworkDetail = CLIUtils.getTestFrameworkDetail()
if (testFrameworkDetail.name.toLowerCase() === 'webdriverio-mocha') {
switch (testFrameworkDetail.name.toLowerCase()) {
case 'webdriverio-mocha':
this.testFramework = new WdioMochaTestFramework([testFrameworkDetail.name], testFrameworkDetail.version, this.binSessionId as string)
break
case 'webdriverio-cucumber':
this.testFramework = new WdioCucumberTestFramework([testFrameworkDetail.name], testFrameworkDetail.version, this.binSessionId as string)
break
default:
this.logger.debug(`setupTestFramework: no CLI test framework for name=${testFrameworkDetail.name}`)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,11 @@ export default class AccessibilityModule extends BaseModule {

const sessionId = AutomationFramework.getState(autoInstance, AutomationFrameworkConstants.KEY_FRAMEWORK_SESSION_ID)
const accessibilityOptions = this.config.accessibilityOptions
const shouldScanTest = this.autoScanning && shouldScanTestForAccessibility(suiteTitle, test.title, accessibilityOptions as { [key: string]: any } | undefined) && this.accessibility
// `world` is set only by service.beforeScenario, so this stays the 3-arg substring
// form for mocha. Without it a cucumber scenario has no test.title and the tag-aware
// branch is never entered, so include/excludeTagsInTestingScope are ignored (row 48).
const world = args.world
const shouldScanTest = this.autoScanning && shouldScanTestForAccessibility(suiteTitle, test.title, accessibilityOptions as { [key: string]: any } | undefined, world, Boolean(world)) && this.accessibility

this.accessibilityMap.set(sessionId, shouldScanTest)
// Create test metadata similar to accessibility-handler
Expand Down
Loading
Loading