UNPKG

adcutil

Version:

Utilities tools for Askia Design Control

166 lines (151 loc) 6.55 kB
describe('InteractiveADXShell', function () { var childProcess = require('child_process'), common = require('../../app/common/common.js'), pathHelper = require('path'), util = require('util'), EventEmitter = require('events').EventEmitter, spies = {}, InteractiveADXShell; function StandardIO() { EventEmitter.call(this); } util.inherits(StandardIO, EventEmitter); function ChildProcessFake() { var self = this; self.stdin = { write : function () {} }; self.stdout = new StandardIO(); self.stderr = new StandardIO(); } beforeEach(function () { // Clean the cache, obtain a fresh instance of the module each time var moduleKey = require.resolve('../../app/common/InteractiveADXShell.js'); delete require.cache[moduleKey]; InteractiveADXShell = require('../../app/common/InteractiveADXShell.js').InteractiveADXShell; // Court-circuit the access of the child process spies.spawn = spyOn(childProcess, 'spawn').andCallFake(function () { return new ChildProcessFake(); }); // CWD spyOn(process, 'cwd').andReturn(''); }); describe('#constructor', function () { it("save the `path` arg in #path", function () { var adxShell = new InteractiveADXShell('/adc/path'); expect(adxShell.path).toEqual('/adc/path'); }); }); describe('#exec', function () { it("should spawn the ADXShell process with the `interactive` command", function () { var adxShell = new InteractiveADXShell('/adc/path'); adxShell.exec(''); var processPath = '.\\' + common.ADC_UNIT_PROCESS_NAME; var processArgs = [ 'interactive', '/adc/path' ]; var processOptions = { cwd : pathHelper.join(pathHelper.resolve(__dirname, '../../'), common.ADC_UNIT_DIR_PATH), env : process.env }; expect(spies.spawn).toHaveBeenCalledWith(processPath, processArgs, processOptions); }); it("should not call spawn twice when the ADXShell process was already initialized", function () { var adxShell = new InteractiveADXShell('/adc/path'); var callCount = 0; spies.spawn.andCallFake(function () { callCount++; return new ChildProcessFake(); }); adxShell.exec(''); adxShell.exec(''); expect(callCount).toBe(1); }); it("should send the command in the standard input of the process", function () { var writeData, mock; spies.spawn.andCallFake(function () { mock = new ChildProcessFake(); mock.stdin.write = function (data) { writeData = data; }; return mock; }); var adxShell = new InteractiveADXShell('/adc/path'); adxShell.exec('this is the command'); mock.stdout.emit('data', 'first data'); expect(writeData).toBe('this is the command\n'); }); [{ name : 'standard output', prop : 'stdout' }, { name : 'standard error', prop : 'stderr' }].forEach(function (obj) { it("should read in the " + obj.name + " of the process", function () { var mock; spies.spawn.andCallFake(function () { mock = new ChildProcessFake(); return mock; }); var adxShell = new InteractiveADXShell('/adc/path'); adxShell.exec('hello'); expect(mock[obj.prop].listeners('data').length).toEqual(1); }); it("should call the callback with the data of the " + obj.name + " of the process when it receive a message starting with [ADXShell:End]", function () { var stub, result; spies.spawn.andCallFake(function () { stub = new ChildProcessFake(); return stub; }); var adxShell = new InteractiveADXShell('/adc/path'); adxShell.exec('hello', function (err, data) { if (obj.prop === 'stdout') { result = data; } else { result = err.message; } }); if (obj.prop === 'stdout') { stub[obj.prop].emit('data', "first call"); } stub[obj.prop].emit('data', "process"); stub[obj.prop].emit('data', " result"); stub[obj.prop].emit('data', "\n Hello World!\n[ADXShell:End]"); expect(result).toBe('process result\n Hello World!'); }); it("should remove the listener after data was emit via the " + obj.name + " of the process", function () { var mock; spies.spawn.andCallFake(function () { mock = new ChildProcessFake(); return mock; }); var adxShell = new InteractiveADXShell('/adc/path'); adxShell.exec('hello'); if (obj.prop === 'stdout') { mock[obj.prop].emit('data', "first call"); } mock[obj.prop].emit('data', "process result"); mock[obj.prop].emit('data', "[ADXShell:End]"); expect(mock.stdout.listeners('data').length).toEqual(0); expect(mock.stderr.listeners('data').length).toEqual(0); }); }); it("should ignore the first output", function () { var stub, result = ''; spies.spawn.andCallFake(function () { stub = new ChildProcessFake(); return stub; }); var adxShell = new InteractiveADXShell('/adc/path'); adxShell.exec('hello', function (err, data) { result += data; }); stub.stdout.emit('data', "first call"); stub.stdout.emit('data', "second call"); stub.stdout.emit('data', "\r\n[ADXShell:End]"); expect(result).toBe('second call'); }); }); });