diff --git a/test/lib/commands/exec.js b/test/lib/commands/exec.js index 2fd11f40379f1..07a3e6ebd8ed9 100644 --- a/test/lib/commands/exec.js +++ b/test/lib/commands/exec.js @@ -129,3 +129,38 @@ t.test('workspaces', async t => { const exists = await fs.stat(path.join(npm.prefix, 'workspace-a', 'npm-exec-test-success')) t.ok(exists.isFile(), 'bin ran, creating file inside workspace') }) + +t.test('npx --no-install @npmcli/npx-test', async t => { + const registry = new MockRegistry({ + tap: t, + registry: 'https://registry.npmjs.org/', + }) + + const manifest = registry.manifest({ name: '@npmcli/npx-test' }) + manifest.versions['1.0.0'].bin = { 'npx-test': 'index.js' } + + const { npm } = await loadMockNpm(t, { + config: { + audit: false, + yes: false, + }, + prefixDir: { + 'npm-exec-test': { + 'package.json': JSON.stringify(manifest), + 'index.js': `#!/usr/bin/env node + require('fs').writeFileSync('npm-exec-test-success', '')`, + }, + }, + }) + + try { + await npm.exec('exec', ['@npmcli/npx-test']) + t.fail('Expected error was not thrown') + } catch (error) { + t.match( + error.message, + 'npx canceled due to missing packages and no YES option: ', + 'Expected error message thrown' + ) + } +}) diff --git a/workspaces/libnpmexec/lib/index.js b/workspaces/libnpmexec/lib/index.js index b7aa43588c0fd..34bb20769bc2c 100644 --- a/workspaces/libnpmexec/lib/index.js +++ b/workspaces/libnpmexec/lib/index.js @@ -245,9 +245,12 @@ const exec = async (opts) => { if (add.length) { if (!yes) { + const missingPackages = add.map(a => `${a.replace(/@$/, '')}`) // set -n to always say no if (yes === false) { - throw new Error('canceled') + // Error message lists missing package(s) when process is canceled + /* eslint-disable-next-line max-len */ + throw new Error(`npx canceled due to missing packages and no YES option: ${JSON.stringify(missingPackages)}`) } if (noTTY() || ciInfo.isCI) { @@ -257,8 +260,7 @@ const exec = async (opts) => { add.map((pkg) => pkg.replace(/@$/, '')).join(', ') }`) } else { - const addList = add.map(a => ` ${a.replace(/@$/, '')}`) - .join('\n') + '\n' + const addList = missingPackages.join('\n') + '\n' const prompt = `Need to install the following packages:\n${ addList }Ok to proceed? `