exec-sh.js
1 /* global describe, it, beforeEach, afterEach */ 2 var execSh = require('..') 3 var assert = require('assert') 4 var sinon = require('sinon') 5 var cp = require('child_process') 6 7 describe('exec-sh', function () { 8 describe('module.exports', function () { 9 it('should export a single function', function () { 10 assert.strictEqual(typeof execSh, 'function') 11 }) 12 13 it('should export promise interface', function () { 14 assert.strictEqual(typeof execSh.promise, 'function') 15 }) 16 }) 17 18 describe('#execSh() arguments', function () { 19 var spawn, exitCode, stream 20 21 stream = { 22 on: function (e, c) { 23 if (e === 'data') { 24 // execute callback two times to check if stream 25 // aggregation works correctly 26 c('1') 27 c('2') 28 } 29 } 30 } 31 32 beforeEach(function () { 33 exitCode = 0 34 spawn = sinon.stub(cp, 'spawn') 35 spawn.returns({ 36 spawn_return: true, 37 on: function (e, c) { 38 if (e === 'close') { 39 c(exitCode) 40 } 41 }, 42 stdout: stream, 43 stderr: stream 44 }) 45 }) 46 47 afterEach(function () { 48 cp.spawn.restore() 49 }) 50 51 it('should pass command to spawn function', function () { 52 execSh('command') 53 sinon.assert.calledOnce(spawn) 54 assert.strictEqual('command', spawn.getCall(0).args[1][1]) 55 }) 56 57 it('should accept array of commands to run', function () { 58 execSh(['command1', 'command2']) 59 sinon.assert.calledOnce(spawn) 60 assert.strictEqual('command1;command2', spawn.getCall(0).args[1][1]) 61 }) 62 63 it('should accept true as options argument', function () { 64 execSh('command', true) 65 sinon.assert.calledOnce(spawn) 66 assert.strictEqual(spawn.getCall(0).args[2].stdio, null) 67 }) 68 69 it('should merge defaults with options', function () { 70 var options = { key: 'value' } 71 var expectedOptions = { 72 key: 'value', 73 stdio: 'inherit' 74 } 75 execSh('command', options) 76 assert.deepStrictEqual(spawn.getCall(0).args[2], expectedOptions) 77 }) 78 79 it('should allow overriding default options', function () { 80 var options = { foo: 'bar', stdio: null } 81 var expectedOptions = { 82 foo: 'bar', 83 stdio: null 84 } 85 execSh('command', options) 86 assert.deepStrictEqual(spawn.getCall(0).args[2], expectedOptions) 87 }) 88 89 it('should allow passing nested environment options', function () { 90 var options = { 91 env: { 92 key1: 'value 1', 93 key2: 'value 2' 94 } 95 } 96 var expectedOptions = { 97 env: { 98 key1: 'value 1', 99 key2: 'value 2' 100 }, 101 stdio: 'inherit' 102 } 103 execSh('command', options) 104 assert.deepStrictEqual(spawn.getCall(0).args[2], expectedOptions) 105 }) 106 107 it("should accept optional 'callback' parameter", function () { 108 var callback = sinon.spy() 109 execSh('command', callback) 110 execSh('command', { key: 'value' }, callback) 111 sinon.assert.callCount(callback, 2) 112 }) 113 114 it("should use 'cmd /C' command prefix on windows", function () { 115 var platform = process.platform 116 Object.defineProperty(process, 'platform', { value: 'win32' }) 117 execSh('command') 118 Object.defineProperty(process, 'platform', { value: platform }) 119 120 sinon.assert.calledOnce(spawn) 121 assert.strictEqual(spawn.getCall(0).args[0], 'cmd') 122 }) 123 124 it("should use 'sh -c' command prefix on *nix", function () { 125 var platform = process.platform 126 process.platform = 'linux' 127 execSh('command') 128 process.platform = platform 129 130 sinon.assert.calledOnce(spawn) 131 assert.strictEqual(spawn.getCall(0).args[1][0], '-c') 132 assert.strictEqual(spawn.getCall(0).args[0], 'sh') 133 }) 134 135 it('should return spawn() result', function () { 136 assert(execSh('command').spawn_return) 137 }) 138 139 it('should aggregate stdoout and stderr', function (done) { 140 execSh('command', function (_err, stdout, stderr) { 141 assert.strictEqual(stdout, '12') 142 assert.strictEqual(stderr, '12') 143 done() 144 }) 145 }) 146 147 it('should catch exceptions thrown by spawn', function (done) { 148 spawn.throws() 149 execSh('command', function (err, stdout, stderr) { 150 assert(err instanceof Error) 151 done() 152 }) 153 }) 154 155 it('should return empty stdout and stderr when spawn throws', function (done) { 156 spawn.throws() 157 stream = null 158 execSh('command', function (_err, stdout, stderr) { 159 assert.strictEqual(stderr, '') 160 assert.strictEqual(stdout, '') 161 done() 162 }) 163 }) 164 165 it('should run callback with error when shell exit with non-zero code', function (done) { 166 exitCode = 1 167 execSh('command', function (err) { 168 assert(err instanceof Error) 169 assert.strictEqual(exitCode, err.code) 170 done() 171 }) 172 }) 173 174 it('promise interface: should return promise', function () { 175 assert(execSh.promise('command') instanceof Promise) 176 }) 177 178 it('promise interface: should resolve with stderr and stdout', function (done) { 179 execSh.promise('command').then(function (data) { 180 assert.ok('stdout' in data) 181 assert.ok('stderr' in data) 182 done() 183 }) 184 }) 185 186 it('promise interface: should reject promise when exceptions thrown by spawn', function (done) { 187 spawn.throws() 188 execSh.promise('command').catch(function (err) { 189 assert(err instanceof Error) 190 done() 191 }) 192 }) 193 }) 194 })