From e97227a246a677a6fcb661044219eea1d15c95f0 Mon Sep 17 00:00:00 2001 From: YASH JAIN Date: Thu, 6 Aug 2026 12:44:23 +0530 Subject: [PATCH 1/3] fix(browserstack-service): run a11y scans for jasmine framework (SDK-7190) Web Accessibility Automation silently produced no report on jasmine: the launcher provisions the a11y build framework-agnostically, but the accessibility handler's beforeTest/afterTest were hard-gated to mocha, so no scan was ever fired and saveTestResults never ran. WDIO's jasmine adapter emits the same beforeTest/afterTest service hooks as mocha, so admit jasmine through the gate and read the spec name from jasmine's `description` field for the include/exclude tag filter. Verified on Automate: identical jasmine spec produced no scan activity before the fix and a saved a11y report after it. Co-Authored-By: Claude Fable 5 --- .changeset/sdk-7190-jasmine-a11y.md | 7 +++ .../src/accessibility-handler.ts | 14 +++-- .../tests/accessibility-handler.test.ts | 54 +++++++++++++++++-- 3 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 .changeset/sdk-7190-jasmine-a11y.md diff --git a/.changeset/sdk-7190-jasmine-a11y.md b/.changeset/sdk-7190-jasmine-a11y.md new file mode 100644 index 0000000..7e8636b --- /dev/null +++ b/.changeset/sdk-7190-jasmine-a11y.md @@ -0,0 +1,7 @@ +--- +"@wdio/browserstack-service": patch +--- + +fix: run Web Accessibility Automation scans for the jasmine framework (SDK-7190) + +The accessibility handler's beforeTest/afterTest hooks were hard-gated to mocha, so jasmine sessions with `accessibility: true` were provisioned on the A11y side (build registered, extension injected) but never orchestrated a scan or saved results — silently producing no report. WDIO's jasmine adapter emits the same beforeTest/afterTest service hooks as mocha, so the gate now admits jasmine, and the scan include/exclude filter reads the spec name from jasmine's `description` field. diff --git a/packages/browserstack-service/src/accessibility-handler.ts b/packages/browserstack-service/src/accessibility-handler.ts index 22f61d5..ecb0f93 100644 --- a/packages/browserstack-service/src/accessibility-handler.ts +++ b/packages/browserstack-service/src/accessibility-handler.ts @@ -78,6 +78,12 @@ import * as PERFORMANCE_SDK_EVENTS from './instrumentation/performance/constants import { BStackLogger } from './bstackLogger.js' class _AccessibilityHandler { + /** + * Frameworks whose per-test lifecycle flows through beforeTest/afterTest. + * WDIO's jasmine adapter emits the same service hooks as mocha (SDK-7190); + * cucumber goes through beforeScenario/afterScenario instead. + */ + private static readonly TEST_HOOK_FRAMEWORKS = ['mocha', 'jasmine'] private _platformA11yMeta: PlatformA11yMeta private _caps: Capabilities.ResolvedTestrunnerCapabilities private _suiteFile?: string @@ -276,7 +282,7 @@ class _AccessibilityHandler { async beforeTest (suiteTitle: string | undefined, test: Frameworks.Test) { try { if ( - this._framework !== 'mocha' || + !AccessibilityHandler.TEST_HOOK_FRAMEWORKS.includes(this._framework as string) || !this.shouldRunTestHooks(this._browser, this._accessibility) ) { /* This is to be used when test events are sent */ @@ -284,8 +290,10 @@ class _AccessibilityHandler { return } + /* jasmine test objects carry the spec name in `description` (`title` is unset) */ + const testTitle = test.title ?? test.description // @ts-expect-error fix type - const shouldScanTest = this._autoScanning && shouldScanTestForAccessibility(suiteTitle, test.title, this._accessibilityOptions) + const shouldScanTest = this._autoScanning && shouldScanTestForAccessibility(suiteTitle, testTitle, this._accessibilityOptions) const testIdentifier = this.getIdentifier(test) this._testIdentifier = testIdentifier @@ -315,7 +323,7 @@ class _AccessibilityHandler { async afterTest (suiteTitle: string | undefined, test: Frameworks.Test) { BStackLogger.debug('Accessibility after test hook. Before sending test stop event') if ( - this._framework !== 'mocha' || + !AccessibilityHandler.TEST_HOOK_FRAMEWORKS.includes(this._framework as string) || !this.shouldRunTestHooks(this._browser, this._accessibility) ) { return diff --git a/packages/browserstack-service/tests/accessibility-handler.test.ts b/packages/browserstack-service/tests/accessibility-handler.test.ts index 417003e..a6bcf90 100644 --- a/packages/browserstack-service/tests/accessibility-handler.test.ts +++ b/packages/browserstack-service/tests/accessibility-handler.test.ts @@ -574,18 +574,48 @@ describe('beforeTest', () => { }) describe('jasmine', () => { - let isBrowserstackSession: any beforeEach(() => { accessibilityHandler = new AccessibilityHandler(browser, caps, options, false, config, 'jasmine', true, false, accessibilityOpts) - isBrowserstackSession = vi.spyOn(utils, 'isBrowserstackSession').mockReturnValue(true) + vi.spyOn(utils, 'isBrowserstackSession').mockReturnValue(true) + vi.spyOn(utils, 'isAccessibilityAutomationSession').mockReturnValue(true) + vi.spyOn(utils, 'getUniqueIdentifier').mockReturnValue('suite title test') }) - it('should execute test started in case of jasmine', async () => { + it('should start scan orchestration for jasmine like mocha (SDK-7190)', async () => { + const logInfoMock = vi.spyOn(log, 'info') + const shouldScanSpy = vi.spyOn(utils, 'shouldScanTestForAccessibility').mockReturnValue(true) + + /* jasmine test objects have `description`/`fullName`, no `title`/`parent` */ + await accessibilityHandler.beforeTest('suite title', { description: 'test', fullName: 'suite title test' } as any) + + expect(shouldScanSpy).toBeCalledWith('suite title', 'test', accessibilityOpts) + expect(logInfoMock.mock.calls[0][0]) + .toContain('Automate test case execution has started.') + expect(accessibilityHandler['_testMetadata']['suite title test']).toEqual({ + scanTestForAccessibility: true, + accessibilityScanStarted: true + }) + }) + + it('should arm the a11y scan session map so command scans fire (SDK-7190)', async () => { vi.spyOn(utils, 'shouldScanTestForAccessibility').mockReturnValue(true) + accessibilityHandler['_sessionId'] = 'session123' + + await accessibilityHandler.beforeTest('suite title', { description: 'test', fullName: 'suite title test' } as any) + + expect(AccessibilityHandler['_a11yScanSessionMap']['session123']).toBe(true) + }) + }) + + describe('cucumber', () => { + it('should not run beforeTest orchestration for cucumber', async () => { + accessibilityHandler = new AccessibilityHandler(browser, caps, options, false, config, 'cucumber', true, false, accessibilityOpts) + vi.spyOn(utils, 'isAccessibilityAutomationSession').mockReturnValue(true) + const shouldScanSpy = vi.spyOn(utils, 'shouldScanTestForAccessibility').mockReturnValue(true) await accessibilityHandler.beforeTest('suite title', { parent: 'parent', title: 'test' } as any) - expect(isBrowserstackSession).toBeCalledTimes(0) + expect(shouldScanSpy).toBeCalledTimes(0) }) }) }) @@ -641,6 +671,22 @@ describe('afterTest', () => { expect(logErrorMock.mock.calls[0][0]) .toContain('Accessibility results could not be processed for the test case test. Error :') }) + + it('should send test stop event for jasmine (SDK-7190)', async () => { + accessibilityHandler = new AccessibilityHandler(browser, caps, options, false, config, 'jasmine', true, false, accessibilityOpts) + vi.spyOn(utils, 'isAccessibilityAutomationSession').mockReturnValue(true) + vi.spyOn(utils, 'getUniqueIdentifier').mockReturnValue('test title') + accessibilityHandler['_testMetadata']['test title'] = { + accessibilityScanStarted: true, + scanTestForAccessibility: true + } + const sendStop = vi.fn() + accessibilityHandler['sendTestStopEvent'] = sendStop + + await accessibilityHandler.afterTest('suite title', { description: 'test', fullName: 'suite title test' } as any) + + expect(sendStop).toBeCalledTimes(1) + }) }) describe('getIdentifier', () => { From 5fc87517f370b148fc42b95ecd4cb3a1f09d932f Mon Sep 17 00:00:00 2001 From: xxshubhamxx Date: Thu, 6 Aug 2026 19:07:59 +0530 Subject: [PATCH 2/3] chore(changeset): drop hand-written changeset in favour of PR-template generation changeset-from-pr.yml derives .changeset/pr-.md from the PR body's "## Release" section, so a hand-written file both duplicates the CHANGELOG bullet and puts internal RCA detail in customer-facing release notes. Co-Authored-By: Claude Opus 5 --- .changeset/sdk-7190-jasmine-a11y.md | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .changeset/sdk-7190-jasmine-a11y.md diff --git a/.changeset/sdk-7190-jasmine-a11y.md b/.changeset/sdk-7190-jasmine-a11y.md deleted file mode 100644 index 7e8636b..0000000 --- a/.changeset/sdk-7190-jasmine-a11y.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@wdio/browserstack-service": patch ---- - -fix: run Web Accessibility Automation scans for the jasmine framework (SDK-7190) - -The accessibility handler's beforeTest/afterTest hooks were hard-gated to mocha, so jasmine sessions with `accessibility: true` were provisioned on the A11y side (build registered, extension injected) but never orchestrated a scan or saved results — silently producing no report. WDIO's jasmine adapter emits the same beforeTest/afterTest service hooks as mocha, so the gate now admits jasmine, and the scan include/exclude filter reads the spec name from jasmine's `description` field. From b688f05c711be4d0895dce836222ebd6cfe25f4e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 6 Aug 2026 13:39:41 +0000 Subject: [PATCH 3/3] chore(changeset): auto-generate from PR template (patch) --- .changeset/pr-123.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/pr-123.md diff --git a/.changeset/pr-123.md b/.changeset/pr-123.md new file mode 100644 index 0000000..667faf7 --- /dev/null +++ b/.changeset/pr-123.md @@ -0,0 +1,5 @@ +--- +"@wdio/browserstack-service": patch +--- + +- Fixed Accessibility Automation producing no report for WebdriverIO suites running on the jasmine framework. Accessibility scans now run for jasmine specs, as they already did for mocha.