spawn(options) {
        options = options || {};

        return new Promise((resolve, reject) => {
            this.spawnedCommand = cp.spawn(this.cliPath, this.command.split(' '), {
                env: Object.assign({}, process.env, {
                    NODE_ENV: options.environment || 'production'
                }, options.env || {}),
                cwd: this.dir,
                stdio: 'pipe'
            });

            // Cleanup spawned processes if our process is killed
            const cleanup = this.cleanup.bind(this);
            process.on('exit', cleanup.bind(this));

            // Buffer up the output so the polling timer can check it
            let stdoutBuffer = '';
            let stderrBuffer = '';
            this.spawnedCommand.stdout.on('data', (d) => {
                const chunk = d.toString();

                if (options.stdin) {
                    const stdin = find(options.stdin, obj => obj.when.test(chunk));

                    if (stdin) {
                        this.spawnedCommand.stdin.write(`${stdin.write}\n`);
                    }
                }

                stdoutBuffer += chunk;
            });
            this.spawnedCommand.stderr.on('data', (d) => {
                stderrBuffer += d.toString();
            });

            // Handle errors from the child process
            this.spawnedCommand.stdout.on('error', reject);
            this.spawnedCommand.stderr.on('error', reject);
            this.spawnedCommand.on('error', reject);
            this.spawnedCommand.on('exit', () => {
                process.removeListener('exit', cleanup);
                this.cleanup();

                if (options.rejectOnExit) {
                    const message = `Command 'ghost ${this.command}' exited before matching the checkOutput function.\n` +
                        `stdout: ${stdoutBuffer} \nstderr: ${stderrBuffer}`;
                    reject(new Error(message));
                    return;
                }

                resolve({
                    stdout: stdoutBuffer,
                    stderr: stderrBuffer,
                    dir: this.dir
                });
            });

            // Poll periodically to check the results
            this.pollOutput = setInterval(() => {
                if (stderrBuffer.length > 0 && options.failOnStderr) {
                    process.removeListener('exit', cleanup);
                    this.cleanup();
                    const error = new Error(`'${this.command}' printed to stderr with failOnStderr enabled:\n`);
                    error.message += `cwd: ${this.dir} \nstdout: ${stdoutBuffer} \nstderr: ${stderrBuffer};`;
                    reject(error);
                }
                const passed = options.checkOutput(stdoutBuffer, stderrBuffer, this.dir);
                if (passed) {
                    process.removeListener('exit', cleanup);
                    this.cleanup();
                    resolve();
                }
            }, options.pollInterval || 50);

            // Ensure the test fails if we don't pass the test after a while
            const timeout = options.timeout || (process.env.CI ? 5 * 60000 : 3 * 60000);

            this.fallbackTimeout = setTimeout(() => {
                process.removeListener('exit', cleanup);
                this.cleanup();
                let message = `Timeout of ${(timeout / 1000) / 60} minutes exceeded for spawned command: ${this.command}\n`;

                message += `stdout: ${stdoutBuffer} \nstderr: ${stderrBuffer}`;
                reject(new Error(message));
            }, timeout);
        });
    }
/**
     * Invoke the command and poll the output every options.pollInterval. Useful for commands that
     * have a definitely completion (i.e. 'build', not 'serve'). Each poll of the output will run the
     * supplied options.checkOutput method, passing in the stdout and stderr buffers. If the
     * options.checkOutput method returns a truthy value, the returned promise will resolve.
     * Otherwise, it will continue to poll the output until options.timeout elapses, after which the
     * returned promsie will reject.
     *
     * @param {Boolean} options.failOnStderr Should any output to stderr result in a rejected promise?
     * @param {Function} options.checkOutput A function invoked with the stdout and stderr buffers of the invoked
     *                            command, and should return true if the output passes
     *
     * @return {Promise} Promise for the command
     */
Invoke the command and poll the output every options.pollInterval. Useful for commands that
have a definitely completion . Each poll of the output will run the
supplied options.checkOutput method, passing in the stdout and stderr buffers. If the
options.checkOutput method returns a truthy value, the returned promise will resolve.
Otherwise, it will continue to poll the output until options.timeout elapses, after which the
returned promsie will reject.

@param {Boolean} options.failOnStderr Should any output to stderr result in a rejected promise.
@param {Function} options.checkOutput A function invoked with the stdout and stderr buffers of the invoked
command, and should return true if the output passes

