1const t = require('tap') 2const fs = require('fs') 3const { resolve } = require('path') 4const setupMockNpm = require('../../fixtures/mock-npm') 5 6t.test('no args', async t => { 7 const { npm, joinedOutput, prefix: path } = await setupMockNpm(t, { 8 prefixDir: { 9 node_modules: { 10 a: { 11 'package.json': JSON.stringify({ 12 name: 'a', 13 version: '1.0.0', 14 bin: 'cwd', 15 scripts: { 16 preinstall: "node -e \"require('fs').writeFileSync('cwd', '')\"", 17 }, 18 }), 19 }, 20 b: { 21 'package.json': JSON.stringify({ 22 name: 'b', 23 version: '1.0.0', 24 bin: 'cwd', 25 scripts: { 26 preinstall: "node -e \"require('fs').writeFileSync('cwd', '')\"", 27 }, 28 }), 29 }, 30 }, 31 }, 32 }) 33 34 const aBuildFile = resolve(path, 'node_modules/a/cwd') 35 const bBuildFile = resolve(path, 'node_modules/b/cwd') 36 const aBinFile = resolve(path, 'node_modules/.bin/a') 37 const bBinFile = resolve(path, 'node_modules/.bin/b') 38 t.throws(() => fs.statSync(aBuildFile)) 39 t.throws(() => fs.statSync(bBuildFile)) 40 t.throws(() => fs.statSync(aBinFile)) 41 t.throws(() => fs.statSync(bBinFile)) 42 43 await npm.exec('rebuild', []) 44 45 t.ok(() => fs.statSync(aBuildFile)) 46 t.ok(() => fs.statSync(bBuildFile)) 47 t.ok(() => fs.statSync(aBinFile)) 48 t.ok(() => fs.statSync(bBinFile)) 49 50 t.equal( 51 joinedOutput(), 52 'rebuilt dependencies successfully', 53 'should output success msg' 54 ) 55}) 56 57t.test('filter by pkg name', async t => { 58 const { npm, prefix: path } = await setupMockNpm(t, { 59 prefixDir: { 60 node_modules: { 61 a: { 62 'index.js': '', 63 'package.json': JSON.stringify({ 64 name: 'a', 65 version: '1.0.0', 66 bin: 'index.js', 67 }), 68 }, 69 b: { 70 'index.js': '', 71 'package.json': JSON.stringify({ 72 name: 'b', 73 version: '1.0.0', 74 bin: 'index.js', 75 }), 76 }, 77 }, 78 }, 79 }) 80 81 const aBinFile = resolve(path, 'node_modules/.bin/a') 82 const bBinFile = resolve(path, 'node_modules/.bin/b') 83 t.throws(() => fs.statSync(aBinFile)) 84 t.throws(() => fs.statSync(bBinFile)) 85 86 await npm.exec('rebuild', ['b']) 87 88 t.throws(() => fs.statSync(aBinFile), 'should not link a bin') 89 t.ok(() => fs.statSync(bBinFile), 'should link filtered pkg bin') 90}) 91 92t.test('filter by pkg@<range>', async t => { 93 const { npm, prefix: path } = await setupMockNpm(t, { 94 prefixDir: { 95 node_modules: { 96 a: { 97 'index.js': '', 98 'package.json': JSON.stringify({ 99 name: 'a', 100 version: '1.0.0', 101 bin: 'index.js', 102 }), 103 node_modules: { 104 b: { 105 'index.js': '', 106 'package.json': JSON.stringify({ 107 name: 'b', 108 version: '2.0.0', 109 bin: 'index.js', 110 }), 111 }, 112 }, 113 }, 114 b: { 115 'index.js': '', 116 'package.json': JSON.stringify({ 117 name: 'b', 118 version: '1.0.0', 119 bin: 'index.js', 120 }), 121 }, 122 }, 123 }, 124 }) 125 126 const bBinFile = resolve(path, 'node_modules/.bin/b') 127 const nestedBinFile = resolve(path, 'node_modules/a/node_modules/.bin/b') 128 129 await npm.exec('rebuild', ['b@2']) 130 131 t.throws(() => fs.statSync(bBinFile), 'should not link b bin') 132 t.ok(() => fs.statSync(nestedBinFile), 'should link filtered pkg bin') 133}) 134 135t.test('filter by directory', async t => { 136 const { npm, prefix: path } = await setupMockNpm(t, { 137 prefixDir: { 138 node_modules: { 139 a: { 140 'index.js': '', 141 'package.json': JSON.stringify({ 142 name: 'a', 143 version: '1.0.0', 144 bin: 'index.js', 145 }), 146 }, 147 b: { 148 'index.js': '', 149 'package.json': JSON.stringify({ 150 name: 'b', 151 version: '1.0.0', 152 bin: 'index.js', 153 }), 154 }, 155 }, 156 }, 157 }) 158 159 const aBinFile = resolve(path, 'node_modules/.bin/a') 160 const bBinFile = resolve(path, 'node_modules/.bin/b') 161 t.throws(() => fs.statSync(aBinFile)) 162 t.throws(() => fs.statSync(bBinFile)) 163 164 await npm.exec('rebuild', ['file:node_modules/b']) 165 166 t.throws(() => fs.statSync(aBinFile), 'should not link a bin') 167 t.ok(() => fs.statSync(bBinFile), 'should link filtered pkg bin') 168}) 169 170t.test('filter must be a semver version/range, or directory', async t => { 171 const { npm } = await setupMockNpm(t) 172 173 await t.rejects( 174 npm.exec('rebuild', ['git+ssh://github.com/npm/arborist']), 175 /`npm rebuild` only supports SemVer version\/range specifiers/, 176 'should throw type error' 177 ) 178}) 179 180t.test('global prefix', async t => { 181 const { npm, globalPrefix, joinedOutput } = await setupMockNpm(t, { 182 config: { 183 global: true, 184 }, 185 globalPrefixDir: { 186 node_modules: { 187 a: { 188 'index.js': '', 189 'package.json': JSON.stringify({ 190 name: 'a', 191 version: '1.0.0', 192 bin: 'index.js', 193 }), 194 }, 195 }, 196 }, 197 }) 198 199 await npm.exec('rebuild', []) 200 t.ok(() => fs.statSync(resolve(globalPrefix, 'lib/node_modules/.bin/a'))) 201 202 t.equal( 203 joinedOutput(), 204 'rebuilt dependencies successfully', 205 'should output success msg' 206 ) 207}) 208