pulsar/spec/buffered-process-spec.js
2022-09-24 23:59:58 -07:00

222 lines
6.9 KiB
JavaScript

/* eslint-disable no-new */
const ChildProcess = require('child_process');
const path = require('path');
const fs = require('fs-plus');
const BufferedProcess = require('../src/buffered-process');
describe('BufferedProcess', function() {
describe('when a bad command is specified', function() {
let [oldOnError] = [];
beforeEach(function() {
oldOnError = window.onerror;
window.onerror = jasmine.createSpy();
});
afterEach(() => (window.onerror = oldOnError));
describe('when there is an error handler specified', function() {
describe('when an error event is emitted by the process', () =>
it('calls the error handler and does not throw an exception', function() {
const bufferedProcess = new BufferedProcess({
command: 'bad-command-nope1',
args: ['nothing'],
options: { shell: false }
});
const errorSpy = jasmine
.createSpy()
.andCallFake(error => error.handle());
bufferedProcess.onWillThrowError(errorSpy);
waitsFor(() => errorSpy.callCount > 0);
runs(function() {
expect(window.onerror).not.toHaveBeenCalled();
expect(errorSpy).toHaveBeenCalled();
expect(errorSpy.mostRecentCall.args[0].error.message).toContain(
'spawn bad-command-nope1 ENOENT'
);
});
}));
describe('when an error is thrown spawning the process', () =>
it('calls the error handler and does not throw an exception', function() {
spyOn(ChildProcess, 'spawn').andCallFake(function() {
const error = new Error('Something is really wrong');
error.code = 'EAGAIN';
throw error;
});
const bufferedProcess = new BufferedProcess({
command: 'ls',
args: [],
options: {}
});
const errorSpy = jasmine
.createSpy()
.andCallFake(error => error.handle());
bufferedProcess.onWillThrowError(errorSpy);
waitsFor(() => errorSpy.callCount > 0);
runs(function() {
expect(window.onerror).not.toHaveBeenCalled();
expect(errorSpy).toHaveBeenCalled();
expect(errorSpy.mostRecentCall.args[0].error.message).toContain(
'Something is really wrong'
);
});
}));
});
describe('when there is not an error handler specified', () =>
it('does throw an exception', function() {
new BufferedProcess({
command: 'bad-command-nope2',
args: ['nothing'],
options: { shell: false }
});
waitsFor(() => window.onerror.callCount > 0);
runs(function() {
expect(window.onerror).toHaveBeenCalled();
expect(window.onerror.mostRecentCall.args[0]).toContain(
'Failed to spawn command `bad-command-nope2`'
);
expect(window.onerror.mostRecentCall.args[4].name).toBe(
'BufferedProcessError'
);
});
}));
});
describe('when autoStart is false', () =>
/**
* TODO: FAILING TEST - This test fails with the following output:
* timeout: timed out after 120000 msec waiting for condition
*/
xit('doesnt start unless start method is called', function() {
let stdout = '';
let stderr = '';
const exitCallback = jasmine.createSpy('exit callback');
const apmProcess = new BufferedProcess({
autoStart: false,
command: atom.packages.getApmPath(),
args: ['-h'],
options: {},
stdout(lines) {
stdout += lines;
},
stderr(lines) {
stderr += lines;
},
exit: exitCallback
});
expect(apmProcess.started).not.toBe(true);
apmProcess.start();
expect(apmProcess.started).toBe(true);
waitsFor(() => exitCallback.callCount === 1);
runs(function() {
expect(stderr).toContain('apm - Atom Package Manager');
expect(stdout).toEqual('');
});
}));
/**
* TODO: FAILING TEST - This test fails with the following output:
* timeout: timed out after 120000 msec waiting for condition
*/
xit('calls the specified stdout, stderr, and exit callbacks', function() {
let stdout = '';
let stderr = '';
const exitCallback = jasmine.createSpy('exit callback');
new BufferedProcess({
command: atom.packages.getApmPath(),
args: ['-h'],
options: {},
stdout(lines) {
stdout += lines;
},
stderr(lines) {
stderr += lines;
},
exit: exitCallback
});
waitsFor(() => exitCallback.callCount === 1);
runs(function() {
expect(stderr).toContain('apm - Atom Package Manager');
expect(stdout).toEqual('');
});
});
it('calls the specified stdout callback with whole lines', function() {
const exitCallback = jasmine.createSpy('exit callback');
const loremPath = require.resolve('./fixtures/lorem.txt');
const content = fs.readFileSync(loremPath).toString();
let stdout = '';
let allLinesEndWithNewline = true;
new BufferedProcess({
command: process.platform === 'win32' ? 'type' : 'cat',
args: [loremPath],
options: {},
stdout(lines) {
const endsWithNewline = lines.charAt(lines.length - 1) === '\n';
if (!endsWithNewline) {
allLinesEndWithNewline = false;
}
stdout += lines;
},
exit: exitCallback
});
waitsFor(() => exitCallback.callCount === 1);
runs(function() {
expect(allLinesEndWithNewline).toBe(true);
expect(stdout).toBe(content);
});
});
describe('on Windows', function() {
let originalPlatform = null;
beforeEach(function() {
// Prevent any commands from actually running and affecting the host
spyOn(ChildProcess, 'spawn');
originalPlatform = process.platform;
Object.defineProperty(process, 'platform', { value: 'win32' });
});
afterEach(() =>
Object.defineProperty(process, 'platform', { value: originalPlatform })
);
describe('when the explorer command is spawned on Windows', () =>
it("doesn't quote arguments of the form /root,C...", function() {
new BufferedProcess({
command: 'explorer.exe',
args: ['/root,C:\\foo']
});
expect(ChildProcess.spawn.argsForCall[0][1][3]).toBe(
'"explorer.exe /root,C:\\foo"'
);
}));
it('spawns the command using a cmd.exe wrapper when options.shell is undefined', function() {
new BufferedProcess({ command: 'dir' });
expect(path.basename(ChildProcess.spawn.argsForCall[0][0])).toBe(
'cmd.exe'
);
expect(ChildProcess.spawn.argsForCall[0][1][0]).toBe('/s');
expect(ChildProcess.spawn.argsForCall[0][1][1]).toBe('/d');
expect(ChildProcess.spawn.argsForCall[0][1][2]).toBe('/c');
expect(ChildProcess.spawn.argsForCall[0][1][3]).toBe('"dir"');
});
});
});