@@ -8,6 +8,13 @@ import { DEFAULT_BROWSER_SIZE } from './helpers/const';
88import * as testPageUtils from './helpers/clearPage' ;
99import 'nconf' ;
1010
11+ interface TestInfo {
12+ testName : string ;
13+ fixtureName : string ;
14+ testId : string ;
15+ attemptNumber : number ;
16+ }
17+
1118interface ParsedArgs {
1219 concurrency : number ;
1320 browsers : string ;
@@ -237,13 +244,56 @@ createTestCafe(TESTCAFE_CONFIG)
237244 ( runner as any ) . cache = args . cache ;
238245 }
239246
247+ const testAttempts = new Map < string , number > ( ) ;
248+
240249 const runOptions : RunOptions = {
241250 quarantineMode : { successThreshold : 1 , attemptLimit : 10 } ,
242251 disableNativeAutomation : true ,
243252 // @ts -expect-error ts-error
244253 hooks : {
245254 test : {
246255 before : async ( t : TestController ) => {
256+ let testName = 'Current Test' ;
257+ let fixtureName = 'Current Fixture' ;
258+
259+ try {
260+ testName = ( t as any ) . testRun ?. test ?. name || 'Unknown Test' ;
261+ fixtureName = ( t as any ) . testRun ?. test ?. fixture ?. name || 'Unknown Fixture' ;
262+ } catch ( e ) {
263+ console . log ( 'Could not get test names from internal API' ) ;
264+ }
265+
266+ const testMetadata = await ClientFunction ( ( ) => {
267+ return {
268+ url : window . location . href ,
269+ timestamp : Date . now ( )
270+ } ;
271+ } ) . with ( { boundTestRun : t } ) ( ) ;
272+
273+ const testInfo : TestInfo = {
274+ testName : testName ,
275+ fixtureName : fixtureName ,
276+ testId : `test_${ testMetadata . timestamp } ` ,
277+ attemptNumber : 0 ,
278+ } ;
279+
280+
281+ const testKey = testInfo . testId ;
282+ const attemptNumber = ( testAttempts . get ( testKey ) || 0 ) + 1 ;
283+ testAttempts . set ( testKey , attemptNumber ) ;
284+
285+
286+ testInfo . attemptNumber = attemptNumber ;
287+ t . ctx . testInfo = testInfo ;
288+ t . ctx . testKey = testKey ;
289+
290+ console . log ( `🚀 [Attempt ${ attemptNumber } /10] Starting test` ) ;
291+ console . log ( `� Test ID: ${ testInfo . testId } ` ) ;
292+
293+ if ( attemptNumber > 1 ) {
294+ console . log ( `⚠️ QUARANTINE MODE: Retry attempt ${ attemptNumber } for failed test` ) ;
295+ }
296+
247297 if ( ! componentFolder . includes ( 'accessibility' ) ) {
248298 const [ width , height ] = DEFAULT_BROWSER_SIZE ;
249299 await t . resizeWindow ( width , height ) ;
@@ -253,18 +303,73 @@ createTestCafe(TESTCAFE_CONFIG)
253303 await addShadowRootTree ( t ) ;
254304 }
255305
256- if ( args . theme ) {
257- await changeTheme ( t , args . theme ) ;
306+ const themeName = args . theme || 'generic.light' ;
307+ console . log ( `🎨 [Attempt ${ attemptNumber } ] Setting theme: ${ themeName } ` ) ;
308+
309+ const currentTheme = await ClientFunction ( ( ) => {
310+ try {
311+ return ( window as any ) . DevExpress ?. ui ?. themes ?. current ( ) ;
312+ } catch ( e ) {
313+ return 'Theme API not available' ;
314+ }
315+ } ) . with ( { boundTestRun : t } ) ( ) ;
316+
317+ console . log ( `✅ [Attempt ${ attemptNumber } ] Current theme before change: ${ currentTheme } ` ) ;
318+
319+ try {
320+ await changeTheme ( t , themeName ) ;
321+
322+ const newTheme = await ClientFunction ( ( ) => {
323+ try {
324+ return ( window as any ) . DevExpress ?. ui ?. themes ?. current ( ) ;
325+ } catch ( e ) {
326+ return 'Theme API not available' ;
327+ }
328+ } ) . with ( { boundTestRun : t } ) ( ) ;
329+
330+ console . log ( `🎯 [Attempt ${ attemptNumber } ] Theme after change: ${ newTheme } ` ) ;
331+ } catch ( error ) {
332+ console . error ( `❌ [Attempt ${ attemptNumber } ] Error setting theme:` , error ) ;
258333 }
259334 } ,
260- after : async ( ) => {
261- await testPageUtils . clearTestPage ( ) ;
335+
336+ after : async ( t : TestController ) => {
337+ const testInfo = t . ctx . testInfo as TestInfo ;
338+
339+ if ( testInfo ) {
340+ console . log ( `🧹 [Attempt ${ testInfo . attemptNumber } ] After hook - clearing page` ) ;
341+ console . log ( `� [Attempt ${ testInfo . attemptNumber } ] Test ID: ${ testInfo . testId } ` ) ;
342+ } else {
343+ console . log ( `🧹 After hook - clearing page (test info not available)` ) ;
344+ }
345+
346+ try {
347+ await testPageUtils . clearTestPage ( t ) ;
348+ console . log ( `✅ ${ testInfo ? `[Attempt ${ testInfo . attemptNumber } ]` : '' } Page cleared successfully` ) ;
349+ } catch ( error ) {
350+ console . error ( `❌ ${ testInfo ? `[Attempt ${ testInfo . attemptNumber } ]` : '' } Error clearing page:` , error ) ;
351+ }
262352 } ,
263353 } ,
354+
355+ fixture : {
356+ afterEach : async ( t : TestController ) => {
357+ const testInfo = t . ctx . testInfo as TestInfo ;
358+ const testKey = t . ctx . testKey as string ;
359+
360+ if ( testInfo && testKey ) {
361+ console . log ( `🏁 Test completed: ${ testInfo . testId } (Final attempt: ${ testInfo . attemptNumber } )` ) ;
362+
363+ if ( testInfo . attemptNumber > 1 ) {
364+ console . log ( `🎯 QUARANTINE RESULT: Test ${ testInfo . testId } required ${ testInfo . attemptNumber } attempts to pass` ) ;
365+ }
366+
367+ testAttempts . delete ( testKey ) ;
368+ }
369+ }
370+ }
264371 } ,
265- } ;
266-
267- if ( args . browsers === 'chrome:docker' ) {
372+ } ; if ( args . browsers === 'chrome:docker' ) {
268373 runOptions . disableScreenshots = true ;
269374 }
270375
0 commit comments