1const t = require('tap') 2const fs = require('fs/promises') 3const path = require('path') 4const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') 5const MockRegistry = require('@npmcli/mock-registry') 6 7t.test('call with args', async t => { 8 const { npm } = await loadMockNpm(t, { 9 config: { 10 call: 'foo', 11 }, 12 }) 13 14 await t.rejects( 15 npm.exec('exec', ['bar']), 16 { code: 'EUSAGE' } 17 ) 18}) 19 20t.test('registry package', async t => { 21 const registry = new MockRegistry({ 22 tap: t, 23 registry: 'https://registry.npmjs.org/', 24 }) 25 26 const manifest = registry.manifest({ name: '@npmcli/npx-test' }) 27 manifest.versions['1.0.0'].bin = { 'npx-test': 'index.js' } 28 29 const { npm } = await loadMockNpm(t, { 30 config: { 31 audit: false, 32 yes: true, 33 }, 34 prefixDir: { 35 'npm-exec-test': { 36 'package.json': JSON.stringify(manifest), 37 'index.js': `#!/usr/bin/env node 38 require('fs').writeFileSync('npm-exec-test-success', '')`, 39 }, 40 }, 41 }) 42 43 await registry.package({ 44 manifest, 45 tarballs: { 46 '1.0.0': path.join(npm.prefix, 'npm-exec-test'), 47 } }) 48 49 await npm.exec('exec', ['@npmcli/npx-test']) 50 const exists = await fs.stat(path.join(npm.prefix, 'npm-exec-test-success')) 51 t.ok(exists.isFile(), 'bin ran, creating file') 52}) 53 54t.test('--prefix', async t => { 55 const registry = new MockRegistry({ 56 tap: t, 57 registry: 'https://registry.npmjs.org/', 58 }) 59 60 const manifest = registry.manifest({ name: '@npmcli/npx-test' }) 61 manifest.versions['1.0.0'].bin = { 'npx-test': 'index.js' } 62 63 const { npm } = await loadMockNpm(t, { 64 config: { 65 audit: false, 66 yes: true, 67 }, 68 prefixDir: { 69 'npm-exec-test': { 70 'package.json': JSON.stringify(manifest), 71 'index.js': `#!/usr/bin/env node 72 require('fs').writeFileSync('npm-exec-test-success', '')`, 73 }, 74 }, 75 }) 76 77 // This is what `--prefix` does 78 npm.globalPrefix = npm.localPrefix 79 80 await registry.package({ 81 manifest, 82 tarballs: { 83 '1.0.0': path.join(npm.prefix, 'npm-exec-test'), 84 } }) 85 86 await npm.exec('exec', ['@npmcli/npx-test']) 87 const exists = await fs.stat(path.join(npm.prefix, 'npm-exec-test-success')) 88 t.ok(exists.isFile(), 'bin ran, creating file') 89}) 90 91t.test('workspaces', async t => { 92 const registry = new MockRegistry({ 93 tap: t, 94 registry: 'https://registry.npmjs.org/', 95 }) 96 97 const manifest = registry.manifest({ name: '@npmcli/npx-test' }) 98 manifest.versions['1.0.0'].bin = { 'npx-test': 'index.js' } 99 100 const { npm } = await loadMockNpm(t, { 101 config: { 102 audit: false, 103 yes: true, 104 workspace: ['workspace-a'], 105 }, 106 prefixDir: { 107 'npm-exec-test': { 108 'package.json': JSON.stringify(manifest), 109 'index.js': `#!/usr/bin/env node 110 require('fs').writeFileSync('npm-exec-test-success', '')`, 111 }, 112 'package.json': JSON.stringify({ 113 name: '@npmcli/npx-workspace-test', 114 workspaces: ['workspace-a'], 115 }), 116 'workspace-a': { 117 'package.json': JSON.stringify({ 118 name: 'workspace-a', 119 }), 120 }, 121 }, 122 }) 123 124 await registry.package({ manifest, 125 tarballs: { 126 '1.0.0': path.join(npm.prefix, 'npm-exec-test'), 127 } }) 128 await npm.exec('exec', ['@npmcli/npx-test']) 129 const exists = await fs.stat(path.join(npm.prefix, 'workspace-a', 'npm-exec-test-success')) 130 t.ok(exists.isFile(), 'bin ran, creating file inside workspace') 131}) 132 133t.test('npx --no-install @npmcli/npx-test', async t => { 134 const registry = new MockRegistry({ 135 tap: t, 136 registry: 'https://registry.npmjs.org/', 137 }) 138 139 const manifest = registry.manifest({ name: '@npmcli/npx-test' }) 140 manifest.versions['1.0.0'].bin = { 'npx-test': 'index.js' } 141 142 const { npm } = await loadMockNpm(t, { 143 config: { 144 audit: false, 145 yes: false, 146 }, 147 prefixDir: { 148 'npm-exec-test': { 149 'package.json': JSON.stringify(manifest), 150 'index.js': `#!/usr/bin/env node 151 require('fs').writeFileSync('npm-exec-test-success', '')`, 152 }, 153 }, 154 }) 155 156 try { 157 await npm.exec('exec', ['@npmcli/npx-test']) 158 t.fail('Expected error was not thrown') 159 } catch (error) { 160 t.match( 161 error.message, 162 'npx canceled due to missing packages and no YES option: ', 163 'Expected error message thrown' 164 ) 165 } 166}) 167