@@ -8,6 +8,14 @@ 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+ startTime ?: number ;
17+ }
18+
1119interface ParsedArgs {
1220 concurrency : number ;
1321 browsers : string ;
@@ -237,13 +245,76 @@ createTestCafe(TESTCAFE_CONFIG)
237245 ( runner as any ) . cache = args . cache ;
238246 }
239247
248+ const testAttempts = new Map < string , number > ( ) ;
249+
240250 const runOptions : RunOptions = {
241251 quarantineMode : { successThreshold : 1 , attemptLimit : 10 } ,
242252 disableNativeAutomation : true ,
243253 // @ts -expect-error ts-error
244254 hooks : {
245255 test : {
246256 before : async ( t : TestController ) => {
257+ let testName = 'Current Test' ;
258+ let fixtureName = 'Current Fixture' ;
259+
260+ try {
261+ // Пробуем разные способы получения имени теста
262+ const testController = t as any ;
263+
264+ if ( testController . testRun ?. test ?. name ) {
265+ testName = testController . testRun . test . name ;
266+ fixtureName = testController . testRun . test . fixture ?. name || 'Unknown Fixture' ;
267+ console . log ( `✅ Got test name via testRun: "${ testName } "` ) ;
268+ } else if ( testController . test ?. name ) {
269+ testName = testController . test . name ;
270+ fixtureName = testController . test . fixture ?. name || 'Unknown Fixture' ;
271+ console . log ( `✅ Got test name via test: "${ testName } "` ) ;
272+ } else if ( testController . _testRun ?. test ?. name ) {
273+ testName = testController . _testRun . test . name ;
274+ fixtureName = testController . _testRun . test . fixture ?. name || 'Unknown Fixture' ;
275+ console . log ( `✅ Got test name via _testRun: "${ testName } "` ) ;
276+ } else {
277+ console . log ( '❌ Could not access test name via any internal API' ) ;
278+ console . log ( 'Available properties on TestController:' , Object . keys ( testController ) ) ;
279+ }
280+ } catch ( e ) {
281+ console . log ( '❌ Error getting test names from internal API:' , e ) ;
282+ }
283+
284+ const testMetadata = await ClientFunction ( ( ) => {
285+ return {
286+ url : window . location . href ,
287+ timestamp : Date . now ( )
288+ } ;
289+ } ) . with ( { boundTestRun : t } ) ( ) ;
290+
291+ const testInfo : TestInfo = {
292+ testName : testName ,
293+ fixtureName : fixtureName ,
294+ testId : `test_${ testMetadata . timestamp } ` ,
295+ attemptNumber : 0 ,
296+ } ;
297+
298+
299+ const testKey = testInfo . testId ;
300+ const attemptNumber = ( testAttempts . get ( testKey ) || 0 ) + 1 ;
301+ testAttempts . set ( testKey , attemptNumber ) ;
302+
303+
304+ testInfo . attemptNumber = attemptNumber ;
305+ testInfo . startTime = Date . now ( ) ;
306+ t . ctx . testInfo = testInfo ;
307+ t . ctx . testKey = testKey ;
308+
309+ console . log ( `🚀 [Attempt ${ attemptNumber } /10] Starting test: "${ testInfo . testName } "` ) ;
310+ console . log ( `📋 Fixture: "${ testInfo . fixtureName } "` ) ;
311+ console . log ( `🔑 Test ID: ${ testInfo . testId } ` ) ;
312+ console . log ( `⏰ Start time: ${ new Date ( testInfo . startTime ) . toISOString ( ) } ` ) ;
313+
314+ if ( attemptNumber > 1 ) {
315+ console . log ( `⚠️ QUARANTINE MODE: Retry attempt ${ attemptNumber } for failed test "${ testInfo . testName } "` ) ;
316+ }
317+
247318 if ( ! componentFolder . includes ( 'accessibility' ) ) {
248319 const [ width , height ] = DEFAULT_BROWSER_SIZE ;
249320 await t . resizeWindow ( width , height ) ;
@@ -253,17 +324,79 @@ createTestCafe(TESTCAFE_CONFIG)
253324 await addShadowRootTree ( t ) ;
254325 }
255326
256- if ( args . theme ) {
257- await changeTheme ( t , args . theme ) ;
327+ const themeName = args . theme || 'generic.light' ;
328+ console . log ( `🎨 [Attempt ${ attemptNumber } ] Setting theme: ${ themeName } ` ) ;
329+
330+ const currentTheme = await ClientFunction ( ( ) => {
331+ try {
332+ return ( window as any ) . DevExpress ?. ui ?. themes ?. current ( ) ;
333+ } catch ( e ) {
334+ return 'Theme API not available' ;
335+ }
336+ } ) . with ( { boundTestRun : t } ) ( ) ;
337+
338+ console . log ( `✅ [Attempt ${ attemptNumber } ] Current theme before change: ${ currentTheme } ` ) ;
339+
340+ try {
341+ if ( currentTheme !== themeName ) {
342+ await changeTheme ( t , themeName ) ;
343+ }
344+
345+ const newTheme = await ClientFunction ( ( ) => {
346+ try {
347+ return ( window as any ) . DevExpress ?. ui ?. themes ?. current ( ) ;
348+ } catch ( e ) {
349+ return 'Theme API not available' ;
350+ }
351+ } ) . with ( { boundTestRun : t } ) ( ) ;
352+
353+ console . log ( `🎯 [Attempt ${ attemptNumber } ] Theme after change: ${ newTheme } ` ) ;
354+ } catch ( error ) {
355+ console . error ( `❌ [Attempt ${ attemptNumber } ] Error setting theme:` , error ) ;
258356 }
259357 } ,
260- after : async ( ) => {
261- await testPageUtils . clearTestPage ( ) ;
358+
359+ after : async ( t : TestController ) => {
360+ const testInfo = t . ctx . testInfo as TestInfo ;
361+
362+ if ( testInfo ) {
363+ const endTime = Date . now ( ) ;
364+ const durationMs = testInfo . startTime ? endTime - testInfo . startTime : 0 ;
365+ const durationSec = ( durationMs / 1000 ) . toFixed ( 2 ) ;
366+ console . log ( `🏁 [Attempt ${ testInfo . attemptNumber } ] Test completed: "${ testInfo . testName } " in ${ durationSec } s (${ durationMs } ms)` ) ;
367+ console . log ( `🔑 [Attempt ${ testInfo . attemptNumber } ] Test ID: ${ testInfo . testId } ` ) ;
368+ console . log ( `🧹 [Attempt ${ testInfo . attemptNumber } ] After hook - clearing page` ) ;
369+ try {
370+ await testPageUtils . clearTestPage ( t ) ;
371+ console . log ( `✅ ${ testInfo ? `[Attempt ${ testInfo . attemptNumber } ]` : '' } Page cleared successfully` ) ;
372+ } catch ( error ) {
373+ console . error ( `❌ ${ testInfo ? `[Attempt ${ testInfo . attemptNumber } ]` : '' } Error clearing page:` , error ) ;
374+ }
375+ } else {
376+ console . log ( `🧹 After hook - clearing page (test info not available)` ) ;
377+ }
262378 } ,
263379 } ,
380+
381+ // fixture: {
382+ // afterEach: async (t: TestController) => {
383+ // const testInfo = t.ctx.testInfo as TestInfo;
384+ // const testKey = t.ctx.testKey as string;
385+
386+ // if (testInfo && testKey) {
387+ // console.log(`🏁 Test completed: ${testInfo.testId} (Final attempt: ${testInfo.attemptNumber})`);
388+
389+ // if (testInfo.attemptNumber > 1) {
390+ // console.log(`🎯 QUARANTINE RESULT: Test ${testInfo.testId} required ${testInfo.attemptNumber} attempts to pass`);
391+ // }
392+
393+ // testAttempts.delete(testKey);
394+ // }
395+ // }
396+ // }
264397 } ,
265- } ;
266-
398+ } ;
399+
267400 if ( args . browsers === 'chrome:docker' ) {
268401 runOptions . disableScreenshots = true ;
269402 }
0 commit comments