diff options
Diffstat (limited to 'deps/npm/test')
39 files changed, 1944 insertions, 156 deletions
diff --git a/deps/npm/test/common-tap.js b/deps/npm/test/common-tap.js index 847c87ba0f..14c1581f78 100644 --- a/deps/npm/test/common-tap.js +++ b/deps/npm/test/common-tap.js @@ -45,6 +45,7 @@ exports.npm = function (cmd, opts, cb) { if (!opts.env.npm_config_cache) { opts.env.npm_config_cache = npm_config_cache } + nodeBin = opts.nodeExecPath || nodeBin var stdout = '' var stderr = '' diff --git a/deps/npm/test/tap/bearer-token-check.js b/deps/npm/test/network/bearer-token-check.js index 8ddbec29a4..8ddbec29a4 100644 --- a/deps/npm/test/tap/bearer-token-check.js +++ b/deps/npm/test/network/bearer-token-check.js diff --git a/deps/npm/test/tap/git-cache-locking.js b/deps/npm/test/network/git-cache-locking.js index 29ab5709b9..29ab5709b9 100644 --- a/deps/npm/test/tap/git-cache-locking.js +++ b/deps/npm/test/network/git-cache-locking.js diff --git a/deps/npm/test/tap/git-cache-no-hooks.js b/deps/npm/test/network/git-cache-no-hooks.js index 0021064cea..0021064cea 100644 --- a/deps/npm/test/tap/git-cache-no-hooks.js +++ b/deps/npm/test/network/git-cache-no-hooks.js diff --git a/deps/npm/test/tap/it.js b/deps/npm/test/network/it.js index 6fc2a6fd49..6fc2a6fd49 100644 --- a/deps/npm/test/tap/it.js +++ b/deps/npm/test/network/it.js diff --git a/deps/npm/test/tap/legacy-bundled-git.js b/deps/npm/test/network/legacy-bundled-git.js index 15fbac84ea..15fbac84ea 100644 --- a/deps/npm/test/tap/legacy-bundled-git.js +++ b/deps/npm/test/network/legacy-bundled-git.js diff --git a/deps/npm/test/tap/legacy-optional-deps.js b/deps/npm/test/network/legacy-optional-deps.js index 80ad7cc47e..80ad7cc47e 100644 --- a/deps/npm/test/tap/legacy-optional-deps.js +++ b/deps/npm/test/network/legacy-optional-deps.js diff --git a/deps/npm/test/tap/legacy-shrinkwrap.js b/deps/npm/test/network/legacy-shrinkwrap.js index 6f53030377..6f53030377 100644 --- a/deps/npm/test/tap/legacy-shrinkwrap.js +++ b/deps/npm/test/network/legacy-shrinkwrap.js diff --git a/deps/npm/test/tap/legacy-url-dep.js b/deps/npm/test/network/legacy-url-dep.js index 46378cd3ef..46378cd3ef 100644 --- a/deps/npm/test/tap/legacy-url-dep.js +++ b/deps/npm/test/network/legacy-url-dep.js diff --git a/deps/npm/test/tap/outdated-symlink.js b/deps/npm/test/network/outdated-symlink.js index 809cfec2e2..809cfec2e2 100644 --- a/deps/npm/test/tap/outdated-symlink.js +++ b/deps/npm/test/network/outdated-symlink.js diff --git a/deps/npm/test/tap/registry.js b/deps/npm/test/network/registry.js index d8ec4a204e..d8ec4a204e 100644 --- a/deps/npm/test/tap/registry.js +++ b/deps/npm/test/network/registry.js diff --git a/deps/npm/test/tap/404-private-registry-scoped.js b/deps/npm/test/tap/404-private-registry-scoped.js index 84251b113c..0f0cbc4ec7 100644 --- a/deps/npm/test/tap/404-private-registry-scoped.js +++ b/deps/npm/test/tap/404-private-registry-scoped.js @@ -1,9 +1,24 @@ var test = require('tap').test +var path = require('path') +var mkdirp = require('mkdirp') +var rimraf = require('rimraf') var common = require('../common-tap.js') var mr = require('npm-registry-mock') var server +var testdir = path.join(__dirname, path.basename(__filename, '.js')) + +function setup () { + cleanup() + mkdirp.sync(testdir) +} + +function cleanup () { + rimraf.sync(testdir) +} + test('setup', function (t) { + setup() mr({port: common.port, throwOnUnmatched: true}, function (err, s) { t.ifError(err, 'registry mocked successfully') server = s @@ -12,8 +27,11 @@ test('setup', function (t) { }) test('scoped package names not mangled on error with non-root registry', function (t) { + server.get('/@scope%2ffoo').reply(404, {}) common.npm( [ + '--registry=' + common.registry, + '--cache=' + testdir, 'cache', 'add', '@scope/foo@*', @@ -23,16 +41,17 @@ test('scoped package names not mangled on error with non-root registry', functio function (er, code, stdout, stderr) { t.ifError(er, 'correctly handled 404') t.equal(code, 1, 'exited with error') - t.match(stderr, /404 Not found/, 'should notify the sort of error as a 404') + t.match(stderr, /E404/, 'should notify the sort of error as a 404') t.match(stderr, /@scope\/foo/, 'should have package name in error') + server.done() t.end() } ) }) test('cleanup', function (t) { - t.pass('cleaned up') - server.done() server.close() + cleanup() + t.pass('cleaned up') t.end() }) diff --git a/deps/npm/test/tap/404-private-registry.js b/deps/npm/test/tap/404-private-registry.js index a30f61432a..a38fa02c12 100644 --- a/deps/npm/test/tap/404-private-registry.js +++ b/deps/npm/test/tap/404-private-registry.js @@ -1,13 +1,25 @@ -require('../common-tap') var test = require('tap').test var path = require('path') +var mkdirp = require('mkdirp') +var rimraf = require('rimraf') var common = require('../common-tap.js') var mr = require('npm-registry-mock') var server var packageName = path.basename(__filename, '.js') +var testdir = path.join(__dirname, packageName) + +function setup () { + cleanup() + mkdirp.sync(testdir) +} + +function cleanup () { + rimraf.sync(testdir) +} test('setup', function (t) { + setup() mr({port: common.port, throwOnUnmatched: true}, function (err, s) { t.ifError(err, 'registry mocked successfully') server = s @@ -16,8 +28,11 @@ test('setup', function (t) { }) test('package names not mangled on error with non-root registry', function (t) { + server.get('/' + packageName).reply(404, {}) common.npm( [ + '--registry=' + common.registry, + '--cache=' + testdir, 'cache', 'add', packageName + '@*' @@ -27,14 +42,15 @@ test('package names not mangled on error with non-root registry', function (t) { t.ifError(er, 'correctly handled 404') t.equal(code, 1, 'exited with error') t.match(stderr, packageName, 'should have package name in error') + server.done() t.end() } ) }) test('cleanup', function (t) { - t.pass('cleaned up') - server.done() server.close() + cleanup() + t.pass('cleaned up') t.end() }) diff --git a/deps/npm/test/tap/add-local.js b/deps/npm/test/tap/add-local.js new file mode 100644 index 0000000000..cc615b8997 --- /dev/null +++ b/deps/npm/test/tap/add-local.js @@ -0,0 +1,137 @@ +var path = require('path') +var test = require('tap').test +var mkdirp = require('mkdirp') +var osenv = require('osenv') +var rimraf = require('rimraf') +var requireInject = require('require-inject') + +var pkg = path.join(__dirname, '/local-dir') +var cache = path.join(pkg, '/cache') +var tmp = path.join(pkg, '/tmp') +var prefix = path.join(pkg, '/prefix') + +var Tacks = require('tacks') +var File = Tacks.File +var Dir = Tacks.Dir + +test('addLocal directory race on Windows', function (t) { + setup() + var p = { + name: 'test', + version: '1.0.0', + type: 'directory', + spec: pkg + } + var fixture = new Tacks( + Dir({ + 'package.json': File(p) + }) + ) + var addLocal = requireInject('../../lib/cache/add-local', { + '../../lib/npm.js': { + cache: cache, + tmp: tmp, + prefix: prefix + }, + '../../lib/cache/get-stat': function (cb) { + cb(null, {}) + }, + chownr: function (x, y, z, cb) { + cb(new Error('chownr should never have been called')) + }, + '../../lib/cache/add-local-tarball.js': function (tgz, data, shasum, cb) { + cb(null) + }, + '../../lib/utils/lifecycle.js': function (data, cycle, p, cb) { + cb(null) + }, + '../../lib/utils/tar.js': { + pack: function (tgz, p, data, cb) { + cb(null) + } + }, + 'sha': { + get: function (tgz, cb) { + cb(null, 'deadbeef') + } + } + }) + + fixture.create(pkg) + addLocal(p, null, function (err) { + t.ifErr(err, 'addLocal completed without error') + t.done() + }) +}) + +test('addLocal temporary cache file race', function (t) { + // See https://github.com/npm/npm/issues/12669 + setup() + var p = { + name: 'test', + version: '1.0.0', + type: 'directory', + spec: pkg + } + var fixture = new Tacks( + Dir({ + 'package.json': File(p) + }) + ) + var addLocal = requireInject('../../lib/cache/add-local', { + // basic setup/mock stuff + '../../lib/npm.js': { + cache: cache, + tmp: tmp, + prefix: prefix + }, + '../../lib/cache/add-local-tarball.js': function (tgz, data, shasum, cb) { + cb(null) + }, + '../../lib/utils/lifecycle.js': function (data, cycle, p, cb) { + cb(null) + }, + '../../lib/utils/tar.js': { + pack: function (tgz, p, data, cb) { + cb(null) + } + }, + 'sha': { + get: function (tgz, cb) { + cb(null, 'deadbeef') + } + }, + + // Test-specific mocked values to simulate race. + '../../lib/cache/get-stat': function (cb) { + cb(null, {uid: 1, gid: 2}) + }, + chownr: function (x, y, z, cb) { + // Simulate a race condition between `tar.pack` and `chownr` + // where the latter will return `ENOENT` when an async process + // removes a file that its internal `fs.readdir` listed. + cb({code: 'ENOENT'}) + } + }) + + fixture.create(pkg) + addLocal(p, null, function (err) { + t.ifErr(err, 'addLocal completed without error') + t.done() + }) +}) + +test('cleanup', function (t) { + cleanup() + t.done() +}) + +function setup () { + mkdirp.sync(cache) + mkdirp.sync(tmp) +} + +function cleanup () { + process.chdir(osenv.tmpdir()) + rimraf.sync(pkg) +} diff --git a/deps/npm/test/tap/bundled-dependencies.js b/deps/npm/test/tap/bundled-dependencies.js new file mode 100644 index 0000000000..a49610e666 --- /dev/null +++ b/deps/npm/test/tap/bundled-dependencies.js @@ -0,0 +1,112 @@ +'use strict' +var test = require('tap').test +var common = require('../common-tap.js') +var path = require('path') +var rimraf = require('rimraf') +var mkdirp = require('mkdirp') +var fs = require('graceful-fs') +var tar = require('tar') +var zlib = require('zlib') +var basepath = path.resolve(__dirname, path.basename(__filename, '.js')) +var fixturepath = path.resolve(basepath, 'npm-test-bundled-deps') +var targetpath = path.resolve(basepath, 'target') +var Tacks = require('tacks') +var File = Tacks.File +var Dir = Tacks.Dir + +test('basic bundling', function (t) { + var fixture = new Tacks( + Dir({ + 'package.json': File({ + name: 'npm-test-files', + version: '1.2.5', + bundledDependencies: [ + 'addme' + ] + }), + node_modules: Dir({ + addme: Dir({ + 'index.js': File('') + }), + iggyme: Dir({ + 'index.js': File('') + }) + }) + }) + ) + withFixture(t, fixture, function (done) { + t.ok(fileExists('node_modules/addme'), 'bundled dep included') + t.notOk(fileExists('node_modules/iggyme'), 'unspecified dep not included') + done() + }) +}) + +test('scoped dep bundling', function (t) { + var fixture = new Tacks( + Dir({ + 'package.json': File({ + name: 'npm-test-files', + version: '1.2.5', + bundledDependencies: [ + '@foo/addme' + ] + }), + node_modules: Dir({ + '@foo': Dir({ + addme: Dir({ + 'index.js': File('') + }), + iggyme: Dir({ + 'index.js': File('') + }) + }) + }) + }) + ) + withFixture(t, fixture, function (done) { + t.ok(fileExists('node_modules/@foo/addme'), 'bundled dep included') + t.notOk( + fileExists('node_modules/@foo/iggyme'), + 'unspecified dep not included') + done() + }) +}) + +function fileExists (file) { + try { + return !!fs.statSync(path.resolve(targetpath, 'package', file)) + } catch (_) { + return false + } +} + +function withFixture (t, fixture, tester) { + fixture.create(fixturepath) + mkdirp.sync(targetpath) + common.npm(['pack', fixturepath], {cwd: basepath}, extractAndCheck) + function extractAndCheck (err, code) { + if (err) throw err + t.is(code, 0, 'pack went ok') + extractTarball(checkTests) + } + function checkTests (err) { + if (err) throw err + tester(removeAndDone) + } + function removeAndDone (err) { + if (err) throw err + fixture.remove(fixturepath) + rimraf.sync(basepath) + t.done() + } +} + +function extractTarball (cb) { + // Unpack to disk so case-insensitive filesystems are consistent + fs.createReadStream(path.join(basepath, 'npm-test-files-1.2.5.tgz')) + .pipe(zlib.Unzip()) + .on('error', cb) + .pipe(tar.Extract(targetpath)) + .on('error', cb) + .on('end', function () { cb() }) +} diff --git a/deps/npm/test/tap/correct-mkdir.js b/deps/npm/test/tap/correct-mkdir.js index 4bfc6b1c97..a4f8659873 100644 --- a/deps/npm/test/tap/correct-mkdir.js +++ b/deps/npm/test/tap/correct-mkdir.js @@ -56,3 +56,108 @@ test('correct-mkdir: no race conditions', function (t) { // Immediate call again in case of race condition there correctMkdir(cache_dir, handleCallFinish) }) + +test('correct-mkdir: ignore ENOENTs from chownr', function (t) { + var mock_fs = {} + mock_fs.stat = function (path, cb) { + if (path === cache_dir) { + cb(null, { + isDirectory: function () { + return true + } + }) + } else { + assert.ok(false, 'Unhandled stat path: ' + path) + } + } + var mock_chownr = function (path, uid, gid, cb) { + cb({code: 'ENOENT'}) + } + var mocks = { + 'graceful-fs': mock_fs, + 'chownr': mock_chownr + } + var correctMkdir = requireInject('../../lib/utils/correct-mkdir.js', mocks) + + function handleCallFinish (err) { + t.ifErr(err, 'chownr\'s ENOENT errors were ignored') + t.end() + } + correctMkdir(cache_dir, handleCallFinish) +}) + +// NEED TO RUN LAST + +// These test checks that Windows users are protected by crashes related to +// unexpectedly having a UID/GID other than 0 if a user happens to add these +// variables to their environment. There are assumptions in correct-mkdir +// that special-case Windows by checking on UID-related things. +test('correct-mkdir: SUDO_UID and SUDO_GID non-Windows', function (t) { + process.env.SUDO_UID = 999 + process.env.SUDO_GID = 999 + process.getuid = function () { return 0 } + process.getgid = function () { return 0 } + var mock_fs = {} + mock_fs.stat = function (path, cb) { + if (path === cache_dir) { + cb(null, { + uid: 0, + isDirectory: function () { + return true + } + }) + } else { + assert.ok(false, 'Unhandled stat path: ' + path) + } + } + var mock_chownr = function (path, uid, gid, cb) { + t.is(uid, +process.env.SUDO_UID, 'using the environment\'s UID') + t.is(gid, +process.env.SUDO_GID, 'using the environment\'s GID') + cb(null, {}) + } + var mocks = { + 'graceful-fs': mock_fs, + 'chownr': mock_chownr + } + var correctMkdir = requireInject('../../lib/utils/correct-mkdir.js', mocks) + + function handleCallFinish () { + t.end() + } + correctMkdir(cache_dir, handleCallFinish) +}) + +test('correct-mkdir: SUDO_UID and SUDO_GID Windows', function (t) { + process.env.SUDO_UID = 999 + process.env.SUDO_GID = 999 + delete process.getuid + delete process.getgid + var mock_fs = {} + mock_fs.stat = function (path, cb) { + if (path === cache_dir) { + cb(null, { + uid: 0, + isDirectory: function () { + return true + } + }) + } else { + assert.ok(false, 'Unhandled stat path: ' + path) + } + } + var mock_chownr = function (path, uid, gid, cb) { + t.fail('chownr should not be called at all on Windows') + cb('nope') + } + var mocks = { + 'graceful-fs': mock_fs, + 'chownr': mock_chownr + } + var correctMkdir = requireInject('../../lib/utils/correct-mkdir.js', mocks) + + function handleCallFinish (err) { + t.ifErr(err, 'chownr was not called because Windows') + t.end() + } + correctMkdir(cache_dir, handleCallFinish) +}) diff --git a/deps/npm/test/tap/files-and-ignores.js b/deps/npm/test/tap/files-and-ignores.js index a8f4b222b8..88d9d12922 100644 --- a/deps/npm/test/tap/files-and-ignores.js +++ b/deps/npm/test/tap/files-and-ignores.js @@ -404,7 +404,8 @@ test('certain files ignored unconditionally', function (t) { '.npmrc', '.foo.swp', '.DS_Store', - '._ohno' + '._ohno', + 'foo.orig' ] }), '.git': Dir({foo: File('')}), @@ -421,7 +422,8 @@ test('certain files ignored unconditionally', function (t) { '.foo.swp': File(''), '.DS_Store': Dir({foo: File('')}), '._ohno': File(''), - '._ohnoes': Dir({noes: File('')}) + '._ohnoes': Dir({noes: File('')}), + 'foo.orig': File('') }) ) withFixture(t, fixture, function (done) { @@ -440,6 +442,7 @@ test('certain files ignored unconditionally', function (t) { t.notOk(fileExists('.DS_Store'), '.DS_Store not included') t.notOk(fileExists('._ohno'), '._ohno not included') t.notOk(fileExists('._ohnoes'), '._ohnoes not included') + t.notOk(fileExists('foo.orig'), 'foo.orig not included') done() }) }) diff --git a/deps/npm/test/tap/full-warning-messages.js b/deps/npm/test/tap/full-warning-messages.js index 3c74c61d0c..6745ee3db2 100644 --- a/deps/npm/test/tap/full-warning-messages.js +++ b/deps/npm/test/tap/full-warning-messages.js @@ -94,8 +94,8 @@ test('tree-style', function (t) { t.notMatch(stdout, /modB/, 'modB not installed') var stderrlines = stderr.trim().split(/\n/) t.is(stderrlines.length, 2, 'two lines of warnings') - t.match(stderr, /Skipping failed optional dependency/, 'expected optional failure warning') - t.match(stderr, /Not compatible with your operating system or architecture/, 'reason for optional failure') + t.match(stderr, /SKIPPING OPTIONAL DEPENDENCY/, 'expected optional failure warning') + t.match(stderr, /Unsupported platform/, 'reason for optional failure') exists(t, modJoin(base, 'modA'), 'module A') notExists(t, modJoin(base, 'modB'), 'module B') t.done() diff --git a/deps/npm/test/tap/install-cli-only-shrinkwrap.js b/deps/npm/test/tap/install-cli-only-shrinkwrap.js new file mode 100644 index 0000000000..17ff1ec955 --- /dev/null +++ b/deps/npm/test/tap/install-cli-only-shrinkwrap.js @@ -0,0 +1,139 @@ +var fs = require('graceful-fs') +var path = require('path') +var existsSync = fs.existsSync || path.existsSync + +var mkdirp = require('mkdirp') +var osenv = require('osenv') +var rimraf = require('rimraf') +var test = require('tap').test + +var common = require('../common-tap.js') + +var pkg = path.join(__dirname, path.basename(__filename, '.js')) + +var EXEC_OPTS = { cwd: pkg } + +var json = { + name: 'install-cli-only-shrinkwrap', + description: 'fixture', + version: '0.0.0', + dependencies: { + dependency: 'file:./dependency' + }, + devDependencies: { + 'dev-dependency': 'file:./dev-dependency' + } +} + +var shrinkwrap = { + name: 'install-cli-only-shrinkwrap', + description: 'fixture', + version: '0.0.0', + dependencies: { + dependency: { + version: '0.0.0', + from: 'file:./dependency' + }, + 'dev-dependency': { + version: '0.0.0', + from: 'file:./dev-dependency', + dev: true + } + } +} + +var dependency = { + name: 'dependency', + description: 'fixture', + version: '0.0.0' +} + +var devDependency = { + name: 'dev-dependency', + description: 'fixture', + version: '0.0.0' +} + +test('setup', function (t) { + setup() + t.pass('setup ran') + t.end() +}) + +test('\'npm install --only=development\' should only install devDependencies', function (t) { + common.npm(['install', '--only=development'], EXEC_OPTS, function (err, code, stderr, stdout) { + if (err) throw err + t.comment(stdout.trim()) + t.comment(stderr.trim()) + t.is(code, 0, 'npm install did not raise error code') + t.ok( + existsSync( + path.resolve(pkg, 'node_modules/dev-dependency/package.json') + ), + 'devDependency was installed' + ) + t.notOk( + existsSync(path.resolve(pkg, 'node_modules/dependency/package.json')), + 'dependency was NOT installed' + ) + t.end() + }) +}) + +test('\'npm install --only=production\' should only install dependencies', function (t) { + cleanup() + setup() + common.npm(['install', '--only=production'], EXEC_OPTS, function (err, code, stdout, stderr) { + if (err) throw err + t.comment(stdout.trim()) + t.comment(stderr.trim()) + t.is(code, 0, 'npm install did not raise error code') + t.ok( + existsSync( + path.resolve(pkg, 'node_modules/dependency/package.json') + ), + 'dependency was installed' + ) + t.notOk( + existsSync(path.resolve(pkg, 'node_modules/dev-dependency/package.json')), + 'devDependency was NOT installed' + ) + t.end() + }) +}) + +test('cleanup', function (t) { + cleanup() + t.pass('cleaned up') + t.end() +}) + +function setup () { + mkdirp.sync(path.join(pkg, 'dependency')) + fs.writeFileSync( + path.join(pkg, 'dependency', 'package.json'), + JSON.stringify(dependency, null, 2) + ) + + mkdirp.sync(path.join(pkg, 'dev-dependency')) + fs.writeFileSync( + path.join(pkg, 'dev-dependency', 'package.json'), + JSON.stringify(devDependency, null, 2) + ) + + mkdirp.sync(path.join(pkg, 'node_modules')) + fs.writeFileSync( + path.join(pkg, 'package.json'), + JSON.stringify(json, null, 2) + ) + fs.writeFileSync( + path.join(pkg, 'npm-shrinkwrap.json'), + JSON.stringify(shrinkwrap, null, 2) + ) + process.chdir(pkg) +} + +function cleanup () { + process.chdir(osenv.tmpdir()) + rimraf.sync(pkg) +} diff --git a/deps/npm/test/tap/install-parse-error.js b/deps/npm/test/tap/install-parse-error.js index b142abb39a..72d19efc25 100644 --- a/deps/npm/test/tap/install-parse-error.js +++ b/deps/npm/test/tap/install-parse-error.js @@ -49,3 +49,4 @@ test('cleanup', function (t) { cleanup() t.end() }) + diff --git a/deps/npm/test/tap/install-property-conflicts.js b/deps/npm/test/tap/install-property-conflicts.js new file mode 100644 index 0000000000..8f293885ab --- /dev/null +++ b/deps/npm/test/tap/install-property-conflicts.js @@ -0,0 +1,74 @@ +var fs = require('fs') +var resolve = require('path').resolve + +var osenv = require('osenv') +var mkdirp = require('mkdirp') +var rimraf = require('rimraf') +var test = require('tap').test + +var common = require('../common-tap.js') + +var pkg = resolve(__dirname, 'install-property-conflicts') +var target = resolve(pkg, '_target') + +var EXEC_OPTS = { + cwd: target +} + +var json = { + name: 'install-property-conflicts', + version: '1.2.3', + type: 'nose-boop!' +} + +test('setup', function (t) { + setup() + t.pass('setup ran') + t.end() +}) + +test('install package with a `type` property', function (t) { + t.comment('issue: https://github.com/npm/npm/issues/11398') + common.npm( + [ + 'install', + '--prefix', target, + pkg + ], + EXEC_OPTS, + function (err, code, stdout, stderr) { + t.ifError(err, 'npm command ran from test') + t.equals(code, 0, 'install exited with success (0)') + var installedPkg = resolve( + target, + 'node_modules', + 'install-property-conflicts', + 'package.json') + t.ok(fs.statSync(installedPkg), 'package installed successfully') + t.end() + } + ) +}) + +test('clean', function (t) { + cleanup() + t.pass('cleaned up') + t.end() +}) + +function setup () { + cleanup() + mkdirp.sync(pkg) + // make sure it installs locally + mkdirp.sync(resolve(target, 'node_modules')) + fs.writeFileSync( + resolve(pkg, 'package.json'), + JSON.stringify(json, null, 2) + '\n' + ) +} + +function cleanup () { + process.chdir(osenv.tmpdir()) + rimraf.sync(pkg) + rimraf.sync(target) +} diff --git a/deps/npm/test/tap/install-shrinkwrapped-git.js b/deps/npm/test/tap/install-shrinkwrapped-git.js new file mode 100644 index 0000000000..34875ffb65 --- /dev/null +++ b/deps/npm/test/tap/install-shrinkwrapped-git.js @@ -0,0 +1,159 @@ +var fs = require('fs') +var path = require('path') +var resolve = path.resolve +var osenv = require('osenv') +var mkdirp = require('mkdirp') +var rimraf = require('rimraf') +var test = require('tap').test +var npm = require('../../lib/npm') +var common = require('../common-tap') +var chain = require('slide').chain + +var mockPath = resolve(__dirname, 'install-shrinkwrapped') +var parentPath = resolve(mockPath, 'parent') +var parentNodeModulesPath = path.join(parentPath, 'node_modules') +var outdatedNodeModulesPath = resolve(mockPath, 'node-modules-backup') +var childPath = resolve(mockPath, 'child.git') + +var gitDaemon +var gitDaemonPID +var git + +var parentPackageJSON = JSON.stringify({ + name: 'parent', + version: '0.1.0' +}) + +var childPackageJSON = JSON.stringify({ + name: 'child', + version: '0.1.0' +}) + +test('setup', function (t) { + setup(function (err, result) { + t.ifError(err, 'git started up successfully') + + if (!err) { + gitDaemon = result[result.length - 2] + gitDaemonPID = result[result.length - 1] + } + + t.end() + }) +}) + +test('shrinkwrapped git dependency got updated', function (t) { + t.comment('test for https://github.com/npm/npm/issues/12718') + + // Prepare the child package git repo with two commits + prepareChildAndGetRefs(function (refs) { + chain([ + // Install & shrinkwrap child package's first commit + [npm.commands.install, ['git://localhost:1234/child.git#' + refs[0]]], + [npm.commands.shrinkwrap, []], + // Backup node_modules with the first commit + [fs.rename, parentNodeModulesPath, outdatedNodeModulesPath], + // Install & shrinkwrap child package's second commit + [npm.commands.install, ['git://localhost:1234/child.git#' + refs[1]]], + [npm.commands.shrinkwrap, []], + // Restore node_modules with the first commit + [rimraf, parentNodeModulesPath], + [fs.rename, outdatedNodeModulesPath, parentNodeModulesPath], + // Update node_modules + [npm.commands.install, []] + ], function () { + var childPackageJSON = require(path.join(parentNodeModulesPath, 'child', 'package.json')) + t.equal( + childPackageJSON._resolved, + 'git://localhost:1234/child.git#' + refs[1], + "Child package wasn't updated" + ) + t.end() + }) + }) +}) + +test('clean', function (t) { + gitDaemon.on('close', function () { + cleanup() + t.end() + }) + process.kill(gitDaemonPID) +}) + +function setup (cb) { + // Setup parent package + mkdirp.sync(parentPath) + fs.writeFileSync(resolve(parentPath, 'package.json'), parentPackageJSON) + process.chdir(parentPath) + + // Setup child + mkdirp.sync(childPath) + fs.writeFileSync(resolve(childPath, 'package.json'), childPackageJSON) + + // Setup npm and then git + npm.load({ + registry: common.registry, + loglevel: 'silent', + save: true // Always install packages with --save + }, function () { + // It's important to initialize git after npm because it uses config + initializeGit(cb) + }) +} + +function cleanup () { + process.chdir(osenv.tmpdir()) + rimraf.sync(mockPath) + rimraf.sync(common['npm_config_cache']) +} + +function prepareChildAndGetRefs (cb) { + var opts = { cwd: childPath, env: { PATH: process.env.PATH } } + chain([ + [fs.writeFile, path.join(childPath, 'README.md'), ''], + git.chainableExec(['add', 'README.md'], opts), + git.chainableExec(['commit', '-m', 'Add README'], opts), + git.chainableExec(['log', '--pretty=format:"%H"', '-2'], opts) + ], function () { + var gitLogStdout = arguments[arguments.length - 1] + var refs = gitLogStdout[gitLogStdout.length - 1].split('\n').map(function (ref) { + return ref.match(/^"(.+)"$/)[1] + }).reverse() // Reverse refs order: last, first -> first, last + cb(refs) + }) +} + +function initializeGit (cb) { + git = require('../../lib/utils/git') + common.makeGitRepo({ + path: childPath, + commands: [startGitDaemon] + }, cb) +} + +function startGitDaemon (cb) { + var daemon = git.spawn( + [ + 'daemon', + '--verbose', + '--listen=localhost', + '--export-all', + '--base-path=' + mockPath, // Path to the dir that contains child.git + '--reuseaddr', + '--port=1234' + ], + { + cwd: parentPath, + env: process.env, + stdio: ['pipe', 'pipe', 'pipe'] + } + ) + daemon.stderr.on('data', function findChild (c) { + var cpid = c.toString().match(/^\[(\d+)\]/) + if (cpid[1]) { + this.removeListener('data', findChild) + cb(null, [daemon, cpid[1]]) + } + }) +} diff --git a/deps/npm/test/tap/invalid-dep-version-filtering.js b/deps/npm/test/tap/invalid-dep-version-filtering.js new file mode 100644 index 0000000000..a4a872f54e --- /dev/null +++ b/deps/npm/test/tap/invalid-dep-version-filtering.js @@ -0,0 +1,135 @@ +'use strict' +var path = require('path') +var test = require('tap').test +var mr = require('npm-registry-mock') +var common = require('../common-tap') +var Tacks = require('tacks') +var File = Tacks.File +var Dir = Tacks.Dir + +var testdir = path.join(__dirname, path.basename(__filename, '.js')) +var cachedir = path.join(testdir, 'cache') + +var fixture = new Tacks(Dir({ + cache: Dir(), + node_modules: Dir(), + tarballs: Dir({ + 'pkgA.tgz': File(new Buffer( + '1f8b0800000000000003edcfcf0a0221100670cf3ec5e0396cfcb703bd8d' + + '842cb5e4ca5a5da2776f5da153b78408fc5d3e6684e133f9e3e4c7b04f35' + + 'e539cf9135868883b5509206b725ea3a6f9c01a634598d8e48134365d0e0' + + 'fadebac827b77cf5cb5ae5db3bf52bf0ce3ff1e00022fa4b100710691abd' + + 'd895cd3d2cf934c7b25412250afee4bfaeda755dd735f40211b5bced0008' + + '0000', + 'hex' + )), + 'pkgB1.tgz': File(new Buffer( + '1f8b0800000000000003edcfc10a0221140550d77ec5c375d8d3d111fa1b' + + '0b196ac891b16913fd7be308adda2544f0cee6e25d3caec99f463f847daa' + + '292f798aac3144ec8d8192aeb75ba2aeef8ded8029ed8c46eb1c1a86aa43' + + 'bd76d87ac8274bbef9799df2ed9dfa1578e79f78700011fd35880388340e' + + '47b12bcd3dccf93cc5522a8912057ff25f4f258410d2d00b247d22080008' + + '0000', + 'hex' + )) + }) +})) + +var pkgAtgz = path.join(testdir, 'tarballs', 'pkgA.tgz') +var pkgB1tgz = path.join(testdir, 'tarballs', 'pkgB1.tgz') + +var server + +var pkgA = { + name: 'pkg-a', + 'dist-tags': { + latest: '1.0.0' + }, + versions: { + '1.0.0': { + name: 'pkg-a', + version: '1.0.0', + dependencies: { + 'pkg-b': '1.0.0' + }, + dist: { + shasum: 'dc5471ce0439f0f47749bb01473cad4570cc7dc5', + tarball: common.registry + '/pkg-a/-/pkg-a-1.0.0.tgz' + } + } + } +} + +var pkgB = { + name: 'pkg-b', + 'dist-tags': { + latest: '1.0.0' + }, + versions: { + '1.0.0': { + name: 'pkg-b', + version: '1.0.0', + dist: { + shasum: '53031aa2cf774c0e841c6fdbbe54c13825cd5640', + tarball: common.registry + '/pkg-b/-/pkg-b-1.0.0.tgz' + } + }, + '1.0.0rc1': { + name: 'pkg-b', + version: '1.0.0rc1', + dist: { + shasum: '7f4b1bf680e3a31113d77619b4dc7c3b4c7dc15c', + tarball: common.registry + '/pkg-b/-/pkg-b-1.0.0-rc1.tgz' + } + } + } +} + +function setup () { + cleanup() + fixture.create(testdir) +} +function cleanup () { + fixture.remove(testdir) +} + +test('setup', function (t) { + setup() + mr({ port: common.port, throwOnUnmatched: true }, function (err, s) { + t.ifError(err, 'registry mocked successfully') + server = s + t.end() + }) +}) + +test('invalid versions should be ignored', function (t) { + server.get('/pkg-a').reply(200, pkgA) + server.get('/pkg-b').reply(200, pkgB) + server.get('/pkg-a/-/pkg-a-1.0.0.tgz').replyWithFile(200, pkgAtgz) + server.get('/pkg-b/-/pkg-b-1.0.0.tgz').replyWithFile(200, pkgB1tgz) + + common.npm( + [ + 'install', + '--cache', cachedir, + '--registry', common.registry, + '--fetch-retries=0', + 'pkg-a@1.0.0' + ], + {cwd: testdir}, + function (err, code, stdout, stderr) { + if (err) throw err + t.equal(code, 0, 'install succeded') + t.comment(stdout.trim()) + t.comment(stderr.trim()) + server.done() + t.end() + } + ) +}) + +test('cleanup', function (t) { + server.close() + cleanup() + t.end() +}) diff --git a/deps/npm/test/tap/lifecycle-order.js b/deps/npm/test/tap/lifecycle-order.js new file mode 100644 index 0000000000..903e1945d1 --- /dev/null +++ b/deps/npm/test/tap/lifecycle-order.js @@ -0,0 +1,57 @@ +var fs = require('graceful-fs') +var path = require('path') + +var mkdirp = require('mkdirp') +var osenv = require('osenv') +var rimraf = require('rimraf') +var test = require('tap').test + +var common = require('../common-tap.js') + +var pkg = path.resolve(__dirname, path.basename(__filename, '.js')) + +var json = { + name: 'lifecycle-order', + version: '1.0.0', + scripts: { + preinstall: 'node -e "var fs = require(\'fs\'); fs.openSync(\'preinstall-step\', \'w+\'); if (fs.existsSync(\'node_modules\')) { throw \'node_modules exists on preinstall\' }"', + install: 'node -e "var fs = require(\'fs\'); if (fs.existsSync(\'preinstall-step\')) { fs.openSync(\'install-step\', \'w+\') } else { throw \'Out of order\' }"', + postinstall: 'node -e "var fs = require(\'fs\'); if (fs.existsSync(\'install-step\')) { fs.openSync(\'postinstall-step\', \'w+\') } else { throw \'Out of order\' }"' + } +} + +test('setup', function (t) { + cleanup() + mkdirp.sync(pkg) + fs.writeFileSync( + path.join(pkg, 'package.json'), + JSON.stringify(json, null, 2) + ) + + process.chdir(pkg) + t.end() +}) + +test('lifecycle scripts execute in the proper order', function (t) { + common.npm('install', {cwd: pkg}, function (err, code, stdout, stderr) { + if (err) throw err + t.is(code, 0, 'no error') + + // All three files should exist + t.ok(fs.existsSync(path.join(pkg, 'preinstall-step')), 'preinstall ok') + t.ok(fs.existsSync(path.join(pkg, 'install-step')), 'install ok') + t.ok(fs.existsSync(path.join(pkg, 'postinstall-step')), 'postinstall ok') + + t.end() + }) +}) + +test('cleanup', function (t) { + cleanup() + t.end() +}) + +function cleanup () { + process.chdir(osenv.tmpdir()) + rimraf.sync(pkg) +} diff --git a/deps/npm/test/tap/lifecycle-path.js b/deps/npm/test/tap/lifecycle-path.js index 3264fe87be..684fd4d3b5 100644 --- a/deps/npm/test/tap/lifecycle-path.js +++ b/deps/npm/test/tap/lifecycle-path.js @@ -31,11 +31,33 @@ test('setup', function (t) { t.end() }) -test('make sure the path is correct', function (t) { +test('make sure the path is correct, without directory of current node', function (t) { + checkPath(false, t) +}) + +test('make sure the path is correct, with directory of current node', function (t) { + checkPath(true, t) +}) + +function checkPath (withDirOfCurrentNode, t) { + var newPATH = PATH + var currentNodeExecPath = process.execPath + if (withDirOfCurrentNode) { + var newNodeExeDir = path.join(pkg, 'node-bin') + mkdirp.sync(newNodeExeDir) + currentNodeExecPath = path.join(newNodeExeDir, 'my_bundled_' + path.basename(process.execPath)) + fs.writeFileSync(currentNodeExecPath, fs.readFileSync(process.execPath)) + fs.chmodSync(currentNodeExecPath, '755') + } else { + // Ensure that current node interpreter will be found in the PATH, + // so the PATH won't be prepended with its parent directory + newPATH = [path.dirname(process.execPath), PATH].join(process.platform === 'win32' ? ';' : ':') + } common.npm(['run-script', 'env'], { cwd: pkg, + nodeExecPath: currentNodeExecPath, env: { - PATH: PATH + PATH: newPATH }, stdio: [ 0, 'pipe', 2 ] }, function (er, code, stdout) { @@ -60,17 +82,18 @@ test('make sure the path is correct', function (t) { }) // get the ones we tacked on, then the system-specific requirements - var expect = [ - '{{ROOT}}/bin/node-gyp-bin', - '{{ROOT}}/test/tap/lifecycle-path/node_modules/.bin', - path.dirname(process.execPath) - ].concat(PATH.split(pathSplit)).map(function (p) { + var expectedPaths = ['{{ROOT}}/bin/node-gyp-bin', + '{{ROOT}}/test/tap/lifecycle-path/node_modules/.bin'] + if (withDirOfCurrentNode) { + expectedPaths.push('{{ROOT}}/test/tap/lifecycle-path/node-bin') + } + var expect = expectedPaths.concat(newPATH.split(pathSplit)).map(function (p) { return p.replace(/\\/g, '/') }) t.same(actual, expect) t.end() }) -}) +} test('cleanup', function (t) { cleanup() diff --git a/deps/npm/test/tap/local-args-relative-to-cwd.js b/deps/npm/test/tap/local-args-relative-to-cwd.js new file mode 100644 index 0000000000..6c424bf67f --- /dev/null +++ b/deps/npm/test/tap/local-args-relative-to-cwd.js @@ -0,0 +1,65 @@ +'use strict' +var fs = require('graceful-fs') +var path = require('path') +var test = require('tap').test +var Tacks = require('tacks') +var File = Tacks.File +var Dir = Tacks.Dir +var common = require('../common-tap.js') +var testdir = path.join(__dirname, path.basename(__filename, '.js')) + +var fixture = new Tacks( + Dir({ + example: Dir({ + }), + mod1: Dir({ + 'package.json': File({ + name: 'mod1', + version: '1.0.0' + }) + }), + node_modules: Dir({ + }) + }) +) + +function setup () { + fixture.create(testdir) +} + +function cleanup () { + fixture.remove(testdir) +} + +test('setup', function (t) { + cleanup() + setup() + t.end() +}) + +function exists (file) { + try { + fs.statSync(file) + return true + } catch (ex) { + return false + } +} + +test('local-args-relative-to-cwd', function (t) { + var instdir = path.join(testdir, 'example') + var config = ['--loglevel=error'] + common.npm(config.concat(['install', '../mod1']), {cwd: instdir}, function (err, code, stdout, stderr) { + if (err) throw err + t.comment(stdout.trim()) + t.comment(stderr.trim()) + t.is(code, 0, 'install ran ok') + t.ok(exists(path.join(testdir, 'node_modules', 'mod1')), 'mod1 installed') + t.end() + }) +}) + +test('cleanup', function (t) { + cleanup() + t.end() +}) diff --git a/deps/npm/test/tap/node-modules-path-munge.js b/deps/npm/test/tap/node-modules-path-munge.js new file mode 100644 index 0000000000..fdca0393cc --- /dev/null +++ b/deps/npm/test/tap/node-modules-path-munge.js @@ -0,0 +1,39 @@ +var common = require('../common-tap.js') +var t = require('tap') +var fs = require('fs') +var rimraf = require('rimraf') +var mkdirp = require('mkdirp') +var path = require('path') +var dir = path.join(__dirname, 'my_node_modules') +var script = process.platform === 'win32' ? 'echo %PATH%' : 'echo $PATH' + +t.test('setup', function (t) { + rimraf.sync(dir) + mkdirp.sync(dir) + fs.writeFileSync(dir + '/package.json', JSON.stringify({ + name: 'my_node_modules', + version: '1.2.3', + scripts: { + test: script + } + })) + t.end() +}) + +t.test('verify PATH is munged right', function (t) { + common.npm(['test'], { cwd: dir }, function (err, code, stdout, stderr) { + if (err) { + throw err + } + t.equal(code, 0, 'exit ok') + t.notOk(stderr, 'should have no stderr') + var expect = path.resolve(dir, 'node_modules', '.bin').toLowerCase() + t.contains(stdout.toLowerCase(), expect) + t.end() + }) +}) + +t.test('cleanup', function (t) { + rimraf.sync(dir) + t.end() +}) diff --git a/deps/npm/test/tap/optional-metadep-rollback-collision.js b/deps/npm/test/tap/optional-metadep-rollback-collision.js index a9294858d2..bc1bccd16e 100644 --- a/deps/npm/test/tap/optional-metadep-rollback-collision.js +++ b/deps/npm/test/tap/optional-metadep-rollback-collision.js @@ -199,14 +199,12 @@ test('go go test racer', function (t) { env: { PATH: process.env.PATH, Path: process.env.Path - }, - stdio: [0, 'pipe', 2] + } }, function (er, code, stdout, stderr) { t.ifError(er, 'install ran to completion without error') t.is(code, 0, 'npm install exited with code 0') - t.is(stderr, '') - + t.comment(stdout.trim()) // stdout should be empty, because we only have one, optional, dep and // if it fails we shouldn't try installing anything t.equal(stdout, '') diff --git a/deps/npm/test/tap/shrinkwrap-default-arg-ver.js b/deps/npm/test/tap/shrinkwrap-default-arg-ver.js new file mode 100644 index 0000000000..d87bc92391 --- /dev/null +++ b/deps/npm/test/tap/shrinkwrap-default-arg-ver.js @@ -0,0 +1,104 @@ +'use strict' +var path = require('path') +var fs = require('graceful-fs') +var test = require('tap').test +var Tacks = require('tacks') +var File = Tacks.File +var Dir = Tacks.Dir +var common = require('../common-tap.js') +var mr = require('npm-registry-mock') + +var testdir = path.join(__dirname, path.basename(__filename, '.js')) +var config = [ + '--loglevel=error', + '--registry=' + common.registry, + '--cache=' + path.join(testdir, 'cache') +] + +var fixture = new Tacks( + Dir({ + 'cache': Dir(), + 'npm-shrinkwrap.json': File({ + name: 'shrinkwrap-default-arg-ver', + version: '1.0.0', + dependencies: { + underscore: { + version: '1.3.1', + from: 'mod1@>=1.3.1 <2.0.0', + resolved: common.registry + '/underscore/-/underscore-1.3.1.tgz' + } + } + }), + 'package.json': File({ + name: 'shrinkwrap-default-arg-ver', + version: '1.0.0', + dependencies: { + underscore: '^1.3.1' + } + }) + }) +) +var installed = path.join(testdir, 'node_modules', 'underscore', 'package.json') + +function setup () { + fixture.create(testdir) +} + +function cleanup () { + fixture.remove(testdir) +} + +var server +test('setup', function (t) { + cleanup() + setup() + mr({port: common.port}, function (er, s) { + if (er) throw er + server = s + t.end() + }) +}) + +function exists (file) { + try { + fs.statSync(file) + return true + } catch (ex) { + return false + } +} +test('shrinkwrap-default-arg-version', function (t) { + // When this feature was malfunctioning npm would select the version of + // `mod1` from the `package.json` instead of the `npm-shrinkwrap.json`, + // which in this case would mean trying the registry instead of installing + // from a local folder. + common.npm(config.concat(['install', 'underscore']), {cwd: testdir}, function (err, code, stdout, stderr) { + if (err) throw err + t.comment(stdout.trim()) + t.comment(stderr.trim()) + t.is(code, 0, 'installed ok') + t.ok(exists(path.join(testdir, 'node_modules', 'underscore')), 'underscore installed') + var pjson = JSON.parse(fs.readFileSync(installed)) + t.is(pjson.version, '1.3.1', 'got shrinkwrap version') + t.end() + }) +}) + +test('can-override', function (t) { + common.npm(config.concat(['install', 'underscore@latest']), {cwd: testdir}, function (err, code, stdout, stderr) { + if (err) throw err + t.comment(stdout.trim()) + t.comment(stderr.trim()) + t.is(code, 0, 'installed ok') + t.ok(exists(path.join(testdir, 'node_modules', 'underscore')), 'underscore installed') + var pjson = JSON.parse(fs.readFileSync(installed)) + t.is(pjson.version, '1.5.1', 'got latest version') + t.end() + }) +}) + +test('cleanup', function (t) { + server.close() + cleanup() + t.end() +}) diff --git a/deps/npm/test/tap/shrinkwrap-dev-dep-cycle.js b/deps/npm/test/tap/shrinkwrap-dev-dep-cycle.js new file mode 100644 index 0000000000..c9511bb152 --- /dev/null +++ b/deps/npm/test/tap/shrinkwrap-dev-dep-cycle.js @@ -0,0 +1,93 @@ +'use strict' +var fs = require('fs') +var path = require('path') +var test = require('tap').test +var Tacks = require('tacks') +var File = Tacks.File +var Dir = Tacks.Dir +var common = require('../common-tap.js') +var testdir = path.join(__dirname, path.basename(__filename, '.js')) + +var fixture = new Tacks( + Dir({ + node_modules: Dir({ + 'a': Dir({ + 'package.json': File({ + _requested: { + rawSpec: 'file:///mods/a' + }, + dependencies: { + 'b': 'file:///mods/b' + }, + name: 'a', + version: '1.0.0' + }) + }), + 'b': Dir({ + 'package.json': File({ + _requested: { + rawSpec: 'file:///mods/b' + }, + dependencies: { + 'a': 'file:///mods/a' + }, + name: 'b', + version: '1.0.0' + }) + }) + }), + 'package.json': File({ + name: 'test', + version: '1.0.0', + devDependencies: { + 'a': 'file:///mods/a' + } + }) + }) +) + +var expectedShrinkwrap = { + name: 'test', + version: '1.0.0', + dependencies: {} +} + +function setup () { + cleanup() + fixture.create(testdir) +} + +function cleanup () { + fixture.remove(testdir) +} + +function readJson (file) { + try { + var contents = fs.readFileSync(file) + return JSON.parse(contents) + } catch (ex) { + return ex + } +} + +test('setup', function (t) { + setup() + t.end() +}) + +test('shrinkwrap cycle in dev deps', function (t) { + common.npm(['shrinkwrap'], {cwd: testdir}, function (err, code, stdout, stderr) { + if (err) throw err + t.is(code, 0, 'result code = ok') + t.comment(stdout.trim()) + t.comment(stderr.trim()) + var actualShrinkwrap = readJson(path.join(testdir, 'npm-shrinkwrap.json')) + t.isDeeply(actualShrinkwrap, expectedShrinkwrap, 'shrinkwrap is right') + t.end() + }) +}) + +test('cleanup', function (t) { + cleanup() + t.end() +}) diff --git a/deps/npm/test/tap/shrinkwrap-local-dependency.js b/deps/npm/test/tap/shrinkwrap-local-dependency.js index 8d7c0712f9..d3537756c0 100644 --- a/deps/npm/test/tap/shrinkwrap-local-dependency.js +++ b/deps/npm/test/tap/shrinkwrap-local-dependency.js @@ -1,121 +1,123 @@ var test = require('tap').test var path = require('path') var fs = require('fs') -var osenv = require('osenv') var rimraf = require('rimraf') -var mkdirp = require('mkdirp') var common = require('../common-tap.js') - -var PKG_DIR = path.resolve(__dirname, 'shrinkwrap-local-dependency') -var CACHE_DIR = path.resolve(PKG_DIR, 'cache') -var DEP_DIR = path.resolve(PKG_DIR, 'dep') - -var desired = { - 'name': 'npm-test-shrinkwrap-local-dependency', - 'version': '0.0.0', - 'dependencies': { - 'npm-test-shrinkwrap-local-dependency-dep': { - 'version': '0.0.0', - 'from': 'dep', - 'resolved': 'file:dep' +var Tacks = require('tacks') +var File = Tacks.File +var Dir = Tacks.Dir + +var testdir = path.resolve(__dirname, path.basename(__filename, '.js')) +var cachedir = path.resolve(testdir, 'cache') +var config = ['--cache=' + cachedir, '--loglevel=error'] + +var shrinkwrap = { + name: 'shrinkwrap-local-dependency', + version: '1.0.0', + dependencies: { + mod2: { + version: '1.0.0', + from: path.join('mods', 'mod2'), + resolved: 'file:' + path.join('mods', 'mod2'), + dependencies: { + mod1: { + version: '1.0.0', + from: path.join('mods', 'mod1'), + resolved: 'file:' + path.join('mods', 'mod1') + } + } } } } -var root = { - 'author': 'Thomas Torp', - 'name': 'npm-test-shrinkwrap-local-dependency', - 'version': '0.0.0', - 'dependencies': { - 'npm-test-shrinkwrap-local-dependency-dep': 'file:./dep' - } +var fixture = new Tacks( + Dir({ + cache: Dir(), + mods: Dir({ + mod1: Dir({ + 'package.json': File({ + name: 'mod1', + version: '1.0.0' + }) + }), + mod2: Dir({ + 'package.json': File({ + name: 'mod2', + version: '1.0.0', + dependencies: { + mod1: 'file:' + path.join('..', 'mod1') + } + }) + }) + }), + 'package.json': File({ + name: 'shrinkwrap-local-dependency', + version: '1.0.0', + dependencies: { + mod2: 'file:' + path.join('mods', 'mod2') + } + }) + }) +) + +function setup () { + cleanup() + fixture.create(testdir) +} + +function cleanNodeModules () { + rimraf.sync(path.resolve(testdir, 'node_modules')) } -var dependency = { - 'author': 'Thomas Torp', - 'name': 'npm-test-shrinkwrap-local-dependency-dep', - 'version': '0.0.0' +function cleanup () { + fixture.remove(testdir) } test('shrinkwrap uses resolved with file: on local deps', function (t) { setup() - common.npm( - ['--cache=' + CACHE_DIR, '--loglevel=silent', 'install', '.'], - {}, - function (err, code) { - t.ifError(err, 'npm install worked') - t.equal(code, 0, 'npm exited normally') - - common.npm( - ['--cache=' + CACHE_DIR, '--loglevel=silent', 'shrinkwrap'], - {}, - function (err, code) { - t.ifError(err, 'npm shrinkwrap worked') - t.equal(code, 0, 'npm exited normally') - - fs.readFile('npm-shrinkwrap.json', { encoding: 'utf8' }, function (err, data) { - t.ifError(err, 'read file correctly') - t.deepEqual(JSON.parse(data), desired, 'shrinkwrap looks correct') + common.npm(config.concat(['install', '--legacy']), {cwd: testdir}, function (err, code, stdout, stderr) { + if (err) throw err + t.comment(stdout.trim()) + t.comment(stderr.trim()) + t.equal(code, 0, 'npm exited normally') - t.end() - }) - } - ) - } - ) + common.npm(config.concat('shrinkwrap'), {cwd: testdir}, function (err, code, stdout, stderr) { + if (err) throw err + t.comment(stdout.trim()) + t.comment(stderr.trim()) + t.equal(code, 0, 'npm exited normally') + var data = fs.readFileSync(path.join(testdir, 'npm-shrinkwrap.json'), { encoding: 'utf8' }) + t.deepEqual(JSON.parse(data), shrinkwrap, 'shrinkwrap looks correct') + t.end() + }) + }) }) +function exists (file) { + try { + fs.statSync(file) + return true + } catch (ex) { + return false + } +} + test("'npm install' should install local packages from shrinkwrap", function (t) { cleanNodeModules() - common.npm( - ['--cache=' + CACHE_DIR, '--loglevel=silent', 'install', '.'], - {}, - function (err, code) { - t.ifError(err, 'install ran correctly') - t.notOk(code, 'npm install exited with code 0') - var dependencyPackageJson = path.resolve( - PKG_DIR, - 'node_modules/npm-test-shrinkwrap-local-dependency-dep/package.json' - ) - t.ok( - JSON.parse(fs.readFileSync(dependencyPackageJson, 'utf8')), - 'package with local dependency installed from shrinkwrap' - ) - - t.end() - } - ) + common.npm(config.concat(['install']), {cwd: testdir}, function (err, code, stdout, stderr) { + if (err) throw err + t.comment(stdout.trim()) + t.comment(stderr.trim()) + t.equal(code, 0, 'npm exited normally') + t.ok(exists(path.join(testdir, 'node_modules', 'mod2')), 'mod2 exists') + t.ok(exists(path.join(testdir, 'node_modules', 'mod2', 'node_modules', 'mod1')), 'mod1 exists') + t.end() + }) }) test('cleanup', function (t) { cleanup() t.end() }) - -function setup () { - cleanup() - mkdirp.sync(PKG_DIR) - mkdirp.sync(CACHE_DIR) - mkdirp.sync(DEP_DIR) - fs.writeFileSync( - path.resolve(PKG_DIR, 'package.json'), - JSON.stringify(root, null, 2) - ) - fs.writeFileSync( - path.resolve(DEP_DIR, 'package.json'), - JSON.stringify(dependency, null, 2) - ) - process.chdir(PKG_DIR) -} - -function cleanNodeModules () { - rimraf.sync(path.resolve(PKG_DIR, 'node_modules')) -} - -function cleanup () { - process.chdir(osenv.tmpdir()) - cleanNodeModules() - rimraf.sync(PKG_DIR) -} diff --git a/deps/npm/test/tap/shrinkwrap-optional-platform.js b/deps/npm/test/tap/shrinkwrap-optional-platform.js new file mode 100644 index 0000000000..09d26f778b --- /dev/null +++ b/deps/npm/test/tap/shrinkwrap-optional-platform.js @@ -0,0 +1,96 @@ +'use strict' +var path = require('path') +var test = require('tap').test +var Tacks = require('tacks') +var File = Tacks.File +var Dir = Tacks.Dir +var extend = Object.assign || require('util')._extend +var common = require('../common-tap.js') + +var basedir = path.join(__dirname, path.basename(__filename, '.js')) +var testdir = path.join(basedir, 'testdir') +var cachedir = path.join(basedir, 'cache') +var globaldir = path.join(basedir, 'global') +var tmpdir = path.join(basedir, 'tmp') + +var conf = { + cwd: testdir, + env: extend(extend({}, process.env), { + npm_config_cache: cachedir, + npm_config_tmp: tmpdir, + npm_config_prefix: globaldir, + npm_config_registry: common.registry, + npm_config_loglevel: 'warn' + }) +} + +var fixture = new Tacks(Dir({ + cache: Dir(), + global: Dir(), + tmp: Dir(), + testdir: Dir({ + mod1: Dir({ + 'package.json': File({ + name: 'mod1', + version: '1.0.0', + scripts: { + + }, + os: ['nosuchos'] + }) + }), + 'npm-shrinkwrap.json': File({ + name: 'shrinkwrap-optional-platform', + version: '1.0.0', + dependencies: { + mod1: { + version: '1.0.0', + from: 'mod1', + resolved: 'file:mod1', + optional: true + } + } + }), + 'package.json': File({ + name: 'shrinkwrap-optional-platform', + version: '1.0.0', + optionalDependencies: { + mod1: 'file:mod1' + }, + description: 'x', + repository: 'x', + license: 'Artistic-2.0' + }) + }) +})) + +function setup () { + cleanup() + fixture.create(basedir) +} + +function cleanup () { + fixture.remove(basedir) +} + +test('setup', function (t) { + setup() + t.done() +}) + +test('example', function (t) { + common.npm(['install'], conf, function (err, code, stdout, stderr) { + if (err) throw err + t.is(code, 0, 'install ran ok') + t.comment(stdout.trim()) + t.comment(stderr.trim()) + t.notMatch(stderr, /Exit status 1/, 'did not try to install opt dep') + t.done() + }) +}) + +test('cleanup', function (t) { + cleanup() + t.done() +}) + diff --git a/deps/npm/test/tap/shrinkwrap-optional-property.js b/deps/npm/test/tap/shrinkwrap-optional-property.js new file mode 100644 index 0000000000..47f11a750b --- /dev/null +++ b/deps/npm/test/tap/shrinkwrap-optional-property.js @@ -0,0 +1,100 @@ +var fs = require('fs') +var path = require('path') + +var mkdirp = require('mkdirp') +var mr = require('npm-registry-mock') +var osenv = require('osenv') +var rimraf = require('rimraf') +var test = require('tap').test + +var common = require('../common-tap.js') +var npm = npm = require('../../') + +var pkg = path.resolve(__dirname, 'shrinkwrap-optional-dependency') + +test('shrinkwrap adds optional property when optional dependency', function (t) { + t.plan(1) + + mr({port: common.port}, function (er, s) { + function fail (err) { + s.close() // Close on failure to allow node to exit + t.fail(err) + } + + setup(function (err) { + if (err) return fail(err) + + // Install with the optional dependency + npm.install('.', function (err) { + if (err) return fail(err) + + writePackage() + + npm.commands.shrinkwrap([], true, function (err, results) { + if (err) return fail(err) + + t.deepEqual(results, desired) + s.close() + t.end() + }) + }) + }) + }) +}) + +test('cleanup', function (t) { + cleanup() + t.end() +}) + +var desired = { + name: 'npm-test-shrinkwrap-optional-dependency', + version: '0.0.0', + dependencies: { + 'test-package': { + version: '0.0.0', + from: 'test-package@0.0.0', + resolved: common.registry + '/test-package/-/test-package-0.0.0.tgz' + }, + 'underscore': { + version: '1.3.3', + from: 'underscore@1.3.3', + resolved: 'http://localhost:1337/underscore/-/underscore-1.3.3.tgz', + optional: true + } + } +} + +var json = { + author: 'Maximilian Antoni', + name: 'npm-test-shrinkwrap-optional-dependency', + version: '0.0.0', + dependencies: { + 'test-package': '0.0.0' + }, + optionalDependencies: { + 'underscore': '1.3.3' + } +} + +function writePackage () { + fs.writeFileSync(path.join(pkg, 'package.json'), JSON.stringify(json, null, 2)) +} + +function setup (cb) { + cleanup() + mkdirp.sync(pkg) + writePackage() + process.chdir(pkg) + + var opts = { + cache: path.resolve(pkg, 'cache'), + registry: common.registry + } + npm.load(opts, cb) +} + +function cleanup () { + process.chdir(osenv.tmpdir()) + rimraf.sync(pkg) +} diff --git a/deps/npm/test/tap/shrinkwrap-prod-dependency-also.js b/deps/npm/test/tap/shrinkwrap-prod-dependency-also.js index 723960ac32..d3e86fcd65 100644 --- a/deps/npm/test/tap/shrinkwrap-prod-dependency-also.js +++ b/deps/npm/test/tap/shrinkwrap-prod-dependency-also.js @@ -70,6 +70,7 @@ var desired = { resolved: common.registry + '/request/-/request-0.9.0.tgz' }, underscore: { + dev: true, version: '1.5.1', from: 'underscore@1.5.1', resolved: common.registry + '/underscore/-/underscore-1.5.1.tgz' diff --git a/deps/npm/test/tap/shrinkwrap-prod-dependency.js b/deps/npm/test/tap/shrinkwrap-prod-dependency.js index 5bc834376e..57d6ecd3b1 100644 --- a/deps/npm/test/tap/shrinkwrap-prod-dependency.js +++ b/deps/npm/test/tap/shrinkwrap-prod-dependency.js @@ -50,6 +50,7 @@ var desired = { resolved: common.registry + '/request/-/request-0.9.0.tgz' }, underscore: { + dev: true, version: '1.5.1', from: 'underscore@1.5.1', resolved: common.registry + '/underscore/-/underscore-1.5.1.tgz' diff --git a/deps/npm/test/tap/shrinkwrap-save-dev-with-existing-deps.js b/deps/npm/test/tap/shrinkwrap-save-dev-with-existing-deps.js new file mode 100644 index 0000000000..eacea9e3ce --- /dev/null +++ b/deps/npm/test/tap/shrinkwrap-save-dev-with-existing-deps.js @@ -0,0 +1,102 @@ +var fs = require('fs') +var path = require('path') + +var mkdirp = require('mkdirp') +var osenv = require('osenv') +var rimraf = require('rimraf') +var test = require('tap').test + +var common = require('../common-tap.js') + +var base = path.resolve(__dirname, path.basename(__filename, '.js')) +var installme = path.join(base, 'installme') +var installme_pkg = path.join(installme, 'package.json') +var example = path.join(base, 'example') +var example_shrinkwrap = path.join(example, 'npm-shrinkwrap.json') +var example_pkg = path.join(example, 'package.json') +var installed_prod = path.join(example, 'node_modules', 'installed-prod') +var installed_prod_pkg = path.join(installed_prod, 'package.json') +var installed_dev = path.join(example, 'node_modules', 'installed-dev') +var installed_dev_pkg = path.join(installed_dev, 'package.json') + +var EXEC_OPTS = { cwd: example } + +var installme_pkg_json = { + name: 'installme', + version: '1.0.0', + dependencies: {} +} + +var example_pkg_json = { + name: 'example', + version: '1.0.0', + dependencies: { + 'installed-prod': '1.0' + }, + devDependencies: { + 'installed-dev': '1.0' + } +} + +var example_shrinkwrap_json = { + name: 'example', + version: '1.0.0', + dependencies: { + 'installed-prod': { + version: '1.0.0' + }, + 'installed-dev': { + version: '1.0.0' + } + } +} + +var installed_prod_pkg_json = { + _id: 'installed-prod@1.0.0', + name: 'installed-prod', + version: '1.0.0' +} + +var installed_dev_pkg_json = { + _id: 'installed-dev@1.0.0', + name: 'installed-dev', + version: '1.0.0' +} + +function writeJson (filename, obj) { + mkdirp.sync(path.dirname(filename)) + fs.writeFileSync(filename, JSON.stringify(obj, null, 2)) +} + +test('setup', function (t) { + cleanup() + writeJson(installme_pkg, installme_pkg_json) + writeJson(example_pkg, example_pkg_json) + writeJson(example_shrinkwrap, example_shrinkwrap_json) + writeJson(installed_prod_pkg, installed_prod_pkg_json) + writeJson(installed_dev_pkg, installed_dev_pkg_json) + t.end() +}) + +test('install --save-dev leaves prod deps alone', function (t) { + common.npm(['install', '--save-dev', 'file://' + installme], EXEC_OPTS, function (er, code, stdout, stderr) { + t.ifError(er, "spawn didn't catch fire") + t.is(code, 0, 'install completed ok') + t.is(stderr, '', 'install completed without error output') + var shrinkwrap = JSON.parse(fs.readFileSync(example_shrinkwrap)) + t.ok(shrinkwrap.dependencies['installed-prod'], "save-dev new install didn't remove prod dep") + t.ok(shrinkwrap.dependencies['installed-dev'], "save-dev new install didn't remove dev dep") + t.ok(shrinkwrap.dependencies.installme, 'save-dev new install DID add new dev dep') + t.end() + }) +}) + +test('cleanup', function (t) { + cleanup() + t.end() +}) + +function cleanup () { + process.chdir(osenv.tmpdir()) + rimraf.sync(base) +} diff --git a/deps/npm/test/tap/shrinkwrap-save-dev-without-existing-dev-deps.js b/deps/npm/test/tap/shrinkwrap-save-dev-without-existing-dev-deps.js new file mode 100644 index 0000000000..436b17895a --- /dev/null +++ b/deps/npm/test/tap/shrinkwrap-save-dev-without-existing-dev-deps.js @@ -0,0 +1,87 @@ +var fs = require('fs') +var path = require('path') + +var mkdirp = require('mkdirp') +var osenv = require('osenv') +var rimraf = require('rimraf') +var test = require('tap').test + +var common = require('../common-tap.js') + +var base = path.resolve(__dirname, path.basename(__filename, '.js')) +var installme = path.join(base, 'installme') +var installme_pkg = path.join(installme, 'package.json') +var example = path.join(base, 'example') +var example_shrinkwrap = path.join(example, 'npm-shrinkwrap.json') +var example_pkg = path.join(example, 'package.json') +var installed = path.join(example, 'node_modules', 'installed') +var installed_pkg = path.join(installed, 'package.json') + +var EXEC_OPTS = { cwd: example } + +var installme_pkg_json = { + name: 'installme', + version: '1.0.0', + dependencies: {} +} + +var example_pkg_json = { + name: 'example', + version: '1.0.0', + dependencies: { + 'installed': '1.0' + }, + devDependencies: {} +} + +var example_shrinkwrap_json = { + name: 'example', + version: '1.0.0', + dependencies: { + installed: { + version: '1.0.0' + } + } +} + +var installed_pkg_json = { + _id: 'installed@1.0.0', + name: 'installed', + version: '1.0.0' +} + +function writeJson (filename, obj) { + mkdirp.sync(path.dirname(filename)) + fs.writeFileSync(filename, JSON.stringify(obj, null, 2)) +} + +test('setup', function (t) { + cleanup() + writeJson(installme_pkg, installme_pkg_json) + writeJson(example_pkg, example_pkg_json) + writeJson(example_shrinkwrap, example_shrinkwrap_json) + writeJson(installed_pkg, installed_pkg_json) + t.end() +}) + +test('install --save-dev leaves dev deps alone', function (t) { + common.npm(['install', '--save-dev', 'file://' + installme], EXEC_OPTS, function (er, code, stdout, stderr) { + t.ifError(er, "spawn didn't catch fire") + t.is(code, 0, 'install completed ok') + t.is(stderr, '', 'install completed without error output') + var shrinkwrap = JSON.parse(fs.readFileSync(example_shrinkwrap)) + t.ok(shrinkwrap.dependencies.installed, "save-dev new install didn't remove dep") + t.notOk(shrinkwrap.dependencies.installme, 'save-dev new install DID NOT add new dev dep') + t.end() + }) +}) + +test('cleanup', function (t) { + cleanup() + t.end() +}) + +function cleanup () { + process.chdir(osenv.tmpdir()) + rimraf.sync(base) +} diff --git a/deps/npm/test/tap/shrinkwrap-transitive-dev.js b/deps/npm/test/tap/shrinkwrap-transitive-dev.js new file mode 100644 index 0000000000..80a38f7f9e --- /dev/null +++ b/deps/npm/test/tap/shrinkwrap-transitive-dev.js @@ -0,0 +1,83 @@ +'use strict' +var fs = require('fs') +var path = require('path') +var test = require('tap').test +var Tacks = require('tacks') +var common = require('../common-tap.js') +var File = Tacks.File +var Dir = Tacks.Dir + +var testname = path.basename(__filename, '.js') +var testdir = path.join(__dirname, testname) +var cachedir = path.join(testdir, 'cache') +var swfile = path.join(testdir, 'npm-shrinkwrap.json') +var fixture = new Tacks( + Dir({ + cache: Dir(), + mods: Dir({ + moda: Dir({ + 'package.json': File({ + name: 'moda', + version: '1.0.0', + dependencies: { + modb: '../modb' + } + }) + }), + modb: Dir({ + 'package.json': File({ + name: 'modb', + version: '1.0.0' + }) + }) + }), + 'package.json': File({ + name: testname, + version: '1.0.0', + devDependencies: { + moda: 'file:mods/moda' + } + }) + }) +) + +function setup () { + cleanup() + fixture.create(testdir) +} + +function cleanup () { + fixture.remove(testdir) +} + +test('setup', function (t) { + setup() + common.npm(['install', '--cache=' + cachedir], {cwd: testdir}, function (err, code, stdout, stderr) { + if (err) throw err + t.is(code, 0, 'setup ok') + t.comment(stdout.trim()) + t.comment(stderr.trim()) + t.end() + }) +}) + +test('transitive-deps-of-dev-deps', function (t) { + common.npm(['shrinkwrap', '--loglevel=error'], {cwd: testdir}, function (err, code, stdout, stderr) { + if (err) throw err + t.is(code, 0, 'shrinkwrap ran ok') + t.comment(stdout.trim()) + t.comment(stderr.trim()) + try { + var shrinkwrap = JSON.parse(fs.readFileSync(swfile)) + t.isDeeply(shrinkwrap.dependencies, {}, 'empty shrinkwrap') + } catch (ex) { + t.ifError(ex) + } + t.end() + }) +}) + +test('cleanup', function (t) { + cleanup() + t.end() +}) diff --git a/deps/npm/test/tap/update-symlink.js b/deps/npm/test/tap/update-symlink.js index 1447fde628..1fb07b8a75 100644 --- a/deps/npm/test/tap/update-symlink.js +++ b/deps/npm/test/tap/update-symlink.js @@ -1,6 +1,5 @@ var fs = require('graceful-fs') var path = require('path') -var osenv = require('osenv') var mkdirp = require('mkdirp') var mr = require('npm-registry-mock') var rimraf = require('rimraf') @@ -8,14 +7,17 @@ var test = require('tap').test var common = require('../common-tap.js') -var pkg = path.resolve(__dirname, 'update-symlink') -var originalLog - -var fakeRoot = path.join(__dirname, 'fakeRoot') +var testdir = path.join(__dirname, path.basename(__filename, '.js')) +var pkg = path.resolve(testdir, 'update-symlink') +var cachedir = path.join(testdir, 'cache') +var globaldir = path.join(testdir, 'global') var OPTS = { env: { - 'npm_config_prefix': fakeRoot - } + 'npm_config_cache': cachedir, + 'npm_config_prefix': globaldir, + 'npm_config_registry': common.registry + }, + cwd: pkg } var jsonLocal = { @@ -28,57 +30,92 @@ var jsonLocal = { } } +var server test('setup', function (t) { cleanup() - originalLog = console.log + mkdirp.sync(cachedir) mkdirp.sync(pkg) - common.npm(['install', '-g', 'underscore@1.3.1'], OPTS, function (err, c, out) { + fs.writeFileSync( + path.join(pkg, 'package.json'), + JSON.stringify(jsonLocal, null, 2) + ) + + mr({ port: common.port }, thenInstallUnderscore) + + function thenInstallUnderscore (er, s) { + server = s + common.npm(['install', '-g', 'underscore@1.3.1'], OPTS, thenLink) + } + + function thenLink (err, c, out) { t.ifError(err, 'global install did not error') - process.chdir(pkg) - fs.writeFileSync( - path.join(pkg, 'package.json'), - JSON.stringify(jsonLocal, null, 2) - ) - common.npm(['link', 'underscore'], OPTS, function (err, c, out) { - t.ifError(err, 'link did not error') - common.npm(['install', 'async@0.2.9'], OPTS, function (err, c, out) { - t.ifError(err, 'local install did not error') - common.npm(['ls'], OPTS, function (err, c, out, stderr) { - t.ifError(err) - t.equal(c, 0) - t.equal(stderr, '', 'got expected stderr') - t.has(out, /async@0.2.9/, 'installed ok') - t.has(out, /underscore@1.3.1/, 'creates local link ok') - t.end() - }) - }) - }) - }) -}) + common.npm(['link', 'underscore'], OPTS, thenInstallAsync) + } -test('when update is called linked packages should be excluded', function (t) { - console.log = function () {} - mr({ port: common.port }, function (er, s) { - common.npm(['update'], OPTS, function (err, c, out, stderr) { + function thenInstallAsync (err, c, out) { + t.ifError(err, 'link did not error') + common.npm(['install', 'async@0.2.9'], OPTS, thenVerify) + } + + function thenVerify (err, c, out) { + t.ifError(err, 'local install did not error') + common.npm(['ls'], OPTS, function (err, c, out, stderr) { t.ifError(err) - t.has(out, /async@1.5.2/, 'updated ok') - t.doesNotHave(stderr, /ERR!/, 'no errors in stderr') - s.close() + t.equal(c, 0) + t.equal(stderr, '', 'got expected stderr') + t.has(out, /async@0.2.9/, 'installed ok') + t.has(out, /underscore@1.3.1/, 'creates local link ok') t.end() }) + } +}) + +test('when update is called linked packages should be excluded', function (t) { + common.npm(['update'], OPTS, function (err, c, out, stderr) { + t.ifError(err) + t.equal(c, 0) + t.has(out, /async@0.2.10/, 'updated ok') + t.doesNotHave(stderr, /ERR!/, 'no errors in stderr') + t.end() + }) +}) + +test('when install is called and the package already exists as a link, outputs a warning if the requested version is not the same as the linked one', function (t) { + common.npm(['install', 'underscore'], OPTS, function (err, c, out, stderr) { + t.ifError(err) + t.equal(c, 0) + + t.comment(out.trim()) + t.comment(stderr.trim()) + t.doesNotHave(out, /underscore/, 'linked package not updated') + t.has(stderr, /underscore/, 'warning output relating to linked package') + t.doesNotHave(stderr, /ERR!/, 'no errors in stderr') + t.end() + }) +}) + +test('when install is called and the package already exists as a link, does not warn if the requested version is same as the linked one', function (t) { + common.npm(['install', 'underscore@1.3.1'], OPTS, function (err, c, out, stderr) { + t.ifError(err) + t.equal(c, 0) + t.comment(out.trim()) + t.comment(stderr.trim()) + t.doesNotHave(out, /underscore/, 'linked package not updated') + t.doesNotHave(stderr, /underscore/, 'no warning or error relating to linked package') + t.doesNotHave(stderr, /ERR!/, 'no errors in stderr') + t.end() }) }) test('cleanup', function (t) { + server.close() common.npm(['rm', 'underscore', 'async'], OPTS, function (err, code) { t.ifError(err, 'npm removed the linked package without error') t.equal(code, 0, 'cleanup in local ok') - process.chdir(osenv.tmpdir()) common.npm(['rm', '-g', 'underscore'], OPTS, function (err, code) { t.ifError(err, 'npm removed the global package without error') t.equal(code, 0, 'cleanup in global ok') - console.log = originalLog cleanup() t.end() }) @@ -86,6 +123,5 @@ test('cleanup', function (t) { }) function cleanup () { - rimraf.sync(pkg) - rimraf.sync(fakeRoot) + rimraf.sync(testdir) } |