UNPKG

concurrently

Version:
99 lines (98 loc) 4.5 kB
import { beforeEach, describe, expect, it, vi } from 'vitest'; import { createMockInstance } from '../__fixtures__/create-mock-instance.js'; import { createFakeCloseEvent, createFakeProcess, FakeCommand, } from '../__fixtures__/fake-command.js'; import { Logger } from '../logger.js'; import { KillOthers } from './kill-others.js'; let commands; let logger; let abortController; beforeEach(() => { commands = [new FakeCommand(), new FakeCommand()]; logger = createMockInstance(Logger); abortController = new AbortController(); }); const createWithConditions = (conditions, opts) => new KillOthers({ logger, abortController, conditions, killSignal: undefined, ...opts, }); const assignProcess = (command) => { const process = createFakeProcess(1); command.pid = process.pid; command.process = process; }; const unassignProcess = (command) => { command.pid = undefined; command.process = undefined; }; it('returns same commands', () => { expect(createWithConditions(['success']).handle(commands)).toMatchObject({ commands }); expect(createWithConditions(['failure']).handle(commands)).toMatchObject({ commands }); }); it('does not kill others if condition does not match', () => { createWithConditions(['failure']).handle(commands); assignProcess(commands[1]); commands[0].close.next(createFakeCloseEvent({ exitCode: 0 })); expect(logger.logGlobalEvent).not.toHaveBeenCalled(); expect(commands[0].kill).not.toHaveBeenCalled(); expect(commands[1].kill).not.toHaveBeenCalled(); }); describe.each(['success', 'failure'])('on %s', (condition) => { const exitCode = condition === 'success' ? 0 : 1; const inversedCode = exitCode === 1 ? 0 : 1; it('kills other processes', () => { createWithConditions([condition]).handle(commands); assignProcess(commands[1]); commands[0].close.next(createFakeCloseEvent({ exitCode })); expect(logger.logGlobalEvent).toHaveBeenCalledExactlyOnceWith('Sending SIGTERM to other processes..'); expect(commands[0].kill).not.toHaveBeenCalled(); expect(commands[1].kill).toHaveBeenCalledWith(undefined); }); it('kills other processes, with specified signal', () => { createWithConditions([condition], { killSignal: 'SIGKILL' }).handle(commands); assignProcess(commands[1]); commands[0].close.next(createFakeCloseEvent({ exitCode })); expect(logger.logGlobalEvent).toHaveBeenCalledExactlyOnceWith('Sending SIGKILL to other processes..'); expect(commands[0].kill).not.toHaveBeenCalled(); expect(commands[1].kill).toHaveBeenCalledWith('SIGKILL'); }); it('sends abort signal on condition match', () => { createWithConditions([condition]).handle(commands); commands[0].close.next(createFakeCloseEvent({ exitCode })); expect(abortController.signal.aborted).toBe(true); }); it('does not send abort signal on condition mismatch', () => { createWithConditions([condition]).handle(commands); commands[0].close.next(createFakeCloseEvent({ exitCode: inversedCode })); expect(abortController.signal.aborted).toBe(false); }); }); it('does nothing if called without conditions', () => { createWithConditions([]).handle(commands); commands[0].close.next(createFakeCloseEvent({ exitCode: 0 })); expect(logger.logGlobalEvent).not.toHaveBeenCalled(); expect(commands[0].kill).not.toHaveBeenCalled(); expect(commands[1].kill).not.toHaveBeenCalled(); }); it('does not try to kill processes already dead', () => { createWithConditions(['failure']).handle(commands); commands[0].close.next(createFakeCloseEvent({ exitCode: 1 })); expect(logger.logGlobalEvent).not.toHaveBeenCalled(); expect(commands[0].kill).not.toHaveBeenCalled(); expect(commands[1].kill).not.toHaveBeenCalled(); }); it('force kills misbehaving processes after a timeout', () => { vi.useFakeTimers(); commands.push(new FakeCommand()); createWithConditions(['failure'], { timeoutMs: 500 }).handle(commands); assignProcess(commands[1]); assignProcess(commands[2]); commands[2].kill = vi.fn(() => unassignProcess(commands[2])); commands[0].close.next(createFakeCloseEvent({ exitCode: 1 })); vi.advanceTimersByTime(500); expect(commands[1].kill).toHaveBeenCalledTimes(2); expect(commands[1].kill).toHaveBeenCalledWith('SIGKILL'); expect(commands[2].kill).toHaveBeenCalledTimes(1); });