diff --git a/packages/wdio-browserstack-service/src/insights-handler.ts b/packages/wdio-browserstack-service/src/insights-handler.ts index e4a2c122f70..10036647c28 100644 --- a/packages/wdio-browserstack-service/src/insights-handler.ts +++ b/packages/wdio-browserstack-service/src/insights-handler.ts @@ -22,7 +22,8 @@ import { isUndefined, o11yClassErrorHandler, removeAnsiColors, - getObservabilityProduct + getObservabilityProduct, + generateHashCodeFromFields } from './util.js' import type { TestData, @@ -395,7 +396,21 @@ class _InsightsHandler { finishedAt: (new Date()).toISOString() } this.flushCBTDataQueue() - this.listener.testFinished(this.getRunData(test, 'TestRunFinished', result)) + const testData = this.getRunData(test, 'TestRunFinished', result) + this.listener.testFinished(testData) + const testFinishHashCode = generateHashCodeFromFields( + [ + testData.integrations?.browserstack?.browser ?? '', + testData.integrations?.browserstack?.browser_version ?? '', + testData.integrations?.browserstack?.platform ?? '', + testData.integrations?.browserstack?.session_id ?? '', + testData.integrations?.capabilities ?? {}, + testData.file_name ?? '', + testData.scopes ?? [], + testData.name ?? '' + ] + ) + TestReporter.hashCodeToHandleTestSkip[testFinishHashCode] = testData.uuid ?? '' } /** @@ -660,6 +675,11 @@ class _InsightsHandler { } if ((eventType === 'TestRunFinished' || eventType === 'HookRunFinished') && results) { + testData.integrations = {} + if (this._browser && this._platformMeta) { + const provider = getCloudProvider(this._browser) + testData.integrations[provider] = this.getIntegrationsObject() + } const { error, passed } = results if (!passed) { testData.result = (error && error.message && error.message.includes('sync skip; aborting execution')) ? 'ignore' : 'failed' diff --git a/packages/wdio-browserstack-service/src/reporter.ts b/packages/wdio-browserstack-service/src/reporter.ts index ad99aae993d..745fda6c02e 100644 --- a/packages/wdio-browserstack-service/src/reporter.ts +++ b/packages/wdio-browserstack-service/src/reporter.ts @@ -15,7 +15,9 @@ import { getGitMetaData, removeAnsiColors, getHookType, - getPlatformVersion + getPlatformVersion, + isObjectEmpty, + generateHashCodeFromFields } from './util.js' import { BStackLogger } from './bstackLogger.js' import type { Capabilities } from '@wdio/types' @@ -35,6 +37,7 @@ class _TestReporter extends WDIOReporter { public static currentTest: CurrentRunInfo = {} private _userCaps?: Capabilities.ResolvedTestrunnerCapabilities = {} private listener = Listener.getInstance() + public static hashCodeToHandleTestSkip: Record = {} async onRunnerStart (runnerStats: RunnerStats) { this._capabilities = runnerStats.capabilities as WebdriverIO.Capabilities @@ -213,7 +216,26 @@ class _TestReporter extends WDIOReporter { testStats.start ||= new Date() testStats.end ||= new Date() - this.listener.testFinished(await this.getRunData(testStats, 'TestRunSkipped')) + const testData = await this.getRunData(testStats, 'TestRunSkipped') + const testFinishHashCode = generateHashCodeFromFields( + [ + testData.integrations?.browserstack?.browser ?? '', + testData.integrations?.browserstack?.browser_version ?? '', + testData.integrations?.browserstack?.platform ?? '', + testData.integrations?.browserstack?.session_id ?? '', + testData.integrations?.capabilities ?? {}, + testData.file_name ?? '', + testData.scopes ?? [], + testData.name ?? '' + ] + ) + if (_TestReporter.hashCodeToHandleTestSkip !== null && !isObjectEmpty(_TestReporter.hashCodeToHandleTestSkip) && testFinishHashCode in _TestReporter.hashCodeToHandleTestSkip) { + if (_TestReporter.hashCodeToHandleTestSkip[testFinishHashCode] !== '') { + testData.uuid = _TestReporter.hashCodeToHandleTestSkip[testFinishHashCode] + } + } + + this.listener.testFinished(testData) } async getRunData(testStats: TestStats | HookStats, eventType: string) { diff --git a/packages/wdio-browserstack-service/src/util.ts b/packages/wdio-browserstack-service/src/util.ts index affc7627d59..8e5f33bea15 100644 --- a/packages/wdio-browserstack-service/src/util.ts +++ b/packages/wdio-browserstack-service/src/util.ts @@ -1,4 +1,5 @@ import { hostname, platform, type, version, arch } from 'node:os' +import crypto from 'node:crypto' import fs from 'node:fs' import zlib from 'node:zlib' import { format, promisify } from 'node:util' @@ -1621,6 +1622,17 @@ export async function executeAccessibilityScript( ) } +export function generateHashCodeFromFields(fields: Array) { + const serialize = (value: {}) => { + if (value && typeof value === 'object') { + return JSON.stringify(value, Object.keys(value).sort()) + } + return String(value) + } + + const serialized = fields.map(serialize).join('|') + return crypto.createHash('sha256').update(serialized).digest('hex') +} export function getBooleanValueFromString(value: string | undefined): boolean { if (!value) { return false