Skip to content
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f360343
Adds method for setting a11y options
akanksha1909 Apr 29, 2024
5b644fc
Fixes lint
akanksha1909 Apr 30, 2024
1e5ee92
Creates new utility function
akanksha1909 Apr 29, 2024
9ca7bda
Changes for test start
akanksha1909 Apr 29, 2024
29081fd
Changes for product_map
akanksha1909 Apr 29, 2024
52e6ae7
Process build endpoint response
akanksha1909 Apr 29, 2024
247d80b
Removes a11y code
akanksha1909 Apr 29, 2024
cbbcd86
Changes in stop endpoint
akanksha1909 Apr 29, 2024
17e5fe6
Removes O11y check
akanksha1909 Apr 29, 2024
c9c6757
Removes unused code
akanksha1909 Apr 29, 2024
e4e6bf3
Fixes
akanksha1909 Apr 29, 2024
91dd23e
Changes in env variable
akanksha1909 Apr 29, 2024
8a130c7
Changes in build hash ID env
akanksha1909 Apr 29, 2024
de2027f
Adds test uuid env variable
akanksha1909 Apr 29, 2024
8a18216
Handles percy env var
akanksha1909 Apr 29, 2024
4e8a83d
Updates logic of processing testhub events
akanksha1909 Apr 29, 2024
a9078af
Adds testhub uuid in percy env
akanksha1909 Apr 29, 2024
4e1bea4
Adds env variable
akanksha1909 Apr 29, 2024
dba7ebe
Changes in request payload
akanksha1909 Apr 29, 2024
d96fc13
Handles API errors
akanksha1909 Apr 30, 2024
c03901e
fix: Fix accessibility usecase and add unit tests
sauravdas1997 May 2, 2024
7d570f7
Merge branch 'v8' of github.com:amaanbs/webdriverio into SDK-493_TH-A11y
amaanbs Oct 16, 2024
8648184
V8 reconciliation + bug fixes
amaanbs Oct 24, 2024
294cfa3
Fix tests
amaanbs Oct 25, 2024
c718e19
PR review changes
amaanbs Oct 25, 2024
2585133
PR review changes pt.2
amaanbs Oct 27, 2024
273b446
PR review changes pt.3
amaanbs Oct 27, 2024
77fc2b6
add unit tests
amaanbs Oct 27, 2024
a5fbc0f
PR review changes
amaanbs Nov 5, 2024
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
4 changes: 2 additions & 2 deletions packages/wdio-browserstack-service/src/Percy/Percy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import PercyBinary from './PercyBinary.js'

import type { BrowserstackConfig, UserConfig } from '../types.js'
import type { Options } from '@wdio/types'

import { BROWSERSTACK_TESTHUB_UUID } from '../constants.js'
const logDir = 'logs'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a line after import statements

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


