66 ITestCaseHookParameter ,
77 AfterAll ,
88 After ,
9- Status
9+ Status ,
10+ AfterStep
1011} from '@cucumber/cucumber'
1112import pino from 'pino'
1213import { Browser , chromium , firefox , webkit } from '@playwright/test'
@@ -19,6 +20,7 @@ import { config } from '../../config'
1920import { Group , User , UserState } from '../../support/types'
2021import { api , environment , utils , store } from '../../support'
2122import { getBrowserLaunchOptions } from '../../support/environment/actor/shared'
23+ import { AxeResults } from 'axe-core'
2224
2325export { World }
2426
@@ -32,10 +34,17 @@ const logger = pino({
3234 }
3335} )
3436
37+ let startTime = 0
38+ const allViolations = [ ]
39+ let totalTest = 0
40+ let failedTest = 0
41+ let passedTest = 0
42+
3543setDefaultTimeout ( config . debug ? - 1 : config . timeout * 1000 )
3644setWorldConstructor ( World )
3745
3846BeforeAll ( async ( ) : Promise < void > => {
47+ startTime = Date . now ( )
3948 const browserConfiguration = getBrowserLaunchOptions ( )
4049
4150 const browsers : Record < string , ( ) => Promise < Browser > > = {
@@ -56,6 +65,7 @@ BeforeAll(async (): Promise<void> => {
5665} )
5766
5867Before ( async function ( this : World , { pickle } : ITestCaseHookParameter ) {
68+ // const firstStepLineNumber = pickle
5969 this . feature = pickle
6070 this . actorsEnvironment . on ( 'console' , ( actorId , message ) : void => {
6171 const msg = {
@@ -111,6 +121,13 @@ After(async function (this: World, { result, willBeRetried, pickle }: ITestCaseH
111121 if ( ! result ) {
112122 return
113123 }
124+ totalTest ++
125+ // console.log(pickle,result)
126+ if ( result . status === 'PASSED' ) {
127+ passedTest ++
128+ } else {
129+ failedTest ++
130+ }
114131
115132 await this . actorsEnvironment . close ( )
116133
@@ -162,18 +179,90 @@ After(async function (this: World, { result, willBeRetried, pickle }: ITestCaseH
162179 config . reportTracing = willBeRetried || defaults . reportTracing
163180} )
164181
182+ AfterStep ( function ( this : World , { result, pickle } : ITestCaseHookParameter ) {
183+ const stepData = this . currentStepData
184+ if ( ! stepData || ! stepData . a11yViolations ) {
185+ return
186+ }
187+ let violations = stepData . a11yViolations
188+ // when we retry test do not keep duplicates
189+ violations = Object . values (
190+ violations . reduce ( ( acc , item ) => {
191+ acc [ item . test ] = item ;
192+ return acc ;
193+ } , { } )
194+ ) ;
195+ violations . forEach ( ( violation ) => {
196+ const vioEle = [ ]
197+ violation . nodes . forEach ( ( element ) => {
198+ vioEle . push ( element . target )
199+ } )
200+ allViolations . push ( {
201+ test : pickle . name ,
202+ file : pickle . uri ,
203+ status : result . status ,
204+ duration : result . duration ,
205+ url : violations . helpUrl ,
206+ violations : violations . tags || [ ] ,
207+ description : violation . description ,
208+
209+ violationCount : violation . nodes . length ,
210+ elements : vioEle
211+ } )
212+ } )
213+ } )
214+
165215AfterAll ( async ( ) => {
166216 environment . closeSSEConnections ( )
167217
168218 if ( state . browser ) {
169219 await state . browser . close ( )
170220 }
221+ let totalViolations = 0
222+ allViolations . forEach ( violation => {
223+ totalViolations = totalViolations + violation . violationCount
224+ } ) ;
171225
172226 // move failed tracing reports
173227 const failedDir = path . dirname ( config . tracingReportDir ) + '/failed'
174228 if ( fs . existsSync ( failedDir ) ) {
175229 fs . renameSync ( failedDir , config . tracingReportDir )
176230 }
231+ // console.log('after all allViolations', allViolations)
232+ const report : A11yReportcucumber = {
233+ summary : {
234+ totalTests : totalTest ,
235+ totalViolations : totalViolations ,
236+ totalPasses : passedTest ,
237+ totalFailure : failedTest ,
238+ timestamp : new Date ( ) . toISOString ( ) ,
239+ duration : Date . now ( ) - startTime
240+ } ,
241+ tests : allViolations
242+ }
243+
244+ try {
245+ const outputfile = 'a11y-report-cucumber.json'
246+ fs . writeFile ( 'a11y-report-cucumber.json' , JSON . stringify ( report , null , 2 ) , ( err ) => {
247+ if ( err ) {
248+ console . error ( 'Error writing file:' , err )
249+ } else {
250+ console . log ( 'File has been written' )
251+ }
252+ } )
253+ console . info ( `\n📊 Accessibility Report Generated:` )
254+ console . info ( ` File: ${ outputfile } ` )
255+ console . info ( ` Tests: ${ report . summary . totalTests } ` )
256+ console . info ( ` Failed Tests: ${ failedTest } ` )
257+ console . info ( ` Violations: ${ report . summary . totalViolations } ` )
258+ if ( report . summary . totalViolations > 0 ) {
259+ console . warn ( `\n⚠️ Found ${ report . summary . totalViolations } accessibility violations` )
260+ } else {
261+ console . info ( `\n✅ No accessibility violations found` )
262+ }
263+ } catch ( error ) {
264+ console . error ( 'Error writing accessibility report:' , error )
265+ }
177266} )
178267
179268function filterTracingReports ( status : string ) {
@@ -295,3 +384,30 @@ const storeKeycloakGroups = async (adminUser: User, usersEnvironment) => {
295384 }
296385 } )
297386}
387+
388+
389+ interface A11yReportcucumber {
390+ summary : {
391+ totalTests : number
392+ totalViolations : number
393+ totalPasses : number
394+ totalFailure : number ,
395+ timestamp : string
396+ duration : number
397+ }
398+ tests : A11yTestResult [ ]
399+ }
400+ interface A11yTestResult {
401+ test : string
402+ file : string
403+ line : number
404+ status : string
405+ duration : number
406+ url ?: string
407+ violations : AxeResults [ 'violations' ]
408+ violationCount : number
409+ passCount : number
410+ incompleteCount : number
411+ }
412+
413+
0 commit comments