UNPKG

firmament-yargs

Version:

Typescript classes for building CLI node applications

451 lines 18.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); require("reflect-metadata"); const inversify_config_1 = require("../inversify.config"); const chai_1 = require("chai"); const sinon = require("sinon"); const _ = require("lodash"); const path = require("path"); const pathToScripts = path.resolve(__dirname, '../../ts/test/shell-scripts'); const testScript = path.resolve(pathToScripts, 'kitchen-sink.sh'); const testArgs = [ 'arg1', 'arg2' ]; function checkError(error, code = 0, signal = '', stdOut = '', stdErr = '') { chai_1.expect(error).to.exist; chai_1.expect(error.message).to.be.not.empty; checkResult(error.message, code, signal, stdOut, stdErr); } function checkResult(result, code = 0, signal = '', stdOut = '', stdErr = '') { const resultObj = JSON.parse(result); chai_1.expect(resultObj.code).to.equal(code); chai_1.expect(resultObj.signal).to.equal(signal); chai_1.expect(resultObj.stderrText).to.equal(stdErr); chai_1.expect(resultObj.stdoutText).to.equal(stdOut); } function getNewSpawnOptions() { return _.clone({ preSpawnMessage: 'PreSpawn Message', postSpawnMessage: 'PostSpawn Message', suppressDiagnostics: true, suppressStdErr: true, suppressStdOut: true, cacheStdErr: true, cacheStdOut: true, suppressResult: true, suppressFinalError: true, sudoUser: '', sudoPassword: '', forceNullChildProcess: false }); } function getArgArray() { return [ testScript, 'writeToStdOutErrExitWithErrCode', '0', 'writeToStdOut', 'writeToStdErr', ...testArgs ]; } describe('Testing Spawn Creation/Force Error', () => { before(() => { }); after(() => { }); it('should be created by kernel', (done) => { const spawn = inversify_config_1.default.get('Spawn'); chai_1.expect(spawn).to.exist; done(); }); it('should have final callback with error', (done) => { const spawn = inversify_config_1.default.get('Spawn'); spawn.forceError = true; spawn.spawnShellCommandAsync(null, null, null, (err) => { chai_1.expect(err).to.exist; chai_1.expect(err.message).to.equal('force error: spawnShellCommandAsync'); done(); }); }); }); describe('Testing Spawn ', () => { let spawn; let argArray; let spawnOptions; let sinonSandbox; let cbStdOutSpy; let cbStdErrSpy; let cbDiagnosticSpy; function cbStatusMock(err, result) { if (err) { cbStdErrSpy(err, result); } else { cbStdOutSpy(err, result); } } const o = { cbStdOutCall: () => { }, cbStdErrCall: () => { }, cbStatus: () => { }, cbDiagnostic: () => { } }; before(() => { }); after(() => { }); beforeEach(() => { spawn = inversify_config_1.default.get('Spawn'); argArray = getArgArray(); spawnOptions = getNewSpawnOptions(); sinonSandbox = sinon.createSandbox(); cbDiagnosticSpy = sinonSandbox.spy(o, 'cbDiagnostic'); cbStdOutSpy = sinonSandbox.spy(o, 'cbStdOutCall'); cbStdErrSpy = sinonSandbox.spy(o, 'cbStdErrCall'); }); afterEach(() => { sinonSandbox.restore(); }); it('spawnShellCommandAsync: undefined options, exit with code 0', (done) => { argArray[1] = 'exitWithErrCode'; spawnOptions = undefined; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(err).to.not.exist; checkResult(result); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.true; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: null options, exit with code 0', (done) => { argArray[1] = 'exitWithErrCode'; spawnOptions = null; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(err).to.not.exist; checkResult(result); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.true; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: null options, undefined arguments exit with code 0', (done) => { argArray = undefined; spawnOptions = null; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(err).to.exist; chai_1.expect(err.message).to.equal('"file" argument must be a non-empty string'); chai_1.expect(result).to.not.exist; chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.true; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: null options, null arguments exit with code 0', (done) => { argArray = null; spawnOptions = null; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(err).to.exist; chai_1.expect(err.message).to.equal('"file" argument must be a non-empty string'); chai_1.expect(result).to.not.exist; chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.true; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: no result, exit with code 0', (done) => { argArray[1] = 'exitWithErrCode'; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(err).to.not.exist; chai_1.expect(result).to.be.empty; chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: no result, yes diagnostics, exit with code 0', (done) => { argArray[1] = 'exitWithErrCode'; spawnOptions.suppressDiagnostics = false; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(err).to.not.exist; chai_1.expect(result).to.be.empty; chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.true; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: yes result, exit with code 0', (done) => { argArray[1] = 'exitWithErrCode'; spawnOptions.suppressResult = false; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(err).to.not.exist; checkResult(result); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: no result, no finalError, exit with code 3', (done) => { argArray[1] = 'exitWithErrCode'; argArray[2] = '3'; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(err).to.not.exist; chai_1.expect(result).to.be.empty; chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: no result, yes finalError, exit with code 3', (done) => { argArray[1] = 'exitWithErrCode'; argArray[2] = '3'; spawnOptions.suppressFinalError = false; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { checkError(err, 3); chai_1.expect(result).to.be.empty; chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: yes result, yes finalError, exit with code 3', (done) => { argArray[1] = 'exitWithErrCode'; argArray[2] = '3'; spawnOptions.suppressFinalError = false; spawnOptions.suppressResult = false; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { checkError(err, 3); checkResult(result, 3); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: yes result, no finalError, exit with code 3', (done) => { argArray[1] = 'exitWithErrCode'; argArray[2] = '3'; spawnOptions.suppressResult = false; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(err).to.not.exist; checkResult(result, 3); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: yes result, no finalError, yes stdout, yes stderr, exit with code 0', (done) => { spawnOptions.suppressStdOut = false; spawnOptions.suppressStdErr = false; spawnOptions.suppressResult = false; spawn.spawnShellCommandAsync(argArray, spawnOptions, cbStatusMock, (err, result) => { chai_1.expect(err).to.not.exist; const concatArgs = testArgs.join(''); checkResult(result, 0, '', concatArgs, concatArgs); chai_1.expect(cbStdErrSpy.called).to.be.true; chai_1.expect(cbStdOutSpy.called).to.be.true; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it('spawnShellCommandAsync: edge: yes suppressStdErr, no cacheStdErr', (done) => { spawnOptions.suppressResult = false; spawnOptions.cacheStdOut = false; spawnOptions.cacheStdErr = false; spawn.spawnShellCommandAsync(argArray, spawnOptions, cbStatusMock, (err, result) => { chai_1.expect(err).to.not.exist; checkResult(result); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it(`spawnShellCommandAsync:edge: fire 'error' event on child process`, (done) => { spawnOptions.suppressResult = false; spawnOptions.suppressFinalError = false; const cp = spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { checkResult(result, 30, 'SIGUSR1'); checkError(err, 30, 'SIGUSR1'); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); cp.emit('error', 30, 'SIGUSR1'); }); it(`spawnShellCommandAsync:edge: EACCES on bad cmd`, (done) => { argArray[0] = '/'; spawnOptions.suppressResult = false; spawnOptions.suppressFinalError = false; spawn.spawnShellCommandAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(result).to.not.exist; chai_1.expect(err['code']).to.equal('EACCES'); chai_1.expect(err['errno']).to.equal('EACCES'); chai_1.expect(err.message).to.equal('spawn EACCES'); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); }); describe('Testing SudoSpawn ', () => { let spawn; let argArray; let spawnOptions; let sinonSandbox; let cbStdOutSpy; let cbStdErrSpy; let cbDiagnosticSpy; const o = { cbStdOutCall: () => { }, cbStdErrCall: () => { }, cbStatus: () => { }, cbDiagnostic: () => { } }; before(() => { }); after(() => { }); beforeEach(() => { spawn = inversify_config_1.default.get('Spawn'); argArray = getArgArray(); spawnOptions = getNewSpawnOptions(); sinonSandbox = sinon.createSandbox(); cbDiagnosticSpy = sinonSandbox.spy(o, 'cbDiagnostic'); cbStdOutSpy = sinonSandbox.spy(o, 'cbStdOutCall'); cbStdErrSpy = sinonSandbox.spy(o, 'cbStdErrCall'); }); afterEach(() => { sinonSandbox.restore(); }); it(`sudoSpawnAsync: forceError `, (done) => { spawn.forceError = true; spawn.sudoSpawnAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(err).to.exist; chai_1.expect(err.message).to.equal('force error: sudoSpawnAsync'); chai_1.expect(result).to.not.exist; chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it(`sudoSpawnAsync: spawnOptions is undefined, `, (done) => { argArray[1] = 'exitWithErrCode'; spawnOptions = undefined; spawn.sudoSpawnAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { checkError(err, 1); checkResult(result, 1); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.true; done(); }, o.cbDiagnostic); }); it(`sudoSpawnAsync: spawnOptions is null, `, (done) => { argArray[1] = 'exitWithErrCode'; spawnOptions = null; spawn.sudoSpawnAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { checkError(err, 1); checkResult(result, 1); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.true; done(); }, o.cbDiagnostic); }); it(`sudoSpawnAsync: non-existent user should return error`, (done) => { argArray[1] = 'exitWithErrCode'; spawnOptions.sudoUser = 'poopuser'; spawnOptions.sudoPassword = 'pooppassword'; spawnOptions.suppressFinalError = false; spawnOptions.suppressStdErr = false; spawnOptions.suppressResult = false; spawn.sudoSpawnAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { const stdErr = 'sudo: unknown user: poopuser\nsudo: unable to initialize policy plugin\n'; checkError(err, 1, '', '', stdErr); checkResult(result, 1, '', '', stdErr); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it(`sudoSpawnAsync: existing user but bad password should return error`, (done) => { argArray[1] = 'exitWithErrCode'; spawnOptions.sudoUser = 'vagrant'; spawnOptions.sudoPassword = 'pooppassword'; spawnOptions.suppressFinalError = false; spawnOptions.suppressStdErr = false; spawnOptions.suppressResult = false; spawn.sudoSpawnAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { const errStdErr = '#login-prompt#Sorry, try again.\n' + '#login-prompt#Sorry, try again.\n' + '#login-prompt#sudo: 3 incorrect password attempts\n'; const resultStdErr = 'Sorry, try again.\n' + 'Sorry, try again.\n' + 'sudo: 3 incorrect password attempts\n'; checkError(err, 1, '', '', errStdErr); checkResult(result, 1, '', '', resultStdErr); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it(`sudoSpawnAsync: forceNullChildProcess should return error`, (done) => { argArray[1] = 'exitWithErrCode'; spawnOptions.sudoUser = 'vagrant'; spawnOptions.sudoPassword = 'pooppassword'; spawnOptions.suppressFinalError = false; spawnOptions.suppressStdErr = false; spawnOptions.suppressResult = false; spawnOptions.forceNullChildProcess = true; spawn.sudoSpawnAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(result).to.not.exist; chai_1.expect(err.message).to.be.equal('error: forceNullChildProcess'); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); it(`sudoSpawnAsync: existing user and good password`, (done) => { argArray[1] = 'exitWithErrCode'; spawnOptions.sudoUser = 'vagrant'; spawnOptions.sudoPassword = 'password'; spawnOptions.suppressFinalError = false; spawnOptions.suppressStdErr = false; spawnOptions.suppressResult = false; spawn.sudoSpawnAsync(argArray, spawnOptions, o.cbStatus, (err, result) => { chai_1.expect(err).to.not.exist; checkResult(result); chai_1.expect(cbStdErrSpy.called).to.be.false; chai_1.expect(cbStdOutSpy.called).to.be.false; chai_1.expect(cbDiagnosticSpy.called).to.be.false; done(); }, o.cbDiagnostic); }); }); //# sourceMappingURL=spawn.test.js.map