aboutsummaryrefslogtreecommitdiff
path: root/deps/npm/test/tap
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/test/tap')
-rw-r--r--deps/npm/test/tap/all-package-metadata-cache-stream-unit.js136
-rw-r--r--deps/npm/test/tap/all-package-metadata-entry-stream-unit.js186
-rw-r--r--deps/npm/test/tap/all-package-metadata-update-stream-unit.js176
-rw-r--r--deps/npm/test/tap/all-package-metadata-write-stream-unit.js130
-rw-r--r--deps/npm/test/tap/all-package-metadata.js202
-rw-r--r--deps/npm/test/tap/bearer-token-check.js120
-rw-r--r--deps/npm/test/tap/bundled-no-add-to-move.js46
-rw-r--r--deps/npm/test/tap/ci-header.js139
-rw-r--r--deps/npm/test/tap/config-meta.js2
-rw-r--r--deps/npm/test/tap/install-actions.js4
-rw-r--r--deps/npm/test/tap/install-scoped-with-bundled-dependency.js84
-rw-r--r--deps/npm/test/tap/it.js77
-rw-r--r--deps/npm/test/tap/legacy-npm-self-install.js106
-rw-r--r--deps/npm/test/tap/legacy-optional-deps.js80
-rw-r--r--deps/npm/test/tap/move-no-clobber-dest-node-modules.js139
-rw-r--r--deps/npm/test/tap/outdated-color.js2
-rw-r--r--deps/npm/test/tap/outdated-depth-deep.js4
-rw-r--r--deps/npm/test/tap/outdated-depth-integer.js4
-rw-r--r--deps/npm/test/tap/outdated-depth.js4
-rw-r--r--deps/npm/test/tap/outdated-git.js5
-rw-r--r--deps/npm/test/tap/outdated-include-devdependencies.js3
-rw-r--r--deps/npm/test/tap/outdated-json.js4
-rw-r--r--deps/npm/test/tap/outdated-local.js6
-rw-r--r--deps/npm/test/tap/outdated-long.js5
-rw-r--r--deps/npm/test/tap/outdated-new-versions.js5
-rw-r--r--deps/npm/test/tap/outdated-private.js6
-rw-r--r--deps/npm/test/tap/outdated-symlink.js104
-rw-r--r--deps/npm/test/tap/outdated.js4
-rw-r--r--deps/npm/test/tap/prepare.js85
-rw-r--r--deps/npm/test/tap/prepublish-only.js141
-rw-r--r--deps/npm/test/tap/prepublish.js42
-rw-r--r--deps/npm/test/tap/scope-header.js160
-rw-r--r--deps/npm/test/tap/search.js545
-rw-r--r--deps/npm/test/tap/semver-tag.js15
-rw-r--r--deps/npm/test/tap/shrinkwrap-complete-except-dev.js159
-rw-r--r--deps/npm/test/tap/shrinkwrap-default-dev.js125
-rw-r--r--deps/npm/test/tap/shrinkwrap-dev-dep-cycle.js2
-rw-r--r--deps/npm/test/tap/shrinkwrap-shared-dev-dependency.js1
-rw-r--r--deps/npm/test/tap/shrinkwrap-transitive-dev.js2
-rw-r--r--deps/npm/test/tap/shrinkwrap-version-match.js8
-rw-r--r--deps/npm/test/tap/uninstall-in-reverse.js2
-rw-r--r--deps/npm/test/tap/unit-deps-earliestInstallable.js111
-rw-r--r--deps/npm/test/tap/unsupported.js41
-rw-r--r--deps/npm/test/tap/update-index.js195
44 files changed, 2944 insertions, 473 deletions
diff --git a/deps/npm/test/tap/all-package-metadata-cache-stream-unit.js b/deps/npm/test/tap/all-package-metadata-cache-stream-unit.js
new file mode 100644
index 0000000000..51be836769
--- /dev/null
+++ b/deps/npm/test/tap/all-package-metadata-cache-stream-unit.js
@@ -0,0 +1,136 @@
+'use strict'
+
+require('../common-tap.js')
+var test = require('tap').test
+var mkdirp = require('mkdirp')
+var rimraf = require('rimraf')
+var path = require('path')
+var ms = require('mississippi')
+var Tacks = require('tacks')
+var File = Tacks.File
+
+var _createCacheEntryStream = require('../../lib/search/all-package-metadata.js')._createCacheEntryStream
+
+var PKG_DIR = path.resolve(__dirname, 'create-cache-entry-stream')
+var CACHE_DIR = path.resolve(PKG_DIR, 'cache')
+
+function setup () {
+ mkdirp.sync(CACHE_DIR)
+}
+
+function cleanup () {
+ rimraf.sync(PKG_DIR)
+}
+
+test('createCacheEntryStream basic', function (t) {
+ setup()
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ var fixture = new Tacks(File({
+ '_updated': 1234,
+ bar: {
+ name: 'bar',
+ version: '1.0.0'
+ },
+ foo: {
+ name: 'foo',
+ version: '1.0.0'
+ }
+ }))
+ fixture.create(cachePath)
+ _createCacheEntryStream(cachePath, function (err, stream, latest) {
+ if (err) throw err
+ t.equals(latest, 1234, '`latest` correctly extracted')
+ t.ok(stream, 'returned a stream')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ if (err) throw err
+ t.deepEquals(results, [{
+ name: 'bar',
+ version: '1.0.0'
+ }, {
+ name: 'foo',
+ version: '1.0.0'
+ }])
+ cleanup()
+ t.done()
+ })
+ })
+})
+
+test('createCacheEntryStream empty cache', function (t) {
+ setup()
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ var fixture = new Tacks(File({}))
+ fixture.create(cachePath)
+ _createCacheEntryStream(cachePath, function (err, stream, latest) {
+ t.ok(err, 'returned an error because there was no _updated')
+ t.match(err.message, /Empty or invalid stream/, 'useful error message')
+ t.notOk(stream, 'no stream returned')
+ t.notOk(latest, 'no latest returned')
+ cleanup()
+ t.done()
+ })
+})
+
+test('createCacheEntryStream no entry cache', function (t) {
+ setup()
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ var fixture = new Tacks(File({
+ '_updated': 1234
+ }))
+ fixture.create(cachePath)
+ _createCacheEntryStream(cachePath, function (err, stream, latest) {
+ if (err) throw err
+ t.equals(latest, 1234, '`latest` correctly extracted')
+ t.ok(stream, 'returned a stream')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ if (err) throw err
+ t.deepEquals(results, [], 'no results')
+ cleanup()
+ t.done()
+ })
+ })
+})
+
+test('createCacheEntryStream missing cache', function (t) {
+ setup()
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ _createCacheEntryStream(cachePath, function (err, stream, latest) {
+ t.ok(err, 'returned an error because there was no cache')
+ t.equals(err.code, 'ENOENT', 'useful error message')
+ t.notOk(stream, 'no stream returned')
+ t.notOk(latest, 'no latest returned')
+ cleanup()
+ t.done()
+ })
+})
+
+test('createCacheEntryStream bad syntax', function (t) {
+ setup()
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ var fixture = new Tacks(File('{"_updated": 1234, uh oh'))
+ fixture.create(cachePath)
+ _createCacheEntryStream(cachePath, function (err, stream, latest) {
+ if (err) throw err
+ t.equals(latest, 1234, '`latest` correctly extracted')
+ t.ok(stream, 'returned a stream')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ t.ok(err, 'stream errored')
+ t.match(err.message, /Invalid JSON/i, 'explains there\'s a syntax error')
+ t.deepEquals(results, [], 'no results')
+ cleanup()
+ t.done()
+ })
+ })
+})
diff --git a/deps/npm/test/tap/all-package-metadata-entry-stream-unit.js b/deps/npm/test/tap/all-package-metadata-entry-stream-unit.js
new file mode 100644
index 0000000000..0e02f84824
--- /dev/null
+++ b/deps/npm/test/tap/all-package-metadata-entry-stream-unit.js
@@ -0,0 +1,186 @@
+'use strict'
+
+var common = require('../common-tap.js')
+var npm = require('../../')
+var test = require('tap').test
+var mkdirp = require('mkdirp')
+var rimraf = require('rimraf')
+var path = require('path')
+var mr = require('npm-registry-mock')
+var ms = require('mississippi')
+var Tacks = require('tacks')
+var File = Tacks.File
+
+var _createEntryStream = require('../../lib/search/all-package-metadata.js')._createEntryStream
+
+var ALL = common.registry + '/-/all'
+var PKG_DIR = path.resolve(__dirname, 'create-entry-update-stream')
+var CACHE_DIR = path.resolve(PKG_DIR, 'cache')
+
+var server
+
+function setup () {
+ mkdirp.sync(CACHE_DIR)
+}
+
+function cleanup () {
+ rimraf.sync(PKG_DIR)
+}
+
+test('setup', function (t) {
+ mr({port: common.port, throwOnUnmatched: true}, function (err, s) {
+ t.ifError(err, 'registry mocked successfully')
+ npm.load({ cache: CACHE_DIR, registry: common.registry }, function (err) {
+ t.ifError(err, 'npm loaded successfully')
+ server = s
+ t.pass('all set up')
+ t.done()
+ })
+ })
+})
+
+test('createEntryStream full request', function (t) {
+ setup()
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ var dataTime = +(new Date())
+ server.get('/-/all').once().reply(200, {
+ '_updated': dataTime,
+ 'bar': { name: 'bar', version: '1.0.0' },
+ 'foo': { name: 'foo', version: '1.0.0' }
+ }, {
+ date: 1234 // should never be used.
+ })
+ _createEntryStream(cachePath, ALL, {}, 600, function (err, stream, latest, newEntries) {
+ if (err) throw err
+ t.equals(latest, dataTime, '`latest` correctly extracted')
+ t.ok(newEntries, 'new entries need to be written to cache')
+ t.ok(stream, 'returned a stream')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ if (err) throw err
+ t.deepEquals(results, [{
+ name: 'bar',
+ version: '1.0.0'
+ }, {
+ name: 'foo',
+ version: '1.0.0'
+ }])
+ server.done()
+ cleanup()
+ t.end()
+ })
+ })
+})
+
+test('createEntryStream cache only', function (t) {
+ setup()
+ var now = Date.now()
+ var cacheTime = now - 100000
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ var fixture = new Tacks(File({
+ '_updated': cacheTime,
+ bar: { name: 'bar', version: '1.0.0' },
+ cool: { name: 'cool', version: '1.0.0' },
+ foo: { name: 'foo', version: '2.0.0' },
+ other: { name: 'other', version: '1.0.0' }
+ }))
+ fixture.create(cachePath)
+ _createEntryStream(cachePath, ALL, {}, 600, function (err, stream, latest, newEntries) {
+ if (err) throw err
+ t.equals(latest, cacheTime, '`latest` is cache time')
+ t.ok(stream, 'returned a stream')
+ t.notOk(newEntries, 'cache only means no need to write to cache')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ t.ifError(err, 'stream finished without error')
+ t.deepEquals(
+ results.map(function (pkg) { return pkg.name }),
+ ['bar', 'cool', 'foo', 'other'],
+ 'packages deduped and sorted'
+ )
+ server.done()
+ cleanup()
+ t.end()
+ })
+ })
+})
+
+test('createEntryStream merged stream', function (t) {
+ setup()
+ var now = Date.now()
+ var cacheTime = now - 6000000
+ server.get('/-/all/since?stale=update_after&startkey=' + cacheTime).once().reply(200, {
+ 'bar': { name: 'bar', version: '2.0.0' },
+ 'car': { name: 'car', version: '1.0.0' },
+ 'foo': { name: 'foo', version: '1.0.0' }
+ }, {
+ date: (new Date(now)).toISOString()
+ })
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ var fixture = new Tacks(File({
+ '_updated': cacheTime,
+ bar: { name: 'bar', version: '1.0.0' },
+ cool: { name: 'cool', version: '1.0.0' },
+ foo: { name: 'foo', version: '2.0.0' },
+ other: { name: 'other', version: '1.0.0' }
+ }))
+ fixture.create(cachePath)
+ _createEntryStream(cachePath, ALL, {}, 600, function (err, stream, latest, newEntries) {
+ if (err) throw err
+ t.equals(latest, now, '`latest` correctly extracted from header')
+ t.ok(stream, 'returned a stream')
+ t.ok(newEntries, 'cache update means entries should be written')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ t.ifError(err, 'stream finished without error')
+ t.deepEquals(
+ results.map(function (pkg) { return pkg.name }),
+ ['bar', 'car', 'cool', 'foo', 'other'],
+ 'packages deduped and sorted'
+ )
+ t.deepEquals(results[0], {
+ name: 'bar',
+ version: '2.0.0'
+ }, 'update stream version wins on dedupe')
+ t.deepEquals(results[3], {
+ name: 'foo',
+ version: '1.0.0'
+ }, 'update stream version wins on dedupe even when the newer one has a lower semver.')
+ server.done()
+ cleanup()
+ t.end()
+ })
+ })
+})
+
+test('createEntryStream no sources', function (t) {
+ setup()
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ server.get('/-/all').once().reply(404, {})
+ _createEntryStream(cachePath, ALL, {}, 600, function (err, stream, latest, newEntries) {
+ t.ok(err, 'no sources, got an error')
+ t.notOk(stream, 'no stream returned')
+ t.notOk(latest, 'no latest returned')
+ t.notOk(newEntries, 'no entries need to be written')
+ t.match(err.message, /No search sources available/, 'useful error message')
+ server.done()
+ cleanup()
+ t.end()
+ })
+})
+
+test('cleanup', function (t) {
+ cleanup()
+ server.close()
+ t.pass('all done')
+ t.done()
+})
diff --git a/deps/npm/test/tap/all-package-metadata-update-stream-unit.js b/deps/npm/test/tap/all-package-metadata-update-stream-unit.js
new file mode 100644
index 0000000000..b9cf337eb9
--- /dev/null
+++ b/deps/npm/test/tap/all-package-metadata-update-stream-unit.js
@@ -0,0 +1,176 @@
+'use strict'
+
+var common = require('../common-tap.js')
+var npm = require('../../')
+var test = require('tap').test
+var mkdirp = require('mkdirp')
+var rimraf = require('rimraf')
+var path = require('path')
+var mr = require('npm-registry-mock')
+var ms = require('mississippi')
+
+var _createEntryUpdateStream = require('../../lib/search/all-package-metadata.js')._createEntryUpdateStream
+
+var ALL = common.registry + '/-/all'
+var PKG_DIR = path.resolve(__dirname, 'create-entry-update-stream')
+var CACHE_DIR = path.resolve(PKG_DIR, 'cache')
+
+var server
+
+function setup () {
+ mkdirp.sync(CACHE_DIR)
+}
+
+function cleanup () {
+ rimraf.sync(PKG_DIR)
+}
+
+test('setup', function (t) {
+ mr({port: common.port, throwOnUnmatched: true}, function (err, s) {
+ t.ifError(err, 'registry mocked successfully')
+ npm.load({ cache: CACHE_DIR, registry: common.registry }, function (err) {
+ t.ifError(err, 'npm loaded successfully')
+ server = s
+ t.pass('all set up')
+ t.done()
+ })
+ })
+})
+
+test('createEntryUpdateStream full request', function (t) {
+ setup()
+ server.get('/-/all').once().reply(200, {
+ '_updated': 1234,
+ 'bar': { name: 'bar', version: '1.0.0' },
+ 'foo': { name: 'foo', version: '1.0.0' }
+ }, {
+ date: Date.now() // should never be used.
+ })
+ _createEntryUpdateStream(ALL, {}, 600, 0, function (err, stream, latest) {
+ if (err) throw err
+ t.equals(latest, 1234, '`latest` correctly extracted')
+ t.ok(stream, 'returned a stream')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ if (err) throw err
+ t.deepEquals(results, [{
+ name: 'bar',
+ version: '1.0.0'
+ }, {
+ name: 'foo',
+ version: '1.0.0'
+ }])
+ server.done()
+ cleanup()
+ t.end()
+ })
+ })
+})
+
+test('createEntryUpdateStream partial update', function (t) {
+ setup()
+ var now = Date.now()
+ server.get('/-/all/since?stale=update_after&startkey=1234').once().reply(200, {
+ 'bar': { name: 'bar', version: '1.0.0' },
+ 'foo': { name: 'foo', version: '1.0.0' }
+ }, {
+ date: (new Date(now)).toISOString()
+ })
+ _createEntryUpdateStream(ALL, {}, 600, 1234, function (err, stream, latest) {
+ if (err) throw err
+ t.equals(latest, now, '`latest` correctly extracted from header')
+ t.ok(stream, 'returned a stream')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ if (err) throw err
+ t.deepEquals(results, [{
+ name: 'bar',
+ version: '1.0.0'
+ }, {
+ name: 'foo',
+ version: '1.0.0'
+ }])
+ server.done()
+ cleanup()
+ t.end()
+ })
+ })
+})
+
+test('createEntryUpdateStream authed request', function (t) {
+ setup()
+ var token = 'thisisanauthtoken'
+ server.get('/-/all', { authorization: 'Bearer ' + token }).once().reply(200, {
+ '_updated': 1234,
+ 'bar': { name: 'bar', version: '1.0.0' },
+ 'foo': { name: 'foo', version: '1.0.0' }
+ }, {
+ date: Date.now() // should never be used.
+ })
+ _createEntryUpdateStream(ALL, { token: token }, 600, 0, function (err, stream, latest) {
+ if (err) throw err
+ t.equals(latest, 1234, '`latest` correctly extracted')
+ t.ok(stream, 'returned a stream')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ if (err) throw err
+ t.deepEquals(results, [{
+ name: 'bar',
+ version: '1.0.0'
+ }, {
+ name: 'foo',
+ version: '1.0.0'
+ }])
+ server.done()
+ cleanup()
+ t.end()
+ })
+ })
+})
+
+test('createEntryUpdateStream bad auth', function (t) {
+ setup()
+ var token = 'thisisanauthtoken'
+ server.get('/-/all', { authorization: 'Bearer ' + token }).once().reply(401, {
+ error: 'unauthorized search request'
+ })
+ _createEntryUpdateStream(ALL, { token: token }, 600, 0, function (err, stream, latest) {
+ t.ok(err, 'got an error from auth failure')
+ t.notOk(stream, 'no stream returned')
+ t.notOk(latest, 'no latest returned')
+ t.match(err, /unauthorized/, 'failure message from request used')
+ server.done()
+ cleanup()
+ t.end()
+ })
+})
+
+test('createEntryUpdateStream not stale', function (t) {
+ setup()
+ var now = Date.now()
+ var staleness = 600
+ _createEntryUpdateStream(ALL, {}, staleness, now, function (err, stream, latest) {
+ t.ifError(err, 'completed successfully')
+ t.notOk(stream, 'no stream returned')
+ t.notOk(latest, 'no latest returned')
+ server.done()
+ cleanup()
+ t.end()
+ })
+})
+
+test('cleanup', function (t) {
+ cleanup()
+ server.close()
+ t.pass('all done')
+ t.done()
+})
diff --git a/deps/npm/test/tap/all-package-metadata-write-stream-unit.js b/deps/npm/test/tap/all-package-metadata-write-stream-unit.js
new file mode 100644
index 0000000000..410f7f9e9d
--- /dev/null
+++ b/deps/npm/test/tap/all-package-metadata-write-stream-unit.js
@@ -0,0 +1,130 @@
+'use strict'
+
+var common = require('../common-tap.js')
+var npm = require('../../')
+var test = require('tap').test
+var mkdirp = require('mkdirp')
+var rimraf = require('rimraf')
+var path = require('path')
+var fs = require('fs')
+var ms = require('mississippi')
+
+var _createCacheWriteStream = require('../../lib/search/all-package-metadata.js')._createCacheWriteStream
+
+var PKG_DIR = path.resolve(__dirname, 'create-cache-write-stream')
+var CACHE_DIR = path.resolve(PKG_DIR, 'cache')
+
+function setup () {
+ mkdirp.sync(CACHE_DIR)
+}
+
+function cleanup () {
+ rimraf.sync(PKG_DIR)
+}
+
+function fromArray (array) {
+ var idx = 0
+ return ms.from.obj(function (size, next) {
+ next(null, array[idx++] || null)
+ })
+}
+
+test('setup', function (t) {
+ // This is pretty much only used for `getCacheStat` in the implementation
+ npm.load({ cache: CACHE_DIR, registry: common.registry }, function (err) {
+ t.ifError(err, 'npm successfully loaded')
+ t.done()
+ })
+})
+
+test('createCacheEntryStream basic', function (t) {
+ setup()
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ var latest = 12345
+ var src = [
+ { name: 'bar', version: '1.0.0' },
+ { name: 'foo', version: '1.0.0' }
+ ]
+ var srcStream = fromArray(src)
+ _createCacheWriteStream(cachePath, latest, function (err, stream) {
+ if (err) throw err
+ t.ok(stream, 'returned a stream')
+ stream = ms.pipeline.obj(srcStream, stream)
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ if (err) throw err
+ t.deepEquals(results, [{
+ name: 'bar',
+ version: '1.0.0'
+ }, {
+ name: 'foo',
+ version: '1.0.0'
+ }])
+ var fileData = JSON.parse(fs.readFileSync(cachePath))
+ t.ok(fileData, 'cache contents written to the right file')
+ t.deepEquals(fileData, {
+ '_updated': latest,
+ bar: {
+ name: 'bar',
+ version: '1.0.0'
+ },
+ foo: {
+ name: 'foo',
+ version: '1.0.0'
+ }
+ }, 'cache contents based on what was written')
+ cleanup()
+ t.done()
+ })
+ })
+})
+
+test('createCacheEntryStream no entries', function (t) {
+ cleanup() // wipe out the cache dir
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ var latest = 12345
+ var src = []
+ var srcStream = fromArray(src)
+ _createCacheWriteStream(cachePath, latest, function (err, stream) {
+ if (err) throw err
+ t.ok(stream, 'returned a stream')
+ stream = ms.pipeline.obj(srcStream, stream)
+ stream.resume()
+ ms.finished(stream, function (err) {
+ if (err) throw err
+ var fileData = JSON.parse(fs.readFileSync(cachePath))
+ t.ok(fileData, 'cache file exists and has stuff in it')
+ cleanup()
+ t.done()
+ })
+ })
+})
+
+test('createCacheEntryStream missing cache dir', function (t) {
+ setup()
+ var cachePath = path.join(CACHE_DIR, '.cache.json')
+ var latest = 12345
+ var src = []
+ var srcStream = fromArray(src)
+ _createCacheWriteStream(cachePath, latest, function (err, stream) {
+ if (err) throw err
+ t.ok(stream, 'returned a stream')
+ stream = ms.pipeline.obj(srcStream, stream)
+ stream.on('data', function (pkg) {
+ t.notOk(pkg, 'stream should not have output any data')
+ })
+ ms.finished(stream, function (err) {
+ if (err) throw err
+ var fileData = JSON.parse(fs.readFileSync(cachePath))
+ t.ok(fileData, 'cache contents written to the right file')
+ t.deepEquals(fileData, {
+ '_updated': latest
+ }, 'cache still contains `_updated`')
+ cleanup()
+ t.done()
+ })
+ })
+})
diff --git a/deps/npm/test/tap/all-package-metadata.js b/deps/npm/test/tap/all-package-metadata.js
new file mode 100644
index 0000000000..9b60822e4e
--- /dev/null
+++ b/deps/npm/test/tap/all-package-metadata.js
@@ -0,0 +1,202 @@
+'use strict'
+
+var common = require('../common-tap.js')
+var npm = require('../../')
+var test = require('tap').test
+var mkdirp = require('mkdirp')
+var rimraf = require('rimraf')
+var path = require('path')
+var fs = require('fs')
+var cacheFile = require('npm-cache-filename')
+var mr = require('npm-registry-mock')
+var ms = require('mississippi')
+var Tacks = require('tacks')
+var File = Tacks.File
+
+var allPackageMetadata = require('../../lib/search/all-package-metadata.js')
+
+var PKG_DIR = path.resolve(__dirname, 'update-index')
+var CACHE_DIR = path.resolve(PKG_DIR, 'cache')
+var cacheBase
+var cachePath
+
+var server
+
+function setup () {
+ mkdirp.sync(cacheBase)
+}
+
+function cleanup () {
+ rimraf.sync(PKG_DIR)
+}
+
+test('setup', function (t) {
+ mr({port: common.port, throwOnUnmatched: true}, function (err, s) {
+ t.ifError(err, 'registry mocked successfully')
+ npm.load({ cache: CACHE_DIR, registry: common.registry }, function (err) {
+ t.ifError(err, 'npm loaded successfully')
+ npm.config.set('cache', CACHE_DIR)
+ cacheBase = cacheFile(npm.config.get('cache'))(common.registry + '/-/all')
+ cachePath = path.join(cacheBase, '.cache.json')
+ server = s
+ t.pass('all set up')
+ t.done()
+ })
+ })
+})
+
+test('allPackageMetadata full request', function (t) {
+ setup()
+ var updated = Date.now()
+ server.get('/-/all').once().reply(200, {
+ '_updated': 1234,
+ 'bar': { name: 'bar', version: '1.0.0' },
+ 'foo': { name: 'foo', version: '1.0.0' }
+ }, {
+ date: updated
+ })
+ var stream = allPackageMetadata(600)
+ t.ok(stream, 'returned a stream')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ if (err) throw err
+ t.deepEquals(results, [{
+ name: 'bar',
+ version: '1.0.0'
+ }, {
+ name: 'foo',
+ version: '1.0.0'
+ }])
+ var fileData = JSON.parse(fs.readFileSync(cachePath))
+ t.ok(fileData, 'cache contents written to the right file')
+ t.deepEquals(fileData, {
+ '_updated': 1234,
+ bar: {
+ name: 'bar',
+ version: '1.0.0'
+ },
+ foo: {
+ name: 'foo',
+ version: '1.0.0'
+ }
+ }, 'cache contents based on what was written')
+ server.done()
+ cleanup()
+ t.end()
+ })
+})
+
+test('allPackageMetadata cache only', function (t) {
+ setup()
+ var now = Date.now()
+ var cacheContents = {
+ '_updated': now,
+ bar: { name: 'bar', version: '1.0.0' },
+ cool: { name: 'cool', version: '1.0.0' },
+ foo: { name: 'foo', version: '2.0.0' },
+ other: { name: 'other', version: '1.0.0' }
+ }
+ var fixture = new Tacks(File(cacheContents))
+ fixture.create(cachePath)
+ var stream = allPackageMetadata(10000000)
+ t.ok(stream, 'returned a stream')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ t.ifError(err, 'stream finished without error')
+ t.deepEquals(
+ results.map(function (pkg) { return pkg.name }),
+ ['bar', 'cool', 'foo', 'other'],
+ 'packages deduped and sorted, without _updated'
+ )
+ var fileData = JSON.parse(fs.readFileSync(cachePath))
+ t.ok(fileData, 'cache contents written to the right file')
+ t.deepEquals(fileData, cacheContents, 'cacheContents written directly')
+ server.done()
+ cleanup()
+ t.end()
+ })
+})
+
+test('createEntryStream merged stream', function (t) {
+ setup()
+ var now = Date.now()
+ var cacheTime = now - 601000
+ var reqTime = (new Date(now)).toISOString()
+ server.get('/-/all/since?stale=update_after&startkey=' + cacheTime).once().reply(200, {
+ 'bar': { name: 'bar', version: '2.0.0' },
+ 'car': { name: 'car', version: '1.0.0' },
+ 'foo': { name: 'foo', version: '1.0.0' }
+ }, {
+ date: reqTime
+ })
+ var fixture = new Tacks(File({
+ '_updated': cacheTime,
+ bar: { name: 'bar', version: '1.0.0' },
+ cool: { name: 'cool', version: '1.0.0' },
+ foo: { name: 'foo', version: '2.0.0' },
+ other: { name: 'other', version: '1.0.0' }
+ }))
+ fixture.create(cachePath)
+ var stream = allPackageMetadata(600)
+ t.ok(stream, 'returned a stream')
+ var results = []
+ stream.on('data', function (pkg) {
+ results.push(pkg)
+ })
+ ms.finished(stream, function (err) {
+ t.ifError(err, 'stream finished without error')
+ t.deepEquals(
+ results.map(function (pkg) { return pkg.name }),
+ ['bar', 'car', 'cool', 'foo', 'other'],
+ 'packages deduped and sorted'
+ )
+ t.deepEquals(results[0], {
+ name: 'bar',
+ version: '2.0.0'
+ }, 'update stream version wins on dedupe')
+ t.deepEquals(results[3], {
+ name: 'foo',
+ version: '1.0.0'
+ }, 'update stream version wins on dedupe even when the newer one has a lower semver.')
+ var cacheContents = {
+ '_updated': Date.parse(reqTime),
+ bar: { name: 'bar', version: '2.0.0' },
+ car: { name: 'car', version: '1.0.0' },
+ cool: { name: 'cool', version: '1.0.0' },
+ foo: { name: 'foo', version: '1.0.0' },
+ other: { name: 'other', version: '1.0.0' }
+ }
+ var fileData = JSON.parse(fs.readFileSync(cachePath))
+ t.ok(fileData, 'cache contents written to the right file')
+ t.deepEquals(fileData, cacheContents, 'cache updated correctly')
+ server.done()
+ cleanup()
+ t.end()
+ })
+})
+
+test('allPackageMetadata no sources', function (t) {
+ setup()
+ server.get('/-/all').once().reply(404, {})
+ var stream = allPackageMetadata(600)
+ ms.finished(stream, function (err) {
+ t.ok(err, 'no sources, got an error')
+ t.match(err.message, /No search sources available/, 'useful error message')
+ server.done()
+ cleanup()
+ t.end()
+ })
+})
+
+test('cleanup', function (t) {
+ cleanup()
+ server.close()
+ t.pass('all done')
+ t.done()
+})
diff --git a/deps/npm/test/tap/bearer-token-check.js b/deps/npm/test/tap/bearer-token-check.js
new file mode 100644
index 0000000000..f400ec1726
--- /dev/null
+++ b/deps/npm/test/tap/bearer-token-check.js
@@ -0,0 +1,120 @@
+var resolve = require('path').resolve
+var writeFileSync = require('graceful-fs').writeFileSync
+
+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 toNerfDart = require('../../lib/config/nerf-dart.js')
+
+var pkg = resolve(__dirname, 'install-bearer-check')
+var outfile = resolve(pkg, '_npmrc')
+var modules = resolve(pkg, 'node_modules')
+var tarballPath = '/scoped-underscore/-/scoped-underscore-1.3.1.tgz'
+// needs to be a different hostname to verify tokens (not) being sent correctly
+var tarballURL = 'http://127.0.0.1:' + common.port + tarballPath
+var tarball = resolve(__dirname, '../fixtures/scoped-underscore-1.3.1.tgz')
+
+var server
+
+var EXEC_OPTS = { cwd: pkg }
+
+function mocks (server) {
+ var auth = 'Bearer 0xabad1dea'
+ server.get(tarballPath, { authorization: auth }).reply(403, {
+ error: 'token leakage',
+ reason: 'This token should not be sent.'
+ })
+ server.get(tarballPath).replyWithFile(200, tarball)
+}
+
+test('setup', function (t) {
+ mr({ port: common.port, plugin: mocks }, function (er, s) {
+ server = s
+ t.ok(s, 'set up mock registry')
+ setup()
+ t.end()
+ })
+})
+
+test('authed npm install with tarball not on registry', function (t) {
+ common.npm(
+ [
+ 'install',
+ '--loglevel', 'silent',
+ '--json',
+ '--fetch-retries', 0,
+ '--registry', common.registry,
+ '--userconfig', outfile
+ ],
+ EXEC_OPTS,
+ function (err, code, stdout, stderr) {
+ t.ifError(err, 'test runner executed without error')
+ t.equal(code, 0, 'npm install exited OK')
+ t.comment(stdout.trim())
+ t.comment(stderr.trim())
+ t.notOk(stderr, 'no output on stderr')
+ try {
+ var results = JSON.parse(stdout)
+ } catch (ex) {
+ t.ifError(ex, 'stdout was valid JSON')
+ }
+
+ if (results) {
+ var installedversion = {
+ 'version': '1.3.1',
+ 'from': '>=1.3.1 <2',
+ 'resolved': tarballURL
+ }
+ t.isDeeply(results.dependencies['@scoped/underscore'], installedversion, '@scoped/underscore installed')
+ }
+
+ t.end()
+ }
+ )
+})
+
+test('cleanup', function (t) {
+ server.close()
+ cleanup()
+ t.end()
+})
+
+var contents = '@scoped:registry=' + common.registry + '\n' +
+ toNerfDart(common.registry) + ':_authToken=0xabad1dea\n'
+
+var json = {
+ name: 'test-package-install',
+ version: '1.0.0'
+}
+
+var shrinkwrap = {
+ name: 'test-package-install',
+ version: '1.0.0',
+ dependencies: {
+ '@scoped/underscore': {
+ resolved: tarballURL,
+ from: '>=1.3.1 <2',
+ version: '1.3.1'
+ }
+ }
+}
+
+function setup () {
+ cleanup()
+ mkdirp.sync(modules)
+ writeFileSync(resolve(pkg, 'package.json'), JSON.stringify(json, null, 2) + '\n')
+ writeFileSync(outfile, contents)
+ writeFileSync(
+ resolve(pkg, 'npm-shrinkwrap.json'),
+ JSON.stringify(shrinkwrap, null, 2) + '\n'
+ )
+}
+
+function cleanup () {
+ process.chdir(osenv.tmpdir())
+ rimraf.sync(pkg)
+}
diff --git a/deps/npm/test/tap/bundled-no-add-to-move.js b/deps/npm/test/tap/bundled-no-add-to-move.js
new file mode 100644
index 0000000000..526af0e431
--- /dev/null
+++ b/deps/npm/test/tap/bundled-no-add-to-move.js
@@ -0,0 +1,46 @@
+'use strict'
+var test = require('tap').test
+var Node = require('../../lib/install/node.js').create
+var diffTrees = require('../../lib/install/diff-trees.js')._diffTrees
+var sortActions = require('../../lib/install/diff-trees.js').sortActions
+
+var oldTree = Node({
+ path: '/',
+ location: '/',
+ children: [
+ Node({
+ package: {name: 'one', version: '1.0.0'},
+ path: '/node_modules/one',
+ location: '/one'
+ })
+ ]
+})
+oldTree.children[0].requiredBy.push(oldTree)
+
+var newTree = Node({
+ path: '/',
+ location: '/',
+ children: [
+ Node({
+ package: {name: 'abc', version: '1.0.0'},
+ path: '/node_modules/abc',
+ location: '/abc',
+ children: [
+ Node({
+ package: {name: 'one', version: '1.0.0'},
+ fromBundle: true,
+ path: '/node_modules/abc/node_modules/one',
+ location: '/abc/one'
+ })
+ ]
+ })
+ ]
+})
+newTree.children[0].requiredBy.push(newTree)
+newTree.children[0].children[0].requiredBy.push(newTree.children[0])
+
+test('test', function (t) {
+ var differences = sortActions(diffTrees(oldTree, newTree)).map(function (diff) { return diff[0] + diff[1].location })
+ t.isDeeply(differences, ['add/abc/one', 'remove/one', 'add/abc'], 'bundled add/remove stays add/remove')
+ t.end()
+})
diff --git a/deps/npm/test/tap/ci-header.js b/deps/npm/test/tap/ci-header.js
new file mode 100644
index 0000000000..dc20cc53c3
--- /dev/null
+++ b/deps/npm/test/tap/ci-header.js
@@ -0,0 +1,139 @@
+'use strict'
+var path = require('path')
+var test = require('tap').test
+var mr = require('npm-registry-mock')
+var Tacks = require('tacks')
+var File = Tacks.File
+var Dir = Tacks.Dir
+var chain = require('slide').chain
+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 ciKeys = ['CI', 'TDDIUM', 'JENKINS_URL', 'bamboo.buildKey']
+
+var filteredEnv = common.newEnv().delete(ciKeys)
+
+var conf = function (extraEnv) {
+ return {
+ cwd: testdir,
+ env: filteredEnv.clone().extend(extraEnv, {
+ npm_config_cache: cachedir,
+ npm_config_tmp: tmpdir,
+ npm_config_prefix: globaldir,
+ npm_config_registry: common.registry,
+ npm_config_loglevel: 'warn'
+ })
+ }
+}
+
+var server
+var fixture = new Tacks(Dir({
+ cache: Dir(),
+ global: Dir(),
+ tmp: Dir(),
+ testdir: Dir({
+ 'package.json': File({
+ name: 'example',
+ version: '1.0.0'
+ })
+ })
+}))
+
+function setup () {
+ cleanup()
+ fixture.create(basedir)
+}
+
+function cleanup () {
+ fixture.remove(basedir)
+}
+
+var ciHeaderTestCI = {
+ 'time': {'1.0.0': ''},
+ 'dist-tags': {'latest': '1.0.0'},
+ 'versions': {
+ '1.0.0': {
+ name: 'ci-header-test',
+ version: '1.0.0',
+ gotCI: true
+ }
+ }
+}
+var ciHeaderTestNotCI = {
+ 'time': {'1.0.0': ''},
+ 'dist-tags': {'latest': '1.0.0'},
+ 'versions': {
+ '1.0.0': {
+ name: 'ci-header-test',
+ version: '1.0.0',
+ gotCI: false
+ }
+ }
+}
+
+var ciHeaderTestNoCI = {
+ 'time': {'1.0.0': ''},
+ 'dist-tags': {'latest': '1.0.0'},
+ 'versions': {
+ '1.0.0': {
+ name: 'ci-header-test',
+ version: '1.0.0',
+ gotCI: null
+ }
+ }
+}
+
+test('setup', function (t) {
+ setup()
+ mr({port: common.port, throwOnUnmatched: true}, function (err, s) {
+ if (err) throw err
+ server = s
+ server.get('/ci-header-test', {
+ 'NPM-In-CI': 'true'
+ }).many().reply('200', ciHeaderTestCI)
+ server.get('/ci-header-test', {
+ 'NPM-In-CI': 'false'
+ }).many().reply('200', ciHeaderTestNotCI)
+ server.get('/ci-header-test', {}).many().reply('200', ciHeaderTestNoCI)
+ t.done()
+ })
+})
+
+test('various-ci', function (t) {
+ var todo = ciKeys.map(function (key) { return [checkKey, key] })
+ return chain(todo, t.done)
+
+ function checkKey (key, next) {
+ var env = {}
+ env[key] = 'true'
+
+ common.npm(['view', '--cache-min=0', 'ci-header-test', 'gotCI'], conf(env), function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, key + ' command ran ok')
+ if (stderr.trim()) t.comment(stderr.trim())
+ t.is(stdout.trim(), 'true', key + ' set results in CI header')
+ next()
+ })
+ }
+})
+
+test('no-ci', function (t) {
+ common.npm(['view', '--cache-min=0', 'ci-header-test', 'gotCI'], conf(), function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'No CI env, command ran ok')
+ if (stderr.trim()) t.comment(stderr.trim())
+ t.is(stdout.trim(), 'false', 'No CI env, not in CI')
+ t.done()
+ })
+})
+
+test('cleanup', function (t) {
+ server.close()
+ cleanup()
+ t.done()
+})
diff --git a/deps/npm/test/tap/config-meta.js b/deps/npm/test/tap/config-meta.js
index bb40e2038d..3cd1bfa7da 100644
--- a/deps/npm/test/tap/config-meta.js
+++ b/deps/npm/test/tap/config-meta.js
@@ -67,7 +67,7 @@ test('get lines', function (t) {
line: i
}
}
- } else if (exceptions.indexOf(f) === -1) {
+ } else if (exceptions.indexOf(f) === -1 && f.indexOf('.cache') === -1) {
t.fail('non-string-literal config used in ' + f + ':' + i)
}
})
diff --git a/deps/npm/test/tap/install-actions.js b/deps/npm/test/tap/install-actions.js
index ad75cacb5e..824a31c1be 100644
--- a/deps/npm/test/tap/install-actions.js
+++ b/deps/npm/test/tap/install-actions.js
@@ -56,7 +56,7 @@ test('->optdep:a->dep:b', function (t) {
moduleB.parent = tree
t.plan(3)
- actions.postinstall('/', '/', moduleA, mockLog, function (er) {
+ actions.postinstall('/', moduleA, mockLog, function (er) {
t.is(er && er.code, 'ELIFECYCLE', 'Lifecycle failed')
t.ok(moduleA.failed, 'moduleA (optional dep) is marked failed')
t.ok(moduleB.failed, 'moduleB (direct dep of moduleA) is marked as failed')
@@ -108,7 +108,7 @@ test('->dep:b,->optdep:a->dep:b', function (t) {
moduleB.parent = tree
t.plan(3)
- actions.postinstall('/', '/', moduleA, mockLog, function (er) {
+ actions.postinstall('/', moduleA, mockLog, function (er) {
t.ok(er && er.code === 'ELIFECYCLE', 'Lifecycle failed')
t.ok(moduleA.failed, 'moduleA (optional dep) is marked failed')
t.ok(!moduleB.failed, 'moduleB (direct dep of moduleA) is marked as failed')
diff --git a/deps/npm/test/tap/install-scoped-with-bundled-dependency.js b/deps/npm/test/tap/install-scoped-with-bundled-dependency.js
new file mode 100644
index 0000000000..7a620dfdcd
--- /dev/null
+++ b/deps/npm/test/tap/install-scoped-with-bundled-dependency.js
@@ -0,0 +1,84 @@
+'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({
+ npm_config_cache: cachedir,
+ npm_config_tmp: tmpdir,
+ npm_config_prefix: globaldir,
+ npm_config_registry: common.registry,
+ npm_config_loglevel: 'warn'
+ }, process.env)
+}
+
+var fixture = new Tacks(Dir({
+ cache: Dir(),
+ global: Dir(),
+ tmp: Dir(),
+ testdir: Dir({
+ node_modules: Dir({
+ }),
+ package: Dir({
+ node_modules: Dir({
+ 'bundled-dep': Dir({
+ 'package.json': File({
+ name: 'bundled-dep',
+ version: '0.0.0'
+ })
+ })
+ }),
+ 'package.json': File({
+ name: '@scope/package',
+ version: '0.0.0',
+ dependencies: {
+ 'bundled-dep': '*'
+ },
+ bundledDependencies: [
+ 'bundled-dep'
+ ]
+ })
+ })
+ })
+}))
+
+function setup () {
+ cleanup()
+ fixture.create(basedir)
+}
+
+function cleanup () {
+ fixture.remove(basedir)
+}
+
+test('setup', function (t) {
+ setup()
+ t.done()
+})
+
+test('install dependencies of bundled dependencies', function (t) {
+ common.npm(['install', './package'], conf, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'command ran ok')
+ t.comment(stdout.trim())
+ t.comment(stderr.trim())
+ t.done()
+ })
+})
+
+test('cleanup', function (t) {
+ cleanup()
+ t.done()
+})
diff --git a/deps/npm/test/tap/it.js b/deps/npm/test/tap/it.js
new file mode 100644
index 0000000000..0381289709
--- /dev/null
+++ b/deps/npm/test/tap/it.js
@@ -0,0 +1,77 @@
+var join = require('path').join
+var statSync = require('graceful-fs').statSync
+var writeFileSync = require('graceful-fs').writeFileSync
+
+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')
+
+var pkg = join(__dirname, 'run-script')
+var installed = join(pkg, 'node_modules', 'underscore', 'package.json')
+
+var json = {
+ name: 'npm-it-test',
+ dependencies: {
+ underscore: '1.5.1'
+ },
+ scripts: {
+ test: 'echo hax'
+ }
+}
+
+var server
+
+test('run up the mock registry', function (t) {
+ mr({ port: common.port }, function (err, s) {
+ if (err) throw err
+ server = s
+ t.end()
+ })
+})
+
+test('npm install-test', function (t) {
+ setup()
+ common.npm(['install-test', '--registry=' + common.registry], { cwd: pkg }, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.equal(code, 0, 'command ran without error')
+ t.ok(statSync(installed), 'package was installed')
+ t.equal(require(installed).version, '1.5.1', 'underscore got installed as expected')
+ t.match(stdout, /hax/, 'found expected test output')
+ t.notOk(stderr, 'stderr should be empty')
+ t.end()
+ })
+})
+
+test('npm it (the form most people will use)', function (t) {
+ setup()
+ common.npm(['it', '--registry=' + common.registry], { cwd: pkg }, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.equal(code, 0, 'command ran without error')
+ t.ok(statSync(installed), 'package was installed')
+ t.equal(require(installed).version, '1.5.1', 'underscore got installed as expected')
+ t.match(stdout, /hax/, 'found expected test output')
+ t.notOk(stderr, 'stderr should be empty')
+ t.end()
+ })
+})
+
+test('cleanup', function (t) {
+ process.chdir(osenv.tmpdir())
+ server.close()
+ cleanup()
+ t.end()
+})
+
+function cleanup () {
+ rimraf.sync(pkg)
+}
+
+function setup () {
+ cleanup()
+ mkdirp.sync(pkg)
+ writeFileSync(join(pkg, 'package.json'), JSON.stringify(json, null, 2))
+}
diff --git a/deps/npm/test/tap/legacy-npm-self-install.js b/deps/npm/test/tap/legacy-npm-self-install.js
new file mode 100644
index 0000000000..2051802c2e
--- /dev/null
+++ b/deps/npm/test/tap/legacy-npm-self-install.js
@@ -0,0 +1,106 @@
+'use strict'
+var test = require('tap').test
+var fs = require('graceful-fs')
+var common = require('../common-tap.js')
+var path = require('path')
+var rimraf = require('rimraf')
+var mkdirp = require('mkdirp')
+var osenv = require('osenv')
+var npmpath = path.resolve(__dirname, '../..')
+var basepath = path.resolve(osenv.tmpdir(), path.basename(__filename, '.js'))
+var globalpath = path.resolve(basepath, 'global')
+var extend = Object.assign || require('util')._extend
+var isWin32 = process.platform === 'win32'
+
+test('setup', function (t) {
+ setup()
+ t.done()
+})
+
+var tarball
+
+test('build-tarball', function (t) {
+ common.npm(['pack'], {cwd: npmpath, stdio: ['ignore', 'pipe', process.stderr]}, function (err, code, stdout) {
+ if (err) throw err
+ t.is(code, 0, 'pack went ok')
+ tarball = path.resolve(npmpath, stdout.trim().replace(/^(?:.|\n)*(?:^|\n)(.*?[.]tgz)$/, '$1'))
+ t.match(tarball, /[.]tgz$/, 'got a tarball')
+ t.done()
+ })
+})
+
+function exists () {
+ try {
+ fs.statSync(path.resolve.apply(null, arguments))
+ return true
+ } catch (ex) {
+ return false
+ }
+}
+
+test('npm-self-install', function (t) {
+ if (!tarball) return t.done()
+
+ var env = extend({}, process.env)
+ var pathsep = isWin32 ? ';' : ':'
+ env.npm_config_prefix = globalpath
+ env.npm_config_global = 'true'
+ env.NODE_PATH = null
+ env.npm_config_user_agent = null
+ env.npm_config_color = 'always'
+ env.npm_config_progress = 'always'
+ var PATH = env.PATH ? env.PATH.split(pathsep) : []
+ var binpath = isWin32 ? globalpath : path.join(globalpath, 'bin')
+ var cmdname = isWin32 ? 'npm.cmd' : 'npm'
+ PATH.unshift(binpath)
+ env.PATH = PATH.join(pathsep)
+
+ var opts = {cwd: basepath, env: env, stdio: ['ignore', 'ignore', process.stderr]}
+
+ common.npm(['install', '--ignore-scripts', tarball], opts, installCheckAndTest)
+ function installCheckAndTest (err, code) {
+ if (err) throw err
+ t.is(code, 0, 'install went ok')
+ t.is(exists(binpath, cmdname), true, 'binary was installed')
+ t.is(exists(globalpath, isWin32 ? '' : 'lib', 'node_modules', 'npm'), true, 'module path exists')
+ common.npm(['ls', '--json', '--depth=0'], {cwd: basepath, env: env}, lsCheckAndRemove)
+ }
+ function lsCheckAndRemove (err, code, stdout, stderr) {
+ t.ifError(err, 'npm test on array bin')
+ t.equal(code, 0, 'exited OK')
+ t.equal(stderr.trim(), '', 'no error output')
+ var installed = JSON.parse(stdout.trim())
+ t.is(Object.keys(installed.dependencies).length, 1, 'one thing installed')
+ t.is(path.resolve(globalpath, installed.dependencies.npm.from), tarball, 'and it was our npm tarball')
+ common.npm(['rm', 'npm'], {cwd: basepath, env: env}, removeCheck)
+ }
+ function removeCheck (err, code) {
+ if (err) throw err
+ t.is(code, 0, 'remove went ok')
+ common.npm(['ls', '--json', '--depth=0'], {cwd: basepath, env: env}, andDone)
+ }
+ function andDone (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'remove went ok')
+ t.equal(stderr.trim(), '', 'no error output')
+ var installed = JSON.parse(stdout.trim())
+ t.ok(!installed.dependencies || installed.dependencies.length === 0, 'nothing left')
+ t.is(exists(binpath, cmdname), false, 'binary was removed')
+ t.is(exists(globalpath, 'lib', 'node_modules', 'npm'), false, 'module was entirely removed')
+ t.done()
+ }
+})
+
+test('cleanup', function (t) {
+ cleanup()
+ t.done()
+})
+
+function setup () {
+ cleanup()
+ mkdirp.sync(globalpath)
+}
+
+function cleanup () {
+ rimraf.sync(basepath)
+}
diff --git a/deps/npm/test/tap/legacy-optional-deps.js b/deps/npm/test/tap/legacy-optional-deps.js
new file mode 100644
index 0000000000..08ac98522d
--- /dev/null
+++ b/deps/npm/test/tap/legacy-optional-deps.js
@@ -0,0 +1,80 @@
+'use strict'
+var path = require('path')
+var fs = require('fs')
+var test = require('tap').test
+var common = require('../common-tap.js')
+var rimraf = require('rimraf')
+var mkdirp = require('mkdirp')
+var mr = require('npm-registry-mock')
+var basepath = path.resolve(__dirname, path.basename(__filename, '.js'))
+var fixturepath = path.resolve(basepath, 'npm-test-optional-deps')
+var modulepath = path.resolve(basepath, 'node_modules')
+var Tacks = require('tacks')
+var File = Tacks.File
+var Dir = Tacks.Dir
+
+var fixture = new Tacks(
+ Dir({
+ README: File(
+ 'just an npm test\n'
+ ),
+ 'package.json': File({
+ name: 'npm-test-optional-deps',
+ version: '1.2.5',
+ optionalDependencies: {
+ 'npm-test-foobarzaaakakaka': common.registry + '/not-a-package',
+ async: '10.999.14234',
+ mkdirp: '0.3.5',
+ optimist: 'some invalid version 99 #! $$ x y z',
+ 'npm-test-failer': '*'
+ }
+ })
+ })
+)
+
+var server
+
+test('setup', function (t) {
+ setup()
+ mr({port: common.port}, function (err, s) {
+ if (err) throw err
+ server = s
+ t.done()
+ })
+})
+
+test('optional-deps', function (t) {
+ server.get('/npm-test-failer').reply(404, {error: 'nope'})
+ server.get('/not-a-package').reply(200, 'HI THERE')
+
+ var opts = ['--registry=' + common.registry, '--timeout=100']
+ common.npm(opts.concat(['install', fixturepath]), {cwd: basepath}, installCheckAndTest)
+
+ function installCheckAndTest (err, code, stdout, stderr) {
+ if (err) throw err
+ if (stderr) console.error(stderr)
+ server.done()
+ t.is(code, 0, 'install went ok')
+ var dir = fs.readdirSync(modulepath).sort()
+ t.isDeeply(dir, ['mkdirp', 'npm-test-optional-deps'], 'only one optional dep should be there')
+ t.is(require(path.resolve(modulepath, 'mkdirp', 'package.json')).version, '0.3.5', 'mkdirp version right')
+ t.done()
+ }
+})
+
+test('cleanup', function (t) {
+ cleanup()
+ server.close()
+ t.done()
+})
+
+function setup () {
+ cleanup()
+ fixture.create(fixturepath)
+ mkdirp.sync(modulepath)
+}
+
+function cleanup () {
+ fixture.remove(fixturepath)
+ rimraf.sync(basepath)
+}
diff --git a/deps/npm/test/tap/move-no-clobber-dest-node-modules.js b/deps/npm/test/tap/move-no-clobber-dest-node-modules.js
new file mode 100644
index 0000000000..4e487837ad
--- /dev/null
+++ b/deps/npm/test/tap/move-no-clobber-dest-node-modules.js
@@ -0,0 +1,139 @@
+'use strict'
+var path = require('path')
+var test = require('tap').test
+var fs = require('graceful-fs')
+var mkdirp = require('mkdirp')
+var rimraf = require('rimraf')
+var base = path.join(__dirname, path.basename(__filename, '.js'))
+var common = require('../common-tap.js')
+
+function fixturepath () {
+ return path.join(base, path.join.apply(path, arguments))
+}
+
+function File (contents) {
+ return {
+ type: 'file',
+ contents: typeof contents === 'object'
+ ? JSON.stringify(contents)
+ : contents
+ }
+}
+
+function Dir (contents) {
+ return {
+ type: 'dir',
+ contents: contents || {}
+ }
+}
+
+function createFixtures (filename, fixture) {
+ if (fixture.type === 'dir') {
+ mkdirp.sync(filename)
+ Object.keys(fixture.contents).forEach(function (content) {
+ createFixtures(path.resolve(filename, content), fixture.contents[content])
+ })
+ } else if (fixture.type === 'file') {
+ fs.writeFileSync(filename, fixture.contents)
+ } else {
+ throw new Error('Unknown fixture type: ' + fixture.type)
+ }
+}
+
+var fixtures = Dir({
+// The fixture modules
+ 'moda@1.0.1': Dir({
+ 'package.json': File({
+ name: 'moda',
+ version: '1.0.1'
+ })
+ }),
+ 'modb@1.0.0': Dir({
+ 'package.json': File({
+ name: 'modb',
+ version: '1.0.0',
+ bundleDependencies: ['modc'],
+ dependencies: {
+ modc: fixturepath('modc@1.0.0')
+ }
+ })
+ }),
+ 'modc@1.0.0': Dir({
+ 'package.json': File({
+ name: 'modc',
+ version: '1.0.0'
+ })
+ }),
+// The local config
+ 'package.json': File({
+ dependencies: {
+ moda: fixturepath('moda@1.0.1'),
+ modb: fixturepath('modb@1.0.0')
+ }
+ }),
+ 'node_modules': Dir({
+ 'moda': Dir({
+ 'package.json': File({
+ name: 'moda',
+ version: '1.0.0',
+ _requested: { rawSpec: fixturepath('moda@1.0.0') },
+ dependencies: {
+ modb: fixturepath('modb@1.0.0')
+ },
+ bundleDependencies: [ 'modb' ]
+ })
+ })
+ })
+})
+
+function setup () {
+ cleanup()
+ createFixtures(base, fixtures)
+}
+
+function cleanup () {
+ rimraf.sync(base)
+}
+
+function exists (t, filepath, msg) {
+ try {
+ fs.statSync(filepath)
+ t.pass(msg)
+ return true
+ } catch (ex) {
+ t.fail(msg, {found: null, wanted: 'exists', compare: 'fs.stat(' + filepath + ')'})
+ return false
+ }
+}
+
+test('setup', function (t) {
+ setup()
+ common.npm('install', {cwd: fixturepath('modb@1.0.0')}, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'modb')
+ common.npm('install', {
+ cwd: fixturepath('node_modules', 'moda')
+ }, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'installed moda')
+ t.done()
+ })
+ })
+})
+
+test('no-clobber', function (t) {
+ common.npm('install', {cwd: base}, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'installed ok')
+ exists(t, fixturepath('node_modules', 'moda'), 'moda')
+ exists(t, fixturepath('node_modules', 'modb'), 'modb')
+ exists(t, fixturepath('node_modules', 'modb', 'node_modules', 'modc'), 'modc')
+ t.done()
+ })
+})
+
+test('cleanup', function (t) {
+ cleanup()
+ t.pass()
+ t.done()
+})
diff --git a/deps/npm/test/tap/outdated-color.js b/deps/npm/test/tap/outdated-color.js
index a0da337026..7fc8c521e5 100644
--- a/deps/npm/test/tap/outdated-color.js
+++ b/deps/npm/test/tap/outdated-color.js
@@ -57,7 +57,7 @@ test('does not use ansi styling', function (t) {
EXEC_OPTS,
function (err, code, stdout) {
t.ifError(err)
- t.notOk(code, 'npm outdated exited with code 0')
+ t.is(code, 1, 'npm outdated exited with code 1')
t.ok(stdout, stdout.length)
t.ok(!hasControlCodes(stdout))
s.close()
diff --git a/deps/npm/test/tap/outdated-depth-deep.js b/deps/npm/test/tap/outdated-depth-deep.js
index 682b1ca958..14d4f1faf8 100644
--- a/deps/npm/test/tap/outdated-depth-deep.js
+++ b/deps/npm/test/tap/outdated-depth-deep.js
@@ -71,8 +71,8 @@ test('outdated depth deep (9999)', function (t) {
function thenValidateOutput (err, code, stdout, stderr) {
if (err) throw err
- t.is(code, 0, 'outdated completed successfully')
- t.is('', stderr, 'no error output')
+ t.ifError(err)
+ t.is(code, 1, 'npm outdated exited with code 1')
t.match(
stdout,
/underscore.*1\.3\.1.*1\.3\.1.*1\.5\.1.*whatever\n/g,
diff --git a/deps/npm/test/tap/outdated-depth-integer.js b/deps/npm/test/tap/outdated-depth-integer.js
index 32bf785f27..5e743a0a77 100644
--- a/deps/npm/test/tap/outdated-depth-integer.js
+++ b/deps/npm/test/tap/outdated-depth-integer.js
@@ -62,7 +62,9 @@ test('outdated depth integer', function (t) {
npm.install('request@0.9.0', function (er) {
if (er) throw new Error(er)
npm.outdated(function (err, d) {
- if (err) throw new Error(err)
+ t.ifError(err, 'outdated did not error')
+ t.is(process.exitCode, 1, 'exitCode set to 1')
+ process.exitCode = 0
t.deepEqual(d, expected)
s.close()
t.end()
diff --git a/deps/npm/test/tap/outdated-depth.js b/deps/npm/test/tap/outdated-depth.js
index 13220dfa7b..91523405e8 100644
--- a/deps/npm/test/tap/outdated-depth.js
+++ b/deps/npm/test/tap/outdated-depth.js
@@ -54,7 +54,9 @@ test('outdated depth zero', function (t) {
npm.install('.', function (er) {
if (er) throw new Error(er)
npm.outdated(function (err, d) {
- if (err) throw new Error(err)
+ t.ifError(err, 'npm outdated ran without error')
+ t.is(process.exitCode, 1, 'exit code set to 1')
+ process.exitCode = 0
t.deepEqual(d[0], expected)
s.close()
t.end()
diff --git a/deps/npm/test/tap/outdated-git.js b/deps/npm/test/tap/outdated-git.js
index 1a61a0c4d2..2a595e5288 100644
--- a/deps/npm/test/tap/outdated-git.js
+++ b/deps/npm/test/tap/outdated-git.js
@@ -31,9 +31,12 @@ test('setup', function (t) {
test('discovers new versions in outdated', function (t) {
process.chdir(pkg)
- t.plan(5)
+ t.plan(7)
npm.load({cache: cache, registry: common.registry, loglevel: 'silent'}, function () {
npm.commands.outdated([], function (er, d) {
+ t.ifError(er, 'npm outdated completed successfully')
+ t.is(process.exitCode, 1, 'exitCode set to 1')
+ process.exitCode = 0
t.equal(d[0][3], 'git')
t.equal(d[0][4], 'git')
t.equal(d[0][5], 'github:robertkowalski/foo')
diff --git a/deps/npm/test/tap/outdated-include-devdependencies.js b/deps/npm/test/tap/outdated-include-devdependencies.js
index 7ab0088430..331d0b3b33 100644
--- a/deps/npm/test/tap/outdated-include-devdependencies.js
+++ b/deps/npm/test/tap/outdated-include-devdependencies.js
@@ -37,6 +37,9 @@ test('includes devDependencies in outdated', function (t) {
mr({ port: common.port }, function (er, s) {
npm.load({ cache: cache, registry: common.registry }, function () {
npm.outdated(function (er, d) {
+ t.ifError(er, 'npm outdated completed successfully')
+ t.is(process.exitCode, 1, 'exitCode set to 1')
+ process.exitCode = 0
t.equal('1.5.1', d[0][3])
s.close()
t.end()
diff --git a/deps/npm/test/tap/outdated-json.js b/deps/npm/test/tap/outdated-json.js
index 2dd6867e32..39d54fb196 100644
--- a/deps/npm/test/tap/outdated-json.js
+++ b/deps/npm/test/tap/outdated-json.js
@@ -79,8 +79,8 @@ test('it should log json data', function (t) {
],
EXEC_OPTS,
function (err, code, stdout) {
- t.ifError(err, 'npm outdated ran without issue')
- t.notOk(code, 'npm outdated ran without raising error code')
+ t.ifError(err, 'npm outdated ran without error')
+ t.is(code, 1, 'npm outdated exited with code 1')
var out
t.doesNotThrow(function () {
out = JSON.parse(stdout)
diff --git a/deps/npm/test/tap/outdated-local.js b/deps/npm/test/tap/outdated-local.js
index 067696ca90..c253331d07 100644
--- a/deps/npm/test/tap/outdated-local.js
+++ b/deps/npm/test/tap/outdated-local.js
@@ -78,7 +78,7 @@ test('setup', function (t) {
})
test('outdated support local modules', function (t) {
- t.plan(4)
+ t.plan(5)
process.chdir(pkg)
mr({ port: common.port, plugin: mocks }, function (err, s) {
t.ifError(err, 'mock registry started without problems')
@@ -115,7 +115,9 @@ test('outdated support local modules', function (t) {
t.ifError(err, 'install success')
bumpLocalModules()
npm.outdated(function (er, d) {
- t.ifError(er, 'outdated success')
+ t.ifError(err, 'npm outdated ran without error')
+ t.is(process.exitCode, 1, 'errorCode set to 1')
+ process.exitCode = 0
t.ok(verify(d, [
[
path.resolve(__dirname, 'outdated-local'),
diff --git a/deps/npm/test/tap/outdated-long.js b/deps/npm/test/tap/outdated-long.js
index 87e1f23b21..8fdf3057bf 100644
--- a/deps/npm/test/tap/outdated-long.js
+++ b/deps/npm/test/tap/outdated-long.js
@@ -75,8 +75,9 @@ test('it should not throw', function (t) {
t.ifError(err, 'install success')
npm.config.set('long', true)
npm.outdated(function (er, d) {
- t.ifError(er, 'outdated success')
-
+ t.ifError(err, 'npm outdated ran without error')
+ t.is(process.exitCode, 1, 'exit code set to 1')
+ process.exitCode = 0
console.log = originalLog
t.same(output, expOut)
diff --git a/deps/npm/test/tap/outdated-new-versions.js b/deps/npm/test/tap/outdated-new-versions.js
index c6fbd426dc..bfd63e18c3 100644
--- a/deps/npm/test/tap/outdated-new-versions.js
+++ b/deps/npm/test/tap/outdated-new-versions.js
@@ -36,11 +36,14 @@ test('setup', function (t) {
test('dicovers new versions in outdated', function (t) {
process.chdir(pkg)
- t.plan(2)
+ t.plan(4)
mr({ port: common.port }, function (er, s) {
npm.load({ cache: cache, registry: common.registry }, function () {
npm.outdated(function (er, d) {
+ t.ifError(er, 'npm outdated completed successfully')
+ t.is(process.exitCode, 1, 'exitCode set to 1')
+ process.exitCode = 0
for (var i = 0; i < d.length; i++) {
if (d[i][1] === 'underscore') t.equal('1.5.1', d[i][4])
if (d[i][1] === 'request') t.equal('2.27.0', d[i][4])
diff --git a/deps/npm/test/tap/outdated-private.js b/deps/npm/test/tap/outdated-private.js
index 1d5e460c6e..39bd6f1ac9 100644
--- a/deps/npm/test/tap/outdated-private.js
+++ b/deps/npm/test/tap/outdated-private.js
@@ -52,7 +52,7 @@ test('setup', function (t) {
})
test('outdated ignores private modules', function (t) {
- t.plan(3)
+ t.plan(4)
process.chdir(pkg)
mr({ port: common.port }, function (er, s) {
npm.load(
@@ -66,7 +66,9 @@ test('outdated ignores private modules', function (t) {
t.ifError(err, 'install success')
bumpLocalPrivate()
npm.outdated(function (er, d) {
- t.ifError(er, 'outdated success')
+ t.ifError(err, 'npm outdated ran without error')
+ t.is(process.exitCode, 1, 'exitCode set to 1')
+ process.exitCode = 0
t.deepEqual(d, [[
path.resolve(__dirname, 'outdated-private'),
'underscore',
diff --git a/deps/npm/test/tap/outdated-symlink.js b/deps/npm/test/tap/outdated-symlink.js
new file mode 100644
index 0000000000..a7792f4a31
--- /dev/null
+++ b/deps/npm/test/tap/outdated-symlink.js
@@ -0,0 +1,104 @@
+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')
+var test = require('tap').test
+
+var common = require('../common-tap.js')
+
+var pkg = path.resolve(__dirname, 'outdated-symlink')
+var cache = path.resolve(pkg, 'cache')
+var extend = Object.assign || require('util')._extend
+
+var fakeRoot = path.join(pkg, 'fakeRoot')
+var OPTS = {
+ env: extend(extend({}, process.env), {
+ 'npm_config_prefix': fakeRoot,
+ 'registry': common.registry
+ })
+}
+
+var json = {
+ name: 'my-local-package',
+ description: 'fixture',
+ version: '1.0.0'
+}
+
+test('setup', function (t) {
+ cleanup()
+ mkdirp.sync(cache)
+ fs.writeFileSync(
+ path.join(pkg, 'package.json'),
+ JSON.stringify(json, null, 2)
+ )
+ process.chdir(pkg)
+ common.npm(['install', '-g', 'async@0.2.9', 'underscore@1.3.1'], OPTS, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.comment(stdout)
+ t.comment(stderr)
+ common.npm(['link'], OPTS, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.comment(stdout)
+ t.comment(stderr)
+ t.is(code, 0)
+ common.npm(['ls', '-g'], OPTS, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0)
+ t.is(stderr, '', 'got expected stderr')
+ t.match(stdout, /my-local-package@1.0.0/, 'creates global link ok')
+ t.end()
+ })
+ })
+ })
+})
+
+test('when outdated is called linked packages should be displayed as such', function (t) {
+ var regOutLinked = /my-local-package\s*1.0.0\s*linked\s*linked\n/
+ var regOutInstallOne = /async\s*0.2.9\s*0.2.9\s*0.2.10\n/
+ var regOutInstallTwo = /underscore\s*1.3.1\s*1.3.1\s*1.5.1\n/
+
+ mr({ port: common.port }, function (er, s) {
+ common.npm(
+ [
+ '--registry', common.registry,
+ 'outdated', '-g'
+ ],
+ OPTS,
+ function (err, c, out, stderr) {
+ if (err) throw err
+ t.is(stderr, '')
+ t.match(out, regOutLinked, 'Global Link format as expected')
+ t.match(out, regOutInstallOne, 'Global Install format as expected')
+ t.match(out, regOutInstallTwo, 'Global Install format as expected')
+ s.close()
+ t.end()
+ }
+ )
+ })
+})
+
+test('cleanup', function (t) {
+ process.chdir(osenv.tmpdir())
+ common.npm(['rm', 'outdated'], OPTS, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.comment(stdout)
+ t.comment(stderr)
+ t.is(code, 0, 'cleanup outdated in local ok')
+ common.npm(['rm', '-g', 'outdated', 'async', 'underscore'], OPTS, function (err, code) {
+ if (err) throw err
+ t.comment(stdout)
+ t.comment(stderr)
+ t.is(code, 0, 'cleanup outdated in global ok')
+
+ cleanup()
+ t.end()
+ })
+ })
+})
+
+function cleanup () {
+ rimraf.sync(pkg)
+ rimraf.sync(fakeRoot)
+}
diff --git a/deps/npm/test/tap/outdated.js b/deps/npm/test/tap/outdated.js
index 3a46705e38..8b1907d95f 100644
--- a/deps/npm/test/tap/outdated.js
+++ b/deps/npm/test/tap/outdated.js
@@ -103,7 +103,9 @@ test('it should not throw', function (t) {
output.push.apply(output, arguments)
}
npm.outdated(function (er, d) {
- t.ifError(er, 'outdated success')
+ t.ifError(err, 'outdated completed without error')
+ t.equals(process.exitCode, 1, 'exitCode set to 1')
+ process.exitCode = 0
output = output.map(function (x) { return x.replace(/\r/g, '') })
console.log = originalLog
diff --git a/deps/npm/test/tap/prepare.js b/deps/npm/test/tap/prepare.js
new file mode 100644
index 0000000000..f179c52672
--- /dev/null
+++ b/deps/npm/test/tap/prepare.js
@@ -0,0 +1,85 @@
+// verify that prepare runs on pack and publish
+var common = require('../common-tap')
+var test = require('tap').test
+var fs = require('graceful-fs')
+var join = require('path').join
+var mkdirp = require('mkdirp')
+var rimraf = require('rimraf')
+
+var pkg = join(__dirname, 'prepare_package')
+var tmp = join(pkg, 'tmp')
+var cache = join(pkg, 'cache')
+
+test('setup', function (t) {
+ var n = 0
+ cleanup()
+ mkdirp(pkg, then())
+ mkdirp(cache, then())
+ mkdirp(tmp, then())
+ function then () {
+ n++
+ return function (er) {
+ if (er) throw er
+ if (--n === 0) next()
+ }
+ }
+
+ function next () {
+ fs.writeFile(join(pkg, 'package.json'), JSON.stringify({
+ name: 'npm-test-prepare',
+ version: '1.2.5',
+ scripts: { prepare: 'echo ok' }
+ }), 'ascii', function (er) {
+ if (er) throw er
+
+ t.pass('setup done')
+ t.end()
+ })
+ }
+})
+
+test('test', function (t) {
+ var env = {
+ 'npm_config_cache': cache,
+ 'npm_config_tmp': tmp,
+ 'npm_config_prefix': pkg,
+ 'npm_config_global': 'false'
+ }
+
+ for (var i in process.env) {
+ if (!/^npm_config_/.test(i)) {
+ env[i] = process.env[i]
+ }
+ }
+
+ common.npm([
+ 'pack',
+ '--loglevel', 'warn'
+ ], { cwd: pkg, env: env }, function (err, code, stdout, stderr) {
+ t.equal(code, 0, 'pack finished successfully')
+ t.ifErr(err, 'pack finished successfully')
+
+ t.notOk(stderr, 'got stderr data:' + JSON.stringify('' + stderr))
+ var c = stdout.trim()
+ var regex = new RegExp(
+ '> npm-test-prepare@1.2.5 prepare [^\\r\\n]+\\r?\\n' +
+ '> echo ok\\r?\\n' +
+ '\\r?\\n' +
+ 'ok\\r?\\n' +
+ 'npm-test-prepare-1.2.5.tgz', 'ig'
+ )
+
+ t.match(c, regex)
+ t.end()
+ })
+})
+
+test('cleanup', function (t) {
+ cleanup()
+ t.pass('cleaned up')
+ t.end()
+})
+
+function cleanup () {
+ rimraf.sync(pkg)
+}
diff --git a/deps/npm/test/tap/prepublish-only.js b/deps/npm/test/tap/prepublish-only.js
new file mode 100644
index 0000000000..3681c76897
--- /dev/null
+++ b/deps/npm/test/tap/prepublish-only.js
@@ -0,0 +1,141 @@
+// verify that prepublishOnly runs _only_ on publish
+var join = require('path').join
+
+var mr = require('npm-registry-mock')
+var test = require('tap').test
+var Tacks = require('tacks')
+var File = Tacks.File
+var Dir = Tacks.Dir
+
+var common = require('../common-tap')
+
+var pkg = join(__dirname, 'prepublish_package')
+var cachedir = join(pkg, 'cache')
+var tmpdir = join(pkg, 'tmp')
+
+var env = {
+ 'npm_config_cache': cachedir,
+ 'npm_config_tmp': tmpdir,
+ 'npm_config_prefix': pkg,
+ 'npm_config_global': 'false'
+}
+
+for (var i in process.env) {
+ if (!/^npm_config_/.test(i)) {
+ env[i] = process.env[i]
+ }
+}
+
+var server
+
+var fixture = new Tacks(Dir({
+ cache: Dir(),
+ tmp: Dir(),
+ '.npmrc': File([
+ 'progress=false',
+ 'registry=' + common.registry,
+ '//localhost:1337/:username=username',
+ '//localhost:1337/:_authToken=deadbeeffeed'
+ ].join('\n') + '\n'),
+ helper: Dir({
+ 'script.js': File([
+ '#!/usr/bin/env node\n',
+ 'console.log("ok")\n'
+ ].join('\n') + '\n'
+ ),
+ 'package.json': File({
+ name: 'helper',
+ version: '6.6.6',
+ bin: './script.js'
+ })
+ }),
+ 'package.json': File({
+ name: 'npm-test-prepublish-only',
+ version: '1.2.5',
+ dependencies: {
+ 'helper': 'file:./helper'
+ },
+ scripts: {
+ build: 'helper',
+ prepublishOnly: 'npm run build'
+ }
+ })
+}))
+
+test('setup', function (t) {
+ cleanup()
+ fixture.create(pkg)
+ mr({port: common.port, throwOnUnmatched: true}, function (err, s) {
+ t.ifError(err, 'registry mocked successfully')
+ server = s
+ common.npm(
+ [
+ 'install',
+ '--loglevel', 'error',
+ '--cache', cachedir,
+ '--tmp', tmpdir
+ ],
+ {
+ cwd: pkg,
+ env: env
+ },
+ function (err, code, stdout, stderr) {
+ t.equal(code, 0, 'install exited OK')
+ t.ifErr(err, 'installed successfully')
+
+ t.notOk(stderr, 'got stderr data:' + JSON.stringify('' + stderr))
+
+ t.end()
+ }
+ )
+ })
+})
+
+test('test', function (t) {
+ server.filteringRequestBody(function () { return true })
+ .put('/npm-test-prepublish-only', true)
+ .reply(201, {ok: true})
+
+ common.npm(
+ [
+ 'publish',
+ '--loglevel', 'warn'
+ ],
+ {
+ cwd: pkg,
+ env: env
+ },
+ function (err, code, stdout, stderr) {
+ t.equal(code, 0, 'publish ran without error')
+ t.ifErr(err, 'published successfully')
+
+ t.notOk(stderr, 'got stderr data:' + JSON.stringify('' + stderr))
+ var c = stdout.trim()
+ var regex = new RegExp(
+ '> npm-test-prepublish-only@1.2.5 prepublishOnly [^\\r\\n]+\\r?\\n' +
+ '> npm run build\\r?\\n' +
+ '\\r?\\n' +
+ '\\r?\\n' +
+ '> npm-test-prepublish-only@1.2.5 build [^\\r\\n]+\\r?\\n' +
+ '> helper\\r?\\n' +
+ '\\r?\\n' +
+ 'ok\\r?\\n' +
+ '\\+ npm-test-prepublish-only@1.2.5', 'ig'
+ )
+
+ t.match(c, regex)
+ t.end()
+ }
+ )
+})
+
+test('cleanup', function (t) {
+ cleanup()
+ server.close()
+ t.pass('cleaned up')
+ t.end()
+})
+
+function cleanup () {
+ fixture.remove(pkg)
+}
diff --git a/deps/npm/test/tap/prepublish.js b/deps/npm/test/tap/prepublish.js
index 556d01ebb0..ef55d79b3b 100644
--- a/deps/npm/test/tap/prepublish.js
+++ b/deps/npm/test/tap/prepublish.js
@@ -1,4 +1,4 @@
-// verify that prepublish runs on pack and publish
+// verify that prepublish runs on install, pack, and publish
var common = require('../common-tap')
var test = require('tap').test
var fs = require('graceful-fs')
@@ -38,7 +38,7 @@ test('setup', function (t) {
}
})
-test('test', function (t) {
+test('prepublish deprecation warning on `npm pack`', function (t) {
var env = {
'npm_config_cache': cache,
'npm_config_tmp': tmp,
@@ -59,7 +59,7 @@ test('test', function (t) {
t.equal(code, 0, 'pack finished successfully')
t.ifErr(err, 'pack finished successfully')
- t.notOk(stderr, 'got stderr data:' + JSON.stringify('' + stderr))
+ t.match(stderr, /`prepublish` scripts will run only for `npm publish`/)
var c = stdout.trim()
var regex = new RegExp('' +
'> npm-test-prepublish@1.2.5 prepublish [^\\r\\n]+\\r?\\n' +
@@ -68,11 +68,45 @@ test('test', function (t) {
'ok\\r?\\n' +
'npm-test-prepublish-1.2.5.tgz', 'ig')
- t.ok(c.match(regex))
+ t.match(c, regex)
t.end()
})
})
+test('prepublish deprecation warning on `npm install`', function (t) {
+ var env = {
+ 'npm_config_cache': cache,
+ 'npm_config_tmp': tmp,
+ 'npm_config_prefix': pkg,
+ 'npm_config_global': 'false'
+ }
+
+ for (var i in process.env) {
+ if (!/^npm_config_/.test(i)) {
+ env[i] = process.env[i]
+ }
+ }
+
+ common.npm([
+ 'install',
+ '--loglevel', 'warn'
+ ], { cwd: pkg, env: env }, function (err, code, stdout, stderr) {
+ t.equal(code, 0, 'pack finished successfully')
+ t.ifErr(err, 'pack finished successfully')
+
+ t.match(stderr, /`prepublish` scripts will run only for `npm publish`/)
+ var c = stdout.trim()
+ var regex = new RegExp('' +
+ '> npm-test-prepublish@1.2.5 prepublish [^\\r\\n]+\\r?\\n' +
+ '> echo ok\\r?\\n' +
+ '\\r?\\n' +
+ 'ok' +
+ '', 'ig')
+
+ t.match(c, regex)
+ t.end()
+ })
+})
test('cleanup', function (t) {
cleanup()
t.pass('cleaned up')
diff --git a/deps/npm/test/tap/scope-header.js b/deps/npm/test/tap/scope-header.js
new file mode 100644
index 0000000000..3eb70f132e
--- /dev/null
+++ b/deps/npm/test/tap/scope-header.js
@@ -0,0 +1,160 @@
+'use strict'
+var path = require('path')
+var test = require('tap').test
+var mr = require('npm-registry-mock')
+var Tacks = require('tacks')
+var File = Tacks.File
+var Dir = Tacks.Dir
+var common = require('../common-tap.js')
+
+var basedir = path.join(__dirname, path.basename(__filename, '.js'))
+var testdir = path.join(basedir, 'testdir')
+var withScope = path.join(testdir, 'with-scope')
+var withoutScope = path.join(testdir, 'without-scope')
+var onlyProjectScope = path.join(testdir, 'only-project-scope')
+var cachedir = path.join(basedir, 'cache')
+var globaldir = path.join(basedir, 'global')
+var tmpdir = path.join(basedir, 'tmp')
+
+var env = common.newEnv().extend({
+ npm_config_cache: cachedir,
+ npm_config_tmp: tmpdir,
+ npm_config_prefix: globaldir,
+ npm_config_registry: common.registry,
+ npm_config_loglevel: 'warn'
+})
+
+var conf = function (cwd) {
+ return {
+ cwd: cwd || testdir,
+ env: env
+ }
+}
+var server
+var fixture = new Tacks(Dir({
+ cache: Dir(),
+ global: Dir(),
+ tmp: Dir(),
+ testdir: Dir({
+ 'with-scope': Dir({
+ 'package.json': File({
+ name: '@example/with-scope',
+ version: '1.0.0'
+ })
+ }),
+ 'without-scope': Dir({
+ 'package.json': File({
+ name: 'without-scope',
+ version: '1.0.0'
+ })
+ }),
+ 'only-project-scope': Dir({
+ '.npmrc': File('@example:registry=thisisinvalid\n'),
+ 'package.json': File({
+ name: '@example/only-project-scope',
+ version: '1.0.0'
+ })
+ })
+ })
+}))
+
+function setup () {
+ cleanup()
+ fixture.create(basedir)
+}
+
+function cleanup () {
+ fixture.remove(basedir)
+}
+
+var scopeHeaderTestGotScope = {
+ 'time': {'1.0.0': ''},
+ 'dist-tags': {'latest': '1.0.0'},
+ 'versions': {
+ '1.0.0': {
+ name: 'scope-header-test',
+ version: '1.0.0',
+ gotScope: true
+ }
+ }
+}
+var scopeHeaderTestNoScope = {
+ 'time': {'1.0.0': ''},
+ 'dist-tags': {'latest': '1.0.0'},
+ 'versions': {
+ '1.0.0': {
+ name: 'scope-header-test',
+ version: '1.0.0',
+ gotScope: false
+ }
+ }
+}
+
+test('setup', function (t) {
+ setup()
+ mr({port: common.port, throwOnUnmatched: true}, function (err, s) {
+ if (err) throw err
+ server = s
+ server.get('/scope-header-test', {
+ 'NPM-Scope': '@example'
+ }).many().reply('200', scopeHeaderTestGotScope)
+ server.get('/scope-header-test', {}).many().reply('200', scopeHeaderTestNoScope)
+ t.done()
+ })
+})
+
+test('with-scope', function (t) {
+ common.npm(['view', '--cache-min=0', 'scope-header-test', 'gotScope'], conf(withScope), function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'command ran ok')
+ t.comment(stderr.trim())
+ t.is(stdout.trim(), 'true', 'got version matched to scope header')
+ t.done()
+ })
+})
+
+test('without-scope', function (t) {
+ common.npm(['view', '--cache-min=0', 'scope-header-test', 'gotScope'], conf(withoutScope), function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'command ran ok')
+ t.comment(stderr.trim())
+ t.is(stdout.trim(), 'false', 'got version matched to NO scope header')
+ t.done()
+ })
+})
+
+test('scope can be forced by having an explicit one', function (t) {
+ common.npm([
+ 'view',
+ '--cache-min=0',
+ '--scope=example',
+ 'scope-header-test',
+ 'gotScope'
+ ], conf(withoutScope), function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'command ran ok')
+ t.comment(stderr.trim())
+ t.is(stdout.trim(), 'true', 'got version matched to scope header')
+ t.done()
+ })
+})
+
+test('only the project scope is used', function (t) {
+ common.npm([
+ 'view',
+ '--cache-min=0',
+ 'scope-header-test', 'gotScope'
+ ], conf(onlyProjectScope), function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'command ran ok')
+ t.comment(stderr.trim())
+ t.is(stdout.trim(), 'true', 'got version scope')
+ t.done()
+ })
+})
+
+test('cleanup', function (t) {
+ server.close()
+ cleanup()
+ t.done()
+})
diff --git a/deps/npm/test/tap/search.js b/deps/npm/test/tap/search.js
index 138517c3bd..dcc46df78e 100644
--- a/deps/npm/test/tap/search.js
+++ b/deps/npm/test/tap/search.js
@@ -1,81 +1,185 @@
-var fs = require('graceful-fs')
var path = require('path')
-
var mkdirp = require('mkdirp')
-var mr = require('npm-registry-mock')
var osenv = require('osenv')
var rimraf = require('rimraf')
+var cacheFile = require('npm-cache-filename')
var test = require('tap').test
+var Tacks = require('tacks')
+var File = Tacks.File
var common = require('../common-tap.js')
-var pkg = path.resolve(__dirname, 'search')
-var cache = path.resolve(pkg, 'cache')
-var registryCache = path.resolve(cache, 'localhost_1337', '-', 'all')
-var cacheJsonFile = path.resolve(registryCache, '.cache.json')
-
-var timeMock = {
- epoch: 1411727900,
- future: 1411727900 + 100,
- all: 1411727900 + 25,
- since: 0 // filled by since server callback
-}
+var PKG_DIR = path.resolve(__dirname, 'search')
+var CACHE_DIR = path.resolve(PKG_DIR, 'cache')
+var cacheBase = cacheFile(CACHE_DIR)(common.registry + '/-/all')
+var cachePath = path.join(cacheBase, '.cache.json')
-var EXEC_OPTS = {}
+test('setup', function (t) {
+ t.pass('all set up')
+ t.done()
+})
-var mocks = {
- /* Since request, always response with an _update time > the time requested */
- sinceFuture: function (server) {
- server.filteringPathRegEx(/startkey=[^&]*/g, function (s) {
- var _allMock = JSON.parse(JSON.stringify(allMock))
- timeMock.since = _allMock._updated = s.replace('startkey=', '')
- server.get('/-/all/since?stale=update_after&' + s)
- .reply(200, _allMock)
- return s
- })
- },
- allFutureUpdatedOnly: function (server) {
- server.get('/-/all')
- .reply(200, stringifyUpdated(timeMock.future))
- },
- all: function (server) {
- server.get('/-/all')
- .reply(200, allMock)
+test('notifies when there are no results', function (t) {
+ setup()
+ var now = Date.now()
+ var cacheContents = {
+ '_updated': now,
+ bar: { name: 'bar', version: '1.0.0' },
+ cool: { name: 'cool', version: '1.0.0' },
+ foo: { name: 'foo', version: '2.0.0' },
+ other: { name: 'other', version: '1.0.0' }
}
-}
+ var fixture = new Tacks(File(cacheContents))
+ fixture.create(cachePath)
+ common.npm([
+ 'search', 'nomatcheswhatsoeverfromthis',
+ '--registry', common.registry,
+ '--loglevel', 'error',
+ '--cache', CACHE_DIR
+ ], {}, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.equal(stderr, '', 'no error output')
+ t.equal(code, 0, 'search gives 0 error code even if no matches')
+ t.match(stdout, /No matches found/, 'Useful message on search failure')
+ t.done()
+ })
+})
-test('No previous cache, init cache triggered by first search', function (t) {
- cleanup()
+test('spits out a useful error when no cache nor network', function (t) {
+ setup()
+ var cacheContents = {}
+ var fixture = new Tacks(File(cacheContents))
+ fixture.create(cachePath)
+ common.npm([
+ 'search', 'foo',
+ '--registry', common.registry,
+ '--loglevel', 'silly',
+ '--fetch-retry-mintimeout', 0,
+ '--fetch-retry-maxtimeout', 0,
+ '--cache', CACHE_DIR
+ ], {}, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.equal(code, 1, 'non-zero exit code')
+ t.equal(stdout, '', 'no stdout output')
+ t.match(stderr, /No search sources available/, 'useful error')
+ t.done()
+ })
+})
- mr({ port: common.port, plugin: mocks.allFutureUpdatedOnly }, function (err, s) {
- t.ifError(err, 'mock registry started')
- common.npm([
- 'search', 'do not do extra search work on my behalf',
- '--registry', common.registry,
- '--cache', cache,
- '--loglevel', 'silent',
- '--color', 'always'
- ],
- EXEC_OPTS,
- function (err, code) {
- s.close()
- t.equal(code, 0, 'search finished successfully')
- t.ifErr(err, 'search finished successfully')
+test('can switch to JSON mode', function (t) {
+ setup()
+ var now = Date.now()
+ var cacheContents = {
+ '_updated': now,
+ bar: { name: 'bar', version: '1.0.0' },
+ cool: { name: 'cool', version: '1.0.0' },
+ foo: { name: 'foo', version: '2.0.0' },
+ other: { name: 'other', version: '1.0.0' }
+ }
+ var fixture = new Tacks(File(cacheContents))
+ fixture.create(cachePath)
+ common.npm([
+ 'search', 'oo',
+ '--json',
+ '--registry', common.registry,
+ '--loglevel', 'error',
+ '--cache', CACHE_DIR
+ ], {}, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.deepEquals(JSON.parse(stdout), [
+ { name: 'cool', version: '1.0.0' },
+ { name: 'foo', version: '2.0.0' }
+ ], 'results returned as valid json')
+ t.equal(stderr, '', 'no error output')
+ t.equal(code, 0, 'search gives 0 error code even if no matches')
+ t.done()
+ })
+})
- t.ok(
- fs.existsSync(cacheJsonFile),
- cacheJsonFile + ' expected to have been created'
- )
+test('JSON mode does not notify on empty', function (t) {
+ setup()
+ var now = Date.now()
+ var cacheContents = {
+ '_updated': now,
+ bar: { name: 'bar', version: '1.0.0' },
+ cool: { name: 'cool', version: '1.0.0' },
+ foo: { name: 'foo', version: '2.0.0' },
+ other: { name: 'other', version: '1.0.0' }
+ }
+ var fixture = new Tacks(File(cacheContents))
+ fixture.create(cachePath)
+ common.npm([
+ 'search', 'nomatcheswhatsoeverfromthis',
+ '--json',
+ '--registry', common.registry,
+ '--loglevel', 'error',
+ '--cache', CACHE_DIR
+ ], {}, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.deepEquals(JSON.parse(stdout), [], 'no notification about no results')
+ t.equal(stderr, '', 'no error output')
+ t.equal(code, 0, 'search gives 0 error code even if no matches')
+ t.done()
+ })
+})
- var cacheData = JSON.parse(fs.readFileSync(cacheJsonFile, 'utf8'))
- t.equal(cacheData._updated, String(timeMock.future))
- t.end()
- })
+test('can switch to tab separated mode', function (t) {
+ setup()
+ var now = Date.now()
+ var cacheContents = {
+ '_updated': now,
+ bar: { name: 'bar', version: '1.0.0' },
+ cool: { name: 'cool', version: '1.0.0' },
+ foo: { name: 'foo', description: 'this\thas\ttabs', version: '2.0.0' },
+ other: { name: 'other', version: '1.0.0' }
+ }
+ var fixture = new Tacks(File(cacheContents))
+ fixture.create(cachePath)
+ common.npm([
+ 'search', 'oo',
+ '--parseable',
+ '--registry', common.registry,
+ '--loglevel', 'error',
+ '--cache', CACHE_DIR
+ ], {}, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.equal(stdout, 'cool\t\t\tprehistoric\t\t\nfoo\tthis has tabs\t\tprehistoric\t\t\n', 'correct output, including replacing tabs in descriptions')
+ t.equal(stderr, '', 'no error output')
+ t.equal(code, 0, 'search gives 0 error code even if no matches')
+ t.done()
+ })
+})
+
+test('tab mode does not notify on empty', function (t) {
+ setup()
+ var now = Date.now()
+ var cacheContents = {
+ '_updated': now,
+ bar: { name: 'bar', version: '1.0.0' },
+ cool: { name: 'cool', version: '1.0.0' },
+ foo: { name: 'foo', version: '2.0.0' },
+ other: { name: 'other', version: '1.0.0' }
+ }
+ var fixture = new Tacks(File(cacheContents))
+ fixture.create(cachePath)
+ common.npm([
+ 'search', 'nomatcheswhatsoeverfromthis',
+ '--parseable',
+ '--registry', common.registry,
+ '--loglevel', 'error',
+ '--cache', CACHE_DIR
+ ], {}, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.equal(stdout, '', 'no notification about no results')
+ t.equal(stderr, '', 'no error output')
+ t.equal(code, 0, 'search gives 0 error code even if no matches')
+ t.done()
})
})
test('no arguments provided should error', function (t) {
- common.npm(['search'], [], function (err, code, stdout, stderr) {
+ cleanup()
+ common.npm(['search'], {}, function (err, code, stdout, stderr) {
if (err) throw err
t.equal(code, 1, 'search finished unsuccessfully')
@@ -88,83 +192,157 @@ test('no arguments provided should error', function (t) {
})
})
-test('previous cache, _updated set, should trigger since request', function (t) {
- setupCache()
-
- function m (server) {
- [ mocks.all, mocks.sinceFuture ].forEach(function (m) {
- m(server)
- })
- }
- mr({ port: common.port, plugin: m }, function (err, s) {
- t.ifError(err, 'mock registry started')
- common.npm([
- 'search', 'do not do extra search work on my behalf',
- '--registry', common.registry,
- '--cache', cache,
- '--loglevel', 'silly',
- '--color', 'always'
- ],
- EXEC_OPTS,
- function (err, code) {
- s.close()
- t.equal(code, 0, 'search finished successfully')
- t.ifErr(err, 'search finished successfully')
-
- var cacheData = JSON.parse(fs.readFileSync(cacheJsonFile, 'utf8'))
- t.equal(
- cacheData._updated,
- timeMock.since,
- 'cache update time gotten from since response'
- )
- t.end()
- })
- })
-})
-
var searches = [
{
- term: 'f36b6a6123da50959741e2ce4d634f96ec668c56',
- description: 'non-regex',
- location: 241
+ term: 'cool',
+ description: 'non-regex search',
+ location: 103
+ },
+ {
+ term: '/cool/',
+ description: 'regex search',
+ location: 103
},
{
- term: '/f36b6a6123da50959741e2ce4d634f96ec668c56/',
- description: 'regex',
- location: 241
+ term: 'cool',
+ description: 'searches name field',
+ location: 103
+ },
+ {
+ term: 'ool',
+ description: 'excludes matches for --searchexclude',
+ location: 205,
+ inject: {
+ other: { name: 'other', description: 'this is a simple tool' }
+ },
+ extraOpts: ['--searchexclude', 'cool']
+ },
+ {
+ term: 'neat lib',
+ description: 'searches description field',
+ location: 141,
+ inject: {
+ cool: {
+ name: 'cool', version: '5.0.0', description: 'this is a neat lib'
+ }
+ }
+ },
+ {
+ term: 'foo',
+ description: 'skips description field with --no-description',
+ location: 80,
+ inject: {
+ cool: {
+ name: 'cool', version: '5.0.0', description: 'foo bar!'
+ }
+ },
+ extraOpts: ['--no-description']
+ },
+ {
+ term: 'zkat',
+ description: 'searches maintainers by name',
+ location: 155,
+ inject: {
+ cool: {
+ name: 'cool',
+ version: '5.0.0',
+ maintainers: [{
+ name: 'zkat'
+ }]
+ }
+ }
+ },
+ {
+ term: '=zkat',
+ description: 'searches maintainers unambiguously by =name',
+ location: 154,
+ inject: {
+ bar: { name: 'bar', description: 'zkat thing', version: '1.0.0' },
+ cool: {
+ name: 'cool',
+ version: '5.0.0',
+ maintainers: [{
+ name: 'zkat'
+ }]
+ }
+ }
+ },
+ {
+ term: 'github.com',
+ description: 'searches projects by url',
+ location: 205,
+ inject: {
+ bar: {
+ name: 'bar',
+ url: 'gitlab.com/bar',
+ // For historical reasons, `url` is only present if `versions` is there
+ versions: ['1.0.0'],
+ version: '1.0.0'
+ },
+ cool: {
+ name: 'cool',
+ version: '5.0.0',
+ versions: ['1.0.0'],
+ url: 'github.com/cool/cool'
+ }
+ }
+ },
+ {
+ term: 'monad',
+ description: 'searches projects by keywords',
+ location: 197,
+ inject: {
+ cool: {
+ name: 'cool',
+ version: '5.0.0',
+ keywords: ['monads']
+ }
+ }
}
]
searches.forEach(function (search) {
- test(search.description + ' search in color', function (t) {
- cleanup()
- mr({ port: common.port, plugin: mocks.all }, function (er, s) {
- common.npm([
- 'search', search.term,
- '--registry', common.registry,
- '--cache', cache,
- '--loglevel', 'silent',
- '--color', 'always'
- ],
- EXEC_OPTS,
- function (err, code, stdout) {
- s.close()
- t.equal(code, 0, 'search finished successfully')
- t.ifErr(err, 'search finished successfully')
- // \033 == \u001B
- var markStart = '\u001B\\[[0-9][0-9]m'
- var markEnd = '\u001B\\[0m'
+ test(search.description, function (t) {
+ setup()
+ var now = Date.now()
+ var cacheContents = {
+ '_updated': now,
+ bar: { name: 'bar', version: '1.0.0' },
+ cool: { name: 'cool', version: '5.0.0' },
+ foo: { name: 'foo', version: '2.0.0' },
+ other: { name: 'other', version: '1.0.0' }
+ }
+ for (var k in search.inject) {
+ cacheContents[k] = search.inject[k]
+ }
+ var fixture = new Tacks(File(cacheContents))
+ fixture.create(cachePath)
+ common.npm([
+ 'search', search.term,
+ '--registry', common.registry,
+ '--cache', CACHE_DIR,
+ '--loglevel', 'error',
+ '--color', 'always'
+ ].concat(search.extraOpts || []),
+ {},
+ function (err, code, stdout, stderr) {
+ t.equal(stderr, '', 'no error output')
+ t.notEqual(stdout, '', 'got output')
+ t.equal(code, 0, 'search finished successfully')
+ t.ifErr(err, 'search finished successfully')
+ // \033 == \u001B
+ var markStart = '\u001B\\[[0-9][0-9]m'
+ var markEnd = '\u001B\\[0m'
- var re = new RegExp(markStart + '.*?' + markEnd)
+ var re = new RegExp(markStart + '.*?' + markEnd)
- var cnt = stdout.search(re)
- t.equal(
- cnt,
- search.location,
- search.description + ' search for ' + search.term
- )
- t.end()
- })
+ var cnt = stdout.search(re)
+ t.equal(
+ cnt,
+ search.location,
+ search.description + ' search for ' + search.term
+ )
+ t.end()
})
})
})
@@ -174,117 +352,12 @@ test('cleanup', function (t) {
t.end()
})
-function cleanup () {
- process.chdir(osenv.tmpdir())
- rimraf.sync(pkg)
-}
-
-function setupCache () {
+function setup () {
cleanup()
- mkdirp.sync(cache)
- mkdirp.sync(registryCache)
- var res = fs.writeFileSync(cacheJsonFile, stringifyUpdated(timeMock.epoch))
- if (res) throw new Error('Creating cache file failed')
+ mkdirp.sync(cacheBase)
}
-function stringifyUpdated (time) {
- return JSON.stringify({ _updated: String(time) })
-}
-
-var allMock = {
- '_updated': timeMock.all,
- 'generator-frontcow': {
- 'name': 'generator-frontcow',
- 'description': 'f36b6a6123da50959741e2ce4d634f96ec668c56 This is a fake description to ensure we do not accidentally search the real npm registry or use some kind of cache',
- 'dist-tags': {
- 'latest': '0.1.19'
- },
- 'maintainers': [
- {
- 'name': 'bcabanes',
- 'email': 'contact@benjamincabanes.com'
- }
- ],
- 'homepage': 'https://github.com/bcabanes/generator-frontcow',
- 'keywords': [
- 'sass',
- 'frontend',
- 'yeoman-generator',
- 'atomic',
- 'design',
- 'sass',
- 'foundation',
- 'foundation5',
- 'atomic design',
- 'bourbon',
- 'polyfill',
- 'font awesome'
- ],
- 'repository': {
- 'type': 'git',
- 'url': 'https://github.com/bcabanes/generator-frontcow'
- },
- 'author': {
- 'name': 'ben',
- 'email': 'contact@benjamincabanes.com',
- 'url': 'https://github.com/bcabanes'
- },
- 'bugs': {
- 'url': 'https://github.com/bcabanes/generator-frontcow/issues'
- },
- 'license': 'MIT',
- 'readmeFilename': 'README.md',
- 'time': {
- 'modified': '2014-10-03T02:26:18.406Z'
- },
- 'versions': {
- '0.1.19': 'latest'
- }
- },
- 'marko': {
- 'name': 'marko',
- 'description': 'Marko is an extensible, streaming, asynchronous, high performance, HTML-based templating language that can be used in Node.js or in the browser.',
- 'dist-tags': {
- 'latest': '1.2.16'
- },
- 'maintainers': [
- {
- 'name': 'pnidem',
- 'email': 'pnidem@gmail.com'
- },
- {
- 'name': 'philidem',
- 'email': 'phillip.idem@gmail.com'
- }
- ],
- 'homepage': 'https://github.com/raptorjs/marko',
- 'keywords': [
- 'templating',
- 'template',
- 'async',
- 'streaming'
- ],
- 'repository': {
- 'type': 'git',
- 'url': 'https://github.com/raptorjs/marko.git'
- },
- 'author': {
- 'name': 'Patrick Steele-Idem',
- 'email': 'pnidem@gmail.com'
- },
- 'bugs': {
- 'url': 'https://github.com/raptorjs/marko/issues'
- },
- 'license': 'Apache License v2.0',
- 'readmeFilename': 'README.md',
- 'users': {
- 'pnidem': true
- },
- 'time': {
- 'modified': '2014-10-03T02:27:31.775Z'
- },
- 'versions': {
- '1.2.16': 'latest'
- }
- }
+function cleanup () {
+ process.chdir(osenv.tmpdir())
+ rimraf.sync(PKG_DIR)
}
diff --git a/deps/npm/test/tap/semver-tag.js b/deps/npm/test/tap/semver-tag.js
deleted file mode 100644
index b4feb75176..0000000000
--- a/deps/npm/test/tap/semver-tag.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// should not allow tagging with a valid semver range
-var common = require('../common-tap.js')
-var test = require('tap').test
-
-test('try to tag with semver range as tag name', function (t) {
- var cmd = ['tag', 'zzzz@1.2.3', 'v2.x', '--registry=http://localhost']
- common.npm(cmd, {
- stdio: 'pipe'
- }, function (er, code, so, se) {
- if (er) throw er
- t.similar(se, /Tag name must not be a valid SemVer range: v2.x\n/)
- t.equal(code, 1)
- t.end()
- })
-})
diff --git a/deps/npm/test/tap/shrinkwrap-complete-except-dev.js b/deps/npm/test/tap/shrinkwrap-complete-except-dev.js
new file mode 100644
index 0000000000..156721507f
--- /dev/null
+++ b/deps/npm/test/tap/shrinkwrap-complete-except-dev.js
@@ -0,0 +1,159 @@
+'use strict'
+var fs = require('graceful-fs')
+var path = require('path')
+var test = require('tap').test
+var mr = require('npm-registry-mock')
+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 appdir = path.join(testdir, 'app')
+var installedModuleA = path.join(appdir, 'node_modules', 'module-a')
+var installedModuleB = path.join(installedModuleA, 'node_modules', 'module-b')
+var installedModuleC = path.join(appdir, 'node_modules', 'module-c')
+var installedModuleD = path.join(appdir, 'node_modules', 'module-d')
+
+var conf = {
+ cwd: appdir,
+ 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 server
+var fixture = new Tacks(Dir({
+ cache: Dir(),
+ global: Dir(),
+ tmp: Dir(),
+ testdir: Dir({
+ app: Dir({
+ 'npm-shrinkwrap.json': File({
+ name: 'app',
+ version: '1.0.0',
+ dependencies: {
+ 'module-a': {
+ version: '1.0.0',
+ from: '../module-a',
+ resolved: 'file:../module-a',
+ dependencies: {
+ 'module-b': {
+ version: '1.0.0',
+ from: '../module-b',
+ resolved: 'file:../module-b'
+ }
+ }
+ }
+ }
+ }),
+ 'package.json': File({
+ name: 'app',
+ version: '1.0.0',
+ dependencies: {
+ 'module-a': '../module-a'
+ },
+ devDependencies: {
+ 'module-d': '../module-d'
+ }
+ })
+ }),
+ 'module-a': Dir({
+ 'package.json': File({
+ name: 'module-a',
+ version: '1.0.0',
+ dependencies: {
+ 'module-b': 'file:' + path.join(testdir, 'module-b'),
+ 'module-c': 'file:' + path.join(testdir, 'module-c')
+ }
+ })
+ }),
+ 'module-b': Dir({
+ 'package.json': File({
+ name: 'module-b',
+ version: '1.0.0'
+ })
+ }),
+ 'module-c': Dir({
+ 'package.json': File({
+ name: 'module-c',
+ version: '1.0.0'
+ })
+ }),
+ 'module-d': Dir({
+ 'package.json': File({
+ name: 'module-d',
+ version: '1.0.0'
+ })
+ })
+ })
+}))
+
+function exists (t, filepath, msg) {
+ try {
+ fs.statSync(filepath)
+ t.pass(msg)
+ return true
+ } catch (ex) {
+ t.fail(msg, {found: ex, wanted: 'exists', compare: 'fs.stat(' + filepath + ')'})
+ return false
+ }
+}
+
+function notExists (t, filepath, msg) {
+ try {
+ fs.statSync(filepath)
+ t.fail(msg, {found: true, wanted: 'does not exist', compare: 'fs.stat(' + filepath + ')'})
+ return true
+ } catch (ex) {
+ t.pass(msg)
+ return false
+ }
+}
+
+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('example', function (t) {
+ common.npm(['install'], conf, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'command ran ok')
+ t.comment('1> ' + stdout.trim())
+ t.comment('2> ' + stderr.trim())
+ exists(t, installedModuleA, 'module-a: dep in shrinkwrap installed')
+ exists(t, installedModuleB, 'module-b: nested dep from shrinkwrap nested')
+ notExists(t, installedModuleC, 'module-c: dependency not installed because not in shrinkwrap')
+ exists(t, installedModuleD, 'module-d: dev dependency installed despite not being in shrinkwrap')
+ t.done()
+ })
+})
+
+test('cleanup', function (t) {
+ server.close()
+ cleanup()
+ t.done()
+})
diff --git a/deps/npm/test/tap/shrinkwrap-default-dev.js b/deps/npm/test/tap/shrinkwrap-default-dev.js
new file mode 100644
index 0000000000..6b1aa181e1
--- /dev/null
+++ b/deps/npm/test/tap/shrinkwrap-default-dev.js
@@ -0,0 +1,125 @@
+'use strict'
+var path = require('path')
+var test = require('tap').test
+var fs = require('fs')
+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({
+ node_modules: Dir({
+ '@npmtest': Dir({
+ example: Dir({
+ 'package.json': File({
+ name: '@npmtest/example',
+ version: '1.0.0'
+ })
+ })
+ })
+ }),
+ 'package.json': File({
+ name: 'shrinkwrap-default-dev',
+ version: '1.0.0',
+ devDependencies: {
+ '@npmtest/example': '1.0.0'
+ }
+ })
+ })
+}))
+
+var shrinkwrapPath = path.join(testdir, 'npm-shrinkwrap.json')
+var shrinkwrapWithDev = {
+ name: 'shrinkwrap-default-dev',
+ version: '1.0.0',
+ dependencies: {
+ '@npmtest/example': {
+ 'version': '1.0.0',
+ 'dev': true
+ }
+ }
+}
+var shrinkwrapWithoutDev = {
+ name: 'shrinkwrap-default-dev',
+ version: '1.0.0',
+ dependencies: {}
+}
+
+function setup () {
+ cleanup()
+ fixture.create(basedir)
+}
+
+function cleanup () {
+ fixture.remove(basedir)
+}
+
+test('setup', function (t) {
+ setup()
+ t.done()
+})
+
+test('shrinkwrap-default-dev', function (t) {
+ common.npm(['shrinkwrap'], conf, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'command ran ok')
+ t.comment(stdout.trim())
+ t.comment(stderr.trim())
+ var swrap = JSON.parse(fs.readFileSync(shrinkwrapPath))
+ t.isDeeply(swrap, shrinkwrapWithDev, 'Shrinkwrap included dev deps by default')
+ t.done()
+ })
+})
+
+test('shrinkwrap-only-prod', function (t) {
+ fs.unlinkSync(shrinkwrapPath)
+ common.npm(['shrinkwrap', '--only=prod'], conf, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'command ran ok')
+ t.comment(stdout.trim())
+ t.comment(stderr.trim())
+ var swrap = JSON.parse(fs.readFileSync(shrinkwrapPath))
+ t.isDeeply(swrap, shrinkwrapWithoutDev, 'Shrinkwrap did not include dev deps with --only=prod')
+ t.done()
+ })
+})
+
+test('shrinkwrap-production', function (t) {
+ fs.unlinkSync(shrinkwrapPath)
+ common.npm(['shrinkwrap', '--production'], conf, function (err, code, stdout, stderr) {
+ if (err) throw err
+ t.is(code, 0, 'command ran ok')
+ t.comment(stdout.trim())
+ t.comment(stderr.trim())
+ var swrap = JSON.parse(fs.readFileSync(shrinkwrapPath))
+ t.isDeeply(swrap, shrinkwrapWithoutDev, 'Shrinkwrap did not include dev deps with --production')
+ t.done()
+ })
+})
+
+test('cleanup', function (t) {
+ cleanup()
+ t.done()
+})
diff --git a/deps/npm/test/tap/shrinkwrap-dev-dep-cycle.js b/deps/npm/test/tap/shrinkwrap-dev-dep-cycle.js
index c9511bb152..cd5237e161 100644
--- a/deps/npm/test/tap/shrinkwrap-dev-dep-cycle.js
+++ b/deps/npm/test/tap/shrinkwrap-dev-dep-cycle.js
@@ -76,7 +76,7 @@ test('setup', function (t) {
})
test('shrinkwrap cycle in dev deps', function (t) {
- common.npm(['shrinkwrap'], {cwd: testdir}, function (err, code, stdout, stderr) {
+ common.npm(['shrinkwrap', '--only=prod'], {cwd: testdir}, function (err, code, stdout, stderr) {
if (err) throw err
t.is(code, 0, 'result code = ok')
t.comment(stdout.trim())
diff --git a/deps/npm/test/tap/shrinkwrap-shared-dev-dependency.js b/deps/npm/test/tap/shrinkwrap-shared-dev-dependency.js
index a6cddae33d..0011f7b6f1 100644
--- a/deps/npm/test/tap/shrinkwrap-shared-dev-dependency.js
+++ b/deps/npm/test/tap/shrinkwrap-shared-dev-dependency.js
@@ -21,6 +21,7 @@ test("shrinkwrap doesn't strip out the shared dependency", function (t) {
npm.install('.', function (err) {
if (err) return t.fail(err)
+ npm.config.set('dev', true) // npm install unsets this
npm.commands.shrinkwrap([], true, function (err, results) {
if (err) return t.fail(err)
diff --git a/deps/npm/test/tap/shrinkwrap-transitive-dev.js b/deps/npm/test/tap/shrinkwrap-transitive-dev.js
index 80a38f7f9e..7a8f5b45d2 100644
--- a/deps/npm/test/tap/shrinkwrap-transitive-dev.js
+++ b/deps/npm/test/tap/shrinkwrap-transitive-dev.js
@@ -62,7 +62,7 @@ test('setup', function (t) {
})
test('transitive-deps-of-dev-deps', function (t) {
- common.npm(['shrinkwrap', '--loglevel=error'], {cwd: testdir}, function (err, code, stdout, stderr) {
+ common.npm(['shrinkwrap', '--loglevel=error', '--only=prod'], {cwd: testdir}, function (err, code, stdout, stderr) {
if (err) throw err
t.is(code, 0, 'shrinkwrap ran ok')
t.comment(stdout.trim())
diff --git a/deps/npm/test/tap/shrinkwrap-version-match.js b/deps/npm/test/tap/shrinkwrap-version-match.js
index 7d9fed729a..bdcff2e4b6 100644
--- a/deps/npm/test/tap/shrinkwrap-version-match.js
+++ b/deps/npm/test/tap/shrinkwrap-version-match.js
@@ -7,6 +7,10 @@ var fs = require('fs')
var path = require('path')
var common = require('../common-tap.js')
+// NOTE: This test will only remain relavent until npm@5 when
+// npm-shrinkwrap.json will override EVERYTHING in you package.json.
+// If you're working on npm@5 and this broke, just remove the test.
+
var testdir = path.resolve(__dirname, path.basename(__filename, '.js'))
var modAdir = path.resolve(testdir, 'modA')
var modB1dir = path.resolve(testdir, 'modB@1')
@@ -16,7 +20,9 @@ var modCdir = path.resolve(testdir, 'modC')
var fixture = new Tacks(Dir({
'package.json': File({
dependencies: {
- modA: 'file://' + modAdir,
+ modA: 'file://' + modAdir
+ },
+ devDependencies: {
modC: 'file://' + modCdir
}
}),
diff --git a/deps/npm/test/tap/uninstall-in-reverse.js b/deps/npm/test/tap/uninstall-in-reverse.js
index 2d8fe2bcfc..e5c7a80c7e 100644
--- a/deps/npm/test/tap/uninstall-in-reverse.js
+++ b/deps/npm/test/tap/uninstall-in-reverse.js
@@ -10,7 +10,7 @@ order. That is, they need to go shallow -> deep.
var removed = []
var npm = requireInject.installGlobally('../../lib/npm.js', {
- '../../lib/install/action/remove.js': function (top, buildpath, pkg, log, next) {
+ '../../lib/install/action/remove.js': function (staging, pkg, log, next) {
removed.push(pkg.package.name)
next()
}
diff --git a/deps/npm/test/tap/unit-deps-earliestInstallable.js b/deps/npm/test/tap/unit-deps-earliestInstallable.js
new file mode 100644
index 0000000000..26a251addc
--- /dev/null
+++ b/deps/npm/test/tap/unit-deps-earliestInstallable.js
@@ -0,0 +1,111 @@
+'use strict'
+var test = require('tap').test
+var requireInject = require('require-inject')
+
+// we're just mocking to avoid having to call `npm.load`
+var deps = requireInject('../../lib/install/deps.js', {
+ '../../lib/npm.js': {
+ config: {
+ get: function (val) { return (val === 'global-style' || val === 'legacy-bundling') ? false : 'mock' }
+ }
+ }
+})
+
+var earliestInstallable = deps.earliestInstallable
+
+test('earliestInstallable should consider devDependencies', function (t) {
+ var dep1 = {
+ children: [],
+ package: {
+ name: 'dep1',
+ dependencies: { dep2: '2.0.0' }
+ }
+ }
+
+ // a library required by the base package
+ var dep2 = {
+ package: {
+ name: 'dep2',
+ version: '1.0.0'
+ }
+ }
+
+ // an incompatible verson of dep2. required by dep1
+ var dep2a = {
+ package: {
+ name: 'dep2',
+ version: '2.0.0',
+ _from: {
+ raw: 'dep2@1.0.0',
+ scope: null,
+ escapedName: 'dep2',
+ name: 'dep2',
+ rawSpec: '1.0.0',
+ spec: '1.0.0',
+ type: 'version'
+ }
+ },
+ parent: dep1
+ }
+
+ var pkg = {
+ isTop: true,
+ children: [dep1],
+ package: {
+ name: 'pkg',
+ dependencies: { dep1: '1.0.0' },
+ devDependencies: { dep2: '1.0.0' }
+ }
+ }
+
+ dep1.parent = pkg
+ dep2a.parent = dep1
+ dep2.parent = pkg
+
+ var earliest = earliestInstallable(dep1, dep1, dep2a.package)
+ t.isDeeply(earliest, dep1, 'should hoist package when an incompatible devDependency is present')
+ t.end()
+})
+
+test('earliestInstallable should reuse shared prod/dev deps when they are identical', function (t) {
+ var dep1 = {
+ children: [],
+ package: {
+ name: 'dep1',
+ dependencies: { dep2: '1.0.0' }
+ }
+ }
+
+ var dep2 = {
+ package: {
+ name: 'dep2',
+ version: '1.0.0',
+ _from: {
+ raw: 'dep2@^1.0.0',
+ scope: null,
+ escapedName: 'dep2',
+ name: 'dep2',
+ rawSpec: '^1.0.0',
+ spec: '>=1.0.0 <2.0.0',
+ type: 'range'
+ }
+ }
+ }
+
+ var pkg = {
+ isTop: true,
+ children: [dep1],
+ package: {
+ name: 'pkg',
+ dependencies: { dep1: '1.0.0' },
+ devDependencies: { dep2: '^1.0.0' }
+ }
+ }
+
+ dep1.parent = pkg
+ dep2.parent = pkg
+
+ var earliest = earliestInstallable(dep1, dep1, dep2.package)
+ t.isDeeply(earliest, pkg, 'should reuse identical shared dev/prod deps when installing both')
+ t.end()
+})
diff --git a/deps/npm/test/tap/unsupported.js b/deps/npm/test/tap/unsupported.js
new file mode 100644
index 0000000000..dff86a6231
--- /dev/null
+++ b/deps/npm/test/tap/unsupported.js
@@ -0,0 +1,41 @@
+'use strict'
+var test = require('tap').test
+var unsupported = require('../../lib/utils/unsupported.js')
+
+var versions = [
+ // broken unsupported
+ ['v0.1.103', true, true],
+ ['v0.2.0', true, true],
+ ['v0.3.5', true, true],
+ ['v0.4.7', true, true],
+ ['v0.5.3', true, true],
+ ['v0.6.17', true, true],
+ ['v0.7.8', true, true],
+ ['v0.8.28', false, true],
+ ['v0.9.6', false, true],
+ ['v0.10.48', false, true],
+ ['v0.11.16', false, true],
+ ['v0.12.9', false, false],
+ ['v1.0.1', false, true],
+ ['v1.6.0', false, true],
+ ['v2.3.1', false, true],
+ ['v3.0.0', false, true],
+ ['v4.5.0', false, false],
+ ['v5.7.1', false, false],
+ ['v6.8.1', false, false],
+ ['v7.0.0-beta23', false, false],
+ ['v7.2.3', false, false]
+]
+
+test('versions', function (t) {
+ t.plan(versions.length * 2)
+ versions.forEach(function (verinfo) {
+ var version = verinfo[0]
+ var broken = verinfo[1]
+ var unsupp = verinfo[2]
+ var nodejs = unsupported.checkVersion(version)
+ t.is(nodejs.broken, broken, version + ' ' + (broken ? '' : 'not ') + 'broken')
+ t.is(nodejs.unsupported, unsupp, version + ' ' + (unsupp ? 'unsupported' : 'supported'))
+ })
+ t.done()
+})
diff --git a/deps/npm/test/tap/update-index.js b/deps/npm/test/tap/update-index.js
deleted file mode 100644
index 91b2f78781..0000000000
--- a/deps/npm/test/tap/update-index.js
+++ /dev/null
@@ -1,195 +0,0 @@
-var common = require('../common-tap.js')
-var test = require('tap').test
-var npm = require('../../')
-var mkdirp = require('mkdirp')
-var rimraf = require('rimraf')
-var path = require('path')
-var mr = require('npm-registry-mock')
-
-var updateIndex = require('../../lib/cache/update-index.js')
-
-var PKG_DIR = path.resolve(__dirname, 'get-basic')
-var CACHE_DIR = path.resolve(PKG_DIR, 'cache')
-
-var server
-
-var mocks = {
- basic: function (mock) {
- mock.get('/-/all').reply(200, allMock)
- },
- auth: function (mock) {
- var littleBobbyTablesAuth = new Buffer('bobby:tables').toString('base64')
- var auth = 'Basic ' + littleBobbyTablesAuth
- mock.get('/-/all', { authorization: auth }).reply(200, allMock)
- mock.get('/-/all').reply(401, {
- error: 'unauthorized',
- reason: 'You are not authorized to access this db.'
- })
- }
-}
-
-var allMock = {
- '_updated': 1411727900 + 25,
- 'generator-frontcow': {
- 'name': 'generator-frontcow',
- 'description': 'f36b6a6123da50959741e2ce4d634f96ec668c56 This is a fake description to ensure we do not accidentally search the real npm registry or use some kind of cache',
- 'dist-tags': {
- 'latest': '0.1.19'
- },
- 'maintainers': [
- {
- 'name': 'bcabanes',
- 'email': 'contact@benjamincabanes.com'
- }
- ],
- 'homepage': 'https://github.com/bcabanes/generator-frontcow',
- 'keywords': [
- 'sass',
- 'frontend',
- 'yeoman-generator',
- 'atomic',
- 'design',
- 'sass',
- 'foundation',
- 'foundation5',
- 'atomic design',
- 'bourbon',
- 'polyfill',
- 'font awesome'
- ],
- 'repository': {
- 'type': 'git',
- 'url': 'https://github.com/bcabanes/generator-frontcow'
- },
- 'author': {
- 'name': 'ben',
- 'email': 'contact@benjamincabanes.com',
- 'url': 'https://github.com/bcabanes'
- },
- 'bugs': {
- 'url': 'https://github.com/bcabanes/generator-frontcow/issues'
- },
- 'license': 'MIT',
- 'readmeFilename': 'README.md',
- 'time': {
- 'modified': '2014-10-03T02:26:18.406Z'
- },
- 'versions': {
- '0.1.19': 'latest'
- }
- },
- 'marko': {
- 'name': 'marko',
- 'description': 'Marko is an extensible, streaming, asynchronous, high performance, HTML-based templating language that can be used in Node.js or in the browser.',
- 'dist-tags': {
- 'latest': '1.2.16'
- },
- 'maintainers': [
- {
- 'name': 'pnidem',
- 'email': 'pnidem@gmail.com'
- },
- {
- 'name': 'philidem',
- 'email': 'phillip.idem@gmail.com'
- }
- ],
- 'homepage': 'https://github.com/raptorjs/marko',
- 'keywords': [
- 'templating',
- 'template',
- 'async',
- 'streaming'
- ],
- 'repository': {
- 'type': 'git',
- 'url': 'https://github.com/raptorjs/marko.git'
- },
- 'author': {
- 'name': 'Patrick Steele-Idem',
- 'email': 'pnidem@gmail.com'
- },
- 'bugs': {
- 'url': 'https://github.com/raptorjs/marko/issues'
- },
- 'license': 'Apache License v2.0',
- 'readmeFilename': 'README.md',
- 'users': {
- 'pnidem': true
- },
- 'time': {
- 'modified': '2014-10-03T02:27:31.775Z'
- },
- 'versions': {
- '1.2.16': 'latest'
- }
- }
-}
-
-function setup (t, mock, extra) {
- mkdirp.sync(CACHE_DIR)
- mr({ port: common.port, plugin: mock }, function (er, s) {
- npm.load({ cache: CACHE_DIR, registry: common.registry }, function (err) {
- if (extra) {
- Object.keys(extra).forEach(function (k) {
- npm.config.set(k, extra[k], 'user')
- })
- }
- t.ifError(err, 'no error')
- server = s
- t.end()
- })
- })
-}
-
-function cleanup (t) {
- server.close(function () {
- rimraf.sync(PKG_DIR)
-
- t.end()
- })
-}
-
-test('setup basic', function (t) {
- setup(t, mocks.basic)
-})
-
-test('request basic', function (t) {
- updateIndex(0, function (er) {
- t.ifError(er, 'no error')
- t.end()
- })
-})
-
-test('cleanup basic', cleanup)
-
-test('setup auth', function (t) {
- setup(t, mocks.auth)
-})
-
-test('request auth failure', function (t) {
- updateIndex(0, function (er) {
- t.equals(er.code, 'E401', 'gotta get that auth')
- t.ok(/^unauthorized/.test(er.message), 'unauthorized message')
- t.end()
- })
-})
-
-test('cleanup auth failure', cleanup)
-
-test('setup auth', function (t) {
- // mimic as if alwaysAuth had been set
- setup(t, mocks.auth, {
- _auth: new Buffer('bobby:tables').toString('base64'),
- 'always-auth': true
- })
-})
-
-test('request auth success', function (t) {
- updateIndex(0, function (er) {
- t.ifError(er, 'no error')
- t.end()
- })
-})
-
-test('cleanup auth', cleanup)