class Percy {
Expand Down Expand Up @@ -78,7 +78,7 @@ class Percy {
this.#proc = spawn(
binaryPath,
commandArgs,
{ env: { ...process.env, PERCY_TOKEN: token } }
{ env: { ...process.env, PERCY_TOKEN: token, TH_BUILD_UUID: process.env[BROWSERSTACK_TESTHUB_UUID] } }
)

this.#proc.stdout.pipe(logStream)
Expand Down
63 changes: 59 additions & 4 deletions packages/wdio-browserstack-service/src/Percy/PercySDK.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import InsightsHandler from '../insights-handler.js'
import TestReporter from '../reporter.js'
import { PercyLogger } from './PercyLogger.js'
import { isUndefined } from '../util.js'

const tryRequire = async function (pkg: string, fallback: any) {
try {
Expand All @@ -17,9 +20,19 @@ let snapshotHandler = (...args: any[]) => {
PercyLogger.error('Unsupported driver for percy')
}
if (percySnapshot) {
snapshotHandler = (browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser, name: string) => {
snapshotHandler = (browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser, snapshotName: string, options?: any) => {
if (process.env.PERCY_SNAPSHOT === 'true') {
return percySnapshot(browser, name)
let { name, uuid } = InsightsHandler._currentTest
if (isUndefined(name)) {
({ name, uuid } = TestReporter._currentTest)
}
options ||= {}
options = {
...options,
testCase: name || '',
thTestCaseExecutionId: uuid || '',
}
return percySnapshot(browser, snapshotName, options)
}
}
}
Expand All @@ -30,7 +43,28 @@ let screenshotHandler = async (...args: any[]) => {
PercyLogger.error('Unsupported driver for percy')
}
if (percySnapshot && percySnapshot.percyScreenshot) {
screenshotHandler = percySnapshot.percyScreenshot
screenshotHandler = (browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | string, screenshotName: any, options?: any) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we give types to screenshotName and options?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Percy screenshot method accepts arguments with method overloading. Arguments accepted are either (browser, name, options) or (name, options) where options can be in any format. Hence I've kept the parameter types to any.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

screenshotName should be string only no?

let { name, uuid } = InsightsHandler._currentTest
if (isUndefined(name)) {
({ name, uuid } = TestReporter._currentTest)
}
if (!browser || typeof browser === 'string') {
screenshotName ||= {}
screenshotName = {
...screenshotName,
testCase: name || '',
thTestCaseExecutionId: uuid || '',
}
} else {
options ||= {}
options = {
...options,
testCase: name || '',
thTestCaseExecutionId: uuid || '',
}
}
return percySnapshot.percyScreenshot(browser, screenshotName, options)
}
}
export const screenshot = screenshotHandler

Expand All @@ -39,6 +73,27 @@ let screenshotAppHandler = async (...args: any[]) => {
PercyLogger.error('Unsupported driver for percy')
}
if (percyAppScreenshot) {
screenshotAppHandler = percyAppScreenshot
screenshotAppHandler = (driverOrName: any, nameOrOptions?: any, options?: any) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here also

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let { name, uuid } = InsightsHandler._currentTest
if (isUndefined(name)) {
({ name, uuid } = TestReporter._currentTest)
}
if (!driverOrName || typeof driverOrName === 'string') {
nameOrOptions ||= {}
nameOrOptions = {
...nameOrOptions,
testCase: name || '',
thTestCaseExecutionId: uuid || '',
}
} else {
options ||= {}
options = {
...options,
testCase: name || '',
thTestCaseExecutionId: uuid || '',
}
}
return percyAppScreenshot(driverOrName, nameOrOptions, options)
}
}
export const screenshotApp = screenshotAppHandler
53 changes: 25 additions & 28 deletions packages/wdio-browserstack-service/src/accessibility-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import type { Capabilities, Frameworks } from '@wdio/types'

import type { ITestCaseHookParameter } from './cucumber-types.js'

import Listener from './testOps/listener.js'

import {
getA11yResultsSummary,
getA11yResults,
Expand All @@ -30,6 +32,7 @@ class _AccessibilityHandler {
private _testMetadata: { [key: string]: any; } = {}
private static _a11yScanSessionMap: { [key: string]: any; } = {}
private _sessionId: string | null = null
private listener = Listener.getInstance()

constructor (
private _browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser,
Expand Down Expand Up @@ -130,6 +133,8 @@ class _AccessibilityHandler {
this._framework !== 'mocha' ||
!this.shouldRunTestHooks(this._browser, this._accessibility)
) {
/* This is to be used when test events are sent */
Listener.setTestRunAccessibilityVar(false)
return
}

Expand All @@ -142,6 +147,9 @@ class _AccessibilityHandler {
AccessibilityHandler._a11yScanSessionMap[this._sessionId] = shouldScanTest
}

/* This is to be used when test events are sent */
Listener.setTestRunAccessibilityVar(this._accessibility && shouldScanTest)

if (!isPageOpened) {
return
}
Expand Down Expand Up @@ -176,22 +184,15 @@ class _AccessibilityHandler {

if (shouldScanTestForAccessibility) {
BStackLogger.info('Automate test case execution has ended. Processing for accessibility testing is underway. ')
}

const dataForExtension = {
saveResults: shouldScanTestForAccessibility,
testDetails: {
'name': test.title,
'testRunId': process.env.BS_A11Y_TEST_RUN_ID,
'filePath': this._suiteFile,
'scopeList': [suiteTitle, test.title]
},
platform: this._platformA11yMeta
}
const dataForExtension = {
'thTestRunUuid': process.env.TEST_ANALYTICS_ID,
'thBuildUuid': process.env.BROWSERSTACK_TESTHUB_UUID,
'thJwtToken': process.env.BROWSERSTACK_TESTHUB_JWT
}

await this.sendTestStopEvent((this._browser as WebdriverIO.Browser), dataForExtension)
await this.sendTestStopEvent((this._browser as WebdriverIO.Browser), dataForExtension)

if (shouldScanTestForAccessibility) {
BStackLogger.info('Accessibility testing for this test case has ended.')
}
} catch (error) {
Expand All @@ -208,6 +209,8 @@ class _AccessibilityHandler {
const featureData = gherkinDocument.feature
const uniqueId = getUniqueIdentifierForCucumber(world)
if (!this.shouldRunTestHooks(this._browser, this._accessibility)) {
/* This is to be used when test events are sent */
Listener.setTestRunAccessibilityVar(false)
return
}

Expand All @@ -220,6 +223,9 @@ class _AccessibilityHandler {
AccessibilityHandler._a11yScanSessionMap[this._sessionId] = shouldScanScenario
}

/* This is to be used when test events are sent */
Listener.setTestRunAccessibilityVar(this._accessibility && shouldScanScenario)

if (!isPageOpened) {
return
}
Expand All @@ -242,8 +248,6 @@ class _AccessibilityHandler {

const pickleData = world.pickle
try {
const gherkinDocument = world.gherkinDocument
const featureData = gherkinDocument.feature
const uniqueId = getUniqueIdentifierForCucumber(world)
const accessibilityScanStarted = this._testMetadata[uniqueId]?.accessibilityScanStarted
const shouldScanTestForAccessibility = this._testMetadata[uniqueId]?.scanTestForAccessibility
Expand All @@ -254,22 +258,15 @@ class _AccessibilityHandler {

if (shouldScanTestForAccessibility) {
BStackLogger.info('Automate test case execution has ended. Processing for accessibility testing is underway. ')
}

const dataForExtension = {
saveResults: shouldScanTestForAccessibility,
testDetails: {
'name': pickleData.name,
'testRunId': process.env.BS_A11Y_TEST_RUN_ID,
'filePath': gherkinDocument.uri,
'scopeList': [featureData?.name, pickleData.name]
},
platform: this._platformA11yMeta
}
const dataForExtension = {
'thTestRunUuid': process.env.TEST_ANALYTICS_ID,
'thBuildUuid': process.env.BROWSERSTACK_TESTHUB_UUID,
'thJwtToken': process.env.BROWSERSTACK_TESTHUB_JWT
}

await this.sendTestStopEvent(( this._browser as WebdriverIO.Browser), dataForExtension)
await this.sendTestStopEvent(( this._browser as WebdriverIO.Browser), dataForExtension)

if (shouldScanTestForAccessibility) {
BStackLogger.info('Accessibility testing for this test case has ended.')
}
} catch (error) {
Expand Down
8 changes: 4 additions & 4 deletions packages/wdio-browserstack-service/src/cleanup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getErrorString, stopBuildUpstream } from './util.js'
import { BStackLogger } from './bstackLogger.js'
import fs from 'node:fs'
import { fireFunnelRequest } from './instrumentation/funnelInstrumentation.js'
import { TESTOPS_BUILD_ID_ENV, TESTOPS_JWT_ENV } from './constants.js'
import { BROWSERSTACK_TESTHUB_UUID, BROWSERSTACK_TESTHUB_JWT, BROWSERSTACK_OBSERVABILITY } from './constants.js'

export default class BStackCleanup {
static async startCleanup() {
Expand All @@ -29,15 +29,15 @@ export default class BStackCleanup {
}
}
static async executeObservabilityCleanup(funnelData: any) {
if (!process.env[TESTOPS_JWT_ENV]) {
if (!process.env[BROWSERSTACK_TESTHUB_JWT]) {
return
}
BStackLogger.debug('Executing observability cleanup')
try {
const killSignal = funnelData?.event_properties?.finishedMetadata?.signal
const result = await stopBuildUpstream(killSignal)
if (process.env[TESTOPS_BUILD_ID_ENV]) {
BStackLogger.info(`\nVisit https://observability.browserstack.com/builds/${process.env[TESTOPS_BUILD_ID_ENV]} to view build report, insights, and many more debugging information all at one place!\n`)
if (process.env[BROWSERSTACK_OBSERVABILITY] && process.env[BROWSERSTACK_TESTHUB_UUID]) {
BStackLogger.info(`\nVisit https://observability.browserstack.com/builds/${process.env[BROWSERSTACK_TESTHUB_UUID]} to view build report, insights, and many more debugging information all at one place!\n`)
}
const status = (result && result.status) || 'failed'
const message = (result && result.message)
Expand Down
17 changes: 14 additions & 3 deletions packages/wdio-browserstack-service/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ export const DEFAULT_WAIT_TIMEOUT_FOR_PENDING_UPLOADS = 5000 // 5s
export const DEFAULT_WAIT_INTERVAL_FOR_PENDING_UPLOADS = 100 // 100ms
export const BSTACK_SERVICE_VERSION = bstackServiceVersion

export const ACCESSIBILITY_API_URL = 'https://accessibility.browserstack.com/api'
export const NOT_ALLOWED_KEYS_IN_CAPS = ['includeTagsInTestingScope', 'excludeTagsInTestingScope']

export const LOGS_FILE = 'logs/bstack-wdio-service.log'
Expand Down Expand Up @@ -82,7 +81,7 @@ export const TCG_INFO = {
// Env variables - Define all the env variable constants over here

// To store the JWT token returned the session launch
export const TESTOPS_JWT_ENV = 'BS_TESTOPS_JWT'
export const BROWSERSTACK_TESTHUB_JWT = 'BROWSERSTACK_TESTHUB_JWT'

// To store tcg auth result for selfHealing feature:
export const BSTACK_TCG_AUTH_RESULT = 'BSTACK_TCG_AUTH_RESULT'
Expand All @@ -91,7 +90,10 @@ export const BSTACK_TCG_AUTH_RESULT = 'BSTACK_TCG_AUTH_RESULT'
export const TESTOPS_SCREENSHOT_ENV = 'BS_TESTOPS_ALLOW_SCREENSHOTS'

// To store build hashed id
export const TESTOPS_BUILD_ID_ENV = 'BS_TESTOPS_BUILD_HASHED_ID'
export const BROWSERSTACK_TESTHUB_UUID = 'BROWSERSTACK_TESTHUB_UUID'

// To store test run uuid
export const TEST_ANALYTICS_ID = 'TEST_ANALYTICS_ID'

// Whether to collect performance instrumentation or not
export const PERF_MEASUREMENT_ENV = 'BROWSERSTACK_O11Y_PERF_MEASUREMENT'
Expand All @@ -105,6 +107,15 @@ export const RERUN_ENV = 'BROWSERSTACK_RERUN'
// To store whether the build launch has completed or not
export const TESTOPS_BUILD_COMPLETED_ENV = 'BS_TESTOPS_BUILD_COMPLETED'

// Whether percy has started successfully or not
export const BROWSERSTACK_PERCY = 'BROWSERSTACK_PERCY'

// Whether session is a accessibility session
export const BROWSERSTACK_ACCESSIBILITY = 'BROWSERSTACK_ACCESSIBILITY'

// Whether session is a observability session
export const BROWSERSTACK_OBSERVABILITY = 'BROWSERSTACK_OBSERVABILITY'

// Maximum size of VCS info which is allowed
export const MAX_GIT_META_DATA_SIZE_IN_BYTES = 64 * 1024

Expand Down
4 changes: 2 additions & 2 deletions packages/wdio-browserstack-service/src/crash-reporter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Capabilities, Options } from '@wdio/types'
import got from 'got'

import { BSTACK_SERVICE_VERSION, DATA_ENDPOINT, TESTOPS_BUILD_ID_ENV } from './constants.js'
import { BSTACK_SERVICE_VERSION, DATA_ENDPOINT, BROWSERSTACK_TESTHUB_UUID } from './constants.js'
import type { BrowserstackConfig, CredentialsForCrashReportUpload, UserConfigforReporting } from './types.js'
import { DEFAULT_REQUEST_CONFIG, getObservabilityKey, getObservabilityUser } from './util.js'
import { BStackLogger } from './bstackLogger.js'
Expand Down Expand Up @@ -61,7 +61,7 @@ export default class CrashReporter {
}

const data = {
hashed_id: process.env[TESTOPS_BUILD_ID_ENV],
hashed_id: process.env[BROWSERSTACK_TESTHUB_UUID],
observability_version: {
frameworkName: 'WebdriverIO-' + (this.userConfigForReporting.framework || 'null'),
sdkVersion: BSTACK_SERVICE_VERSION
Expand Down
4 changes: 2 additions & 2 deletions packages/wdio-browserstack-service/src/exitHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'node:path'
import BrowserStackConfig from './config.js'
import { saveFunnelData } from './instrumentation/funnelInstrumentation.js'
import { fileURLToPath } from 'node:url'
import { TESTOPS_JWT_ENV } from './constants.js'
import { BROWSERSTACK_TESTHUB_JWT } from './constants.js'
import { BStackLogger } from './bstackLogger.js'

const __filename = fileURLToPath(import.meta.url)
Expand Down Expand Up @@ -46,7 +46,7 @@ export function setupExitHandlers() {

export function shouldCallCleanup(config: BrowserStackConfig): string[] {
const args: string[] = []
if (!!process.env[TESTOPS_JWT_ENV] && !config.testObservability.buildStopped) {
if (!!process.env[BROWSERSTACK_TESTHUB_JWT] && !config.testObservability.buildStopped) {
args.push('--observability')
}

Expand Down
Loading