diff --git a/packages/wdio-browserstack-service/src/insights-handler.ts b/packages/wdio-browserstack-service/src/insights-handler.ts index 030d18dd682..9ffea731c04 100644 --- a/packages/wdio-browserstack-service/src/insights-handler.ts +++ b/packages/wdio-browserstack-service/src/insights-handler.ts @@ -14,6 +14,7 @@ import { getCloudProvider, getGitMetaData, getHookType, + getPlatformVersion, getScenarioExamples, getUniqueIdentifier, getUniqueIdentifierForCucumber, @@ -43,9 +44,10 @@ class _InsightsHandler { scenariosStarted: false, steps: [] } + private _userCaps?: Capabilities.RemoteCapability = {} private listener = Listener.getInstance() - constructor (private _browser: Browser<'async'> | MultiRemoteBrowser<'async'>, browserCaps?: Capabilities.Capabilities, isAppAutomate?: boolean, sessionId?: string, private _framework?: string) { + constructor (private _browser: Browser<'async'> | MultiRemoteBrowser<'async'>, browserCaps?: Capabilities.Capabilities, isAppAutomate?: boolean, sessionId?: string, private _framework?: string, _userCaps?: Capabilities.RemoteCapability) { this._platformMeta = { browserName: browserCaps?.browserName, browserVersion: browserCaps?.browserVersion, @@ -55,6 +57,8 @@ class _InsightsHandler { product: isAppAutomate ? 'app-automate' : 'automate' } + this._userCaps = _userCaps + this.registerListeners() } @@ -779,7 +783,8 @@ class _InsightsHandler { browser: browserCaps?.browserName, browser_version: browserCaps?.browserVersion, platform: browserCaps?.platformName, - product: this._platformMeta?.product + product: this._platformMeta?.product, + platform_version: getPlatformVersion(this._userCaps as Capabilities.Capabilities) } } diff --git a/packages/wdio-browserstack-service/src/reporter.ts b/packages/wdio-browserstack-service/src/reporter.ts index 98bc5a2d347..b27b995db24 100644 --- a/packages/wdio-browserstack-service/src/reporter.ts +++ b/packages/wdio-browserstack-service/src/reporter.ts @@ -14,6 +14,7 @@ import { o11yClassErrorHandler, removeAnsiColors, getHookType, + getPlatformVersion } from './util' import Listener from './testOps/listener' @@ -31,10 +32,12 @@ class _TestReporter extends WDIOReporter { private _gitConfigured: boolean = false private _currentHook: CurrentRunInfo = {} private _currentTest: CurrentRunInfo = {} + private _userCaps?: Capabilities.RemoteCapability = {} private listener = Listener.getInstance() async onRunnerStart (runnerStats: RunnerStats) { this._capabilities = runnerStats.capabilities as Capabilities.Capabilities + this._userCaps = this.getUserCaps(runnerStats) as Capabilities.RemoteCapability | undefined this._config = runnerStats.config as BrowserstackConfig & Options.Testrunner this._sessionId = runnerStats.sessionId if (typeof this._config.testObservability !== 'undefined') this._observability = this._config.testObservability @@ -50,6 +53,10 @@ class _TestReporter extends WDIOReporter { process.on(`bs:addLog:${process.pid}`, this.appendTestItemLog.bind(this)) } + private getUserCaps(runnerStats: RunnerStats) { + return runnerStats.instanceOptions[runnerStats.sessionId]?.capabilities + } + public async appendTestItemLog(stdLog: StdLog) { if (this._currentHook.uuid && !this._currentHook.finished) { stdLog.hook_run_uuid = this._currentHook.uuid @@ -234,6 +241,7 @@ class _TestReporter extends WDIOReporter { browser: this._capabilities?.browserName, browser_version: this._capabilities?.browserVersion, platform: this._capabilities?.platformName, + platform_version: getPlatformVersion(this._userCaps as Capabilities.Capabilities) } } diff --git a/packages/wdio-browserstack-service/src/service.ts b/packages/wdio-browserstack-service/src/service.ts index b7610457641..127bcb2ad45 100644 --- a/packages/wdio-browserstack-service/src/service.ts +++ b/packages/wdio-browserstack-service/src/service.ts @@ -138,7 +138,14 @@ export default class BrowserstackService implements Services.ServiceInstance { try { if (this._observability) { patchConsoleLogs() - this._insightsHandler = new InsightsHandler(this._browser, this._browser.capabilities as Capabilities.Capabilities, this._isAppAutomate(), this._browser.sessionId as string, this._config.framework) + this._insightsHandler = new InsightsHandler( + this._browser, + this._browser.capabilities as Capabilities.Capabilities, + this._isAppAutomate(), + this._browser.sessionId as string, + this._config.framework, + this._caps + ) await this._insightsHandler.before() } diff --git a/packages/wdio-browserstack-service/src/types.ts b/packages/wdio-browserstack-service/src/types.ts index bd97c9286d7..31f5152eb53 100644 --- a/packages/wdio-browserstack-service/src/types.ts +++ b/packages/wdio-browserstack-service/src/types.ts @@ -285,6 +285,7 @@ interface IntegrationObject { browser_version?: string platform?: string product?: string + platform_version?: string } interface TestCodeBody { diff --git a/packages/wdio-browserstack-service/src/util.ts b/packages/wdio-browserstack-service/src/util.ts index 387d0fa874b..f0afa69524c 100644 --- a/packages/wdio-browserstack-service/src/util.ts +++ b/packages/wdio-browserstack-service/src/util.ts @@ -1117,6 +1117,22 @@ export const ObjectsAreEqual = (object1: any, object2: any) => { return true } +export const getPlatformVersion = o11yErrorHandler(function getPlatformVersion(caps: Capabilities.Capabilities) { + if (!caps) { + return undefined + } + const bstackOptions = (caps)?.['bstack:options'] + const keys = ['platformVersion', 'platform_version', 'osVersion', 'os_version', 'appium:platformVersion'] + + for (const key of keys) { + if (bstackOptions && bstackOptions?.[key as keyof Capabilities.BrowserStackCapabilities]) { + return String(bstackOptions?.[key as keyof Capabilities.BrowserStackCapabilities]) + } else if (caps[key as keyof Capabilities.Capabilities]) { + return String(caps[key as keyof Capabilities.Capabilities]) + } + } + return undefined +}) export const isObjectEmpty = (objectName: unknown) => { return ( objectName && diff --git a/packages/wdio-browserstack-service/tests/insight-handler.test.ts b/packages/wdio-browserstack-service/tests/insight-handler.test.ts index e88d1929e9e..6c8cbc02a64 100644 --- a/packages/wdio-browserstack-service/tests/insight-handler.test.ts +++ b/packages/wdio-browserstack-service/tests/insight-handler.test.ts @@ -767,7 +767,9 @@ describe('afterHook', () => { describe('getIntegrationsObject', () => { let insightsHandler: InsightsHandler + let getPlatformVersionSpy beforeAll(() => { + getPlatformVersionSpy = jest.spyOn(utils, 'getPlatformVersion').mockImplementation(() => { return 'some version' }) insightsHandler = new InsightsHandler(browser, {} as any, false, 'sessionId', 'framework') insightsHandler['_platformMeta'] = { caps: {}, @@ -780,7 +782,9 @@ describe('getIntegrationsObject', () => { }) it('return hash', () => { - expect(insightsHandler['getIntegrationsObject']()).toBeInstanceOf(Object) + const integrationsObject = insightsHandler['getIntegrationsObject']() + expect(integrationsObject).toBeInstanceOf(Object) + expect(integrationsObject.platform_version).toEqual('some version') }) it('should fetch latest details', () => { @@ -790,6 +794,10 @@ describe('getIntegrationsObject', () => { expect(integrationsObject.session_id).toEqual('session-new') expect(integrationsObject.capabilities.os).toEqual('Windows') }) + + afterAll(() => { + getPlatformVersionSpy.mockClear() + }) }) describe('browserCommand', () => { diff --git a/packages/wdio-browserstack-service/tests/reporter.test.ts b/packages/wdio-browserstack-service/tests/reporter.test.ts index 30f7a224019..a6effca669e 100644 --- a/packages/wdio-browserstack-service/tests/reporter.test.ts +++ b/packages/wdio-browserstack-service/tests/reporter.test.ts @@ -131,6 +131,16 @@ describe('test-reporter', () => { const uploadEventDataSpy = jest.spyOn(reporter['listener'], 'testFinished').mockImplementation() const getCloudProviderSpy = jest.spyOn(utils, 'getCloudProvider').mockReturnValue('browserstack') + let getPlatformVersionSpy + + beforeAll(() => { + getPlatformVersionSpy = jest.spyOn(utils, 'getPlatformVersion').mockImplementation(() => { return 'some version' }) + }) + + afterAll(() => { + getPlatformVersionSpy.mockClear() + }) + beforeEach(() => { uploadEventDataSpy.mockClear() getCloudProviderSpy.mockClear() @@ -216,6 +226,15 @@ describe('test-reporter', () => { let reporter: TestReporter, uploadEventDataSpy: jest.SpyInstance jest.spyOn(utils, 'getCloudProvider').mockReturnValue('browserstack') let testStartStats = { ...testStats } + let getPlatformVersionSpy + + beforeAll(() => { + getPlatformVersionSpy = jest.spyOn(utils, 'getPlatformVersion').mockImplementation(() => { return 'some version' }) + }) + + afterAll(() => { + getPlatformVersionSpy.mockClear() + }) beforeEach(() => { reporter = new TestReporter({}) @@ -259,6 +278,15 @@ describe('test-reporter', () => { let reporter: TestReporter, uploadEventDataSpy: jest.SpyInstance jest.spyOn(utils, 'getCloudProvider').mockReturnValue('browserstack') let testEndStats = { ...testStats } + let getPlatformVersionSpy + + beforeAll(() => { + getPlatformVersionSpy = jest.spyOn(utils, 'getPlatformVersion').mockImplementation(() => { return 'some version' }) + }) + + afterAll(() => { + getPlatformVersionSpy.mockClear() + }) beforeEach(() => { reporter = new TestReporter({}) diff --git a/packages/wdio-browserstack-service/tests/util.test.ts b/packages/wdio-browserstack-service/tests/util.test.ts index 50a87da27c0..77a328b950d 100644 --- a/packages/wdio-browserstack-service/tests/util.test.ts +++ b/packages/wdio-browserstack-service/tests/util.test.ts @@ -2,6 +2,7 @@ import gitRepoInfo from 'git-repo-info' import got from 'got' import path from 'path' import logger from '@wdio/logger' +import type { Capabilities } from '@wdio/types' import * as utils from '../src/util' import type { Browser, MultiRemoteBrowser } from 'webdriverio' @@ -1363,3 +1364,27 @@ describe('ObjectsAreEqual', function () { expect(utils.ObjectsAreEqual({ 'a': true }, { 'b': false })).toEqual(false) }) }) + +describe('getPlatformVersion', () => { + it('should return undefined if no capabilities are provided', () => { + expect(utils.getPlatformVersion(null)).toBeUndefined() + }) + + it('should return platform version from bstack:options if available', () => { + const caps: Capabilities.Capabilities = { + 'bstack:options': { + osVersion: '10.0' + }, + } + + expect(utils.getPlatformVersion(caps)).toBe('10.0') + }) + + it('should return undefined if no platform version is found', () => { + const caps: Capabilities.Capabilities = { + browserName: 'chrome', + } + + expect(utils.getPlatformVersion(caps)).toBeUndefined() + }) +})