concurrently
Version:
Run commands concurrently
97 lines (96 loc) • 4.18 kB
JavaScript
import { Writable } from 'node:stream';
import { beforeEach, describe, expect, it } from 'vitest';
import { createMockInstance } from './__fixtures__/create-mock-instance.js';
import { createFakeCloseEvent, FakeCommand } from './__fixtures__/fake-command.js';
import { OutputWriter } from './output-writer.js';
let outputStream;
let commands;
function createWriter(overrides) {
const options = {
outputStream,
group: false,
commands,
...overrides,
};
return new OutputWriter(options);
}
function closeCommand(command) {
command.state = 'exited';
command.close.next(createFakeCloseEvent({ command, index: command.index }));
}
beforeEach(() => {
outputStream = createMockInstance(Writable);
commands = [
new FakeCommand('', undefined, 0),
new FakeCommand('', undefined, 1),
new FakeCommand('', undefined, 2),
];
});
it('throws if outputStream already is in errored state', () => {
Object.defineProperty(outputStream, 'errored', { value: new Error('test') });
expect(() => createWriter()).toThrow(TypeError);
});
describe('#write()', () => {
it('throws if outputStream has errored', () => {
const writer = createWriter();
Object.defineProperty(outputStream, 'errored', { value: new Error('test') });
expect(() => writer.write(commands[0], 'hello')).toThrow(TypeError);
});
describe('with group=false', () => {
it('writes instantly', () => {
const writer = createWriter({ group: false });
writer.write(commands[2], 'hello');
expect(outputStream.write).toHaveBeenCalledExactlyOnceWith('hello');
});
});
describe('with group=true', () => {
it('writes for null commands', () => {
const writer = createWriter({ group: true });
writer.write(undefined, 'hello');
expect(outputStream.write).toHaveBeenCalledExactlyOnceWith('hello');
});
it('does not write instantly for non-active command', () => {
const writer = createWriter({ group: true });
writer.write(commands[2], 'hello');
expect(outputStream.write).toHaveBeenCalledTimes(0);
expect(writer.buffers[2]).toEqual(['hello']);
});
it('write instantly for active command', () => {
const writer = createWriter({ group: true });
writer.write(commands[0], 'hello');
expect(outputStream.write).toHaveBeenCalledExactlyOnceWith('hello');
});
it('does not wait for write from next command to flush', () => {
const writer = createWriter({ group: true });
writer.write(commands[1], 'hello');
writer.write(commands[1], 'foo bar');
expect(outputStream.write).toHaveBeenCalledTimes(0);
closeCommand(commands[0]);
expect(outputStream.write).toHaveBeenCalledTimes(2);
expect(writer.activeCommandIndex).toBe(1);
outputStream.write.mockClear();
writer.write(commands[1], 'blah');
expect(outputStream.write).toHaveBeenCalledTimes(1);
});
it('does not flush for non-active command', () => {
const writer = createWriter({ group: true });
writer.write(commands[1], 'hello');
writer.write(commands[1], 'foo bar');
expect(outputStream.write).toHaveBeenCalledTimes(0);
closeCommand(commands[1]);
expect(outputStream.write).toHaveBeenCalledTimes(0);
closeCommand(commands[0]);
expect(outputStream.write).toHaveBeenCalledTimes(2);
});
it('flushes multiple commands at a time if necessary', () => {
const writer = createWriter({ group: true });
writer.write(commands[2], 'hello');
closeCommand(commands[1]);
closeCommand(commands[2]);
expect(outputStream.write).toHaveBeenCalledTimes(0);
closeCommand(commands[0]);
expect(outputStream.write).toHaveBeenCalledExactlyOnceWith('hello');
expect(writer.activeCommandIndex).toBe(2);
});
});
});