UNPKG

chimpy

Version:

Develop acceptance tests & end-to-end tests with realtime feedback.

210 lines (200 loc) 8.29 kB
// jest.dontMock('../lib/process-helper'); describe('process-helper', () => { describe('start', () => { it('spawns a child, calls the callback and returns the child', () => { const processHelper = require('../lib/process-helper.js'); const child = {}; const mockedSpawn = jest.spyOn(processHelper, "spawn"); mockedSpawn.mockReturnValue(child); const options = {}; const callback = jest.fn(); const ret = processHelper.start(options, callback); expect(ret).toBe(child); expect(callback.mock.calls.length).toBe(1); expect(callback.mock.calls[0][0]).toBeFalsy(); mockedSpawn.mockRestore(); }); it('waits for message if waitForMessage is provided and delegates the callback as is', () => { const processHelper = require('../lib/process-helper.js'); const cp = require('child_process'); const child = {}; cp.spawn = jest.fn().mockReturnValue(child); const mockedSpawn = jest.spyOn(processHelper, "spawn"); mockedSpawn.mockImplementation(() => {}); const mockedWaitForMessage = jest.spyOn(processHelper, "waitForMessage"); mockedWaitForMessage.mockImplementation(function (options, child, callback) { callback.apply(this, [1, 2, 3, 4]); }); const options = { waitForMessage: 'not null' }; const callback = jest.fn(); const ret = processHelper.start(options, callback); expect(processHelper.waitForMessage.mock.calls.length).toBe(1); expect(callback.mock.calls.length).toBe(1); expect(callback.mock.calls[0]).toEqual([1, 2, 3, 4]); mockedSpawn.mockRestore(); mockedWaitForMessage.mockRestore(); }); }); describe('spawn', () => { it('calls spawn with the binary and args and returns the child process', () => { const cp = require('child_process'); const processHelper = require('../lib/process-helper.js'); processHelper.logOutputs = jest.fn(); const child = {}; cp.spawn = jest.fn().mockReturnValue(child); const options = { bin: '/someBinary', args: ['bunch', 'of', 'args'] }; const ret = processHelper.spawn(options); expect(cp.spawn.mock.calls.length).toBe(1); expect(cp.spawn.mock.calls[0][0]).toBe(options.bin); expect(cp.spawn.mock.calls[0][1]).toBe(options.args); expect(ret).toBe(child); }); it('logs the outputs of the child process', () => { let cp = require('child_process'), processHelper = require('../lib/process-helper.js'); processHelper.logOutputs = jest.fn(); const child = {}; spyOn(cp, 'spawn').and.returnValue(child); const options = { prefix: 'hey bear' }; const ret = processHelper.spawn(options); expect(processHelper.logOutputs.mock.calls.length).toBe(1); expect(processHelper.logOutputs.mock.calls[0][0]).toBe(options.prefix); expect(processHelper.logOutputs.mock.calls[0][1]).toBe(child); }); }); describe('logOutputs', () => { it('logs the output of the child process stderr events', () => { let log = require('../lib/log.js'), processHelper = require('../lib/process-helper.js'); log.debug = jest.fn(); const child = { stdout: { on: jest.fn().mockImplementation((event, eventTrigger) => { eventTrigger('blah'); expect(event).toBe('data'); expect(log.debug.mock.calls.length).toBe(1); expect(log.debug.mock.calls[0][0]).toBe('[chimp][prefix.stdout]'); expect(log.debug.mock.calls[0][1]).toBe('blah'); }) }, stderr: { on: jest.fn().mockImplementation((event, eventTrigger) => { eventTrigger('blah blah'); expect(event).toBe('data'); expect(log.debug.mock.calls.length).toBe(2); expect(log.debug.mock.calls[1][0]).toBe('[chimp][prefix.stderr]'); expect(log.debug.mock.calls[1][1]).toBe('blah blah'); }) } }; processHelper.logOutputs('prefix', child); }); }); describe('waitForMessage', () => { it('removes the listener if the success message is seen and calls the callback', () => { const processHelper = require('../lib/process-helper.js'); const callback = jest.fn(); const options = { prefix: '[apollo]', waitForMessage: 'we have lift off' }; let eventToBeRemovedStdOut = false; let eventToBeRemovedStdErr = false; const child = { stdout: { on: jest.fn().mockImplementation((event, eventTrigger) => { eventToBeRemovedStdOut = eventTrigger; eventTrigger('Huston, we have lift off!'); }), removeListener: jest.fn() }, stderr: { on: jest.fn().mockImplementation((event, eventTrigger) => { eventToBeRemovedStdErr = eventTrigger; eventTrigger('Huston, we have lift off!'); }), removeListener: jest.fn() } }; processHelper.waitForMessage(options, child, callback); expect(child.stdout.removeListener.mock.calls.length).toBe(1); expect(child.stdout.removeListener.mock.calls[0][0]).toBe('data'); expect(child.stdout.removeListener.mock.calls[0][1]).toBe(eventToBeRemovedStdOut); expect(child.stderr.removeListener.mock.calls.length).toBe(1); expect(child.stderr.removeListener.mock.calls[0][0]).toBe('data'); expect(child.stderr.removeListener.mock.calls[0][1]).toBe(eventToBeRemovedStdErr); expect(callback.mock.calls.length).toBe(2); expect(callback.mock.calls[0][0]).toBeFalsy(); expect(callback.mock.calls[1][0]).toBeFalsy(); }); it('calls back with an error if the error message is seen', () => { const processHelper = require('../lib/process-helper.js'); const callback = jest.fn(); const options = { prefix: '[apollo]', waitForMessage: 'not empty', errorMessage: 'engine failure' }; const eventToBeRemoved = false; const child = { stdout: { on: jest.fn().mockImplementation((event, eventTrigger) => { eventTrigger('Huston, we have a problem - engine failure!'); }) }, stderr: { on: jest.fn().mockImplementation((event, eventTrigger) => { eventTrigger('Huston, we have a problem - engine failure!'); }) } }; processHelper.waitForMessage(options, child, callback); expect(callback.mock.calls.length).toBe(2); expect(callback.mock.calls[0][0]).toBe('Huston, we have a problem - engine failure!'); expect(callback.mock.calls[1][0]).toBe('Huston, we have a problem - engine failure!'); }); }); describe('kill', () => { it('kills the provided process, sets it to null and calls the callback when the process is dead', () => { const processHelper = require('../lib/process-helper.js'); process.kill = jest.fn().mockImplementation(() => { // the first call checks if the process exists // the second call is the actual kill // subsequent calls are checking if the process exists // it takes 3 calls to go through all the execution paths for this SUT if (process.kill.mock.calls.length === 4) { throw { code: 'ESRCH' }; } }); const options = { child: { pid: 1234 } }; const callback = jest.fn(); jest.useFakeTimers(); processHelper.kill(options, callback); jest.runAllTimers(); expect(process.kill.mock.calls.length).toBe(4); expect(process.kill.mock.calls[0][0]).toEqual(1234); expect(process.kill.mock.calls[0][1]).toBe(0); expect(process.kill.mock.calls[1][1]).toBe('SIGTERM'); expect(process.kill.mock.calls[2][0]).toEqual(1234); expect(process.kill.mock.calls[2][1]).toEqual(0); expect(process.kill.mock.calls[3][0]).toEqual(1234); expect(process.kill.mock.calls[3][1]).toEqual(0); expect(options.child).toBe(null); expect(callback.mock.calls.length).toBe(1); expect(callback.mock.calls[0][0]).toBeFalsy(); }); }); });