import { ElementPresence , DEFAULT_WAIT_TIMEOUT_MILLISECONDS } from './Settings' ; import ms from 'ms' ; import { Browser } from '../interface/IBrowser' ; param name param fn param options export const step = ( ... nameOrOptionsOrFn ) => { } ; step . once = ( ... nameOrOptionsOrFn ) => { } ; step . if = ( condition , ... nameOrOptionsOrFn ) => { } ; step . unless = ( condition , ... nameOrOptionsOrFn ) => { } ; step . skip = ( ... nameOrOptionsOrFn ) => { } ; step . recovery = ( ... nameOrOptionsOrFn ) => { } ; step . repeat = ( count , ... nameOrOptionsOrFn ) => { } ; step . while = ( condition , ... nameOrOptionsOrFn ) => { } ; export interface StepBase { ( stepName , options , testFn ) : void ; ( stepName , testFn ) : void ; ( options , testFn ) : void ; ( testFn ) : void ; } export interface StepConditionBase { ( condition , name , options , testFn ) ; ( condition , name , testFn ) ; ( condition , ... optionsOrFn ) ; } export interface StepRepeatableBase { ( count , name , options , testFn ) ; ( count , name , testFn ) ; ( count , ... optionsOrFn ) ; } export interface StepExtended extends StepBase { /**
     * Defines a test step which will run in all iterations assuming the previous step succeeded
     */ once : StepBase ; /**
     * Creates a conditional step, which will only run if the preceeding predicate returns true
     */ if : StepConditionBase ; /**
     * Creates a conditional step, which will only run if the preceeding predicate returns false
     */ unless : StepConditionBase ; /**
     * Creates a conditional step, which will skip this test
     */ skip : StepBase ; /**
     * Creates a recovery step
     */ recovery : StepBase ; /**
     * Creates a repeatable step
     */ repeat : StepRepeatableBase ; /**
     * Creates a while step
     */ while : StepConditionBase ; } export type StepDefinition = ( name : string , fn : TestFn ) => Promise < any > ; export type TestFn = ( this : void , browser : Browser , data ? : any ) => Promise < any > ; export type ConditionFn = ( this : void , browser : Browser ) => boolean | Promise < boolean > ; export type StepOptions = { pending ? : boolean ; once ? : boolean ; predicate ? : ConditionFn ; skip ? : boolean ; waitTimeout ? : string | number ; waitUntil ? : ElementPresence ; tries ? : number ; repeat ? : { count : number ; iteration : number ; } ; stepWhile ? : { predicate : ConditionFn ; } ; } ; export function extractStep ( args ) { if ( args . length === 0 ) throw new Error ( 'Step called with at least one argument' ) ; if ( args . length === 1 ) { return [ 'global' , { } , args [ 0 ] as TestFn ] ; } else if ( args . length === 2 ) { const [ name , fnc ] = args as [ string , TestFn ] ; if ( typeof name === 'string' ) { return [ name , { } , fnc ] ; } const [ options , fn ] = args as [ StepOptions , TestFn ] ; const { waitTimeout , waitUntil , tries } = options ; return [ 'global' , { waitTimeout , waitUntil , tries } , fn ] ; } else if ( args . length === 3 ) { const [ name , options , fn ] = args as [ string , StepOptions , TestFn ] ; const { waitTimeout , waitUntil , tries } = options ; return [ name , { waitTimeout , waitUntil , tries } , fn ] ; } throw new Error ( `Step called with too many arguments` ) ; } /**
 * The `StepFunction` type represents a function to be called as a Test step.
 *
 * - `browser` <[Browser]> the browser
 * - `data` <`T`> (Optional) a row of test data of type <`T`>. Only available when the test is set up using <[suite]>.
 *
 * **Example:**
 *
 * ```
 * const step1: StepFunction = async (browser: Browser) => {
 * 	await browser.click(...)
 * }
 * ```
 */ export type StepFunction < T > = ( driver : Browser , data ? : T ) => Promise < void > ; export type StepRecoveryObject = { [ name ] : { recoveryStep : Step ; loopCount : number ; iteration : number ; } ; } ; /**
 * The `RecoverWith` represents an action which we will do after the recovery step has finished
 * ```
 * RETRY: retry the failed step
 * RESTART: re-run the first step
 * CONTINUE: continue next step
 * ```
 */ export enum RecoverWith { RETRY = 'retry' , RESTART = 'restart' , CONTINUE = 'continue' } internal export type Step = { name : string ; options : Partial < StepOptions > ; fn : TestFn ; subTitle ? : string ; duration ? : number ; prop ? : { recoveryTries ? : number ; skipped ? : boolean ; unexecuted ? : boolean ; passed ? : boolean ; error ? : string ; } ; } ; internal export function normalizeStepOptions ( stepOpts ) { if ( ! stepOpts . waitTimeout ) return stepOpts ; let convertedWaitTimeout = DEFAULT_WAIT_TIMEOUT_MILLISECONDS ; if ( typeof stepOpts . waitTimeout === 'string' ) { convertedWaitTimeout = ms ( stepOpts . waitTimeout ) ; } else { convertedWaitTimeout = stepOpts . waitTimeout ; if ( convertedWaitTimeout <= 0 ) { convertedWaitTimeout = DEFAULT_WAIT_TIMEOUT_MILLISECONDS ; } else if ( convertedWaitTimeout < 1e3 ) { convertedWaitTimeout *= 1e3 ; } } stepOpts . waitTimeout = convertedWaitTimeout ; return stepOpts ; }