routie dev init since i didn't adhere to any proper guidance up until now

This commit is contained in:
2026-04-29 22:27:29 -06:00
commit e1dabb71e2
15301 changed files with 3562618 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const nodeApi = require('../lib')
const BufferStream = require('./lib/buffer-stream')
const util = require('./lib/util')
const runAll = util.runAll
const runPar = util.runPar
const runSeq = util.runSeq
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe('[aggregated-output] npm-run-all', () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
/**
* create expected text
* @param {string} term the term to use when creating a line
* @returns {string} the complete line
*/
function createExpectedOutput (term) {
return `[${term}]__[${term}]`
}
describe('should not intermingle output of various commands', () => {
const EXPECTED_PARALLELIZED_TEXT = [
createExpectedOutput('second'),
createExpectedOutput('third'),
createExpectedOutput('first'),
'',
].join('\n')
let stdout = null
beforeEach(() => {
stdout = new BufferStream()
})
it('Node API with parallel', async () => {
await nodeApi(
['test-task:delayed first 5000', 'test-task:delayed second 1000', 'test-task:delayed third 3000'],
{ stdout, parallel: true, silent: true, aggregateOutput: true }
)
assert.equal(stdout.value, EXPECTED_PARALLELIZED_TEXT)
})
it('Node API without parallel should fail', async () => {
try {
await nodeApi(
['test-task:delayed first 5000', 'test-task:delayed second 1000', 'test-task:delayed third 3000'],
{ stdout, silent: true, aggregateOutput: true }
)
} catch (_err) {
return
}
assert(false, 'should fail')
})
it('npm-run-all command with parallel', async () => {
await runAll(
['--parallel', 'test-task:delayed first 5000', 'test-task:delayed second 1000', 'test-task:delayed third 3000', '--silent', '--aggregate-output'],
stdout
)
assert.equal(stdout.value, EXPECTED_PARALLELIZED_TEXT)
})
it('npm-run-all command without parallel should fail', async () => {
try {
await runAll(
['test-task:delayed first 5000', 'test-task:delayed second 1000', 'test-task:delayed third 3000', '--silent', '--aggregate-output'],
stdout
)
} catch (_err) {
return
}
assert(false, 'should fail')
})
it('run-s command should fail', async () => {
try {
await runSeq(
['test-task:delayed first 5000', 'test-task:delayed second 1000', 'test-task:delayed third 3000', '--silent', '--aggregate-output'],
stdout
)
} catch (_err) {
return
}
assert(false, 'should fail')
})
it('run-p command', async () => {
await runPar(
[
'test-task:delayed first 5000',
'test-task:delayed second 1000',
'test-task:delayed third 3000',
'--silent', '--aggregate-output',
],
stdout
)
assert.equal(stdout.value, EXPECTED_PARALLELIZED_TEXT)
})
})
})
+204
View File
@@ -0,0 +1,204 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const { strictEqual } = assert
const nodeApi = require('../lib')
const { result, removeResult, runAll, runPar, runSeq } = require('./lib/util')
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe('[argument-placeholders]', () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
beforeEach(removeResult)
describe("If arguments preceded by '--' are nothing, '{1}' should be empty:", () => {
it('Node API', () =>
nodeApi('test-task:dump {1}')
.then(() => strictEqual(result(), '[]')))
it('npm-run-all command', () =>
runAll(['test-task:dump {1}'])
.then(() => strictEqual(result(), '[]')))
it("npm-run-all command (only '--' exists)", () =>
runAll(['test-task:dump {1}', '--'])
.then(() => strictEqual(result(), '[]')))
it('run-s command', () =>
runSeq(['test-task:dump {1}'])
.then(() => strictEqual(result(), '[]')))
it("run-s command (only '--' exists)", () =>
runSeq(['test-task:dump {1}', '--'])
.then(() => strictEqual(result(), '[]')))
it('run-p command', () =>
runPar(['test-task:dump {1}'])
.then(() => strictEqual(result(), '[]')))
it("run-p command (only '--' exists)", () =>
runPar(['test-task:dump {1}', '--'])
.then(() => strictEqual(result(), '[]')))
})
describe("'{1}' should be replaced by the 1st argument preceded by '--':", () => {
it('Node API', () =>
nodeApi('test-task:dump {1}', { arguments: ['1st', '2nd'] })
.then(() => strictEqual(result(), '["1st"]')))
it('npm-run-all command', () =>
runAll(['test-task:dump {1}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st"]')))
it('run-s command', () =>
runSeq(['test-task:dump {1}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st"]')))
it('run-p command', () =>
runPar(['test-task:dump {1}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st"]')))
})
describe("'{2}' should be replaced by the 2nd argument preceded by '--':", () => {
it('Node API', () =>
nodeApi('test-task:dump {2}', { arguments: ['1st', '2nd'] })
.then(() => strictEqual(result(), '["2nd"]')))
it('npm-run-all command', () =>
runAll(['test-task:dump {2}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["2nd"]')))
it('run-s command', () =>
runSeq(['test-task:dump {2}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["2nd"]')))
it('run-p command', () =>
runPar(['test-task:dump {2}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["2nd"]')))
})
describe("'{@}' should be replaced by the every argument preceded by '--':", () => {
it('Node API', () =>
nodeApi('test-task:dump {@}', { arguments: ['1st', '2nd'] })
.then(() => strictEqual(result(), '["1st","2nd"]')))
it('npm-run-all command', () =>
runAll(['test-task:dump {@}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st","2nd"]')))
it('run-s command', () =>
runSeq(['test-task:dump {@}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st","2nd"]')))
it('run-p command', () =>
runPar(['test-task:dump {@}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st","2nd"]')))
})
describe("'{*}' should be replaced by the all arguments preceded by '--':", () => {
it('Node API', () =>
nodeApi('test-task:dump {*}', { arguments: ['1st', '2nd'] })
.then(() => strictEqual(result(), '["1st 2nd"]')))
it('npm-run-all command', () =>
runAll(['test-task:dump {*}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st 2nd"]')))
it('run-s command', () =>
runSeq(['test-task:dump {*}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st 2nd"]')))
it('run-p command', () =>
runPar(['test-task:dump {*}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st 2nd"]')))
})
describe("'{%}' should be unfolded into one command for each argument following '--':", () => {
it('Node API', () =>
nodeApi('test-task:dump {%}', { arguments: ['1st', '2nd'] })
.then(() => strictEqual(result(), '["1st"]["2nd"]')))
it('npm-run-all command', () =>
runAll(['test-task:dump {%}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st"]["2nd"]')))
it('run-s command', () =>
runSeq(['test-task:dump {%}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st"]["2nd"]')))
it('run-p command', () =>
runPar(['test-task:dump {%}', '--', '1st', '2nd'])
.then(() => {
const value = result()
assert(value === '["1st"]["2nd"]' || value === '["2nd"]["1st"]')
}))
})
describe("Every '{1}', '{2}', '{@}' and '{*}' should be replaced by the arguments preceded by '--':", () => {
it('Node API', () =>
nodeApi('test-task:dump {1} {2} {3} {@} {*}', { arguments: ['1st', '2nd'] })
.then(() => strictEqual(result(), '["1st","2nd","1st","2nd","1st 2nd"]')))
it('npm-run-all command', () =>
runAll(['test-task:dump {1} {2} {3} {@} {*}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st","2nd","1st","2nd","1st 2nd"]')))
it('run-s command', () =>
runSeq(['test-task:dump {1} {2} {3} {@} {*}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st","2nd","1st","2nd","1st 2nd"]')))
it('run-p command', () =>
runPar(['test-task:dump {1} {2} {3} {@} {*}', '--', '1st', '2nd'])
.then(() => strictEqual(result(), '["1st","2nd","1st","2nd","1st 2nd"]')))
})
describe("'{1:-foo}' should be replaced by 'foo' if arguments are nothing:", () => {
it('Node API', () =>
nodeApi('test-task:dump {1:-foo} {1}')
.then(() => strictEqual(result(), '["foo"]')))
it('npm-run-all command', () =>
runAll(['test-task:dump {1:-foo} {1}'])
.then(() => strictEqual(result(), '["foo"]')))
it('run-s command', () =>
runSeq(['test-task:dump {1:-foo} {1}'])
.then(() => strictEqual(result(), '["foo"]')))
it('run-p command', () =>
runPar(['test-task:dump {1:-foo} {1}'])
.then(() => strictEqual(result(), '["foo"]')))
})
describe("'{1:=foo}' should be replaced by 'foo' and should affect following '{1}' if arguments are nothing:", () => {
it('Node API', () =>
nodeApi('test-task:dump {1:=foo} {1}')
.then(() => strictEqual(result(), '["foo","foo"]')))
it('npm-run-all command', () =>
runAll(['test-task:dump {1:=foo} {1}'])
.then(() => strictEqual(result(), '["foo","foo"]')))
it('run-s command', () =>
runSeq(['test-task:dump {1:=foo} {1}'])
.then(() => strictEqual(result(), '["foo","foo"]')))
it('run-p command', () =>
runPar(['test-task:dump {1:=foo} {1}'])
.then(() => strictEqual(result(), '["foo","foo"]')))
})
})
+329
View File
@@ -0,0 +1,329 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const nodeApi = require('../lib')
const BufferStream = require('./lib/buffer-stream')
const { result, removeResult, runAll, runPar, runSeq } = require('./lib/util')
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe('[common]', () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
beforeEach(removeResult)
describe('should print a help text if arguments are nothing.', () => {
it('npm-run-all command', async () => {
const buf = new BufferStream()
await runAll([], buf)
assert(/Usage:/.test(buf.value))
})
it('run-s command', async () => {
const buf = new BufferStream()
await runSeq([], buf)
assert(/Usage:/.test(buf.value))
})
it('run-p command', async () => {
const buf = new BufferStream()
await runPar([], buf)
assert(/Usage:/.test(buf.value))
})
})
describe('should print a help text if the first argument is --help (-h)', () => {
it('npm-run-all command (-h)', async () => {
const buf = new BufferStream()
await runAll(['-h'], buf)
assert(/Usage:/.test(buf.value))
})
it('run-s command (-h)', async () => {
const buf = new BufferStream()
await runSeq(['-h'], buf)
assert(/Usage:/.test(buf.value))
})
it('run-p command (-h)', async () => {
const buf = new BufferStream()
await runPar(['-h'], buf)
assert(/Usage:/.test(buf.value))
})
it('npm-run-all command (--help)', async () => {
const buf = new BufferStream()
await runAll(['--help'], buf)
assert(/Usage:/.test(buf.value))
})
it('run-s command (--help)', async () => {
const buf = new BufferStream()
await runSeq(['--help'], buf)
assert(/Usage:/.test(buf.value))
})
it('run-p command (--help)', async () => {
const buf = new BufferStream()
await runPar(['--help'], buf)
assert(/Usage:/.test(buf.value))
})
})
describe('should print a version number if the first argument is --version (-v)', () => {
it('npm-run-all command (-v)', async () => {
const buf = new BufferStream()
await runAll(['-v'], buf)
assert(/v[0-9]+\.[0-9]+\.[0-9]+/.test(buf.value))
})
it('run-s command (-v)', async () => {
const buf = new BufferStream()
await runSeq(['-v'], buf)
assert(/v[0-9]+\.[0-9]+\.[0-9]+/.test(buf.value))
})
it('run-p command (-v)', async () => {
const buf = new BufferStream()
await runPar(['-v'], buf)
assert(/v[0-9]+\.[0-9]+\.[0-9]+/.test(buf.value))
})
it('npm-run-all command (--version)', async () => {
const buf = new BufferStream()
await runAll(['--version'], buf)
assert(/v[0-9]+\.[0-9]+\.[0-9]+/.test(buf.value))
})
it('run-s command (--version)', async () => {
const buf = new BufferStream()
await runSeq(['--version'], buf)
assert(/v[0-9]+\.[0-9]+\.[0-9]+/.test(buf.value))
})
it('run-p command (--version)', async () => {
const buf = new BufferStream()
await runPar(['--version'], buf)
assert(/v[0-9]+\.[0-9]+\.[0-9]+/.test(buf.value))
})
})
describe('should do nothing if a task list is empty.', () => {
it('Node API', async () => {
await nodeApi(null)
assert(result() == null)
})
})
describe('should run a task by npm (check an environment variable):', () => {
it('Node API', async () => {
await nodeApi('test-task:package-config')
assert(result() === 'OK')
})
it('npm-run-all command', async () => {
await runAll(['test-task:package-config'])
assert(result() === 'OK')
})
it('run-s command', async () => {
await runSeq(['test-task:package-config'])
assert(result() === 'OK')
})
it('run-p command', async () => {
await runPar(['test-task:package-config'])
assert(result() === 'OK')
})
})
describe('stdin can be used in tasks:', () => {
it('Node API', async () => {
await nodeApi('test-task:stdin')
assert(result().trim() === 'STDIN')
})
it('npm-run-all command', async () => {
await runAll(['test-task:stdin'])
assert(result().trim() === 'STDIN')
})
it('run-s command', async () => {
await runSeq(['test-task:stdin'])
assert(result().trim() === 'STDIN')
})
it('run-p command', async () => {
await runPar(['test-task:stdin'])
assert(result().trim() === 'STDIN')
})
})
describe('stdout can be used in tasks:', () => {
it('Node API', async () => {
await nodeApi('test-task:stdout')
assert(result() === 'STDOUT')
})
it('npm-run-all command', async () => {
await runAll(['test-task:stdout'])
assert(result() === 'STDOUT')
})
it('run-s command', async () => {
await runSeq(['test-task:stdout'])
assert(result() === 'STDOUT')
})
it('run-p command', async () => {
await runPar(['test-task:stdout'])
assert(result() === 'STDOUT')
})
})
describe('stderr can be used in tasks:', () => {
it('Node API', async () => {
await nodeApi('test-task:stderr')
assert(result() === 'STDERR')
})
it('npm-run-all command', async () => {
await runAll(['test-task:stderr'])
assert(result() === 'STDERR')
})
it('run-s command', async () => {
await runSeq(['test-task:stderr'])
assert(result() === 'STDERR')
})
it('run-p command', async () => {
await runPar(['test-task:stderr'])
assert(result() === 'STDERR')
})
})
describe('should be able to use `restart` built-in task:', () => {
it('Node API', () => nodeApi('restart'))
it('npm-run-all command', () => runAll(['restart']))
it('run-s command', () => runSeq(['restart']))
it('run-p command', () => runPar(['restart']))
})
describe('should be able to use `env` built-in task:', () => {
it('Node API', () => nodeApi('env'))
it('npm-run-all command', () => runAll(['env']))
it('run-s command', () => runSeq(['env']))
it('run-p command', () => runPar(['env']))
})
if (process.platform === 'win32') {
describe('issue14', () => {
it('Node API', () => nodeApi('test-task:issue14:win32'))
it('npm-run-all command', () => runAll(['test-task:issue14:win32']))
it('run-s command', () => runSeq(['test-task:issue14:win32']))
it('run-p command', () => runPar(['test-task:issue14:win32']))
})
} else {
describe('issue14', () => {
it('Node API', () => nodeApi('test-task:issue14:posix'))
it('npm-run-all command', () => runAll(['test-task:issue14:posix']))
it('run-s command', () => runSeq(['test-task:issue14:posix']))
it('run-p command', () => runPar(['test-task:issue14:posix']))
})
}
describe('should not print log if silent option was given:', () => {
it('Node API', async () => {
const stdout = new BufferStream()
const stderr = new BufferStream()
try {
await nodeApi('test-task:error', { silent: true, stdout, stderr })
} catch (_err) {
assert(stdout.value === '' && stderr.value === '')
return
}
assert(false, 'Should fail.')
})
/**
* Strip unknown istanbul's warnings.
* @param {string} str - The string to be stripped.
* @returns {string} The stripped string.
*/
function stripIstanbulWarnings (str) {
return str.replace(/File \[.+?] ignored, nothing could be mapped\r?\n/, '')
}
it('npm-run-all command', async () => {
const stdout = new BufferStream()
const stderr = new BufferStream()
try {
await runAll(['--silent', 'test-task:error'], stdout, stderr)
} catch (_err) {
assert(stdout.value === '' && stripIstanbulWarnings(stderr.value) === '')
return
}
assert(false, 'Should fail.')
})
it('run-s command', async () => {
const stdout = new BufferStream()
const stderr = new BufferStream()
try {
await runSeq(['--silent', 'test-task:error'], stdout, stderr)
} catch (_err) {
assert(stdout.value === '' && stripIstanbulWarnings(stderr.value) === '')
return
}
assert(false, 'Should fail.')
})
it('run-p command', async () => {
const stdout = new BufferStream()
const stderr = new BufferStream()
try {
await runPar(['--silent', 'test-task:error'], stdout, stderr)
} catch (_err) {
assert(stdout.value === '' && stripIstanbulWarnings(stderr.value) === '')
return
}
assert(false, 'Should fail.')
})
})
// https://github.com/mysticatea/npm-run-all/issues/105
describe('should not print MaxListenersExceededWarning when it runs 10 tasks:', () => {
const tasks = Array.from({ length: 10 }, () => 'test-task:append:a')
it('npm-run-all command', async () => {
const buf = new BufferStream()
await runAll(tasks, null, buf)
assert(buf.value.indexOf('MaxListenersExceededWarning') === -1)
})
it('run-s command', async () => {
const buf = new BufferStream()
await runSeq(tasks, null, buf)
assert(buf.value.indexOf('MaxListenersExceededWarning') === -1)
})
it('run-p command', async () => {
const buf = new BufferStream()
await runPar(tasks, null, buf)
assert(buf.value.indexOf('MaxListenersExceededWarning') === -1)
})
})
})
+86
View File
@@ -0,0 +1,86 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const nodeApi = require('../lib')
const { result, removeResult, runAll, runPar, runSeq } = require('./lib/util')
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe('[config] it should have an ability to set config variables:', () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
beforeEach(removeResult)
it('Node API should address "config" option', async () => {
await nodeApi('test-task:config', { config: { test: 'this is a config' } })
assert(result() === 'this is a config')
})
it('Node API should address "config" option for multiple variables', async () => {
await nodeApi('test-task:config2', { config: { test: '1', test2: '2', test3: '3' } })
assert(result() === '1\n2\n3')
})
describe('CLI commands should address "--a=b" style options', () => {
it('npm-run-all command', async () => {
await runAll(['test-task:config', '--test=GO'])
assert(result() === 'GO')
})
it('run-s command', async () => {
await runSeq(['test-task:config', '--test=GO'])
assert(result() === 'GO')
})
it('run-p command', async () => {
await runPar(['test-task:config', '--test=GO'])
assert(result() === 'GO')
})
})
describe('CLI commands should address "--b=c" style options for multiple variables', () => {
it('npm-run-all command', async () => {
await runAll(['test-task:config2', '--test=1', '--test2=2', '--test3=3'])
assert(result() === '1\n2\n3')
})
it('run-s command', async () => {
await runSeq(['test-task:config2', '--test=1', '--test2=2', '--test3=3'])
assert(result() === '1\n2\n3')
})
it('run-p command', async () => {
await runPar(['test-task:config2', '--test=1', '--test2=2', '--test3=3'])
assert(result() === '1\n2\n3')
})
})
describe('CLI commands should transfar configs to nested commands.', () => {
it('npm-run-all command', async () => {
await runAll(['test-task:nested-config', '--test=GO DEEP'])
assert(result() === 'GO DEEP')
})
it('run-s command', async () => {
await runSeq(['test-task:nested-config', '--test=GO DEEP'])
assert(result() === 'GO DEEP')
})
it('run-p command', async () => {
await runPar(['test-task:nested-config', '--test=GO DEEP'])
assert(result() === 'GO DEEP')
})
})
})
+114
View File
@@ -0,0 +1,114 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const nodeApi = require('../lib')
const { delay, removeResult, runAll, runPar, runSeq } = require('./lib/util')
// ------------------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------------------
/**
* Throws an assertion error if a given promise comes to be fulfilled.
*
* @param {Promise} p - A promise to check.
* @returns {Promise} A promise which is checked.
*/
function shouldFail (p) {
return p.then(
() => assert(false, 'should fail'),
() => null // OK!
)
}
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe('[fail] it should fail', () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
beforeEach(removeResult)
afterEach(() => delay(1000))
describe('if an invalid option exists.', () => {
it('npm-run-all command', () => shouldFail(runAll(['--invalid'])))
it('run-s command', () => shouldFail(runSeq(['--parallel'])))
it('run-p command', () => shouldFail(runPar(['--sequential'])))
it('npm-run-all command with --race without --parallel', () => shouldFail(runAll(['--race'])))
it('npm-run-all command with --r without --parallel', () => shouldFail(runAll(['--r'])))
it('run-s command with --race', () => shouldFail(runSeq(['--race'])))
it('run-s command with --r', () => shouldFail(runSeq(['--r'])))
})
describe('if invalid `options.taskList` is given.', () => {
it('Node API', () => shouldFail(nodeApi('test-task:append a', { taskList: { invalid: 0 } })))
})
describe('if unknown tasks are given:', () => {
it('Node API', () => shouldFail(nodeApi('unknown-task')))
it('npm-run-all command', () => shouldFail(runAll(['unknown-task'])))
it('run-s command', () => shouldFail(runSeq(['unknown-task'])))
it('run-p command', () => shouldFail(runPar(['unknown-task'])))
})
describe('if unknown tasks are given (2):', () => {
it('Node API', () => shouldFail(nodeApi(['test-task:append:a', 'unknown-task'])))
it('npm-run-all command', () => shouldFail(runAll(['test-task:append:a', 'unknown-task'])))
it('run-s command', () => shouldFail(runSeq(['test-task:append:a', 'unknown-task'])))
it('run-p command', () => shouldFail(runPar(['test-task:append:a', 'unknown-task'])))
})
describe('if package.json is not found:', () => {
before(() => process.chdir('no-package-json'))
after(() => process.chdir('..'))
it('Node API', () => shouldFail(nodeApi(['test-task:append:a'])))
it('npm-run-all command', () => shouldFail(runAll(['test-task:append:a'])))
it('run-s command', () => shouldFail(runSeq(['test-task:append:a'])))
it('run-p command', () => shouldFail(runPar(['test-task:append:a'])))
})
describe('if package.json does not have scripts field:', () => {
before(() => process.chdir('no-scripts'))
after(() => process.chdir('..'))
it('Node API', () => shouldFail(nodeApi(['test-task:append:a'])))
it('npm-run-all command', () => shouldFail(runAll(['test-task:append:a'])))
it('run-s command', () => shouldFail(runSeq(['test-task:append:a'])))
it('run-p command', () => shouldFail(runPar(['test-task:append:a'])))
})
describe('if tasks exited with non-zero code:', () => {
it('Node API', () => shouldFail(nodeApi('test-task:error')))
it('npm-run-all command', () => shouldFail(runAll(['test-task:error'])))
it('run-s command', () => shouldFail(runSeq(['test-task:error'])))
it('run-p command', () => shouldFail(runPar(['test-task:error'])))
})
describe('if tasks exited via a signal:', () => {
it('Node API', () => shouldFail(nodeApi('test-task:abort')))
it('npm-run-all command', () => shouldFail(runAll(['test-task:abort'])))
it('run-s command', () => shouldFail(runSeq(['test-task:abort'])))
it('run-p command', () => shouldFail(runPar(['test-task:abort'])))
it('with correct exit code', () => nodeApi('test-task:abort').then(() =>
assert(false, 'should fail')).catch(err => {
// In NodeJS versions > 6, the child process correctly sends back
// the signal + code of null. In NodeJS versions <= 6, the child
// process does not set the signal, and sets the code to 1.
const code = Number(process.version.match(/^v(\d+)/)[1]) > 6 ? 134 : 1
assert(err.code === code, 'should have correct exit code')
}))
})
})
+47
View File
@@ -0,0 +1,47 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const stream = require('stream')
// ------------------------------------------------------------------------------
// Public Interface
// ------------------------------------------------------------------------------
/**
* The stream to accumulate written data as a single string.
*/
module.exports = class BufferStream extends stream.Writable {
/**
* Initialize the current data as a empty string.
*/
constructor () {
super()
/**
* Accumulated data.
* @type {string}
*/
this.value = ''
}
/**
* Accumulates written data.
*
* @param {string|Buffer} chunk - A written data.
* @param {string} _encoding - The encoding of chunk.
* @param {function} callback - The callback to notify done.
* @returns {void}
*/
_write (chunk, _encoding, callback) {
this.value += chunk.toString()
callback()
}
}
+26
View File
@@ -0,0 +1,26 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const spawn = require('../../lib/spawn')
// ------------------------------------------------------------------------------
// Public Interface
// ------------------------------------------------------------------------------
module.exports = function spawnWithKill (command, args) {
return new Promise((resolve, reject) => {
const cp = spawn(command, args, {})
cp.on('exit', resolve)
cp.on('error', reject)
setTimeout(() => cp.kill(), 1000)
})
}
+161
View File
@@ -0,0 +1,161 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const cp = require('child_process')
const fs = require('fs')
const path = require('path')
const BufferStream = require('./buffer-stream')
// ------------------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------------------
const FILE_NAME = 'test.txt'
const NPM_RUN_ALL = path.resolve(__dirname, '../../bin/npm-run-all/index.js')
const RUN_P = path.resolve(__dirname, '../../bin/run-p/index.js')
const RUN_S = path.resolve(__dirname, '../../bin/run-s/index.js')
/**
* Spawns the given script with the given arguments.
*
* @param {string} filePath - The file path to be executed.
* @param {string[]} args - The arguments to execute.
* @param {Writable} [stdout] - The writable stream to receive stdout.
* @param {Writable} [stderr] - The writable stream to receive stderr.
* @returns {Promise<void>} The promise which becomes fulfilled if the child
* process finished.
*/
function spawn (filePath, args, stdout, stderr) {
return new Promise((resolve, reject) => {
const child = cp.spawn(
process.execPath,
[filePath].concat(args),
{ stdio: 'pipe' }
)
const out = new BufferStream()
const error = new BufferStream()
if (stdout != null) {
child.stdout.pipe(stdout)
}
if (stderr != null) {
child.stderr.pipe(stderr)
} else {
child.stderr.pipe(error)
}
child.stdout.pipe(out)
child.on('close', (exitCode) => {
if (exitCode) {
reject(new Error(error.value || 'Exited with non-zero code.'))
} else {
resolve()
}
})
child.on('error', reject)
})
}
// ------------------------------------------------------------------------------
// Public Interface
// ------------------------------------------------------------------------------
/**
* Gets the result text from `test.txt`.
*
* @returns {string|null} The result text.
*/
module.exports.result = function result () {
try {
return fs.readFileSync(FILE_NAME, { encoding: 'utf8' })
} catch (err) {
if (err.code === 'ENOENT') {
return null
}
throw err
}
}
/**
* Appends text to `test.txt`.
*
* @param {string} content - A text to append.
* @returns {void}
*/
module.exports.appendResult = function appendResult (content) {
fs.appendFileSync(FILE_NAME, content)
}
/**
* Removes `test.txt`.
*
* @returns {void}
*/
module.exports.removeResult = function removeResult () {
try {
fs.unlinkSync(FILE_NAME)
} catch (err) {
if (err.code === 'ENOENT') {
return
}
throw err
}
}
/**
* Delay.
*
* @param {number} timeoutInMillis - The time to delay.
* @returns {Promise<void>} The promise which fulfilled after the given time.
*/
module.exports.delay = function delay (timeoutInMillis) {
return new Promise(resolve => {
setTimeout(resolve, timeoutInMillis)
})
}
/**
* Executes `npm-run-all` with the given arguments.
*
* @param {string[]} args - The arguments to execute.
* @param {Writable} [stdout] - The writable stream to receive stdout.
* @param {Writable} [stderr] - The writable stream to receive stderr.
* @returns {Promise<void>} The promise which becomes fulfilled if the child
* process finished.
*/
module.exports.runAll = function runAll (args, stdout, stderr) {
return spawn(NPM_RUN_ALL, args, stdout, stderr)
}
/**
* Executes `run-p` with the given arguments.
*
* @param {string[]} args - The arguments to execute.
* @param {Writable} [stdout] - The writable stream to receive stdout.
* @param {Writable} [stderr] - The writable stream to receive stderr.
* @returns {Promise<void>} The promise which becomes fulfilled if the child
* process finished.
*/
module.exports.runPar = function runPar (args, stdout, stderr) {
return spawn(RUN_P, args, stdout, stderr)
}
/**
* Executes `run-s` with the given arguments.
*
* @param {string[]} args - The arguments to execute.
* @param {Writable} [stdout] - The writable stream to receive stdout.
* @param {Writable} [stderr] - The writable stream to receive stderr.
* @returns {Promise<void>} The promise which becomes fulfilled if the child
* process finished.
*/
module.exports.runSeq = function runSeq (args, stdout, stderr) {
return spawn(RUN_S, args, stdout, stderr)
}
+59
View File
@@ -0,0 +1,59 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const { result, removeResult, runAll } = require('./lib/util')
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe('[mixed] npm-run-all', () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
beforeEach(removeResult)
it('should run a mix of sequential and parallel tasks (has the default group):', async () => {
await runAll([
'test-task:append a',
'-p', 'test-task:append b', 'test-task:append c',
'-s', 'test-task:append d', 'test-task:append e',
])
assert(
result() === 'aabcbcddee' ||
result() === 'aabccbddee' ||
result() === 'aacbbcddee' ||
result() === 'aacbcbddee'
)
})
it("should run a mix of sequential and parallel tasks (doesn't have the default group):", async () => {
await runAll([
'-p', 'test-task:append b', 'test-task:append c',
'-s', 'test-task:append d', 'test-task:append e',
])
assert(
result() === 'bcbcddee' ||
result() === 'bccbddee' ||
result() === 'cbbcddee' ||
result() === 'cbcbddee'
)
})
it('should not throw errors for --race and --max-parallel options if --parallel exists:', () =>
runAll([
'test-task:append a',
'-p', 'test-task:append b', 'test-task:append c',
'-s', 'test-task:append d', 'test-task:append e',
'-r',
]))
})
+110
View File
@@ -0,0 +1,110 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const { execSync } = require('child_process')
const assert = require('assert').strict
const nodeApi = require('../lib')
const { result, removeResult, runAll, runPar, runSeq } = require('./lib/util')
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe("[package-config] it should have an ability to overwrite package's config:", () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
beforeEach(removeResult)
const [major] = execSync('npm --version', { encoding: 'utf8' }).trim().split('.')
const supportsOverrides = major <= 6
if (supportsOverrides) {
it('Node API should address "packageConfig" option', async () => {
await nodeApi('test-task:package-config', { packageConfig: { 'npm-run-all-test': { test: 'OVERWRITTEN' } } })
assert.equal(result(), 'OVERWRITTEN')
})
it('Node API should address "packageConfig" option for multiple variables', async () => {
await nodeApi('test-task:package-config2', { packageConfig: { 'npm-run-all-test': { test: '1', test2: '2', test3: '3' } } })
assert.equal(result(), '1\n2\n3')
})
describe('CLI commands should address "--a:b=c" style options', () => {
it('npm-run-all command', async () => {
await runAll(['test-task:package-config', '--npm-run-all-test:test=OVERWRITTEN'])
assert.equal(result(), 'OVERWRITTEN')
})
it('run-s command', async () => {
await runSeq(['test-task:package-config', '--npm-run-all-test:test=OVERWRITTEN'])
assert.equal(result(), 'OVERWRITTEN')
})
it('run-p command', async () => {
await runPar(['test-task:package-config', '--npm-run-all-test:test=OVERWRITTEN'])
assert.equal(result(), 'OVERWRITTEN')
})
})
describe('CLI commands should address "--a:b=c" style options for multiple variables', () => {
it('npm-run-all command', async () => {
await runAll(['test-task:package-config2', '--npm-run-all-test:test=1', '--npm-run-all-test:test2=2', '--npm-run-all-test:test3=3'])
assert.equal(result(), '1\n2\n3')
})
it('run-s command', async () => {
await runSeq(['test-task:package-config2', '--npm-run-all-test:test=1', '--npm-run-all-test:test2=2', '--npm-run-all-test:test3=3'])
assert.equal(result(), '1\n2\n3')
})
it('run-p command', async () => {
await runPar(['test-task:package-config2', '--npm-run-all-test:test=1', '--npm-run-all-test:test2=2', '--npm-run-all-test:test3=3'])
assert.equal(result(), '1\n2\n3')
})
})
describe('CLI commands should address "--a:b c" style options', () => {
it('npm-run-all command', async () => {
await runAll(['test-task:package-config', '--npm-run-all-test:test', 'OVERWRITTEN'])
assert.equal(result(), 'OVERWRITTEN')
})
it('run-s command', async () => {
await runSeq(['test-task:package-config', '--npm-run-all-test:test', 'OVERWRITTEN'])
assert.equal(result(), 'OVERWRITTEN')
})
it('run-p command', async () => {
await runPar(['test-task:package-config', '--npm-run-all-test:test', 'OVERWRITTEN'])
assert.equal(result(), 'OVERWRITTEN')
})
})
describe('CLI commands should transfar overriting nested commands.', () => {
it('npm-run-all command', async () => {
await runAll(['test-task:nested-package-config', '--npm-run-all-test:test', 'OVERWRITTEN'])
assert.equal(result(), 'OVERWRITTEN')
})
it('run-s command', async () => {
await runSeq(['test-task:nested-package-config', '--npm-run-all-test:test', 'OVERWRITTEN'])
assert.equal(result(), 'OVERWRITTEN')
})
it('run-p command', async () => {
await runPar(['test-task:nested-package-config', '--npm-run-all-test:test', 'OVERWRITTEN'])
assert.equal(result(), 'OVERWRITTEN')
})
})
}
})
+307
View File
@@ -0,0 +1,307 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const nodeApi = require('../lib')
const spawnWithKill = require('./lib/spawn-with-kill')
const { delay, result, removeResult, runAll, runPar } = require('./lib/util')
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe('[parallel]', () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
beforeEach(() => delay(1000).then(removeResult))
describe('should run tasks on parallel when was given --parallel option:', () => {
it('Node API', async () => {
const results = await nodeApi(['test-task:append a', 'test-task:append b'], { parallel: true })
assert(results.length === 2)
assert(results[0].name === 'test-task:append a')
assert(results[0].code === 0)
assert(results[1].name === 'test-task:append b')
assert(results[1].code === 0)
assert(
result() === 'abab' ||
result() === 'baba' ||
result() === 'abba' ||
result() === 'baab'
)
})
it('npm-run-all command', async () => {
await runAll(['--parallel', 'test-task:append a', 'test-task:append b'])
assert(
result() === 'abab' ||
result() === 'baba' ||
result() === 'abba' ||
result() === 'baab'
)
})
it('run-p command', async () => {
await runPar(['test-task:append a', 'test-task:append b'])
assert(
result() === 'abab' ||
result() === 'baba' ||
result() === 'abba' ||
result() === 'baab'
)
})
})
describe('should kill all tasks when was given --parallel option if a task exited with a non-zero code:', () => {
it('Node API', async () => {
try {
await nodeApi(['test-task:append2 a', 'test-task:error'], { parallel: true })
} catch (err) {
assert(err.results.length === 2)
assert(err.results[0].name === 'test-task:append2 a')
assert(err.results[0].code === undefined)
assert(err.results[1].name === 'test-task:error')
assert(err.results[1].code === 1)
assert(result() == null || result() === 'a')
return
}
assert(false, 'should fail')
})
it('npm-run-all command', async () => {
try {
await runAll(['--parallel', 'test-task:append2 a', 'test-task:error'])
} catch (_err) {
assert(result() == null || result() === 'a')
return
}
assert(false, 'should fail')
})
it('run-p command', async () => {
try {
await runPar(['test-task:append2 a', 'test-task:error'])
} catch (_err) {
assert(result() == null || result() === 'a')
return
}
assert(false, 'should fail')
})
})
describe('should remove intersected tasks from two or more patterns:', () => {
it('Node API', async () => {
await nodeApi(['test-task:*:a', '*:append:a'], { parallel: true })
assert(result() === 'aa')
})
it('npm-run-all command', async () => {
await runAll(['--parallel', 'test-task:*:a', '*:append:a'])
assert(result() === 'aa')
})
it('run-p command', async () => {
await runPar(['test-task:*:a', '*:append:a'])
assert(result() === 'aa')
})
})
describe('should not remove duplicate tasks from two or more the same pattern:', () => {
it('Node API', async () => {
await nodeApi(['test-task:*:a', 'test-task:*:a'], { parallel: true })
assert(result() === 'aaaa')
})
it('npm-run-all command', async () => {
await runAll(['--parallel', 'test-task:*:a', 'test-task:*:a'])
assert(result() === 'aaaa')
})
it('run-p command', async () => {
await runPar(['test-task:*:a', 'test-task:*:a'])
assert(result() === 'aaaa')
})
})
describe("should kill child processes when it's killed", () => {
it('npm-run-all command', async () => {
await spawnWithKill(
'node',
['../bin/npm-run-all/index.js', '--parallel', 'test-task:append2 a']
)
assert(result() == null || result() === 'a')
})
it('run-p command', async () => {
await spawnWithKill(
'node',
['../bin/run-p/index.js', 'test-task:append2 a']
)
assert(result() == null || result() === 'a')
})
})
describe('should continue on error when --continue-on-error option was specified:', () => {
it('Node API', async () => {
try {
await nodeApi(['test-task:append a', 'test-task:error', 'test-task:append b'], { parallel: true, continueOnError: true })
} catch (_err) {
console.log(result()) // TODO: This is randomly failing
assert(
result() === 'abab' ||
result() === 'baba' ||
result() === 'abba' ||
result() === 'baab'
)
return
}
assert(false, 'should fail.')
})
it('npm-run-all command (--continue-on-error)', async () => {
try {
await runAll(['--continue-on-error', '--parallel', 'test-task:append a', 'test-task:error', 'test-task:append b'])
} catch (_err) {
assert(
result() === 'abab' ||
result() === 'baba' ||
result() === 'abba' ||
result() === 'baab'
)
return
}
assert(false, 'should fail.')
})
it('npm-run-all command (-c)', async () => {
try {
await runAll(['-cp', 'test-task:append a', 'test-task:error', 'test-task:append b'])
} catch (_err) {
assert(
result() === 'abab' ||
result() === 'baba' ||
result() === 'abba' ||
result() === 'baab'
)
return
}
assert(false, 'should fail.')
})
it('run-p command (--continue-on-error)', async () => {
try {
await runPar(['--continue-on-error', 'test-task:append a', 'test-task:error', 'test-task:append b'])
} catch (_err) {
assert(
result() === 'abab' ||
result() === 'baba' ||
result() === 'abba' ||
result() === 'baab'
)
return
}
assert(false, 'should fail.')
})
it('run-p command (-c)', async () => {
try {
await runPar(['-c', 'test-task:append a', 'test-task:error', 'test-task:append b'])
} catch (_err) {
assert(
result() === 'abab' ||
result() === 'baba' ||
result() === 'abba' ||
result() === 'baab'
)
return
}
assert(false, 'should fail.')
})
})
describe('should abort other tasks when a task finished, when --race option was specified:', () => {
it('Node API', async () => {
await nodeApi(['test-task:append1 a', 'test-task:append2 b'], { parallel: true, race: true })
await delay(5000)
assert(result() === 'a' || result() === 'ab' || result() === 'ba')
})
it('npm-run-all command (--race)', async () => {
await runAll(['--race', '--parallel', 'test-task:append1 a', 'test-task:append2 b'])
await delay(5000)
assert(result() === 'a' || result() === 'ab' || result() === 'ba')
})
it('npm-run-all command (-r)', async () => {
await runAll(['-rp', 'test-task:append1 a', 'test-task:append2 b'])
await delay(5000)
assert(result() === 'a' || result() === 'ab' || result() === 'ba')
})
it('run-p command (--race)', async () => {
await runPar(['--race', 'test-task:append1 a', 'test-task:append2 b'])
await delay(5000)
assert(result() === 'a' || result() === 'ab' || result() === 'ba')
})
it('run-p command (-r)', async () => {
await runPar(['-r', 'test-task:append1 a', 'test-task:append2 b'])
await delay(5000)
assert(result() === 'a' || result() === 'ab' || result() === 'ba')
})
it('run-p command (no -r)', async () => {
await runPar(['test-task:append1 a', 'test-task:append2 b'])
await delay(5000)
assert(result() === 'abb' || result() === 'bab')
})
})
describe('should run tasks in parallel-2 when was given --max-parallel 2 option:', () => {
it('Node API', async () => {
const results = await nodeApi(['test-task:append a', 'test-task:append b', 'test-task:append c'], { parallel: true, maxParallel: 2 })
assert(results.length === 3)
assert(results[0].name === 'test-task:append a')
assert(results[0].code === 0)
assert(results[1].name === 'test-task:append b')
assert(results[1].code === 0)
assert(results[2].name === 'test-task:append c')
assert(results[2].code === 0)
assert(
result() === 'ababcc' ||
result() === 'babacc' ||
result() === 'abbacc' ||
result() === 'baabcc'
)
})
it('npm-run-all command', async () => {
await runAll(['--parallel', 'test-task:append a', 'test-task:append b', 'test-task:append c', '--max-parallel', '2'])
assert(
result() === 'ababcc' ||
result() === 'babacc' ||
result() === 'abbacc' ||
result() === 'baabcc'
)
})
it('run-p command', async () => {
await runPar(['test-task:append a', 'test-task:append b', 'test-task:append c', '--max-parallel', '2'])
assert(
result() === 'ababcc' ||
result() === 'babacc' ||
result() === 'abbacc' ||
result() === 'baabcc'
)
})
})
})
+218
View File
@@ -0,0 +1,218 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const nodeApi = require('../lib')
const BufferStream = require('./lib/buffer-stream')
const { result, removeResult, runAll, runPar, runSeq } = require('./lib/util')
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe('[pattern] it should run matched tasks if glob like patterns are given.', () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
beforeEach(removeResult)
describe('"test-task:append:*" to "test-task:append:a" and "test-task:append:b"', () => {
it('Node API', async () => {
await nodeApi('test-task:append:*')
assert(result() === 'aabb')
})
it('npm-run-all command', async () => {
await runAll(['test-task:append:*'])
assert(result() === 'aabb')
})
it('run-s command', async () => {
await runSeq(['test-task:append:*'])
assert(result() === 'aabb')
})
it('run-p command', async () => {
await runPar(['test-task:append:*'])
assert(
result() === 'abab' ||
result() === 'abba' ||
result() === 'baba' ||
result() === 'baab'
)
})
})
describe('"test-task:append:**" to "test-task:append:a", "test-task:append:a:c", "test-task:append:a:d", and "test-task:append:b"', () => {
it('Node API', async () => {
await nodeApi('test-task:append:**')
assert(result() === 'aaacacadadbb')
})
it('npm-run-all command', async () => {
await runAll(['test-task:append:**'])
assert(result() === 'aaacacadadbb')
})
it('run-s command', async () => {
await runSeq(['test-task:append:**'])
assert(result() === 'aaacacadadbb')
})
})
// should act same way as section above
describe('"test-task:append:**:*" to "test-task:append:a", "test-task:append:a:c", "test-task:append:a:d", and "test-task:append:b"', () => {
it('Node API', async () => {
await nodeApi('test-task:append:**:*')
assert(result() === 'aaacacadadbb')
})
it('npm-run-all command', async () => {
await runAll(['test-task:append:**:*'])
assert(result() === 'aaacacadadbb')
})
it('run-s command', async () => {
await runSeq(['test-task:append:**:*'])
assert(result() === 'aaacacadadbb')
})
})
describe('(should ignore duplications) "test-task:append:b" "test-task:append:*" to "test-task:append:b", "test-task:append:a"', () => {
it('Node API', async () => {
await nodeApi(['test-task:append:b', 'test-task:append:*'])
assert(result() === 'bbaa')
})
it('npm-run-all command', async () => {
await runAll(['test-task:append:b', 'test-task:append:*'])
assert(result() === 'bbaa')
})
it('run-s command', async () => {
await runSeq(['test-task:append:b', 'test-task:append:*'])
assert(result() === 'bbaa')
})
it('run-p command', async () => {
await runPar(['test-task:append:b', 'test-task:append:*'])
assert(
result() === 'baba' ||
result() === 'baab' ||
result() === 'abab' ||
result() === 'abba'
)
})
})
describe('"a" should not match to "test-task:append:a"', () => {
it('Node API', async () => {
try {
await nodeApi('a')
assert(false, 'should not match')
} catch (err) {
assert((/not found/i).test(err.message))
}
})
it('npm-run-all command', async () => {
const stderr = new BufferStream()
try {
await runAll(['a'], null, stderr)
assert(false, 'should not match')
} catch (_err) {
assert((/not found/i).test(stderr.value))
}
})
it('run-s command', async () => {
const stderr = new BufferStream()
try {
await runSeq(['a'], null, stderr)
assert(false, 'should not match')
} catch (_err) {
assert((/not found/i).test(stderr.value))
}
})
it('run-p command', async () => {
const stderr = new BufferStream()
try {
await runPar(['a'], null, stderr)
assert(false, 'should not match')
} catch (_err) {
assert((/not found/i).test(stderr.value))
}
})
})
describe('"!test-task:**" should not match to anything', () => {
it('Node API', async () => {
try {
await nodeApi('!test-task:**')
assert(false, 'should not match')
} catch (err) {
assert((/not found/i).test(err.message))
}
})
it('npm-run-all command', async () => {
const stderr = new BufferStream()
try {
await runAll(['!test-task:**'], null, stderr)
assert(false, 'should not match')
} catch (_err) {
assert((/not found/i).test(stderr.value))
}
})
it('run-s command', async () => {
const stderr = new BufferStream()
try {
await runSeq(['!test-task:**'], null, stderr)
assert(false, 'should not match')
} catch (_err) {
assert((/not found/i).test(stderr.value))
}
})
it('run-p command', async () => {
const stderr = new BufferStream()
try {
await runPar(['!test-task:**'], null, stderr)
assert(false, 'should not match')
} catch (_err) {
assert((/not found/i).test(stderr.value))
}
})
})
describe('"!test" "?test" to "!test", "?test"', () => {
it('Node API', async () => {
await nodeApi(['!test', '?test'])
assert(result().trim() === 'XQ')
})
it('npm-run-all command', async () => {
await runAll(['!test', '?test'])
assert(result().trim() === 'XQ')
})
it('run-s command', async () => {
await runSeq(['!test', '?test'])
assert(result().trim() === 'XQ')
})
it('run-p command', async () => {
await runPar(['!test', '?test'])
assert(result().trim() === 'XQ' || result().trim() === 'QX')
})
})
})
+224
View File
@@ -0,0 +1,224 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const nodeApi = require('../lib')
const BufferStream = require('./lib/buffer-stream')
const util = require('./lib/util')
const runAll = util.runAll
const runPar = util.runPar
const runSeq = util.runSeq
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe('[print-label] npm-run-all', () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
describe('should print labels at the head of every line:', () => {
const EXPECTED_TEXT = [
'[test-task:echo abc] abcabc',
'[test-task:echo abc] abc',
'[test-task:echo abc] abcabc',
'[test-task:echo abc] abc',
'[test-task:echo abc] abc',
'[test-task:echo abc] abc',
'[test-task:echo abc] abc',
'[test-task:echo abc] abc',
'[test-task:echo abc] ',
'[test-task:echo abc] abc',
'[test-task:echo abc] abcabc',
'[test-task:echo abc] ',
'[test-task:echo abc] ',
'[test-task:echo abc] ',
'[test-task:echo abc] abc',
].join('\n')
it('Node API', async () => {
const stdout = new BufferStream()
await nodeApi('test-task:echo abc', { stdout, silent: true, printLabel: true })
assert.equal(stdout.value, EXPECTED_TEXT)
})
it('npm-run-all command (--print-label)', async () => {
const stdout = new BufferStream()
await runAll(['test-task:echo abc', '--silent', '--print-label'], stdout)
assert.equal(stdout.value, EXPECTED_TEXT)
})
it('run-s command (--print-label)', async () => {
const stdout = new BufferStream()
await runSeq(['test-task:echo abc', '--silent', '--print-label'], stdout)
assert.equal(stdout.value, EXPECTED_TEXT)
})
it('run-p command (--print-label)', async () => {
const stdout = new BufferStream()
await runPar(['test-task:echo abc', '--silent', '--print-label'], stdout)
assert.equal(stdout.value, EXPECTED_TEXT)
})
it('npm-run-all command (-l)', async () => {
const stdout = new BufferStream()
await runAll(['test-task:echo abc', '--silent', '-l'], stdout)
assert.equal(stdout.value, EXPECTED_TEXT)
})
it('run-s command (-l)', async () => {
const stdout = new BufferStream()
await runSeq(['test-task:echo abc', '--silent', '-l'], stdout)
assert.equal(stdout.value, EXPECTED_TEXT)
})
it('run-p command (-l)', async () => {
const stdout = new BufferStream()
await runPar(['test-task:echo abc', '--silent', '-l'], stdout)
assert.equal(stdout.value, EXPECTED_TEXT)
})
})
describe('should print all labels with the same width:', () => {
const EXPECTED_TEXT = [
'[test-task:echo a ] aa',
'[test-task:echo a ] a',
'[test-task:echo a ] aa',
'[test-task:echo a ] a',
'[test-task:echo a ] a',
'[test-task:echo a ] a',
'[test-task:echo a ] a',
'[test-task:echo a ] a',
'[test-task:echo a ] ',
'[test-task:echo a ] a',
'[test-task:echo a ] aa',
'[test-task:echo a ] ',
'[test-task:echo a ] ',
'[test-task:echo a ] ',
'[test-task:echo a ] a',
'[test-task:echo abcd] abcdabcd',
'[test-task:echo abcd] abcd',
'[test-task:echo abcd] abcdabcd',
'[test-task:echo abcd] abcd',
'[test-task:echo abcd] abcd',
'[test-task:echo abcd] abcd',
'[test-task:echo abcd] abcd',
'[test-task:echo abcd] abcd',
'[test-task:echo abcd] ',
'[test-task:echo abcd] abcd',
'[test-task:echo abcd] abcdabcd',
'[test-task:echo abcd] ',
'[test-task:echo abcd] ',
'[test-task:echo abcd] ',
'[test-task:echo abcd] abcd',
'[test-task:echo ab ] abab',
'[test-task:echo ab ] ab',
'[test-task:echo ab ] abab',
'[test-task:echo ab ] ab',
'[test-task:echo ab ] ab',
'[test-task:echo ab ] ab',
'[test-task:echo ab ] ab',
'[test-task:echo ab ] ab',
'[test-task:echo ab ] ',
'[test-task:echo ab ] ab',
'[test-task:echo ab ] abab',
'[test-task:echo ab ] ',
'[test-task:echo ab ] ',
'[test-task:echo ab ] ',
'[test-task:echo ab ] ab',
].join('\n')
it('Node API', async () => {
const stdout = new BufferStream()
await nodeApi(
['test-task:echo a', 'test-task:echo abcd', 'test-task:echo ab'],
{ stdout, silent: true, printLabel: true }
)
assert.equal(stdout.value, EXPECTED_TEXT)
})
it('npm-run-all command', async () => {
const stdout = new BufferStream()
await runAll(
['test-task:echo a', 'test-task:echo abcd', 'test-task:echo ab', '--silent', '--print-label'],
stdout
)
assert.equal(stdout.value, EXPECTED_TEXT)
})
it('run-s command', async () => {
const stdout = new BufferStream()
await runSeq(
['test-task:echo a', 'test-task:echo abcd', 'test-task:echo ab', '--silent', '--print-label'],
stdout
)
assert.equal(stdout.value, EXPECTED_TEXT)
})
})
describe('should work printing labels in parallel:', () => {
const EXPECTED_LINES = [
'\n[test-task:echo a ] ',
'\n[test-task:echo a ] a',
'\n[test-task:echo ab ] ',
'\n[test-task:echo ab ] ab',
'\n[test-task:echo abcd] ',
'\n[test-task:echo abcd] abcd',
]
const UNEXPECTED_PATTERNS = [
/aab(cd)?/,
/ab(cd)?a\b/,
/\n\n/,
]
it('Node API', async () => {
const stdout = new BufferStream()
await nodeApi(
['test-task:echo a', 'test-task:echo abcd', 'test-task:echo ab'],
{ stdout, parallel: true, printLabel: true }
)
for (const line of EXPECTED_LINES) {
assert(stdout.value.indexOf(line) !== -1)
}
for (const pattern of UNEXPECTED_PATTERNS) {
assert(!pattern.test(stdout.value))
}
})
it('npm-run-all command', async () => {
const stdout = new BufferStream()
await runAll(
['--parallel', 'test-task:echo a', 'test-task:echo abcd', 'test-task:echo ab', '--print-label'],
stdout
)
for (const line of EXPECTED_LINES) {
assert(stdout.value.indexOf(line) !== -1)
}
for (const pattern of UNEXPECTED_PATTERNS) {
assert(!pattern.test(stdout.value))
}
})
it('run-p command', async () => {
const stdout = new BufferStream()
await runPar(
['test-task:echo a', 'test-task:echo abcd', 'test-task:echo ab', '--print-label'],
stdout
)
for (const line of EXPECTED_LINES) {
assert(stdout.value.indexOf(line) !== -1)
}
for (const pattern of UNEXPECTED_PATTERNS) {
assert(!pattern.test(stdout.value))
}
})
})
})
+95
View File
@@ -0,0 +1,95 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const nodeApi = require('../lib')
const createHeader = require('../lib/create-header')
const readPackageJson = require('../lib/read-package-json')
const BufferStream = require('./lib/buffer-stream')
const util = require('./lib/util')
const ansiStylesPromise = import('ansi-styles')
const runAll = util.runAll
const runPar = util.runPar
const runSeq = util.runSeq
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe('[print-name] npm-run-all', () => {
let packageInfo = null
before(() => {
process.chdir('test-workspace')
return readPackageJson().then(info => {
packageInfo = info.packageInfo
})
})
after(() => process.chdir('..'))
describe('should print names before running tasks:', () => {
it('Node API', async () => {
const ansiStyles = (await ansiStylesPromise).default
const stdout = new BufferStream()
await nodeApi('test-task:echo abc', { stdout, silent: true, printName: true })
const header = createHeader('test-task:echo abc', packageInfo, false, ansiStyles)
assert.equal(stdout.value.slice(0, header.length), header)
})
it('npm-run-all command (--print-name)', async () => {
const ansiStyles = (await ansiStylesPromise).default
const stdout = new BufferStream()
await runAll(['test-task:echo abc', '--silent', '--print-name'], stdout)
const header = createHeader('test-task:echo abc', packageInfo, false, ansiStyles)
assert.equal(stdout.value.slice(0, header.length), header)
})
it('run-s command (--print-name)', async () => {
const ansiStyles = (await ansiStylesPromise).default
const stdout = new BufferStream()
await runSeq(['test-task:echo abc', '--silent', '--print-name'], stdout)
const header = createHeader('test-task:echo abc', packageInfo, false, ansiStyles)
assert.equal(stdout.value.slice(0, header.length), header)
})
it('run-p command (--print-name)', async () => {
const ansiStyles = (await ansiStylesPromise).default
const stdout = new BufferStream()
await runPar(['test-task:echo abc', '--silent', '--print-name'], stdout)
const header = createHeader('test-task:echo abc', packageInfo, false, ansiStyles)
assert.equal(stdout.value.slice(0, header.length), header)
})
it('npm-run-all command (-n)', async () => {
const ansiStyles = (await ansiStylesPromise).default
const stdout = new BufferStream()
await runAll(['test-task:echo abc', '--silent', '-n'], stdout)
const header = createHeader('test-task:echo abc', packageInfo, false, ansiStyles)
assert.equal(stdout.value.slice(0, header.length), header)
})
it('run-s command (-n)', async () => {
const ansiStyles = (await ansiStylesPromise).default
const stdout = new BufferStream()
await runSeq(['test-task:echo abc', '--silent', '-n'], stdout)
const header = createHeader('test-task:echo abc', packageInfo, false, ansiStyles)
assert.equal(stdout.value.slice(0, header.length), header)
})
it('run-p command (-n)', async () => {
const ansiStyles = (await ansiStylesPromise).default
const stdout = new BufferStream()
await runPar(['test-task:echo abc', '--silent', '-n'], stdout)
const header = createHeader('test-task:echo abc', packageInfo, false, ansiStyles)
assert.equal(stdout.value.slice(0, header.length), header)
})
})
})
+192
View File
@@ -0,0 +1,192 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const nodeApi = require('../lib')
const spawnWithKill = require('./lib/spawn-with-kill')
const { delay, result, removeResult, runAll, runSeq } = require('./lib/util')
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
describe('[sequencial] npm-run-all', () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
beforeEach(() => delay(1000).then(removeResult))
describe('should run tasks sequentially:', () => {
it('Node API', async () => {
const results = await nodeApi(['test-task:append a', 'test-task:append b'], { parallel: false })
assert(results.length === 2)
assert(results[0].name === 'test-task:append a')
assert(results[0].code === 0)
assert(results[1].name === 'test-task:append b')
assert(results[1].code === 0)
assert(result() === 'aabb')
})
it('npm-run-all command', async () => {
await runAll(['test-task:append a', 'test-task:append b'])
assert(result() === 'aabb')
})
it('run-s command', async () => {
await runSeq(['test-task:append a', 'test-task:append b'])
assert(result() === 'aabb')
})
})
describe('should not run subsequent tasks if a task exited with a non-zero code:', () => {
it('Node API', async () => {
try {
await nodeApi(['test-task:append2 a', 'test-task:error', 'test-task:append2 b'])
} catch (err) {
assert(err.results.length === 3)
assert(err.results[0].name === 'test-task:append2 a')
assert(err.results[0].code === 0)
assert(err.results[1].name === 'test-task:error')
assert(err.results[1].code === 1)
assert(err.results[2].name === 'test-task:append2 b')
assert(err.results[2].code === undefined)
assert(result() === 'aa')
return
}
assert(false, 'should fail')
})
it('npm-run-all command', async () => {
try {
await runAll(['test-task:append2 a', 'test-task:error', 'test-task:append2 b'])
} catch (_err) {
assert(result() === 'aa')
return
}
assert(false, 'should fail')
})
it('run-s command', async () => {
try {
await runSeq(['test-task:append2 a', 'test-task:error', 'test-task:append2 b'])
} catch (_err) {
assert(result() === 'aa')
return
}
assert(false, 'should fail')
})
})
describe('should remove intersected tasks from two or more patterns:', () => {
it('Node API', async () => {
await nodeApi(['test-task:*:a', '*:append:a'], { parallel: false })
assert(result() === 'aa')
})
it('npm-run-all command', async () => {
await runAll(['test-task:*:a', '*:append:a'])
assert(result() === 'aa')
})
it('run-s command', async () => {
await runSeq(['test-task:*:a', '*:append:a'])
assert(result() === 'aa')
})
})
describe('should not remove duplicate tasks from two or more the same pattern:', () => {
it('Node API', async () => {
await nodeApi(['test-task:*:a', 'test-task:*:a'], { parallel: false })
assert(result() === 'aaaa')
})
it('npm-run-all command', async () => {
await runAll(['test-task:*:a', 'test-task:*:a'])
assert(result() === 'aaaa')
})
it('run-s command', async () => {
await runSeq(['test-task:*:a', 'test-task:*:a'])
assert(result() === 'aaaa')
})
})
describe("should kill child processes when it's killed", () => {
it('npm-run-all command', async () => {
await spawnWithKill(
'node',
['../bin/npm-run-all.js', 'test-task:append2 a']
)
assert(result() == null || result() === 'a')
})
it('run-s command', async () => {
await spawnWithKill(
'node',
['../bin/run-s/index.js', 'test-task:append2 a']
)
assert(result() == null || result() === 'a')
})
})
describe('should continue on error when --continue-on-error option was specified:', () => {
it('Node API', async () => {
try {
await nodeApi(['test-task:append a', 'test-task:error', 'test-task:append b'], { continueOnError: true })
} catch (_err) {
console.log(result()) // TODO: Spurious failures windows
assert(result() === 'aabb')
return
}
assert(false, 'should fail')
})
it('npm-run-all command (--continue-on-error)', async () => {
try {
await runAll(['--continue-on-error', 'test-task:append a', 'test-task:error', 'test-task:append b'])
} catch (_err) {
assert(result() === 'aabb')
return
}
assert(false, 'should fail')
})
it('run-s command (--continue-on-error)', async () => {
try {
await runSeq(['--continue-on-error', 'test-task:append a', 'test-task:error', 'test-task:append b'])
} catch (_err) {
assert(result() === 'aabb')
return
}
assert(false, 'should fail')
})
it('npm-run-all command (-c)', async () => {
try {
await runAll(['-c', 'test-task:append a', 'test-task:error', 'test-task:append b'])
} catch (_err) {
assert(result() === 'aabb')
return
}
assert(false, 'should fail')
})
it('run-s command (-c)', async () => {
try {
await runSeq(['-c', 'test-task:append a', 'test-task:error', 'test-task:append b'])
} catch (_err) {
assert(result() === 'aabb')
return
}
assert(false, 'should fail')
})
})
})
+62
View File
@@ -0,0 +1,62 @@
/**
* @author Toru Nagashima
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const assert = require('assert').strict
const spawn = require('cross-spawn')
const BufferStream = require('./lib/buffer-stream')
const { result, removeResult } = require('./lib/util')
// ------------------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------------------
/**
* Execute a command.
* @param {string} command A command to execute.
* @param {string[]} args Arguments for the command.
* @returns {Promise<void>} The result of child process's stdout.
*/
function exec (command, args) {
return new Promise((resolve, reject) => {
const stderr = new BufferStream()
const cp = spawn(command, args, { stdio: ['ignore', 'ignore', 'pipe'] })
cp.stderr.pipe(stderr)
cp.on('exit', (exitCode) => {
if (exitCode) {
reject(new Error(`Exited with ${exitCode}: ${stderr.value}`))
return
}
resolve()
})
cp.on('error', reject)
})
}
const nodeVersion = Number(process.versions.node.split('.')[0])
// ------------------------------------------------------------------------------
// Test
// ------------------------------------------------------------------------------
;(nodeVersion >= 6 ? describe : xdescribe)('[yarn]', () => {
before(() => process.chdir('test-workspace'))
after(() => process.chdir('..'))
beforeEach(removeResult)
describe("'yarn run' command", () => {
it("should run 'npm-run-all' in scripts with yarn.", async () => {
await exec('yarn', ['run', 'test-task:yarn'])
assert(result() === 'aabb')
})
})
})