1'use strict' 2var Bluebird = require('bluebird') 3var test = require('tap').test 4var fs = require('fs') 5var mkdirp = require('mkdirp') 6var rimraf = require('rimraf') 7var path = require('path') 8var common = require('../common-tap.js') 9 10var testname = path.basename(__filename, '.js') 11var testdir = common.pkg 12var testmod = path.resolve(testdir, 'top-test') 13var testtgz = testmod + '-1.0.0.tgz' 14 15var bundleupdatesrc = path.resolve(testmod, 'bundle-update') 16var bundleupdatetgz = bundleupdatesrc + '-1.0.0.tgz' 17var bundleupdateNEW = path.resolve(bundleupdatesrc, 'NEW') 18var bundleupdateNEWpostinstall = path.resolve(testdir, 'node_modules', 'bundle-update', 'NEW') 19var bundleupdatebad = path.resolve(testmod, 'node_modules', 'bundle-update') 20 21var bundlekeepsrc = path.resolve(testmod, 'bundle-keep') 22var bundlekeeptgz = bundlekeepsrc + '-1.0.0.tgz' 23var bundlekeep = path.resolve(testmod, 'node_modules', 'bundle-keep') 24var bundlekeepOLD = path.resolve(bundlekeep, 'OLD') 25var bundlekeepOLDpostinstall = path.resolve(testdir, 'node_modules', 'top-test', 'node_modules', 'bundle-keep', 'OLD') 26 27var bundledeepsrc = path.resolve(testmod, 'bundle-deep') 28var bundledeeptgz = bundledeepsrc + '-1.0.0.tgz' 29var bundledeep = path.resolve(testmod, 'node_modules', 'bundle-deep') 30var bundledeepOLD = path.resolve(bundledeep, 'OLD') 31var bundledeepOLDpostinstall = path.resolve(testdir, 'node_modules', 'top-test', 'node_modules', 'bundle-deep', 'OLD') 32 33var bundledeepupdatesrc = path.resolve(testmod, 'bundle-deep-update') 34var bundledeepupdatetgz = bundledeepupdatesrc + '-1.0.0.tgz' 35var bundledeepupdate = path.resolve(bundledeep, 'node_modules', 'bundle-deep-update') 36var bundledeepupdateNEW = path.resolve(bundledeepupdatesrc, 'NEW') 37var bundledeepupdateNEWpostinstall = path.resolve(testdir, 'node_modules', 'bundle-deep-update', 'NEW') 38 39var testjson = { 40 dependencies: {'top-test': 'file:' + testtgz} 41} 42 43var testmodjson = { 44 name: 'top-test', 45 version: '1.0.0', 46 dependencies: { 47 'bundle-update': bundleupdatetgz, 48 'bundle-keep': bundlekeeptgz, 49 'bundle-deep': bundledeeptgz 50 }, 51 bundledDependencies: ['bundle-update', 'bundle-keep', 'bundle-deep'], 52 files: ['OLD', 'NEW'] 53} 54var bundlejson = { 55 name: 'bundle-update', 56 version: '1.0.0', 57 files: ['OLD', 'NEW'] 58} 59 60var bundlekeepjson = { 61 name: 'bundle-keep', 62 version: '1.0.0', 63 _requested: { 64 rawSpec: bundlekeeptgz 65 }, 66 _resolved: bundlekeeptgz, 67 _shasum: 'baadf00d', 68 files: ['OLD', 'NEW'] 69 70} 71var bundledeepjson = { 72 name: 'bundle-deep', 73 version: '1.0.0', 74 dependencies: { 75 'bundle-deep-update': bundledeepupdatetgz 76 }, 77 _requested: { 78 rawSpec: bundledeeptgz 79 }, 80 _resolved: bundlekeeptgz, 81 _shasum: 'deadbeef', 82 files: ['OLD', 'NEW'] 83 84} 85 86var bundledeepupdatejson = { 87 version: '1.0.0', 88 name: 'bundle-deep-update', 89 files: ['OLD', 'NEW'] 90 91} 92 93function writepjs (dir, content) { 94 fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify(content, null, 2)) 95} 96 97function setup () { 98 mkdirp.sync(testdir) 99 writepjs(testdir, testjson) 100 mkdirp.sync(testmod) 101 writepjs(testmod, testmodjson) 102 103 mkdirp.sync(bundleupdatesrc) 104 writepjs(bundleupdatesrc, bundlejson) 105 fs.writeFileSync(bundleupdateNEW, '') 106 mkdirp.sync(bundleupdatebad) 107 writepjs(bundleupdatebad, bundlejson) 108 109 mkdirp.sync(bundlekeepsrc) 110 writepjs(bundlekeepsrc, bundlekeepjson) 111 mkdirp.sync(bundlekeep) 112 writepjs(bundlekeep, bundlekeepjson) 113 fs.writeFileSync(bundlekeepOLD, '') 114 115 mkdirp.sync(bundledeepsrc) 116 writepjs(bundledeepsrc, bundledeepjson) 117 mkdirp.sync(bundledeep) 118 writepjs(bundledeep, bundledeepjson) 119 fs.writeFileSync(bundledeepOLD, '') 120 121 mkdirp.sync(bundledeepupdatesrc) 122 writepjs(bundledeepupdatesrc, bundledeepupdatejson) 123 mkdirp.sync(bundledeepupdate) 124 writepjs(bundledeepupdate, bundledeepupdatejson) 125 fs.writeFileSync(bundledeepupdateNEW, '') 126} 127 128function cleanup () { 129 rimraf.sync(testdir) 130} 131 132test('setup', function (t) { 133 cleanup() 134 setup() 135 return Bluebird.all([ 136 common.npm(['pack', bundleupdatesrc], {cwd: path.dirname(bundleupdatetgz), stdio: 'inherit'}), 137 common.npm(['pack', bundlekeepsrc], {cwd: path.dirname(bundlekeeptgz), stdio: 'inherit'}), 138 common.npm(['pack', bundledeepupdatesrc], {cwd: path.dirname(bundledeepupdatetgz), stdio: 'inherit'}) 139 ]).map((result) => result[0]).spread((bundleupdate, bundlekeep, bundledeepupdate) => { 140 t.is(bundleupdate, 0, 'bundleupdate') 141 t.is(bundlekeep, 0, 'bundlekeep') 142 t.is(bundledeepupdate, 0, 'bundledeepupdate') 143 }).then(() => { 144 return common.npm(['pack', bundledeepsrc], {cwd: path.dirname(bundledeeptgz), stdio: 'inherit'}) 145 }).spread((code) => { 146 t.is(code, 0, 'bundledeep') 147 return common.npm(['pack', testmod], {cwd: path.dirname(testtgz), stdio: 'inherit'}) 148 }).spread((code) => { 149 t.is(code, 0, 'testmod') 150 }) 151}) 152 153test('bundled', function (t) { 154 common.npm(['install', '--loglevel=verbose'], {cwd: testdir}, function (err, code, stdout, stderr) { 155 if (err) throw err 156 t.plan(9) 157 t.is(code, 0, 'npm itself completed ok') 158 159 // This tests that after the install we have a freshly installed version 160 // of `bundle-update` (in alignment with the package.json), instead of the 161 // version that was bundled with `top-test`. 162 // If npm doesn't do this, and selects the bundled version, things go very 163 // wrong because npm thinks it has a different module (with different 164 // metadata) installed in that location and will go off and try to do 165 // _things_ to it. Things like chmod in particular, which in turn results 166 // in the dreaded ENOENT errors. 167 t.like(stderr, new RegExp('npm WARN ' + testname), "didn't stomp on other warnings") 168 t.like(stderr, /npm verb.*bundle-update/, 'included update warning about bundled dep') 169 t.like(stderr, /npm verb.*bundle-deep-update/, 'included update warning about deeply bundled dep') 170 t.like(stderr, /npm WARN top-test@1\.0\.0 had bundled packages that do not match/, 'single grouped warning') 171 fs.stat(bundleupdateNEWpostinstall, function (missing) { 172 t.ok(!missing, 'package.json overrode bundle') 173 }) 174 fs.stat(bundledeepupdateNEWpostinstall, function (missing) { 175 t.ok(!missing, 'deep package.json overrode bundle') 176 }) 177 // Relatedly, when upgrading, if a bundled module is replacing an existing 178 // module we want to choose the bundled version, not the version we're replacing. 179 fs.stat(bundlekeepOLDpostinstall, function (missing) { 180 t.ok(!missing, 'no override when package.json matches') 181 }) 182 fs.stat(bundledeepOLDpostinstall, function (missing) { 183 t.ok(!missing, 'deep no override when package.json matches') 184 }) 185 }) 186}) 187 188test('cleanup', function (t) { 189 cleanup() 190 t.end() 191}) 192