import { Suite , Context } from 'mocha' ; import { Application , ApplicationOptions , Logger } from '../../automation' ; export function describeRepeat ( n , description , callback ) { for ( let i = 0 ; i < n ; i ++ ) { describe ( `${ description } (iteration ${ i })` , callback ) ; } } export function itRepeat ( n , description , callback ) { for ( let i = 0 ; i < n ; i ++ ) { it ( `${ description } (iteration ${ i })` , callback ) ; } } param title param callback export function itSkipOnFail ( title , callback ) { it ( title , function ( ) { return Promise . resolve ( ) . then ( ( ) => { return callback . apply ( this , arguments ) ; } ) . catch ( e => { console . warn ( `Test "${ title }" failed but was marked as skip on fail:` , e ) ; this . skip ( ) ; } ) ; } ) ; } export function installAllHandlers ( logger , optionsTransform ? ) { installDiagnosticsHandler ( logger ) ; installAppBeforeHandler ( optionsTransform ) ; installAppAfterHandler ( ) ; } export function installDiagnosticsHandler ( logger , appFn ? ) { before ( async function ( ) { const suiteTitle = this . currentTest ?. parent ?. title ; logger . log ( '' ) ; logger . log ( `>>> Suite start: '${ suiteTitle ?? 'unknown' }' <<<` ) ; logger . log ( '' ) ; } ) ; beforeEach ( async function ( ) { const testTitle = this . currentTest ?. title ; logger . log ( '' ) ; logger . log ( `>>> Test start: '${ testTitle ?? 'unknown' }' <<<` ) ; logger . log ( '' ) ; const app = appFn ?. ( ) ?? this . app ; await app ?. startTracing ( testTitle ?? 'unknown' ) ; } ) ; afterEach ( async function ( ) { const currentTest = this . currentTest ; if ( ! currentTest ) { return ; } const failed = currentTest . state === 'failed' ; const testTitle = currentTest . title ; logger . log ( '' ) ; if ( failed ) { logger . log ( `>>> !!! FAILURE !!! Test end: '${ testTitle }' !!! FAILURE !!! <<<` ) ; } else { logger . log ( `>>> Test end: '${ testTitle }' <<<` ) ; } logger . log ( '' ) ; const app = appFn ?. ( ) ?? this . app ; await app ?. stopTracing ( testTitle . replace ( /[^a-z0-9\-]/ig , '_' ) , failed ) ; } ) ; } function installAppBeforeHandler ( optionsTransform ? ) { before ( async function ( ) { this . app = createApp ( this . defaultOptions , optionsTransform ) ; await this . app . start ( ) ; } ) ; } export function installAppAfterHandler ( appFn ? , joinFn ? ) { after ( async function ( ) { const app = appFn ?. ( ) ?? this . app ; if ( app ) { await app . stop ( ) ; } if ( joinFn ) { await joinFn ( ) ; } } ) ; } export function createApp ( options , optionsTransform ? ) { if ( optionsTransform ) { options = optionsTransform ( { ... options } ) ; } const app = new Application ( { ... options , userDataDir : getRandomUserDataDir ( options ) } ) ; return app ; } export function getRandomUserDataDir ( options ) { const userDataPathSuffix = [ ... Array ( 8 ) ] . map ( ( ) => Math . random ( ) . toString ( 36 ) [ 3 ] ) . join ( '' ) ; return options . userDataDir . concat ( `-${ userDataPathSuffix }` ) ; } export function timeout ( i ) { return new Promise < void > ( resolve => { setTimeout ( ( ) => { resolve ( ) ; } , i ) ; } ) ; } export interface ITask < T > { ( ) : T ; } export async function retry < T > ( task , delay , retries ) { let lastError ; for ( let i = 0 ; i < retries ; i ++ ) { try { return await task ( ) ; } catch ( error ) { lastError = error ; await timeout ( delay ) ; } } throw lastError ; }