diff options
Diffstat (limited to 'deps/npm/test')
-rw-r--r-- | deps/npm/test/broken-under-nyc-and-travis/lifecycle-path.js | 2 | ||||
-rw-r--r-- | deps/npm/test/tap/adduser-always-auth.js | 3 | ||||
-rw-r--r-- | deps/npm/test/tap/adduser-legacy-auth.js | 3 | ||||
-rw-r--r-- | deps/npm/test/tap/adduser-oauth.js | 3 | ||||
-rw-r--r-- | deps/npm/test/tap/adduser-saml.js | 3 | ||||
-rw-r--r-- | deps/npm/test/tap/auto-prune.js | 148 | ||||
-rw-r--r-- | deps/npm/test/tap/bundled-dependencies-no-pkgjson.js | 55 | ||||
-rw-r--r-- | deps/npm/test/tap/ci.js | 304 | ||||
-rw-r--r-- | deps/npm/test/tap/config-envReplace.js | 55 | ||||
-rw-r--r-- | deps/npm/test/tap/config-list.js | 2 | ||||
-rw-r--r-- | deps/npm/test/tap/install-contributors-count.js | 70 | ||||
-rw-r--r-- | deps/npm/test/tap/install-save-consistent-newlines.js | 122 | ||||
-rw-r--r-- | deps/npm/test/tap/override-bundled.js | 10 | ||||
-rw-r--r-- | deps/npm/test/tap/shrinkwrap-resolve-conflict.js | 117 | ||||
-rw-r--r-- | deps/npm/test/tap/tagged-version-matching.js | 30 | ||||
-rw-r--r-- | deps/npm/test/tap/unit-deps-earliestInstallable.js | 5 | ||||
-rw-r--r-- | deps/npm/test/tap/unit-token-validate-cidr.js | 19 | ||||
-rw-r--r-- | deps/npm/test/tap/version-consistent-newlines.js | 91 |
18 files changed, 951 insertions, 91 deletions
diff --git a/deps/npm/test/broken-under-nyc-and-travis/lifecycle-path.js b/deps/npm/test/broken-under-nyc-and-travis/lifecycle-path.js index 61fe229bcf..5804eb59a8 100644 --- a/deps/npm/test/broken-under-nyc-and-travis/lifecycle-path.js +++ b/deps/npm/test/broken-under-nyc-and-travis/lifecycle-path.js @@ -162,7 +162,7 @@ function checkPath (testconfig, t) { }) // get the ones we tacked on, then the system-specific requirements - var expectedPaths = ['{{ROOT}}/bin/node-gyp-bin', + var expectedPaths = ['{{ROOT}}/node_modules/npm-lifecycle/node-gyp-bin', '{{PKG}}/node_modules/.bin'] // Check that the behaviour matches the configuration that was actually diff --git a/deps/npm/test/tap/adduser-always-auth.js b/deps/npm/test/tap/adduser-always-auth.js index 375c3ab262..c0f302eef5 100644 --- a/deps/npm/test/tap/adduser-always-auth.js +++ b/deps/npm/test/tap/adduser-always-auth.js @@ -35,8 +35,11 @@ function mocks (server) { server.filteringRequestBody(function (r) { if (r.match(/\"_id\":\"org\.couchdb\.user:u\"/)) { return 'auth' + } else { + return 'invalid' } }) + server.post('/-/v1/login', 'invalid').reply(404, 'not found') server.put('/-/user/org.couchdb.user:u', 'auth') .reply(201, { username: 'u', password: 'p', email: 'u@p.me' }) } diff --git a/deps/npm/test/tap/adduser-legacy-auth.js b/deps/npm/test/tap/adduser-legacy-auth.js index 67292cf06a..677d378d89 100644 --- a/deps/npm/test/tap/adduser-legacy-auth.js +++ b/deps/npm/test/tap/adduser-legacy-auth.js @@ -25,8 +25,11 @@ function mocks (server) { server.filteringRequestBody(function (r) { if (r.match(/"_id":"org\.couchdb\.user:u"/)) { return 'auth' + } else { + return 'invalid' } }) + server.post('/-/v1/login', 'invalid').reply(404, 'not found') server.put('/-/user/org.couchdb.user:u', 'auth') .reply(409, { error: 'user exists' }) server.get('/-/user/org.couchdb.user:u?write=true') diff --git a/deps/npm/test/tap/adduser-oauth.js b/deps/npm/test/tap/adduser-oauth.js index dc4ff895e0..20159bcebd 100644 --- a/deps/npm/test/tap/adduser-oauth.js +++ b/deps/npm/test/tap/adduser-oauth.js @@ -20,8 +20,11 @@ function mocks (server) { server.filteringRequestBody(function (r) { if (r.match(/"_id":"org\.couchdb\.user:npm_oauth_auth_dummy_user"/)) { return 'auth' + } else { + return 'invalid' } }) + server.post('/-/v1/login', 'invalid').reply(404, 'not found') server.put('/-/user/org.couchdb.user:npm_oauth_auth_dummy_user', 'auth') .reply(201, { token: 'foo', sso: ssoUri }) } diff --git a/deps/npm/test/tap/adduser-saml.js b/deps/npm/test/tap/adduser-saml.js index 7fd1da2392..a7941f6d6a 100644 --- a/deps/npm/test/tap/adduser-saml.js +++ b/deps/npm/test/tap/adduser-saml.js @@ -20,8 +20,11 @@ function mocks (server) { server.filteringRequestBody(function (r) { if (r.match(/"_id":"org\.couchdb\.user:npm_saml_auth_dummy_user"/)) { return 'auth' + } else { + return 'invalid' } }) + server.post('/-/v1/login', 'invalid').reply(404, 'not found') server.put('/-/user/org.couchdb.user:npm_saml_auth_dummy_user', 'auth') .reply(201, { token: 'foo', sso: ssoUri }) } diff --git a/deps/npm/test/tap/auto-prune.js b/deps/npm/test/tap/auto-prune.js new file mode 100644 index 0000000000..00d01675c5 --- /dev/null +++ b/deps/npm/test/tap/auto-prune.js @@ -0,0 +1,148 @@ +'use strict' +const path = require('path') +const test = require('tap').test +const mr = require('npm-registry-mock') +const Tacks = require('tacks') +const File = Tacks.File +const Dir = Tacks.Dir +const extend = Object.assign || require('util')._extend +const common = require('../common-tap.js') + +const basedir = path.join(__dirname, path.basename(__filename, '.js')) +const testdir = path.join(basedir, 'testdir') +const cachedir = path.join(basedir, 'cache') +const globaldir = path.join(basedir, 'global') +const tmpdir = path.join(basedir, 'tmp') + +const 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' + }) +} + +let server +const fixture = new Tacks(Dir({ + cache: Dir(), + global: Dir(), + tmp: Dir(), + testdir: Dir({ + node_modules: Dir({ + minimist: Dir({ + 'package.json': File({ + _integrity: 'sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=', + _resolved: 'https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz', + name: 'minimist', + version: '0.0.8' + }) + }), + mkdirp: Dir({ + 'package.json': File({ + _integrity: 'sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=', + _resolved: 'https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz', + dependencies: { + minimist: '0.0.8' + }, + name: 'mkdirp', + version: '0.5.1' + }) + }), + null: Dir({ + 'package.json': File({ + _integrity: 'sha1-WoIdUnAxMlyG06AasQFzKgkfoew=', + _resolved: 'https://registry.npmjs.org/null/-/null-1.0.1.tgz', + _spec: 'null', + name: 'null', + version: '1.0.1' + }) + }) + }), + 'package-lock.json': File({ + name: 'with-lock', + version: '1.0.0', + lockfileVersion: 1, + requires: true, + dependencies: { + minimist: { + version: '0.0.8', + resolved: 'https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz', + integrity: 'sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=' + }, + mkdirp: { + version: '0.5.1', + resolved: 'https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz', + integrity: 'sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=', + requires: { + minimist: '0.0.8' + } + } + } + }), + 'package.json': File({ + name: 'with-lock', + version: '1.0.0', + dependencies: { + mkdirp: '^0.5.1' + } + }) + }) +})) + +function setup () { + cleanup() + fixture.create(basedir) +} + +function cleanup () { + fixture.remove(basedir) +} + +test('setup', function (t) { + setup() + mr({port: common.port, throwOnUnmatched: true}, function (err, s) { + if (err) throw err + server = s + t.done() + }) +}) + +test('auto-prune w/ package-lock', function (t) { + common.npm(['install', '--dry-run', '--json'], conf, function (err, code, stdout, stderr) { + if (err) throw err + t.is(code, 0, 'command ran ok') + t.comment(stderr.trim()) + const result = JSON.parse(stdout) + t.is(result.added.length, 0, 'nothing added') + t.is(result.updated.length, 0, 'nothing updated') + t.is(result.moved.length, 0, 'nothing moved') + t.is(result.failed.length, 0, 'nothing failed') + t.is(result.removed.length, 1, 'pruned 1') + t.like(result, {'removed': [{'name': 'null'}]}, 'pruned the right one') + t.done() + }) +}) + +test('auto-prune w/ --no-package-lock', function (t) { + common.npm(['install', '--dry-run', '--json', '--no-package-lock'], conf, function (err, code, stdout, stderr) { + if (err) throw err + t.is(code, 0, 'command ran ok') + t.comment(stderr.trim()) + const result = JSON.parse(stdout) + t.is(result.added.length, 0, 'nothing added') + t.is(result.updated.length, 0, 'nothing updated') + t.is(result.moved.length, 0, 'nothing moved') + t.is(result.failed.length, 0, 'nothing failed') + t.is(result.removed.length, 0, 'nothing pruned') + t.done() + }) +}) + +test('cleanup', function (t) { + server.close() + cleanup() + t.done() +}) diff --git a/deps/npm/test/tap/bundled-dependencies-no-pkgjson.js b/deps/npm/test/tap/bundled-dependencies-no-pkgjson.js deleted file mode 100644 index a7056408a9..0000000000 --- a/deps/npm/test/tap/bundled-dependencies-no-pkgjson.js +++ /dev/null @@ -1,55 +0,0 @@ -var test = require('tap').test -var path = require('path') -var fs = require('graceful-fs') - -var mkdirp = require('mkdirp') -var rimraf = require('rimraf') -var common = require('../common-tap.js') - -var dir = path.resolve(__dirname, 'bundled-dependencies-no-pkgjson') -var pkg = path.resolve(dir, 'pkg-with-bundled-dep') -var dep = path.resolve(pkg, 'node_modules', 'a-bundled-dep') - -var pkgJson = JSON.stringify({ - name: 'pkg-with-bundled-dep', - version: '1.0.0', - dependencies: { - }, - bundledDependencies: [ - 'a-bundled-dep' - ] -}, null, 2) + '\n' -var packed - -test('setup', function (t) { - rimraf.sync(dir) - mkdirp.sync(path.join(dir, 'node_modules')) - mkdirp.sync(dep) - - fs.writeFileSync(path.resolve(pkg, 'package.json'), pkgJson) - fs.writeFileSync(path.resolve(dep, 'index.js'), '') - common.npm(['pack', pkg], {cwd: dir}, function (err, code, stdout, stderr) { - if (err) throw err - t.is(code, 0, 'packed ok') - packed = stdout.trim() - t.comment(stderr) - t.end() - }) -}) - -test('proper error on bundled dep with no package.json', function (t) { - t.plan(2) - var npmArgs = ['install', packed] - - common.npm(npmArgs, { cwd: dir }, function (err, code, stdout, stderr) { - if (err) throw err - t.notEqual(code, 0, 'npm ended in error') - t.like(stderr, /ENOENT/, 'ENOENT should be in stderr') - t.end() - }) -}) - -test('cleanup', function (t) { - rimraf.sync(dir) - t.end() -}) diff --git a/deps/npm/test/tap/ci.js b/deps/npm/test/tap/ci.js new file mode 100644 index 0000000000..5a67b57e77 --- /dev/null +++ b/deps/npm/test/tap/ci.js @@ -0,0 +1,304 @@ +'use strict' + +const BB = require('bluebird') + +const common = BB.promisifyAll(require('../common-tap.js')) +const fs = BB.promisifyAll(require('fs')) +const mr = BB.promisify(require('npm-registry-mock')) +const path = require('path') +const rimraf = BB.promisify(require('rimraf')) +const Tacks = require('tacks') +const test = require('tap').test + +const Dir = Tacks.Dir +const File = Tacks.File +const testDir = path.join(__dirname, 'ci') + +const EXEC_OPTS = { cwd: testDir } + +const PKG = { + name: 'top', + version: '1.2.3', + dependencies: { + optimist: '0.6.0', + clean: '2.1.6' + } +} +let RAW_LOCKFILE +let SERVER +let TREE + +function scrubFrom (tree) { + // npm ci and npm i write different `from` fields for dependency deps. This + // is fine any ok, but it messes with `t.deepEqual` comparisons. + function _scrubFrom (deps) { + Object.keys(deps).forEach((k) => { + deps[k].from = '' + if (deps[k].dependencies) { _scrubFrom(deps[k].dependencies) } + }) + } + tree.dependencies && _scrubFrom(tree.dependencies) +} + +test('setup', () => { + const fixture = new Tacks(Dir({ + 'package.json': File(PKG) + })) + fixture.create(testDir) + return mr({port: common.port}) + .then((server) => { + SERVER = server + return common.npm([ + 'install', + '--registry', common.registry + ], EXEC_OPTS) + .then(() => fs.readFileAsync( + path.join(testDir, 'package-lock.json'), + 'utf8') + ) + .then((lock) => { + RAW_LOCKFILE = lock + }) + .then(() => common.npm(['ls', '--json'], EXEC_OPTS)) + .then((ret) => { + TREE = scrubFrom(JSON.parse(ret[1])) + }) + }) +}) + +test('basic installation', (t) => { + const fixture = new Tacks(Dir({ + 'package.json': File(PKG), + 'package-lock.json': File(RAW_LOCKFILE) + })) + return rimraf(testDir) + .then(() => fixture.create(testDir)) + .then(() => common.npm([ + 'ci', + '--registry', common.registry, + '--loglevel', 'warn' + ], EXEC_OPTS)) + .then((ret) => { + const code = ret[0] + const stdout = ret[1] + const stderr = ret[2] + t.equal(code, 0, 'command completed without error') + t.equal(stdout.trim(), '', 'no output on stdout') + t.match( + stderr.trim(), + /^added 6 packages in \d+(?:\.\d+)?s$/, + 'no warnings on stderr, and final output has right number of packages' + ) + return fs.readdirAsync(path.join(testDir, 'node_modules')) + }) + .then((modules) => { + t.deepEqual(modules.sort(), [ + 'async', 'checker', 'clean', 'minimist', 'optimist', 'wordwrap' + ], 'packages installed') + return BB.all(modules.map((mod) => { + return fs.readFileAsync( + path.join(testDir, 'node_modules', mod, 'package.json') + ) + .then((f) => JSON.parse(f)) + .then((pkgjson) => { + t.equal(pkgjson.name, mod, `${mod} package name correct`) + t.match( + pkgjson._integrity, + /sha\d+-[a-z0-9=+/]+$/i, + `${mod} pkgjson has _integrity` + ) + t.match( + pkgjson._resolved, + new RegExp(`http.*/-/${mod}-${pkgjson.version}.tgz`), + `${mod} pkgjson has correct _resolved` + ) + t.match( + pkgjson._from, + new RegExp(`${mod}@.*`), + `${mod} pkgjson has _from field` + ) + }) + })) + }) + .then(() => fs.readFileAsync( + path.join(testDir, 'package-lock.json'), + 'utf8') + ) + .then((lock) => t.equal(lock, RAW_LOCKFILE, 'package-lock.json unchanged')) + .then(() => common.npm(['ls', '--json'], EXEC_OPTS)) + .then((ret) => { + const lsResult = JSON.parse(ret[1]) + t.equal(ret[0], 0, 'ls exited successfully') + t.deepEqual(scrubFrom(lsResult), TREE, 'tree matches one from `install`') + }) +}) + +test('supports npm-shrinkwrap.json as well', (t) => { + const fixture = new Tacks(Dir({ + 'package.json': File(PKG), + 'npm-shrinkwrap.json': File(RAW_LOCKFILE) + })) + return rimraf(testDir) + .then(() => fixture.create(testDir)) + .then(() => common.npm([ + 'ci', + '--registry', common.registry, + '--loglevel', 'warn' + ], EXEC_OPTS)) + .then((ret) => { + const code = ret[0] + const stdout = ret[1] + const stderr = ret[2] + t.equal(code, 0, 'command completed without error') + t.equal(stdout.trim(), '', 'no output on stdout') + t.match( + stderr.trim(), + /^added 6 packages in \d+(?:\.\d+)?s$/, + 'no warnings on stderr, and final output has right number of packages' + ) + }) + .then(() => common.npm(['ls', '--json'], EXEC_OPTS)) + .then((ret) => { + t.equal(ret[0], 0, 'ls exited successfully') + t.deepEqual( + scrubFrom(JSON.parse(ret[1])), + TREE, + 'tree matches one from `install`' + ) + }) + .then(() => fs.readFileAsync( + path.join(testDir, 'npm-shrinkwrap.json'), + 'utf8') + ) + .then((lock) => t.equal(lock, RAW_LOCKFILE, 'npm-shrinkwrap.json unchanged')) + .then(() => fs.readdirAsync(path.join(testDir))) + .then((files) => t.notOk( + files.some((f) => f === 'package-lock.json'), + 'no package-lock.json created' + )) +}) + +test('removes existing node_modules/ before installing', (t) => { + const fixture = new Tacks(Dir({ + 'package.json': File(PKG), + 'package-lock.json': File(RAW_LOCKFILE), + 'node_modules': Dir({ + foo: Dir({ + 'index.js': File('"hello world"') + }) + }) + })) + return rimraf(testDir) + .then(() => fixture.create(testDir)) + .then(() => common.npm([ + 'ci', + '--registry', common.registry, + '--loglevel', 'warn' + ], EXEC_OPTS)) + .then((ret) => { + const code = ret[0] + const stdout = ret[1] + const stderr = ret[2] + t.equal(code, 0, 'command completed without error') + t.equal(stdout.trim(), '', 'no output on stdout') + t.match( + stderr.trim(), + /^npm.*WARN.*removing existing node_modules/, + 'user warned that existing node_modules were removed' + ) + return fs.readdirAsync(path.join(testDir, 'node_modules')) + }) + .then((modules) => { + t.deepEqual(modules.sort(), [ + 'async', 'checker', 'clean', 'minimist', 'optimist', 'wordwrap' + ], 'packages installed, with old node_modules dir gone') + }) + .then(() => common.npm(['ls'], EXEC_OPTS)) + .then((ret) => t.equal(ret[0], 0, 'ls exited successfully')) + .then(() => fs.readFileAsync( + path.join(testDir, 'package-lock.json'), + 'utf8') + ) + .then((lock) => t.equal(lock, RAW_LOCKFILE, 'package-lock.json unchanged')) +}) + +test('installs all package types correctly') + +test('errors if package-lock.json missing', (t) => { + const fixture = new Tacks(Dir({ + 'package.json': File(PKG) + })) + return rimraf(testDir) + .then(() => fixture.create(testDir)) + .then(() => common.npm([ + 'ci', + '--registry', common.registry, + '--loglevel', 'warn' + ], EXEC_OPTS)) + .then((ret) => { + const code = ret[0] + const stdout = ret[1] + const stderr = ret[2] + t.equal(code, 1, 'command errored') + t.equal(stdout.trim(), '', 'no output on stdout') + t.match( + stderr.trim(), + /can only install packages with an existing package-lock/i, + 'user informed about the issue' + ) + return fs.readdirAsync(path.join(testDir)) + }) + .then((dir) => { + t.notOk(dir.some((f) => f === 'node_modules'), 'no node_modules installed') + t.notOk( + dir.some((f) => f === 'package-lock.json'), + 'no package-lock.json created' + ) + }) +}) + +test('errors if package-lock.json invalid', (t) => { + const badJson = JSON.parse(RAW_LOCKFILE) + delete badJson.dependencies.optimist + const fixture = new Tacks(Dir({ + 'package.json': File(PKG), + 'package-lock.json': File(badJson) + })) + return rimraf(testDir) + .then(() => fixture.create(testDir)) + .then(() => common.npm([ + 'ci', + '--registry', common.registry, + '--loglevel', 'warn' + ], EXEC_OPTS)) + .then((ret) => { + const code = ret[0] + const stdout = ret[1] + const stderr = ret[2] + t.equal(code, 1, 'command errored') + t.equal(stdout.trim(), '', 'no output on stdout') + t.match( + stderr.trim(), + /can only install packages when your package.json/i, + 'user informed about the issue' + ) + return fs.readdirAsync(path.join(testDir)) + }) + .then((dir) => { + t.notOk(dir.some((f) => f === 'node_modules'), 'no node_modules installed') + }) + .then(() => fs.readFileAsync( + path.join(testDir, 'package-lock.json'), + 'utf8') + ) + .then((lock) => t.deepEqual( + JSON.parse(lock), + badJson, + 'bad package-lock.json left unchanged') + ) +}) + +test('cleanup', () => { + SERVER.close() + return rimraf(testDir) +}) diff --git a/deps/npm/test/tap/config-envReplace.js b/deps/npm/test/tap/config-envReplace.js new file mode 100644 index 0000000000..edec9e40db --- /dev/null +++ b/deps/npm/test/tap/config-envReplace.js @@ -0,0 +1,55 @@ +const fs = require('fs') +const mkdirp = require('mkdirp') +const rimraf = require('rimraf') +const path = require('path') +const ini = require('ini') +const test = require('tap').test +const npmconf = require('../../lib/config/core.js') + +const packagePath = path.resolve(__dirname, 'config-envReplace') + +const packageJsonFile = JSON.stringify({ + name: 'config-envReplace' +}) + +const inputConfigFile = [ + 'registry=${NPM_REGISTRY_URL}', + '//${NPM_REGISTRY_HOST}/:_authToken=${NPM_AUTH_TOKEN}', + 'always-auth=true', + '' +].join('\n') + +const expectConfigFile = [ + 'registry=http://my.registry.com/', + '//my.registry.com/:_authToken=xxxxxxxxxxxxxxx', + 'always-auth=true', + '' +].join('\n') + +test('environment variables replacing in configs', function (t) { + process.env = Object.assign(process.env, { + NPM_REGISTRY_URL: 'http://my.registry.com/', + NPM_REGISTRY_HOST: 'my.registry.com', + NPM_AUTH_TOKEN: 'xxxxxxxxxxxxxxx' + }) + mkdirp.sync(packagePath) + const packageJsonPath = path.resolve(packagePath, 'package.json') + const configPath = path.resolve(packagePath, '.npmrc') + fs.writeFileSync(packageJsonPath, packageJsonFile) + fs.writeFileSync(configPath, inputConfigFile) + + const originalCwdPath = process.cwd() + process.chdir(packagePath) + npmconf.load(function (error, conf) { + if (error) throw error + + const foundConfigFile = ini.stringify(conf.sources.project.data) + t.same(ini.parse(foundConfigFile), ini.parse(expectConfigFile)) + + fs.unlinkSync(packageJsonPath) + fs.unlinkSync(configPath) + rimraf.sync(packagePath) + process.chdir(originalCwdPath) + t.end() + }) +}) diff --git a/deps/npm/test/tap/config-list.js b/deps/npm/test/tap/config-list.js index b06dc154b2..05402d4bbe 100644 --- a/deps/npm/test/tap/config-list.js +++ b/deps/npm/test/tap/config-list.js @@ -6,7 +6,7 @@ var mkdirp = require('mkdirp') var common = require('../common-tap.js') var pkg = path.resolve(__dirname, 'config-list') -var opts = { cwd: pkg } +var opts = { cwd: pkg, env: common.emptyEnv() } var npmrc = path.resolve(pkg, '.npmrc') var npmrcContents = ` _private=private; diff --git a/deps/npm/test/tap/install-contributors-count.js b/deps/npm/test/tap/install-contributors-count.js new file mode 100644 index 0000000000..52fba0fd24 --- /dev/null +++ b/deps/npm/test/tap/install-contributors-count.js @@ -0,0 +1,70 @@ +'use strict' +var path = require('path') +var test = require('tap').test +var Tacks = require('tacks') +var Dir = Tacks.Dir +var File = Tacks.File +var common = require('../common-tap.js') + +var testdir = path.resolve(__dirname, path.basename(__filename, '.js')) +var fixture = new Tacks(Dir({ + node_modules: Dir({ + a: Dir({ + 'package.json': File({ + name: 'a', + version: '1.0.0', + dependencies: { + b: '1.0.0' + } + }), + node_modules: Dir({ + b: Dir({ + 'package.json': File({ + name: 'b', + version: '1.0.0' + }) + }) + }) + }) + }), + 'b-src': Dir({ + 'package.json': File({ + name: 'b', + author: 'Author Contributor', + contributors: [ + {name: 'Author Contributor'}, + 'Another Contributor' + ], + version: '1.0.0' + }) + }) +})) + +function setup () { + cleanup() + fixture.create(testdir) +} + +function cleanup () { + fixture.remove(testdir) +} + +test('setup', function (t) { + setup() + t.end() +}) + +test('install', function (t) { + common.npm(['install', '--no-save', './b-src'], {cwd: testdir}, function (err, code, stdout, stderr) { + if (err) throw err + t.is(code, 0, 'installed successfully') + t.is(stderr, '', 'no warnings') + t.includes(stdout, 'added 1 package from 2 contributors', 'lists number of unique contributors') + t.end() + }) +}) + +test('cleanup', function (t) { + cleanup() + t.end() +}) diff --git a/deps/npm/test/tap/install-save-consistent-newlines.js b/deps/npm/test/tap/install-save-consistent-newlines.js new file mode 100644 index 0000000000..6250377445 --- /dev/null +++ b/deps/npm/test/tap/install-save-consistent-newlines.js @@ -0,0 +1,122 @@ +'use strict' + +const fs = require('graceful-fs') +const path = require('path') + +const mkdirp = require('mkdirp') +const mr = require('npm-registry-mock') +const osenv = require('osenv') +const rimraf = require('rimraf') +const test = require('tap').test + +const common = require('../common-tap.js') + +const pkg = path.join(__dirname, 'install-save-consistent-newlines') + +const EXEC_OPTS = { cwd: pkg } + +const json = { + name: 'install-save-consistent-newlines', + version: '0.0.1', + description: 'fixture' +} + +var server + +test('setup', function (t) { + setup('\n') + mr({ port: common.port }, function (er, s) { + server = s + t.end() + }) +}) + +test('\'npm install --save\' should keep the original package.json line endings (LF)', function (t) { + common.npm( + [ + '--loglevel', 'silent', + '--registry', common.registry, + '--save', + 'install', 'underscore@1.3.1' + ], + EXEC_OPTS, + function (err, code) { + t.ifError(err, 'npm ran without issue') + t.notOk(code, 'npm install exited without raising an error code') + + const pkgPath = path.resolve(pkg, 'package.json') + const pkgStr = fs.readFileSync(pkgPath, 'utf8') + + t.match(pkgStr, '\n') + t.notMatch(pkgStr, '\r') + + const pkgLockPath = path.resolve(pkg, 'package-lock.json') + const pkgLockStr = fs.readFileSync(pkgLockPath, 'utf8') + + t.match(pkgLockStr, '\n') + t.notMatch(pkgLockStr, '\r') + + t.end() + } + ) +}) + +test('\'npm install --save\' should keep the original package.json line endings (CRLF)', function (t) { + setup('\r\n') + + common.npm( + [ + '--loglevel', 'silent', + '--registry', common.registry, + '--save', + 'install', 'underscore@1.3.1' + ], + EXEC_OPTS, + function (err, code) { + t.ifError(err, 'npm ran without issue') + t.notOk(code, 'npm install exited without raising an error code') + + const pkgPath = path.resolve(pkg, 'package.json') + const pkgStr = fs.readFileSync(pkgPath, 'utf8') + + t.match(pkgStr, '\r\n') + t.notMatch(pkgStr, /[^\r]\n/) + + const pkgLockPath = path.resolve(pkg, 'package-lock.json') + const pkgLockStr = fs.readFileSync(pkgLockPath, 'utf8') + + t.match(pkgLockStr, '\r\n') + t.notMatch(pkgLockStr, /[^\r]\n/) + + t.end() + } + ) +}) + +test('cleanup', function (t) { + server.close() + cleanup() + t.end() +}) + +function cleanup () { + process.chdir(osenv.tmpdir()) + rimraf.sync(pkg) +} + +function setup (lineEnding) { + cleanup() + mkdirp.sync(path.resolve(pkg, 'node_modules')) + + var jsonStr = JSON.stringify(json, null, 2) + + if (lineEnding === '\r\n') { + jsonStr = jsonStr.replace(/\n/g, '\r\n') + } + + fs.writeFileSync( + path.join(pkg, 'package.json'), + jsonStr + ) + process.chdir(pkg) +} diff --git a/deps/npm/test/tap/override-bundled.js b/deps/npm/test/tap/override-bundled.js index cf6049a128..493ebf4a5d 100644 --- a/deps/npm/test/tap/override-bundled.js +++ b/deps/npm/test/tap/override-bundled.js @@ -15,7 +15,7 @@ var testtgz = testmod + '-1.0.0.tgz' var bundleupdatesrc = path.resolve(testmod, 'bundle-update') var bundleupdatetgz = bundleupdatesrc + '-1.0.0.tgz' var bundleupdateNEW = path.resolve(bundleupdatesrc, 'NEW') -var bundleupdateNEWpostinstall = path.resolve(testdir, 'node_modules', 'top-test', 'node_modules', 'bundle-update', 'NEW') +var bundleupdateNEWpostinstall = path.resolve(testdir, 'node_modules', 'bundle-update', 'NEW') var bundleupdatebad = path.resolve(testmod, 'node_modules', 'bundle-update') var bundlekeepsrc = path.resolve(testmod, 'bundle-keep') @@ -34,8 +34,7 @@ var bundledeepupdatesrc = path.resolve(testmod, 'bundle-deep-update') var bundledeepupdatetgz = bundledeepupdatesrc + '-1.0.0.tgz' var bundledeepupdate = path.resolve(bundledeep, 'node_modules', 'bundle-deep-update') var bundledeepupdateNEW = path.resolve(bundledeepupdatesrc, 'NEW') -var bundledeepupdateNEWpostinstall = path.resolve(testdir, 'node_modules', 'top-test', - 'node_modules', 'bundle-deep', 'node_modules', 'bundle-deep-update', 'NEW') +var bundledeepupdateNEWpostinstall = path.resolve(testdir, 'node_modules', 'bundle-deep-update', 'NEW') var testjson = { dependencies: {'top-test': 'file:' + testtgz} @@ -56,7 +55,6 @@ var bundlejson = { name: 'bundle-update', version: '1.0.0', files: ['OLD', 'NEW'] - } var bundlekeepjson = { @@ -65,6 +63,8 @@ var bundlekeepjson = { _requested: { rawSpec: bundlekeeptgz }, + _resolved: bundlekeeptgz, + _shasum: 'baadf00d', files: ['OLD', 'NEW'] } @@ -77,6 +77,8 @@ var bundledeepjson = { _requested: { rawSpec: bundledeeptgz }, + _resolved: bundlekeeptgz, + _shasum: 'deadbeef', files: ['OLD', 'NEW'] } diff --git a/deps/npm/test/tap/shrinkwrap-resolve-conflict.js b/deps/npm/test/tap/shrinkwrap-resolve-conflict.js new file mode 100644 index 0000000000..c06be7d59e --- /dev/null +++ b/deps/npm/test/tap/shrinkwrap-resolve-conflict.js @@ -0,0 +1,117 @@ +'use strict' + +const BB = require('bluebird') + +const common = require('../common-tap.js') +const fs = BB.promisifyAll(require('fs')) +const path = require('path') +const rimraf = BB.promisify(require('rimraf')) +const test = require('tap').test +const Tacks = require('tacks') + +const File = Tacks.File +const Dir = Tacks.Dir + +const testDir = path.resolve(__dirname, path.basename(__filename, '.js')) +const modAdir = path.resolve(testDir, 'modA') +const modBdir = path.resolve(testDir, 'modB') +const modCdir = path.resolve(testDir, 'modC') + +test('conflicts in shrinkwrap are auto-resolved on install', (t) => { + const fixture = new Tacks(Dir({ + 'package.json': File({ + name: 'foo', + dependencies: { + modA: 'file://' + modAdir, + modB: 'file://' + modBdir + }, + devDependencies: { + modC: 'file://' + modCdir + } + }), + 'npm-shrinkwrap.json': File( +` +{ + "name": "foo", + "requires": true, + "lockfileVersion": 1, + "dependencies": { +<<<<<<< HEAD + "modA": { + "version": "file:modA" +||||||| merged common ancestors + "modB": { + "version": "file:modB" +======= + "modC": { + "version": "file:modC", + "dev": true +>>>>>>> branch + } + } +} +`), + 'modA': Dir({ + 'package.json': File({ + name: 'modA', + version: '1.0.0' + }) + }), + 'modB': Dir({ + 'package.json': File({ + name: 'modB', + version: '1.0.0' + }) + }), + 'modC': Dir({ + 'package.json': File({ + name: 'modC', + version: '1.0.0' + }) + }) + })) + fixture.create(testDir) + function readJson (file) { + return fs.readFileAsync(path.join(testDir, file)).then(JSON.parse) + } + return BB.fromNode((cb) => { + common.npm([ + 'install', + '--loglevel', 'warn' + ], {cwd: testDir}, (err, code, out, stderr) => { + t.comment(stderr) + t.match(stderr, /warn.*conflict/gi, 'warns about a conflict') + cb(err || (code && new Error('non-zero exit code')) || null, out) + }) + }) + .then(() => BB.join( + readJson('npm-shrinkwrap.json'), + readJson('node_modules/modA/package.json'), + readJson('node_modules/modB/package.json'), + readJson('node_modules/modC/package.json'), + (lockfile, A, B, C) => { + t.deepEqual(lockfile, { + name: 'foo', + requires: true, + lockfileVersion: 1, + dependencies: { + modA: { + version: 'file:modA' + }, + modB: { + version: 'file:modB' + }, + modC: { + version: 'file:modC', + dev: true + } + } + }, 'resolved lockfile matches expectations') + t.equal(A.name, 'modA', 'installed modA') + t.equal(B.name, 'modB', 'installed modB') + t.equal(C.name, 'modC', 'installed modC') + } + )) +}) + +test('cleanup', () => rimraf(testDir)) diff --git a/deps/npm/test/tap/tagged-version-matching.js b/deps/npm/test/tap/tagged-version-matching.js index 9d3f5f38e9..a04e749146 100644 --- a/deps/npm/test/tap/tagged-version-matching.js +++ b/deps/npm/test/tap/tagged-version-matching.js @@ -46,24 +46,6 @@ var fixture = new Tacks(Dir({ 'package.json': File({ _from: 'npm/example-gitdep', _id: 'gitdep@1.0.0', - _requested: { - raw: 'gitdep@git://github.com/npm/example-gitdep.git#da39a3ee5e6b4b0d3255bfef95601890afd80709', - scope: null, - escapedName: 'gitdep', - name: 'gitdep', - rawSpec: 'git://github.com/npm/example-gitdep.git#da39a3ee5e6b4b0d3255bfef95601890afd80709', - spec: 'git://github.com/npm/example-gitdep.git#da39a3ee5e6b4b0d3255bfef95601890afd80709', - type: 'hosted', - hosted: { - type: 'github', - ssh: 'git@github.com:npm/example-gitdep.git#da39a3ee5e6b4b0d3255bfef95601890afd80709', - sshUrl: 'git+ssh://git@github.com/npm/example-gitdep.git#da39a3ee5e6b4b0d3255bfef95601890afd80709', - httpsUrl: 'git+https://github.com/npm/example-gitdep.git#da39a3ee5e6b4b0d3255bfef95601890afd80709', - gitUrl: 'git://github.com/npm/example-gitdep.git#da39a3ee5e6b4b0d3255bfef95601890afd80709', - shortcut: 'github:npm/example-gitdep#da39a3ee5e6b4b0d3255bfef95601890afd80709', - directUrl: 'https://raw.githubusercontent.com/npm/example-gitdep/da39a3ee5e6b4b0d3255bfef95601890afd80709/package.json' - } - }, _resolved: 'github:npm/example-gitdep#da39a3ee5e6b4b0d3255bfef95601890afd80709', name: 'gitdep', version: '1.0.0' @@ -74,15 +56,7 @@ var fixture = new Tacks(Dir({ _from: 'tagdep@latest', _id: 'tagdep@1.0.0', _integrity: 'sha1-0EJSKmsdk39848LlrRg/hZQo2B8=', - _requested: { - raw: 'tagdep@https://registry.example.com/tagdep/-/tagdep-1.0.0.tgz', - scope: null, - escapedName: 'tagdep', - name: 'tagdep', - rawSpec: 'https://registry.example.com/tagdep/-/tagdep-1.0.0.tgz', - spec: 'https://registry.example.com/tagdep/-/tagdep-1.0.0.tgz', - type: 'remote' - }, + _resolved: 'https://registry.example.com/tagdep/-/tagdep-1.0.0.tgz', name: 'tagdep', version: '1.0.0' }) @@ -102,7 +76,7 @@ var fixture = new Tacks(Dir({ example: { version: 'file:example', requires: { - tagdep: '1.0.0', + tagdep: '^1.0.0', gitdep: 'github:npm/example-gitdep#da39a3ee5e6b4b0d3255bfef95601890afd80709' } }, diff --git a/deps/npm/test/tap/unit-deps-earliestInstallable.js b/deps/npm/test/tap/unit-deps-earliestInstallable.js index 538cfe6c09..8c5ca06ad8 100644 --- a/deps/npm/test/tap/unit-deps-earliestInstallable.js +++ b/deps/npm/test/tap/unit-deps-earliestInstallable.js @@ -2,6 +2,7 @@ var test = require('tap').test var requireInject = require('require-inject') var npa = require('npm-package-arg') +var log = require('npmlog') // we're just mocking to avoid having to call `npm.load` var deps = requireInject('../../lib/install/deps.js', { @@ -66,7 +67,7 @@ test('earliestInstallable should consider devDependencies', function (t) { dep2a.parent = dep1 dep2.parent = pkg - var earliest = earliestInstallable(dep1, dep1, dep2a.package) + var earliest = earliestInstallable(dep1, dep1, dep2a.package, log) t.isDeeply(earliest, dep1, 'should hoist package when an incompatible devDependency is present') t.end() }) @@ -107,7 +108,7 @@ test('earliestInstallable should reuse shared prod/dev deps when they are identi dep1.parent = pkg dep2.parent = pkg - var earliest = earliestInstallable(dep1, dep1, dep2.package) + var earliest = earliestInstallable(dep1, dep1, dep2.package, log) t.isDeeply(earliest, pkg, 'should reuse identical shared dev/prod deps when installing both') t.end() }) diff --git a/deps/npm/test/tap/unit-token-validate-cidr.js b/deps/npm/test/tap/unit-token-validate-cidr.js new file mode 100644 index 0000000000..db963c31f3 --- /dev/null +++ b/deps/npm/test/tap/unit-token-validate-cidr.js @@ -0,0 +1,19 @@ +'use strict' +const test = require('tap').test +const requireInject = require('require-inject') +const validateCIDRList = requireInject('../../lib/token.js', {'../../lib/npm.js': {}})._validateCIDRList + +test('validateCIDRList', (t) => { + t.plan(10) + const single = ['127.0.0.0/24'] + const double = ['127.0.0.0/24', '192.168.0.0/16'] + const ipv6 = '2620:0:2d0:200::7/32' + const ipv6Mixed = ['127.0.0/24', '2620:0:2d0:200::7/32', '192.168.0.0/16'] + t.doesNotThrow(() => t.isDeeply(validateCIDRList(single.join(',')), single), 'single string ipv4') + t.doesNotThrow(() => t.isDeeply(validateCIDRList(single), single), 'single array ipv4') + t.doesNotThrow(() => t.isDeeply(validateCIDRList(double.join(',')), double), 'double string ipv4') + t.doesNotThrow(() => t.isDeeply(validateCIDRList(double), double), 'double array ipv4') + t.throws(() => validateCIDRList(ipv6)) + t.throws(() => validateCIDRList(ipv6Mixed)) + t.done() +}) diff --git a/deps/npm/test/tap/version-consistent-newlines.js b/deps/npm/test/tap/version-consistent-newlines.js new file mode 100644 index 0000000000..11020b2a70 --- /dev/null +++ b/deps/npm/test/tap/version-consistent-newlines.js @@ -0,0 +1,91 @@ +'use strict' + +const common = require('../common-tap.js') +const test = require('tap').test +const npm = require('../../') +const osenv = require('osenv') +const path = require('path') +const fs = require('fs') +const mkdirp = require('mkdirp') +const rimraf = require('rimraf') +const requireInject = require('require-inject') + +const pkg = path.resolve(__dirname, 'version-no-git') +const cache = path.resolve(pkg, 'cache') +const gitDir = path.resolve(pkg, '.git') + +test('npm version does not alter the line endings in package.json (LF)', function (t) { + setup('\n') + + npm.load({cache: cache, registry: common.registry}, function () { + const version = requireInject('../../lib/version', { + which: function (cmd, cb) { + process.nextTick(function () { + cb(new Error('ENOGIT!')) + }) + } + }) + + version(['patch'], function (err) { + if (!t.error(err)) return t.end() + + const pkgPath = path.resolve(pkg, 'package.json') + const pkgStr = fs.readFileSync(pkgPath, 'utf8') + + t.match(pkgStr, '\n') + t.notMatch(pkgStr, '\r') + + t.end() + }) + }) +}) + +test('npm version does not alter the line endings in package.json (CRLF)', function (t) { + setup('\r\n') + + npm.load({cache: cache, registry: common.registry}, function () { + const version = requireInject('../../lib/version', { + which: function (cmd, cb) { + process.nextTick(function () { + cb(new Error('ENOGIT!')) + }) + } + }) + + version(['patch'], function (err) { + if (!t.error(err)) return t.end() + + const pkgPath = path.resolve(pkg, 'package.json') + const pkgStr = fs.readFileSync(pkgPath, 'utf8') + + t.match(pkgStr, '\r\n') + t.notMatch(pkgStr, /[^\r]\n/) + + t.end() + }) + }) +}) + +test('cleanup', function (t) { + process.chdir(osenv.tmpdir()) + + rimraf.sync(pkg) + t.end() +}) + +function setup (lineEnding) { + mkdirp.sync(pkg) + mkdirp.sync(cache) + mkdirp.sync(gitDir) + fs.writeFileSync( + path.resolve(pkg, 'package.json'), + JSON.stringify({ + author: 'Terin Stock', + name: 'version-no-git-test', + version: '0.0.0', + description: "Test for npm version if git binary doesn't exist" + }, null, 2).replace(/\n/g, lineEnding), + 'utf8' + ) + process.chdir(pkg) +} |