Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions packages/wdio-browserstack-service/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ export const EDS_URL = 'https://eds.browserstack.com'

export const SUPPORTED_BROWSERS_FOR_AI = ['chrome', 'microsoftedge', 'firefox']

export const SUPPORTED_BROWSERS_FOR_ACCESSIBILITY = ['chrome', 'chromefortesting', 'safari']

export const MIN_BROWSER_VERSIONS_A11Y = {
chrome: 95,
chromefortesting: 141,
safari: 18.4
} as const

export const MIN_BROWSER_VERSIONS_A11Y_NON_BSTACK = {
chrome: 100,
chromefortesting: 141,
safari: 18.4
} as const

export const TCG_URL = 'https://tcg.browserstack.com'

export const TCG_INFO = {
Expand Down
95 changes: 75 additions & 20 deletions packages/wdio-browserstack-service/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ import {
APP_ALLY_ISSUES_SUMMARY_ENDPOINT,
APP_ALLY_ISSUES_ENDPOINT,
CLI_DEBUG_LOGS_FILE,
WDIO_NAMING_PREFIX
WDIO_NAMING_PREFIX,
MIN_BROWSER_VERSIONS_A11Y,
MIN_BROWSER_VERSIONS_A11Y_NON_BSTACK
} from './constants.js'
import CrashReporter from './crash-reporter.js'
import { BStackLogger } from './bstackLogger.js'
Expand Down Expand Up @@ -479,39 +481,92 @@ export const validateCapsWithA11y = (deviceName?: any, platformMeta?: { [key: st
return false
}

if (platformMeta?.browser_name?.toLowerCase() !== 'chrome') {
BStackLogger.warn('Accessibility Automation will run only on Chrome browsers.')
return false
}
const browserName = platformMeta?.browser_name?.toLowerCase()
const browserVersion = platformMeta?.browser_version
if (!isUndefined(browserVersion) && !(browserVersion === 'latest' || parseFloat(browserVersion + '') > 94)) {
BStackLogger.warn('Accessibility Automation will run only on Chrome browser version greater than 94.')

const validBrowsers = ['chrome', 'chromefortesting', 'safari']
if (!browserName || !validBrowsers.includes(browserName)) {
BStackLogger.warn(`Accessibility Automation supports Chrome 95+, Chrome for Testing 141+, and Safari 18.4+. Current browser: ${browserName}`)
return false
}

if (chromeOptions?.args?.includes('--headless')) {
BStackLogger.warn('Accessibility Automation will not run on legacy headless mode. Switch to new headless mode or avoid using headless mode.')
return false
if (browserName === 'chrome' || browserName === 'chromefortesting') {
const minVersion = MIN_BROWSER_VERSIONS_A11Y[browserName as keyof typeof MIN_BROWSER_VERSIONS_A11Y]
if (browserVersion && browserVersion !== 'latest') {
const version = parseInt(browserVersion.toString().split('.')[0] || '0', 10)
if (version < minVersion) {
BStackLogger.warn(`Accessibility Automation requires ${browserName === 'chrome' ? 'Chrome' : 'Chrome for Testing'} version ${minVersion} or higher.`)
return false
}
}

if (chromeOptions?.args?.includes('--headless')) {
BStackLogger.warn('Accessibility Automation will not run on legacy headless mode. Switch to new headless mode or avoid using headless mode.')
return false
}
}

// Safari validation
if (browserName === 'safari') {
if (browserVersion && browserVersion !== 'latest') {
const [currentMajor = 0, currentMinor = 0] = browserVersion.toString().split('.').map(Number)
const [requiredMajor = 0, requiredMinor = 0] = MIN_BROWSER_VERSIONS_A11Y.safari.toString().split('.').map(Number)

if (currentMajor < requiredMajor || (currentMajor === requiredMajor && currentMinor < requiredMinor)) {
BStackLogger.warn(`Accessibility Automation requires Safari version ${MIN_BROWSER_VERSIONS_A11Y.safari} or higher.`)
return false
}
}
}

return true
} catch (error) {
BStackLogger.debug(`Exception in checking capabilities compatibility with Accessibility. Error: ${error}`)
}
return false
}

export const validateCapsWithNonBstackA11y = (browserName?: string | undefined, browserVersion?: string | undefined) => {
export const validateCapsWithNonBstackA11y = (browserName?: string | undefined, browserVersion?:string | undefined) => {
try {
const browser = browserName?.toLowerCase()

if (browserName?.toLowerCase() !== 'chrome') {
BStackLogger.warn('Accessibility Automation will run only on Chrome browsers.')
return false
}
if (!isUndefined(browserVersion) && !(browserVersion === 'latest' || parseFloat(browserVersion + '') > 100)) {
BStackLogger.warn('Accessibility Automation will run only on Chrome browser version greater than 100.')
return false
}
return true
// Support Chrome, Chrome for Testing (ChromeForTesting), and Safari on non-BrowserStack infrastructure
const validBrowsers = ['chrome', 'chromefortesting', 'safari']
if (!browser || !validBrowsers.includes(browser)) {
BStackLogger.warn('Accessibility Automation on non-BrowserStack infrastructure supports Chrome 100+, Chrome for Testing 141+, and Safari 18.4+.')
return false
}

// Chrome/Chrome for Testing validation
if (browser === 'chrome' || browser === 'chromefortesting') {
const minVersion = MIN_BROWSER_VERSIONS_A11Y_NON_BSTACK[browser as keyof typeof MIN_BROWSER_VERSIONS_A11Y_NON_BSTACK]
if (browserVersion && browserVersion !== 'latest') {
const version = parseInt(browserVersion.toString().split('.')[0] || '0', 10)
if (version < minVersion) {
BStackLogger.warn(`Accessibility Automation requires ${browser === 'chrome' ? 'Chrome' : 'Chrome for Testing'} version ${minVersion}+ on non-BrowserStack infrastructure.`)
return false
}
}
}

// Safari validation
if (browser === 'safari') {
if (browserVersion && browserVersion !== 'latest') {
const [currentMajor = 0, currentMinor = 0] = browserVersion.toString().split('.').map(Number)
const [requiredMajor = 0, requiredMinor = 0] = MIN_BROWSER_VERSIONS_A11Y_NON_BSTACK.safari.toString().split('.').map(Number)

if (currentMajor < requiredMajor || (currentMajor === requiredMajor && currentMinor < requiredMinor)) {
BStackLogger.warn(`Accessibility Automation requires Safari version ${MIN_BROWSER_VERSIONS_A11Y_NON_BSTACK.safari}+ on non-BrowserStack infrastructure.`)
return false
}
}
}

return true
} catch (error) {
BStackLogger.debug(`Exception in checking capabilities compatibility with Accessibility. Error: ${error}`)
}
return false
}

export const shouldScanTestForAccessibility = (suiteTitle: string | undefined, testTitle: string, accessibilityOptions?: { [key: string]: string; }, world?: { [key: string]: unknown; }, isCucumber?: boolean) => {
Expand Down
86 changes: 77 additions & 9 deletions packages/wdio-browserstack-service/tests/util.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1153,25 +1153,25 @@ describe('validateCapsWithA11y', () => {
.toContain('Accessibility Automation will run only on Desktop browsers.')
})

it('returns false if browser is not chrome', async () => {
it('returns false if browser is not supported', async () => {
const platformMeta = {
'browser_name': 'safari'
'browser_name': 'firefox'
}

expect(validateCapsWithA11y(undefined, platformMeta)).toEqual(false)
expect(logInfoMock.mock.calls[0][0])
.toContain('Accessibility Automation will run only on Chrome browsers.')
.toContain('Accessibility Automation supports Chrome 95+, Chrome for Testing 141+, and Safari 18.4+')
})

it('returns false if browser version is lesser than 94', async () => {
it('returns false if browser version is lesser than 95', async () => {
const platformMeta = {
'browser_name': 'chrome',
'browser_version': '90'
}

expect(validateCapsWithA11y(undefined, platformMeta)).toEqual(false)
expect(logInfoMock.mock.calls[0][0])
.toContain('Accessibility Automation will run only on Chrome browser version greater than 94.')
.toContain('Accessibility Automation requires Chrome version 95 or higher')
})

it('returns false if browser version is lesser than 94', async () => {
Expand All @@ -1197,6 +1197,50 @@ describe('validateCapsWithA11y', () => {

expect(validateCapsWithA11y(undefined, platformMeta, chromeOptions)).toEqual(true)
})

it('returns true for Safari 18.4+', async () => {
const platformMeta = {
'browser_name': 'safari',
'browser_version': '18.4'
}
expect(validateCapsWithA11y(undefined, platformMeta)).toEqual(true)
})

it('returns true for Safari latest', async () => {
const platformMeta = {
'browser_name': 'safari',
'browser_version': 'latest'
}
expect(validateCapsWithA11y(undefined, platformMeta)).toEqual(true)
})

it('returns false for Safari < 18.4', async () => {
const platformMeta = {
'browser_name': 'safari',
'browser_version': '16.0'
}
expect(validateCapsWithA11y(undefined, platformMeta)).toEqual(false)
expect(logInfoMock.mock.calls[0][0])
.toContain('Safari version 18.4 or higher')
})

it('returns true for ChromeForTesting 141+', async () => {
const platformMeta = {
'browser_name': 'ChromeForTesting',
'browser_version': '141'
}
expect(validateCapsWithA11y(undefined, platformMeta)).toEqual(true)
})

it('returns false for ChromeForTesting < 141', async () => {
const platformMeta = {
'browser_name': 'ChromeForTesting',
'browser_version': '140'
}
expect(validateCapsWithA11y(undefined, platformMeta)).toEqual(false)
expect(logInfoMock.mock.calls[0][0])
.toContain('Accessibility Automation requires Chrome for Testing version 141 or higher')
})
})

describe('validateCapsWithNonBstackA11y', () => {
Expand All @@ -1205,14 +1249,38 @@ describe('validateCapsWithNonBstackA11y', () => {
logInfoMock = vi.spyOn(log, 'warn')
})

it('returns false if browser is not chrome', async () => {
it('returns true for safari 18.4+', async () => {
expect(validateCapsWithNonBstackA11y('safari', '18.4')).toEqual(true)
})

it('returns true for safari latest', async () => {
expect(validateCapsWithNonBstackA11y('safari', 'latest')).toEqual(true)
})

it('returns false for safari < 18.4', async () => {
expect(validateCapsWithNonBstackA11y('safari', '16.0')).toEqual(false)
expect(logInfoMock.mock.calls[0][0])
.toContain('Safari version 18.4+')
})

it('returns true for ChromeForTesting 141+', async () => {
expect(validateCapsWithNonBstackA11y('ChromeForTesting', '141')).toEqual(true)
})

it('returns false for ChromeForTesting < 141', async () => {
expect(validateCapsWithNonBstackA11y('ChromeForTesting', '140')).toEqual(false)
expect(logInfoMock.mock.calls[0][0])
.toContain('Accessibility Automation requires Chrome for Testing version 141+')
})

it('returns false if browser is not supported', async () => {

const browserName = 'safari'
const browserName = 'firefox'
const browserVersion = 'latest'

expect(validateCapsWithNonBstackA11y(browserName, browserVersion)).toEqual(false)
expect(logInfoMock.mock.calls[0][0])
.toContain('Accessibility Automation will run only on Chrome browsers.')
.toContain('Accessibility Automation on non-BrowserStack infrastructure supports Chrome 100+, Chrome for Testing 141+, and Safari 18.4+')
})

it('returns false if browser version is lesser than 100', async () => {
Expand All @@ -1222,7 +1290,7 @@ describe('validateCapsWithNonBstackA11y', () => {

expect(validateCapsWithNonBstackA11y(browserName, browserVersion)).toEqual(false)
expect(logInfoMock.mock.calls[0][0])
.toContain('Accessibility Automation will run only on Chrome browser version greater than 100.')
.toContain('Accessibility Automation requires Chrome version 100+')
})

it('returns true if validation done', async () => {
Expand Down
Loading