11const path = require ( 'path' ) ;
22const helper = require ( './utils/helper' ) ;
33const Logger = require ( './utils/logger' ) ;
4+ const { APP_ALLY_ENDPOINT , APP_ALLY_ISSUES_SUMMARY_ENDPOINT , APP_ALLY_ISSUES_ENDPOINT } = require ( './utils/constants' ) ;
45const util = require ( 'util' ) ;
56const AccessibilityScripts = require ( './scripts/accessibilityScripts' ) ;
67
@@ -162,14 +163,38 @@ class AccessibilityAutomation {
162163 return false ;
163164 }
164165
166+ validateAppA11yCaps ( capabilities = { } ) {
167+ /* Check if the current driver platform is eligible for AppAccessibility scan */
168+ if (
169+ capabilities ?. platformName &&
170+ String ( capabilities ?. platformName ) . toLowerCase ( ) === 'android' &&
171+ capabilities ?. platformVersion &&
172+ parseInt ( capabilities ?. platformVersion ?. toString ( ) ) < 11
173+ ) {
174+ Logger . warn (
175+ 'App Accessibility Automation tests are supported on OS version 11 and above for Android devices.'
176+ ) ;
177+
178+ return false ;
179+ }
180+
181+ return true ;
182+ }
183+
165184 async beforeEachExecution ( testMetaData ) {
166185 try {
167186 this . currentTest = browser . currentTest ;
168187 this . currentTest . shouldScanTestForAccessibility = this . shouldScanTestForAccessibility (
169188 testMetaData
170189 ) ;
171190 this . currentTest . accessibilityScanStarted = true ;
172- this . _isAccessibilitySession = this . validateA11yCaps ( browser ) ;
191+
192+ this . _isAppAccessibility = helper . isAppAccessibilitySession ( ) ;
193+ if ( this . _isAppAccessibility ) {
194+ this . _isAccessibilitySession = this . validateAppA11yCaps ( testMetaData . metadata . sessionCapabilities ) ;
195+ } else {
196+ this . _isAccessibilitySession = this . validateA11yCaps ( browser ) ;
197+ }
173198
174199 if ( this . isAccessibilityAutomationSession ( ) && browser && this . _isAccessibilitySession ) {
175200 try {
@@ -267,10 +292,9 @@ class AccessibilityAutomation {
267292 }
268293
269294 if ( this . currentTest . shouldScanTestForAccessibility === false ) {
270- Logger . info ( 'Skipping Accessibility scan for this test as it\'s disabled.' ) ;
271-
272295 return ;
273296 }
297+
274298 try {
275299 const browser = browserInstance ;
276300
@@ -279,6 +303,16 @@ class AccessibilityAutomation {
279303
280304 return ;
281305 }
306+
307+ if ( helper . isAppAccessibilitySession ( ) ) {
308+ const results = await browser . executeScript (
309+ helper . formatString ( AccessibilityScripts . performScan , JSON . stringify ( this . getParamsForAppAccessibility ( commandName ) ) ) ,
310+ { }
311+ ) ;
312+ Logger . debug ( util . inspect ( results ) ) ;
313+
314+ return results ;
315+ }
282316 AccessibilityAutomation . pendingAllyReq ++ ;
283317 const results = await browser . executeAsyncScript ( AccessibilityScripts . performScan , {
284318 method : commandName || ''
@@ -297,9 +331,79 @@ class AccessibilityAutomation {
297331 }
298332 }
299333
334+ async getAppAccessibilityResults ( browser ) {
335+ if ( ! helper . isBrowserstackInfra ( ) ) {
336+ return [ ] ;
337+ }
338+
339+ if ( ! helper . isAppAccessibilitySession ( ) ) {
340+ Logger . warn ( 'Not an Accessibility Automation session, cannot retrieve Accessibility results.' ) ;
341+
342+ return [ ] ;
343+ }
344+
345+ try {
346+ const apiUrl = `${ APP_ALLY_ENDPOINT } /${ APP_ALLY_ISSUES_ENDPOINT } ` ;
347+ const apiRespone = await this . getAppA11yResultResponse ( apiUrl , browser , browser . sessionId ) ;
348+ const result = apiRespone ?. data ?. data ?. issues ;
349+ Logger . debug ( `Results: ${ JSON . stringify ( result ) } ` ) ;
350+
351+ return result ;
352+ } catch ( error ) {
353+ Logger . error ( 'No accessibility results were found.' ) ;
354+ Logger . debug ( `getAppAccessibilityResults Failed. Error: ${ error } ` ) ;
355+
356+ return [ ] ;
357+ }
358+
359+ }
360+
361+ async getAppAccessibilityResultsSummary ( browser ) {
362+ if ( ! helper . isBrowserstackInfra ( ) ) {
363+ return { } ;
364+ }
365+
366+ if ( ! helper . isAppAccessibilitySession ( ) ) {
367+ Logger . warn ( 'Not an Accessibility Automation session, cannot retrieve Accessibility results summary.' ) ;
368+
369+ return { } ;
370+ }
371+ try {
372+ const apiUrl = `${ APP_ALLY_ENDPOINT } /${ APP_ALLY_ISSUES_SUMMARY_ENDPOINT } ` ;
373+ const apiRespone = await this . getAppA11yResultResponse ( apiUrl , browser , browser . sessionId ) ;
374+ const result = apiRespone ?. data ?. data ?. summary ;
375+ Logger . debug ( `Results Summary: ${ JSON . stringify ( result ) } ` ) ;
376+
377+ return result ;
378+ } catch ( error ) {
379+ Logger . error ( 'No accessibility result summary were found.' ) ;
380+ Logger . debug ( `getAppAccessibilityResultsSummary Failed. Error: ${ error } ` ) ;
381+
382+ return { } ;
383+ }
384+ }
385+
386+ async getAppA11yResultResponse ( apiUrl , browser , sessionId ) {
387+ Logger . debug ( 'Performing scan before getting results/results summary' ) ;
388+ await this . performScan ( browser ) ;
389+
390+ const upperTimeLimit = process . env . BSTACK_A11Y_POLLING_TIMEOUT ? Date . now ( ) + parseInt ( process . env . BSTACK_A11Y_POLLING_TIMEOUT ) * 1000 : Date . now ( ) + 30000 ;
391+ const params = { test_run_uuid : process . env . TEST_RUN_UUID , session_id : sessionId , timestamp : Date . now ( ) } ; // Query params to pass
392+ const header = { Authorization : `Bearer ${ process . env . BSTACK_A11Y_JWT } ` } ;
393+ const apiRespone = await helper . pollApi ( apiUrl , params , header , upperTimeLimit ) ;
394+ Logger . debug ( `Polling Result: ${ JSON . stringify ( apiRespone . message ) } ` ) ;
395+
396+ return apiRespone ;
397+
398+ }
399+
400+
300401 async saveAccessibilityResults ( browser , dataForExtension = { } ) {
301402 Logger . debug ( 'Performing scan before saving results' ) ;
302403 await this . performScan ( browser ) ;
404+ if ( helper . isAppAccessibilitySession ( ) ) {
405+ return ;
406+ }
303407 const results = await browser . executeAsyncScript ( AccessibilityScripts . saveTestResults , dataForExtension ) ;
304408
305409 return results ;
@@ -336,7 +440,12 @@ class AccessibilityAutomation {
336440 const originalCommandFn = originalCommand . command ;
337441
338442 originalCommand . command = async function ( ...args ) {
339- await accessibilityInstance . performScan ( browser , commandName ) ;
443+ if (
444+ ! commandName . includes ( 'execute' ) ||
445+ ! accessibilityInstance . shouldPatchExecuteScript ( args . length ? args [ 0 ] : null )
446+ ) {
447+ await accessibilityInstance . performScan ( browser , commandName ) ;
448+ }
340449
341450 return originalCommandFn . apply ( this , args ) ;
342451 } ;
@@ -347,6 +456,28 @@ class AccessibilityAutomation {
347456 }
348457 }
349458 }
459+
460+ shouldPatchExecuteScript ( script ) {
461+ if ( ! script || typeof script !== 'string' ) {
462+ return true ;
463+ }
464+
465+ return (
466+ script . toLowerCase ( ) . indexOf ( 'browserstack_executor' ) !== - 1 ||
467+ script . toLowerCase ( ) . indexOf ( 'browserstack_accessibility_automation_script' ) !== - 1
468+ ) ;
469+ }
470+
471+ getParamsForAppAccessibility ( commandName ) {
472+ return {
473+ 'thTestRunUuid' : process . env . TEST_RUN_UUID ,
474+ 'thBuildUuid' : process . env . BROWSERSTACK_TESTHUB_UUID ,
475+ 'thJwtToken' : process . env . BROWSERSTACK_TESTHUB_JWT ,
476+ 'authHeader' : process . env . BSTACK_A11Y_JWT ,
477+ 'scanTimestamp' : Date . now ( ) ,
478+ 'method' : commandName
479+ } ;
480+ }
350481}
351482
352483module . exports = AccessibilityAutomation ;
0 commit comments