🏡 index : quine-global/webdriverio.git

import { asyncExitHook, gracefulExit } from 'exit-hook'

import logger from '@wdio/logger'
import Runner from '@wdio/runner'
import type { Workers } from '@wdio/types'

import { SHUTDOWN_TIMEOUT } from './constants.js'

const log = logger('@wdio/local-runner')

/**
 * ToDo(Christian): remove when @wdio/runner got typed
 */
interface RunnerInterface extends NodeJS.EventEmitter {
    sigintWasCalled: boolean
    [key: string]: unknown
}

/**
 * send ready event to testrunner to start receive command messages
 */
if (typeof process.send === 'function') {
    process.send(<Workers.WorkerMessage>{
        name: 'ready',
        origin: 'worker'
    })
}

export const runner = new Runner() as unknown as RunnerInterface
runner.on('exit', (code = 0) => gracefulExit(code))
runner.on('error', ({ name, message, stack }) => process.send!({
    origin: 'worker',
    name: 'error',
    content: { name, message, stack }
}))

process.on('message', (m: Workers.WorkerCommand) => {
    if (!m || !m.command || !runner[m.command] || typeof runner[m.command] !== 'function') {
        return
    }

    log.info(`Run worker command: ${m.command}`)
    ;(runner[m.command] as Function)(m).then(
        (result: unknown) => process.send!({
            origin: 'worker',
            name: 'finishedCommand',
            content: {
                command: m.command,
                result
            }
        }),
        (e: Error) => {
            log.error(`Failed launching test session: ${e.stack}`)
            setTimeout(() => process.exit(1), 10)
        }
    )
})

process.once('SIGINT', () => {
    runner.sigintWasCalled = true
    gracefulExit(130)
})

/**
 * registers an asynchronous exit hook to allow graceful shutdown
 * if the process is being terminated due to SIGINT, delays exit for SHUTDOWN_TIMEOUT ms to allow cleanup
 * otherwise, exits immediately without delay
 */
asyncExitHook(
    async () => {
        if (runner.sigintWasCalled) {
            log.info(`Received SIGINT, giving process ${SHUTDOWN_TIMEOUT}ms to shutdown gracefully`)

            return await new Promise(res => setTimeout(res, SHUTDOWN_TIMEOUT))
        }
    }, {
        wait: SHUTDOWN_TIMEOUT
    }
)