%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream
const t = require('tap') let RPJ_ERROR = null let RPJ_CALLED = '' const mockRPJ = async path => { if (RPJ_ERROR) { try { throw RPJ_ERROR } finally { RPJ_ERROR = null } } RPJ_CALLED = path return { some: 'package' } } let RUN_SCRIPT_ERROR = null let RUN_SCRIPT_EXIT_CODE = 0 let RUN_SCRIPT_SIGNAL = null let RUN_SCRIPT_EXEC = null const mockRunScript = ({ pkg, banner, path, event, stdio }) => { if (event !== '_explore') { throw new Error('got wrong event name') } RUN_SCRIPT_EXEC = pkg.scripts._explore if (RUN_SCRIPT_ERROR) { try { return Promise.reject(RUN_SCRIPT_ERROR) } finally { RUN_SCRIPT_ERROR = null } } if (RUN_SCRIPT_EXIT_CODE || RUN_SCRIPT_SIGNAL) { return Promise.reject(Object.assign(new Error('command failed'), { code: RUN_SCRIPT_EXIT_CODE, signal: RUN_SCRIPT_SIGNAL, })) } return Promise.resolve({ code: 0, signal: null }) } const output = [] const logs = [] const getExplore = (windows) => { const Explore = t.mock('../../../lib/commands/explore.js', { path: require('path')[windows ? 'win32' : 'posix'], 'read-package-json-fast': mockRPJ, '@npmcli/run-script': mockRunScript, 'proc-log': { error: (...msg) => logs.push(msg), warn: () => {}, }, npmlog: { disableProgress: () => {}, enableProgress: () => {}, }, }) const npm = { dir: windows ? 'c:\\npm\\dir' : '/npm/dir', flatOptions: { shell: 'shell-command', }, output: out => { output.push(out) }, } return new Explore(npm) } const windowsExplore = getExplore(true) const posixExplore = getExplore(false) t.test('basic interactive', t => { t.afterEach(() => output.length = 0) t.test('windows', async t => { await windowsExplore.exec(['pkg']) t.strictSame({ RPJ_CALLED, RUN_SCRIPT_EXEC, }, { RPJ_CALLED: 'c:\\npm\\dir\\pkg\\package.json', RUN_SCRIPT_EXEC: 'shell-command', }) t.strictSame(output, [ "\nExploring c:\\npm\\dir\\pkg\nType 'exit' or ^D when finished\n", ]) }) t.test('posix', async t => { await posixExplore.exec(['pkg']) t.strictSame({ RPJ_CALLED, RUN_SCRIPT_EXEC, }, { RPJ_CALLED: '/npm/dir/pkg/package.json', RUN_SCRIPT_EXEC: 'shell-command', }) t.strictSame(output, [ "\nExploring /npm/dir/pkg\nType 'exit' or ^D when finished\n", ]) }) t.end() }) t.test('interactive tracks exit code', t => { const { exitCode } = process t.beforeEach(() => { process.exitCode = exitCode RUN_SCRIPT_EXIT_CODE = 99 }) t.afterEach(() => { RUN_SCRIPT_EXIT_CODE = 0 output.length = 0 process.exitCode = exitCode }) t.test('windows', async t => { await windowsExplore.exec(['pkg']) t.strictSame({ RPJ_CALLED, RUN_SCRIPT_EXEC, }, { RPJ_CALLED: 'c:\\npm\\dir\\pkg\\package.json', RUN_SCRIPT_EXEC: 'shell-command', }) t.strictSame(output, [ "\nExploring c:\\npm\\dir\\pkg\nType 'exit' or ^D when finished\n", ]) t.equal(process.exitCode, 99) }) t.test('posix', async t => { await posixExplore.exec(['pkg']) t.strictSame({ RPJ_CALLED, RUN_SCRIPT_EXEC, }, { RPJ_CALLED: '/npm/dir/pkg/package.json', RUN_SCRIPT_EXEC: 'shell-command', }) t.strictSame(output, [ "\nExploring /npm/dir/pkg\nType 'exit' or ^D when finished\n", ]) t.equal(process.exitCode, 99) }) t.test('posix spawn fail', async t => { RUN_SCRIPT_ERROR = Object.assign(new Error('glorb'), { code: 33, }) await t.rejects( posixExplore.exec(['pkg']), { message: 'glorb', code: 33 } ) t.strictSame(output, [ "\nExploring /npm/dir/pkg\nType 'exit' or ^D when finished\n", ]) t.equal(process.exitCode, 33) }) t.test('posix spawn fail, 0 exit code', async t => { RUN_SCRIPT_ERROR = Object.assign(new Error('glorb'), { code: 0, }) await t.rejects( posixExplore.exec(['pkg']), { message: 'glorb', code: 0 } ) t.strictSame(output, [ "\nExploring /npm/dir/pkg\nType 'exit' or ^D when finished\n", ]) t.equal(process.exitCode, 1) }) t.test('posix spawn fail, no exit code', async t => { RUN_SCRIPT_ERROR = Object.assign(new Error('command failed'), { code: 'EPROBLEM', }) await t.rejects( posixExplore.exec(['pkg']), { message: 'command failed', code: 'EPROBLEM' } ) t.strictSame(output, [ "\nExploring /npm/dir/pkg\nType 'exit' or ^D when finished\n", ]) t.equal(process.exitCode, 1) }) t.end() }) t.test('basic non-interactive', t => { t.afterEach(() => output.length = 0) t.test('windows', async t => { await windowsExplore.exec(['pkg', 'ls']) t.strictSame({ RPJ_CALLED, RUN_SCRIPT_EXEC, }, { RPJ_CALLED: 'c:\\npm\\dir\\pkg\\package.json', RUN_SCRIPT_EXEC: 'ls', }) t.strictSame(output, []) }) t.test('posix', async t => { await posixExplore.exec(['pkg', 'ls']) t.strictSame({ RPJ_CALLED, RUN_SCRIPT_EXEC, }, { RPJ_CALLED: '/npm/dir/pkg/package.json', RUN_SCRIPT_EXEC: 'ls', }) t.strictSame(output, []) t.end() }) t.end() }) t.test('signal fails non-interactive', t => { const { exitCode } = process t.afterEach(() => { output.length = 0 logs.length = 0 }) t.beforeEach(() => { RUN_SCRIPT_SIGNAL = 'SIGPROBLEM' RUN_SCRIPT_EXIT_CODE = null process.exitCode = exitCode }) t.afterEach(() => process.exitCode = exitCode) t.test('windows', async t => { await t.rejects( windowsExplore.exec(['pkg', 'ls']), { message: 'command failed', signal: 'SIGPROBLEM', } ) t.strictSame({ RPJ_CALLED, RUN_SCRIPT_EXEC, }, { RPJ_CALLED: 'c:\\npm\\dir\\pkg\\package.json', RUN_SCRIPT_EXEC: 'ls', }) t.strictSame(output, []) }) t.test('posix', async t => { await t.rejects( posixExplore.exec(['pkg', 'ls']), { message: 'command failed', signal: 'SIGPROBLEM', } ) t.strictSame({ RPJ_CALLED, RUN_SCRIPT_EXEC, }, { RPJ_CALLED: '/npm/dir/pkg/package.json', RUN_SCRIPT_EXEC: 'ls', }) t.strictSame(output, []) t.end() }) t.end() }) t.test('usage if no pkg provided', t => { t.teardown(() => { output.length = 0 }) const noPkg = [ [], ['foo/../..'], ['asdf/..'], ['.'], ['..'], ['../..'], ] t.plan(noPkg.length) for (const args of noPkg) { t.test(JSON.stringify(args), async t => { await t.rejects( posixExplore.exec(args), 'Usage:' ) t.strictSame({ RPJ_CALLED, RUN_SCRIPT_EXEC, }, { RPJ_CALLED: '/npm/dir/pkg/package.json', RUN_SCRIPT_EXEC: 'ls', }) }) } }) t.test('pkg not installed', async t => { t.teardown(() => { logs.length = 0 }) RPJ_ERROR = new Error('plurple') await t.rejects( posixExplore.exec(['pkg', 'ls']), { message: 'plurple' } ) t.strictSame({ RPJ_CALLED, RUN_SCRIPT_EXEC, }, { RPJ_CALLED: '/npm/dir/pkg/package.json', RUN_SCRIPT_EXEC: 'ls', }) t.strictSame(output, []) t.match(logs, [['explore', `It doesn't look like pkg is installed.`]]) })