import { KarmaEventListener } from "./karma-event-listener" ; import { ChildProcess , SpawnOptions } from "child_process" ; import { Logger } from "../shared/logger" ; const spawn = require ( "cross-spawn" ) ; export class CommandlineProcessHandler { private angularProcess ! : ChildProcess ; public constructor ( private readonly logger , private readonly karmaEventListener ) { } public create ( command , processArguments , options ) { let sConfigPath = '' ; if ( options . env ) { if ( options . env . userKarmaConfigPath ) { sConfigPath = `, env.userKarmaConfigPath: ${ options . env . userKarmaConfigPath }` ; } } this . logger . info ( `Running command: "${ command } ${ processArguments . join ( ' ' ) }"
    with options: {cwd: ${ options . cwd }${ sConfigPath }}` ) ; this . angularProcess = spawn ( command , processArguments , options ) ; this . setupProcessOutputs ( ) ; } public isProcessRunning ( ) { return this . angularProcess !== undefined ; } public killAsync ( ) { return new Promise < void > ( resolve => { const kill = require ( "tree-kill" ) ; kill ( this . angularProcess . pid , "SIGTERM" , ( ) => { this . logger . info ( `Angular exited succesfully` ) ; resolve ( ) ; } ) ; } ) ; } public kill ( ) { const kill = require ( "tree-kill" ) ; kill ( this . angularProcess . pid , "SIGKILL" ) ; } private setupProcessOutputs ( ) { if ( this . angularProcess . stdout ) { this . angularProcess . stdout . on ( "data" , ( data ) => { const { isTestRunning } = this . karmaEventListener ; if ( isTestRunning ) { const regex = new RegExp ( /\(.*?)\m/ , "g" ) ; let log = data . toString ( ) . replace ( regex , "" ) ; if ( log . startsWith ( "e " ) ) { log = "HeadlessChrom" + log ; } this . logger . karmaLogs ( `${ log }` ) ; } else { const sMessage = data . toString ( ) . trim ( ) ; if ( sMessage . includes ( 'Exception' ) || sMessage . includes ( 'error' ) ) { this . logger . error ( sMessage ) ; } } } ) ; } else { this . logger . error ( 'Ng process stdout was not defined: ' + this . angularProcess . stdout ) ; } if ( this . angularProcess . stderr ) { this . angularProcess . stderr . on ( "data" , ( data ) => { this . logger . error ( `stderr: ${ data }` ) ; } ) ; this . angularProcess . stderr . on ( "error" , ( data ) => { this . logger . error ( `stderr: ${ data }` ) ; } ) ; } else { this . logger . error ( 'Ng process stderr was not defined: ' + this . angularProcess . stderr ) ; } this . angularProcess . on ( "error" , ( err ) => { this . logger . error ( `error from ng child process: ${ err }` ) ; } ) ; process . stdin . on ( "close" , async ( ) => { this . kill ( ) ; } ) ; } }