@return {Promise} Promise for the command
Invoke the command and poll the output every options . pollInterval . Useful for commands that have a definitely completion . Each poll of the output will run the supplied options . checkOutput method passing in the stdout and stderr buffers . If the options . checkOutput method returns a truthy value the returned promise will resolve . Otherwise it will continue to poll the output until options . timeout elapses after which the returned promsie will reject . @param { Boolean } options . failOnStderr Should any output to stderr result in a rejected promise . @param { Function } options . checkOutput A function invoked with the stdout and stderr buffers of the invoked command and should return true if the output passes @return { Promise } Promise for the command
spawn(options) {
        options = options || {};
        return new Promise((resolve, reject) => {
            this.spawnedCommand = cp.spawn(this.cliPath, this.command.split(' '), {
                env: Object.assign({}, process.env, {
                    NODE_ENV: options.environment || 'production'
                }, options.env || {}),
                cwd: this.dir,
                stdio: 'pipe'
            });
            const cleanup = this.cleanup.bind(this);
            process.on('exit', cleanup.bind(this));
            let stdoutBuffer = '';
            let stderrBuffer = '';
            this.spawnedCommand.stdout.on('data', (d) => {
                const chunk = d.toString();
                if (options.stdin) {
                    const stdin = find(options.stdin, obj => obj.when.test(chunk));
                    if (stdin) {
                        this.spawnedCommand.stdin.write(`${stdin.write}\n`);
                    }
                }
                stdoutBuffer += chunk;
            });
            this.spawnedCommand.stderr.on('data', (d) => {
                stderrBuffer += d.toString();
            });
            this.spawnedCommand.stdout.on('error', reject);
            this.spawnedCommand.stderr.on('error', reject);
            this.spawnedCommand.on('error', reject);
            this.spawnedCommand.on('exit', () => {
                process.removeListener('exit', cleanup);
                this.cleanup();
                if (options.rejectOnExit) {
                    const message = `Command 'ghost ${this.command}' exited before matching the checkOutput function.\n` +
                        `stdout: ${stdoutBuffer} \nstderr: ${stderrBuffer}`;
                    reject(new Error(message));
                    return;
                }
                resolve({
                    stdout: stdoutBuffer,
                    stderr: stderrBuffer,
                    dir: this.dir
                });
            });
            this.pollOutput = setInterval(() => {
                if (stderrBuffer.length > 0 && options.failOnStderr) {
                    process.removeListener('exit', cleanup);
                    this.cleanup();
                    const error = new Error(`'${this.command}' printed to stderr with failOnStderr enabled:\n`);
                    error.message += `cwd: ${this.dir} \nstdout: ${stdoutBuffer} \nstderr: ${stderrBuffer};`;
                    reject(error);
                }
                const passed = options.checkOutput(stdoutBuffer, stderrBuffer, this.dir);
                if (passed) {
                    process.removeListener('exit', cleanup);
                    this.cleanup();
                    resolve();
                }
            }, options.pollInterval || 50);
            const timeout = options.timeout || (process.env.CI ? 5 * 60000 : 3 * 60000);
            this.fallbackTimeout = setTimeout(() => {
                process.removeListener('exit', cleanup);
                this.cleanup();
                let message = `Timeout of ${(timeout / 1000) / 60} minutes exceeded for spawned command: ${this.command}\n`;
                message += `stdout: ${stdoutBuffer} \nstderr: ${stderrBuffer}`;
                reject(new Error(message));
            }, timeout);
        });
    }
spawn ( options ) { options = options || { } ; return new Promise ( ( resolve , reject ) => { this . spawnedCommand = cp . spawn ( this . cliPath , this . command . split ( ' ' ) , { env : Object . assign ( { } , process . env , { NODE_ENV : options . environment || 'production' } , options . env || { } ) , cwd : this . dir , stdio : 'pipe' } ) ; const cleanup = this . cleanup . bind ( this ) ; process . on ( 'exit' , cleanup . bind ( this ) ) ; let stdoutBuffer = '' ; let stderrBuffer = '' ; this . spawnedCommand . stdout . on ( 'data' , ( d ) => { const chunk = d . toString ( ) ; if ( options . stdin ) { const stdin = find ( options . stdin , obj => obj . when . test ( chunk ) ) ; if ( stdin ) { this . spawnedCommand . stdin . write ( ` ${ stdin . write } \n ` ) ; } } stdoutBuffer += chunk ; } ) ; this . spawnedCommand . stderr . on ( 'data' , ( d ) => { stderrBuffer += d . toString ( ) ; } ) ; this . spawnedCommand . stdout . on ( 'error' , reject ) ; this . spawnedCommand . stderr . on ( 'error' , reject ) ; this . spawnedCommand . on ( 'error' , reject ) ; this . spawnedCommand . on ( 'exit' , ( ) => { process . removeListener ( 'exit' , cleanup ) ; this . cleanup ( ) ; if ( options . rejectOnExit ) { const message = ` ${ this . command } \n ` + ` ${ stdoutBuffer } \n ${ stderrBuffer } ` ; reject ( new Error ( message ) ) ; return ; } resolve ( { stdout : stdoutBuffer , stderr : stderrBuffer , dir : this . dir } ) ; } ) ; this . pollOutput = setInterval ( ( ) => { if ( stderrBuffer . length > 0 && options . failOnStderr ) { process . removeListener ( 'exit' , cleanup ) ; this . cleanup ( ) ; const error = new Error ( ` ${ this . command } \n ` ) ; error . message += ` ${ this . dir } \n ${ stdoutBuffer } \n ${ stderrBuffer } ` ; reject ( error ) ; } const passed = options . checkOutput ( stdoutBuffer , stderrBuffer , this . dir ) ; if ( passed ) { process . removeListener ( 'exit' , cleanup ) ; this . cleanup ( ) ; resolve ( ) ; } } , options . pollInterval || 50 ) ; const timeout = options . timeout || ( process . env . CI ? 5 * 60000 : 3 * 60000 ) ; this . fallbackTimeout = setTimeout ( ( ) => { process . removeListener ( 'exit' , cleanup ) ; this . cleanup ( ) ; let message = ` ${ ( timeout / 1000 ) / 60 } ${ this . command } \n ` ; message += ` ${ stdoutBuffer } \n ${ stderrBuffer } ` ; reject ( new Error ( message ) ) ; } , timeout ) ; } ) ; }
Invoke the command and poll the output every options.pollInterval.
Invoke the command and poll the output every options . pollInterval .
// Cleanup spawned processes if our process is killed // Buffer up the output so the polling timer can check it // Handle errors from the child process // Poll periodically to check the results // Ensure the test fails if we don't pass the test after a while