summaryrefslogtreecommitdiff
path: root/deps/npm/test/lib
diff options
context:
space:
mode:
authorRuy Adorno <ruyadorno@hotmail.com>2020-12-18 15:39:05 -0500
committerMichaƫl Zasso <targos@protonmail.com>2020-12-21 14:29:20 +0100
commitffc11c6015bbf5d950328fca28de77a9cebd2ae2 (patch)
treef3343108a6aea58f8d7d0007b0e3d6032609cd2b /deps/npm/test/lib
parenteefb424c6060582714bcef09a12fc7a74c35384a (diff)
downloadnode-new-ffc11c6015bbf5d950328fca28de77a9cebd2ae2.tar.gz
deps: upgrade npm to 7.3.0
PR-URL: https://github.com/nodejs/node/pull/36572 Reviewed-By: Myles Borins <myles.borins@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Diffstat (limited to 'deps/npm/test/lib')
-rw-r--r--deps/npm/test/lib/adduser.js24
-rw-r--r--deps/npm/test/lib/config.js92
-rw-r--r--deps/npm/test/lib/deprecate.js4
-rw-r--r--deps/npm/test/lib/dist-tag.js2
-rw-r--r--deps/npm/test/lib/help-search.js3
-rw-r--r--deps/npm/test/lib/ls.js24
-rw-r--r--deps/npm/test/lib/npm.js9
-rw-r--r--deps/npm/test/lib/owner.js2
-rw-r--r--deps/npm/test/lib/profile.js1465
-rw-r--r--deps/npm/test/lib/publish.js77
-rw-r--r--deps/npm/test/lib/utils/error-handler.js5
-rw-r--r--deps/npm/test/lib/utils/flat-options.js5
-rw-r--r--deps/npm/test/lib/utils/reify-output.js5
-rw-r--r--deps/npm/test/lib/utils/replace-info.js2
14 files changed, 1665 insertions, 54 deletions
diff --git a/deps/npm/test/lib/adduser.js b/deps/npm/test/lib/adduser.js
index 4e6a56fc19..36f59e0857 100644
--- a/deps/npm/test/lib/adduser.js
+++ b/deps/npm/test/lib/adduser.js
@@ -9,21 +9,27 @@ const _flatOptions = {
authType: 'legacy',
registry: 'https://registry.npmjs.org/',
scope: '',
+ fromFlatOptions: true,
}
let failSave = false
let deletedConfig = {}
let registryOutput = ''
let setConfig = {}
-const authDummy = () => Promise.resolve({
- message: 'success',
- newCreds: {
- username: 'u',
- password: 'p',
- email: 'u@npmjs.org',
- alwaysAuth: false,
- },
-})
+const authDummy = (options) => {
+ if (!options.fromFlatOptions)
+ throw new Error('did not pass full flatOptions to auth function')
+
+ return Promise.resolve({
+ message: 'success',
+ newCreds: {
+ username: 'u',
+ password: 'p',
+ email: 'u@npmjs.org',
+ alwaysAuth: false,
+ },
+ })
+}
const deleteMock = (key, where) => {
deletedConfig = {
diff --git a/deps/npm/test/lib/config.js b/deps/npm/test/lib/config.js
index 74cd530c68..5d2f54249c 100644
--- a/deps/npm/test/lib/config.js
+++ b/deps/npm/test/lib/config.js
@@ -122,7 +122,7 @@ t.test('config list overrides', t => {
config(['list'], (err) => {
t.ifError(err, 'npm config list')
- t.matchSnapshot(result, 'should list overriden configs')
+ t.matchSnapshot(result, 'should list overridden configs')
})
})
@@ -212,6 +212,33 @@ t.test('config delete key', t => {
})
})
+t.test('config delete multiple key', t => {
+ t.plan(6)
+
+ const expect = [
+ 'foo',
+ 'bar',
+ ]
+
+ npm.config.delete = (key, where) => {
+ t.equal(key, expect.shift(), 'should delete expected keyword')
+ t.equal(where, 'user', 'should delete key from user config by default')
+ }
+
+ npm.config.save = where => {
+ t.equal(where, 'user', 'should save user config post-delete')
+ }
+
+ config(['delete', 'foo', 'bar'], (err) => {
+ t.ifError(err, 'npm config delete keys')
+ })
+
+ t.teardown(() => {
+ delete npm.config.delete
+ delete npm.config.save
+ })
+})
+
t.test('config delete key --global', t => {
t.plan(4)
@@ -293,12 +320,43 @@ t.test('config set key=val', t => {
})
})
+t.test('config set multiple keys', t => {
+ t.plan(11)
+
+ const expect = [
+ ['foo', 'bar'],
+ ['bar', 'baz'],
+ ['asdf', ''],
+ ]
+ const args = ['foo', 'bar', 'bar=baz', 'asdf']
+
+ npm.config.set = (key, val, where) => {
+ const [expectKey, expectVal] = expect.shift()
+ t.equal(key, expectKey, 'should set expected key to user config')
+ t.equal(val, expectVal, 'should set expected value to user config')
+ t.equal(where, 'user', 'should set key/val in user config by default')
+ }
+
+ npm.config.save = where => {
+ t.equal(where, 'user', 'should save user config')
+ }
+
+ config(['set', ...args], (err) => {
+ t.ifError(err, 'npm config set key')
+ })
+
+ t.teardown(() => {
+ delete npm.config.set
+ delete npm.config.save
+ })
+})
+
t.test('config set key to empty value', t => {
t.plan(5)
npm.config.set = (key, val, where) => {
t.equal(key, 'foo', 'should set expected key to user config')
- t.equal(val, '', 'should set empty value to user config')
+ t.equal(val, '', 'should set "" to user config')
t.equal(where, 'user', 'should set key/val in user config by default')
}
@@ -403,6 +461,36 @@ t.test('config get key', t => {
})
})
+t.test('config get multiple keys', t => {
+ t.plan(4)
+
+ const expect = [
+ 'foo',
+ 'bar',
+ ]
+
+ const npmConfigGet = npm.config.get
+ npm.config.get = (key) => {
+ t.equal(key, expect.shift(), 'should use expected key')
+ return 'asdf'
+ }
+
+ npm.config.save = where => {
+ throw new Error('should not save')
+ }
+
+ config(['get', 'foo', 'bar'], (err) => {
+ t.ifError(err, 'npm config get multiple keys')
+ t.equal(result, 'foo=asdf\nbar=asdf')
+ })
+
+ t.teardown(() => {
+ result = ''
+ npm.config.get = npmConfigGet
+ delete npm.config.save
+ })
+})
+
t.test('config get private key', t => {
config(['get', '//private-reg.npmjs.org/:_authThoken'], (err) => {
t.match(
diff --git a/deps/npm/test/lib/deprecate.js b/deps/npm/test/lib/deprecate.js
index 3908254ed0..229cb9137a 100644
--- a/deps/npm/test/lib/deprecate.js
+++ b/deps/npm/test/lib/deprecate.js
@@ -13,6 +13,7 @@ npmFetch.json = async (uri, opts) => {
versions: {
'1.0.0': {},
'1.0.1': {},
+ '1.0.1-pre': {},
},
}
}
@@ -126,6 +127,9 @@ test('deprecates all versions when no range is specified', t => {
'1.0.1': {
deprecated: 'this version is deprecated',
},
+ '1.0.1-pre': {
+ deprecated: 'this version is deprecated',
+ },
},
})
diff --git a/deps/npm/test/lib/dist-tag.js b/deps/npm/test/lib/dist-tag.js
index e9dde48062..8b1106fa39 100644
--- a/deps/npm/test/lib/dist-tag.js
+++ b/deps/npm/test/lib/dist-tag.js
@@ -323,6 +323,6 @@ test('completion', t => {
},
},
}, (err) => {
- t.notOk(err, 'should ignore any unkown name')
+ t.notOk(err, 'should ignore any unknown name')
})
})
diff --git a/deps/npm/test/lib/help-search.js b/deps/npm/test/lib/help-search.js
index 5ecf5db061..f74e2f1efe 100644
--- a/deps/npm/test/lib/help-search.js
+++ b/deps/npm/test/lib/help-search.js
@@ -40,7 +40,8 @@ const globDir = {
'npm-more-useless.md': 'exec exec',
'npm-extra-useless.md': 'exec\nexec\nexec',
}
-const glob = (p, cb) => cb(null, Object.keys(globDir).map((file) => join(globRoot, file)))
+const glob = (p, cb) =>
+ cb(null, Object.keys(globDir).map((file) => join(globRoot, file)))
const helpSearch = requireInject('../../lib/help-search.js', {
'../../lib/npm.js': npm,
diff --git a/deps/npm/test/lib/ls.js b/deps/npm/test/lib/ls.js
index 256ebf3534..7bbfc5f772 100644
--- a/deps/npm/test/lib/ls.js
+++ b/deps/npm/test/lib/ls.js
@@ -209,7 +209,7 @@ t.test('ls', (t) => {
})
ls(['lorem'], (err) => {
t.ifError(err, 'npm ls')
- t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurences of filtered by package and coloured output')
+ t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of filtered by package and colored output')
_flatOptions.color = false
t.end()
})
@@ -231,7 +231,7 @@ t.test('ls', (t) => {
})
ls(['.'], (err) => {
t.ifError(err, 'should not throw on missing dep above current level')
- t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurences of filtered by package and coloured output')
+ t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of filtered by package and colored output')
_flatOptions.all = true
_flatOptions.depth = Infinity
t.end()
@@ -252,7 +252,7 @@ t.test('ls', (t) => {
})
ls(['bar'], (err) => {
t.ifError(err, 'npm ls')
- t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurences of filtered package and its ancestors')
+ t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of filtered package and its ancestors')
t.end()
})
})
@@ -280,7 +280,7 @@ t.test('ls', (t) => {
})
ls(['bar@*', 'lorem@1.0.0'], (err) => {
t.ifError(err, 'npm ls')
- t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurences of multiple filtered packages and their ancestors')
+ t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of multiple filtered packages and their ancestors')
t.end()
})
})
@@ -443,7 +443,7 @@ t.test('ls', (t) => {
})
})
- t.test('coloured output', (t) => {
+ t.test('colored output', (t) => {
_flatOptions.color = true
prefix = t.testdir({
'package.json': JSON.stringify({
@@ -1588,7 +1588,7 @@ t.test('ls --parseable', (t) => {
})
ls(['lorem'], (err) => {
t.ifError(err, 'npm ls')
- t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurences of filtered by package')
+ t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurrences of filtered by package')
t.end()
})
})
@@ -1607,7 +1607,7 @@ t.test('ls --parseable', (t) => {
})
ls(['bar'], (err) => {
t.ifError(err, 'npm ls')
- t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurences of filtered package')
+ t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurrences of filtered package')
t.end()
})
})
@@ -1635,7 +1635,7 @@ t.test('ls --parseable', (t) => {
})
ls(['bar@*', 'lorem@1.0.0'], (err) => {
t.ifError(err, 'npm ls')
- t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurences of multiple filtered packages and their ancestors')
+ t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurrences of multiple filtered packages and their ancestors')
t.end()
})
})
@@ -2158,7 +2158,7 @@ t.test('ls --parseable', (t) => {
},
})
ls([], () => {
- t.matchSnapshot(redactCwd(result), 'should print tree output ommiting deduped ref')
+ t.matchSnapshot(redactCwd(result), 'should print tree output omitting deduped ref')
t.end()
})
})
@@ -2482,7 +2482,7 @@ t.test('ls --json', (t) => {
},
},
},
- 'should output json contaning only occurences of filtered by package'
+ 'should output json contaning only occurrences of filtered by package'
)
t.equal(
process.exitCode,
@@ -2523,7 +2523,7 @@ t.test('ls --json', (t) => {
},
},
},
- 'should output json contaning only occurences of filtered by package'
+ 'should output json contaning only occurrences of filtered by package'
)
t.end()
})
@@ -2571,7 +2571,7 @@ t.test('ls --json', (t) => {
},
},
},
- 'should output json contaning only occurences of multiple filtered packages and their ancestors'
+ 'should output json contaning only occurrences of multiple filtered packages and their ancestors'
)
t.end()
})
diff --git a/deps/npm/test/lib/npm.js b/deps/npm/test/lib/npm.js
index 2c71d229a7..8494af6bb8 100644
--- a/deps/npm/test/lib/npm.js
+++ b/deps/npm/test/lib/npm.js
@@ -202,8 +202,6 @@ t.test('npm.load', t => {
t.equal(npm.bin, npm.globalBin, 'bin is global bin after prefix setter')
t.notEqual(npm.bin, npm.localBin, 'bin is not local bin after prefix setter')
- t.equal(npm.config.get('metrics-registry'), npm.config.get('registry'))
-
beWindows()
t.equal(npm.bin, npm.globalBin, 'bin is global bin in windows mode')
t.equal(npm.dir, npm.globalDir, 'dir is global dir in windows mode')
@@ -261,7 +259,6 @@ t.test('npm.load', t => {
process.argv = [
node,
process.argv[1],
- '--metrics-registry', 'http://example.com',
'--prefix', dir,
'--userconfig', `${dir}/.npmrc`,
'--usage',
@@ -292,7 +289,6 @@ t.test('npm.load', t => {
throw er
t.equal(npm.config.get('scope'), '@foo', 'added the @ sign to scope')
- t.equal(npm.config.get('metrics-registry'), 'http://example.com')
t.match(logs.filter(l => l[0] !== 'timing' || !/^config:/.test(l[1])), [
[
'verbose',
@@ -342,7 +338,7 @@ t.test('npm.load', t => {
/Completed in [0-9]+ms/,
],
])
- t.same(consoleLogs, [['@foo']])
+ t.same(consoleLogs, [['scope=@foo\n\u2010not-a-dash=undefined']])
})
// need this here or node 10 will improperly end the promise ahead of time
@@ -396,7 +392,6 @@ t.test('set process.title', t => {
argv: [
process.execPath,
process.argv[1],
- '--metrics-registry', 'http://example.com',
'--usage',
'--scope=foo',
'ls',
@@ -415,7 +410,6 @@ t.test('set process.title', t => {
argv: [
process.execPath,
process.argv[1],
- '--metrics-registry', 'http://example.com',
'--usage',
'--scope=foo',
'token',
@@ -436,7 +430,6 @@ t.test('set process.title', t => {
argv: [
process.execPath,
process.argv[1],
- '--metrics-registry', 'http://example.com',
'--usage',
'--scope=foo',
'token',
diff --git a/deps/npm/test/lib/owner.js b/deps/npm/test/lib/owner.js
index e217533f0d..c5f9d646c2 100644
--- a/deps/npm/test/lib/owner.js
+++ b/deps/npm/test/lib/owner.js
@@ -119,7 +119,7 @@ t.test('owner ls fails to retrieve packument', t => {
t.match(
err,
/ERR/,
- 'should throw unkown error'
+ 'should throw unknown error'
)
})
})
diff --git a/deps/npm/test/lib/profile.js b/deps/npm/test/lib/profile.js
new file mode 100644
index 0000000000..48a558cace
--- /dev/null
+++ b/deps/npm/test/lib/profile.js
@@ -0,0 +1,1465 @@
+const t = require('tap')
+const requireInject = require('require-inject')
+
+let result = ''
+const flatOptions = {
+ otp: '',
+ json: false,
+ parseable: false,
+ registry: 'https://registry.npmjs.org/',
+}
+const npm = { config: {}, flatOptions: { ...flatOptions }}
+const mocks = {
+ ansistyles: { bright: a => a },
+ npmlog: {
+ gauge: { show () {} },
+ info () {},
+ notice () {},
+ warn () {},
+ },
+ 'npm-profile': {
+ async get () {},
+ async set () {},
+ async createToken () {},
+ },
+ 'qrcode-terminal': { generate: (url, cb) => cb() },
+ 'cli-table3': class extends Array {
+ toString () {
+ return this
+ .filter(Boolean)
+ .map(i => [...Object.entries(i)]
+ .map(i => i.join(': ')))
+ .join('\n')
+ }
+ },
+ '../../lib/npm.js': npm,
+ '../../lib/utils/output.js': (...msg) => {
+ result += msg.join('\n')
+ },
+ '../../lib/utils/pulse-till-done.js': {
+ withPromise: async a => a,
+ },
+ '../../lib/utils/otplease.js': async (opts, fn) => fn(opts),
+ '../../lib/utils/usage.js': () => 'usage instructions',
+ '../../lib/utils/read-user-info.js': {
+ async password () {},
+ async otp () {},
+ },
+}
+const userProfile = {
+ tfa: { pending: false, mode: 'auth-and-writes' },
+ name: 'foo',
+ email: 'foo@github.com',
+ email_verified: true,
+ created: '2015-02-26T01:26:37.384Z',
+ updated: '2020-08-12T16:19:35.326Z',
+ cidr_whitelist: null,
+ fullname: 'Foo Bar',
+ homepage: 'https://github.com',
+ freenode: 'foobar',
+ twitter: 'https://twitter.com/npmjs',
+ github: 'https://github.com/npm',
+}
+
+t.afterEach(cb => {
+ result = ''
+ npm.config = {}
+ npm.flatOptions = { ...flatOptions }
+ cb()
+})
+
+const profile = requireInject('../../lib/profile.js', mocks)
+
+t.test('no args', t => {
+ profile([], err => {
+ t.match(
+ err,
+ /usage instructions/,
+ 'should throw usage instructions'
+ )
+ t.end()
+ })
+})
+
+t.test('profile get no args', t => {
+ const npmProfile = {
+ async get () {
+ return userProfile
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ })
+
+ t.test('default output', t => {
+ profile(['get'], err => {
+ if (err)
+ throw err
+
+ t.matchSnapshot(
+ result,
+ 'should output table with contents'
+ )
+ t.end()
+ })
+ })
+
+ t.test('--json', t => {
+ npm.flatOptions.json = true
+
+ profile(['get'], err => {
+ if (err)
+ throw err
+
+ t.deepEqual(
+ JSON.parse(result),
+ userProfile,
+ 'should output json profile result'
+ )
+ t.end()
+ })
+ })
+
+ t.test('--parseable', t => {
+ npm.flatOptions.parseable = true
+
+ profile(['get'], err => {
+ if (err)
+ throw err
+
+ t.matchSnapshot(
+ result,
+ 'should output all profile info as parseable result'
+ )
+ t.end()
+ })
+ })
+
+ t.test('no tfa enabled', t => {
+ const npmProfile = {
+ async get () {
+ return {
+ ...userProfile,
+ tfa: null,
+ }
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ })
+
+ profile(['get'], err => {
+ if (err)
+ throw err
+
+ t.matchSnapshot(
+ result,
+ 'should output expected profile values'
+ )
+ t.end()
+ })
+ })
+
+ t.test('unverified email', t => {
+ const npmProfile = {
+ async get () {
+ return {
+ ...userProfile,
+ email_verified: false,
+ }
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ })
+
+ profile(['get'], err => {
+ if (err)
+ throw err
+
+ t.matchSnapshot(
+ result,
+ 'should output table with contents'
+ )
+ t.end()
+ })
+ })
+
+ t.test('profile has cidr_whitelist item', t => {
+ const npmProfile = {
+ async get () {
+ return {
+ ...userProfile,
+ cidr_whitelist: ['192.168.1.1'],
+ }
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ })
+
+ profile(['get'], err => {
+ if (err)
+ throw err
+
+ t.matchSnapshot(
+ result,
+ 'should output table with contents'
+ )
+ t.end()
+ })
+ })
+
+ t.end()
+})
+
+t.test('profile get <key>', t => {
+ const npmProfile = {
+ async get () {
+ return userProfile
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ })
+
+ t.test('default output', t => {
+ profile(['get', 'name'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'foo',
+ 'should output value result'
+ )
+ t.end()
+ })
+ })
+
+ t.test('--json', t => {
+ npm.flatOptions.json = true
+
+ profile(['get', 'name'], err => {
+ if (err)
+ throw err
+
+ t.deepEqual(
+ JSON.parse(result),
+ userProfile,
+ 'should output json profile result ignoring args filter'
+ )
+ t.end()
+ })
+ })
+
+ t.test('--parseable', t => {
+ npm.flatOptions.parseable = true
+
+ profile(['get', 'name'], err => {
+ if (err)
+ throw err
+
+ t.matchSnapshot(
+ result,
+ 'should output parseable result value'
+ )
+ t.end()
+ })
+ })
+
+ t.end()
+})
+
+t.test('profile get multiple args', t => {
+ const npmProfile = {
+ async get () {
+ return userProfile
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ })
+
+ t.test('default output', t => {
+ profile(['get', 'name', 'email', 'github'], err => {
+ if (err)
+ throw err
+
+ t.matchSnapshot(
+ result,
+ 'should output all keys'
+ )
+ t.end()
+ })
+ })
+
+ t.test('--json', t => {
+ npm.flatOptions.json = true
+
+ profile(['get', 'name', 'email', 'github'], err => {
+ if (err)
+ throw err
+
+ t.deepEqual(
+ JSON.parse(result),
+ userProfile,
+ 'should output json profile result and ignore args'
+ )
+ t.end()
+ })
+ })
+
+ t.test('--parseable', t => {
+ npm.flatOptions.parseable = true
+
+ profile(['get', 'name', 'email', 'github'], err => {
+ if (err)
+ throw err
+
+ t.matchSnapshot(
+ result,
+ 'should output parseable profile value results'
+ )
+ t.end()
+ })
+ })
+
+ t.test('comma separated', t => {
+ profile(['get', 'name,email,github'], err => {
+ if (err)
+ throw err
+
+ t.matchSnapshot(
+ result,
+ 'should output all keys'
+ )
+ t.end()
+ })
+ })
+
+ t.end()
+})
+
+t.test('profile set <key> <value>', t => {
+ const npmProfile = t => ({
+ async get () {
+ return userProfile
+ },
+ async set (newUser, conf) {
+ t.match(
+ newUser,
+ {
+ fullname: 'Lorem Ipsum',
+ },
+ 'should set new value to key'
+ )
+ return {
+ ...userProfile,
+ ...newUser,
+ }
+ },
+ })
+
+ t.test('no key', t => {
+ profile(['set'], err => {
+ t.match(
+ err,
+ /npm profile set <prop> <value>/,
+ 'should throw proper usage message'
+ )
+ t.end()
+ })
+ })
+
+ t.test('no value', t => {
+ profile(['set', 'email'], err => {
+ t.match(
+ err,
+ /npm profile set <prop> <value>/,
+ 'should throw proper usage message'
+ )
+ t.end()
+ })
+ })
+
+ t.test('set password', t => {
+ profile(['set', 'password', '1234'], err => {
+ t.match(
+ err,
+ /Do not include your current or new passwords on the command line./,
+ 'should throw an error refusing to set password from args'
+ )
+ t.end()
+ })
+ })
+
+ t.test('unwritable key', t => {
+ profile(['set', 'name', 'foo'], err => {
+ t.match(
+ err,
+ /"name" is not a property we can set./,
+ 'should throw the unwritable key error'
+ )
+ t.end()
+ })
+ })
+
+ t.test('writable key', t => {
+ t.test('default output', t => {
+ t.plan(2)
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile(t),
+ })
+
+ profile(['set', 'fullname', 'Lorem Ipsum'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'Set\nfullname\nto\nLorem Ipsum',
+ 'should output set key success msg'
+ )
+ })
+ })
+
+ t.test('--json', t => {
+ t.plan(2)
+
+ npm.flatOptions.json = true
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile(t),
+ })
+
+ profile(['set', 'fullname', 'Lorem Ipsum'], err => {
+ if (err)
+ throw err
+
+ t.deepEqual(
+ JSON.parse(result),
+ {
+ fullname: 'Lorem Ipsum',
+ },
+ 'should output json set key success msg'
+ )
+ })
+ })
+
+ t.test('--parseable', t => {
+ t.plan(2)
+
+ npm.flatOptions.parseable = true
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile(t),
+ })
+
+ profile(['set', 'fullname', 'Lorem Ipsum'], err => {
+ if (err)
+ throw err
+
+ t.matchSnapshot(
+ result,
+ 'should output parseable set key success msg'
+ )
+ })
+ })
+
+ t.end()
+ })
+
+ t.test('write new email', t => {
+ t.plan(3)
+
+ const npmProfile = {
+ async get () {
+ return userProfile
+ },
+ async set (newUser, conf) {
+ t.match(
+ newUser,
+ {
+ email: 'foo@npmjs.com',
+ },
+ 'should set new value to email'
+ )
+ t.match(
+ conf,
+ npm.flatOptions,
+ 'should forward flatOptions config'
+ )
+ return {
+ ...userProfile,
+ ...newUser,
+ }
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ })
+
+ profile(['set', 'email', 'foo@npmjs.com'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'Set\nemail\nto\nfoo@npmjs.com',
+ 'should output set key success msg'
+ )
+ })
+ })
+
+ t.test('change password', t => {
+ t.plan(6)
+
+ const npmProfile = {
+ async get () {
+ return userProfile
+ },
+ async set (newUser, conf) {
+ t.match(
+ newUser,
+ {
+ password: {
+ old: 'currentpassword1234',
+ new: 'newpassword1234',
+ },
+ },
+ 'should set new password'
+ )
+ t.match(
+ conf,
+ npm.flatOptions,
+ 'should forward flatOptions config'
+ )
+ return {
+ ...userProfile,
+ }
+ },
+ }
+
+ const readUserInfo = {
+ async password (label) {
+ if (label === 'Current password: ')
+ t.ok('should interactively ask for password confirmation')
+ else if (label === 'New password: ')
+ t.ok('should interactively ask for new password')
+ else if (label === ' Again: ')
+ t.ok('should interactively ask for new password confirmation')
+ else
+ throw new Error('Unexpected label: ' + label)
+
+ return label === 'Current password: '
+ ? 'currentpassword1234'
+ : 'newpassword1234'
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ '../../lib/utils/read-user-info.js': readUserInfo,
+ })
+
+ profile(['set', 'password'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'Set\npassword',
+ 'should output set password success msg'
+ )
+ t.end()
+ })
+ })
+
+ t.test('password confirmation mismatch', t => {
+ t.plan(3)
+ let passwordPromptCount = 0
+
+ const npmProfile = {
+ async get () {
+ return userProfile
+ },
+ async set (newUser, conf) {
+ return {
+ ...userProfile,
+ }
+ },
+ }
+
+ const readUserInfo = {
+ async password (label) {
+ passwordPromptCount++
+
+ switch (label) {
+ case 'Current password: ':
+ return 'currentpassword1234'
+ case 'New password: ':
+ return passwordPromptCount < 3
+ ? 'password-that-will-not-be-confirmed'
+ : 'newpassword'
+ case ' Again: ':
+ return 'newpassword'
+ default:
+ return 'password1234'
+ }
+ },
+ }
+
+ const npmlog = {
+ gauge: {
+ show () {},
+ },
+ warn (title, msg) {
+ t.equal(title, 'profile', 'should use expected profile')
+ t.equal(
+ msg,
+ 'Passwords do not match, please try again.',
+ 'should log password mismatch message'
+ )
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ npmlog,
+ 'npm-profile': npmProfile,
+ '../../lib/utils/read-user-info.js': readUserInfo,
+ })
+
+ profile(['set', 'password'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'Set\npassword',
+ 'should output set password success msg'
+ )
+ t.end()
+ })
+ })
+
+ t.end()
+})
+
+t.test('enable-2fa', t => {
+ t.test('invalid args', t => {
+ profile(['enable-2fa', 'foo', 'bar'], err => {
+ t.match(
+ err,
+ /npm profile enable-2fa \[auth-and-writes|auth-only\]/,
+ 'should throw usage error'
+ )
+ t.end()
+ })
+ })
+
+ t.test('invalid two factor auth mode', t => {
+ profile(['enable-2fa', 'foo'], err => {
+ t.match(
+ err,
+ /Invalid two-factor authentication mode "foo"/,
+ 'should throw invalid auth mode error'
+ )
+ t.end()
+ })
+ })
+
+ t.test('no support for --json output', t => {
+ npm.flatOptions.json = true
+
+ profile(['enable-2fa', 'auth-only'], err => {
+ t.match(
+ err.message,
+ 'Enabling two-factor authentication is an interactive ' +
+ 'operation and JSON output mode is not available',
+ 'should throw no support msg'
+ )
+ t.end()
+ })
+ })
+
+ t.test('no support for --parseable output', t => {
+ npm.flatOptions.parseable = true
+
+ profile(['enable-2fa', 'auth-only'], err => {
+ t.match(
+ err.message,
+ 'Enabling two-factor authentication is an interactive ' +
+ 'operation and parseable output mode is not available',
+ 'should throw no support msg'
+ )
+ t.end()
+ })
+ })
+
+ t.test('no bearer tokens returned by registry', t => {
+ t.plan(3)
+
+ // mock legacy basic auth style
+ npm.config.getCredentialsByURI = reg => {
+ t.equal(reg, flatOptions.registry, 'should use expected registry')
+ return { auth: Buffer.from('foo:bar').toString('base64') }
+ }
+
+ const npmProfile = {
+ async createToken (pass) {
+ t.match(pass, 'bar', 'should use password for basic auth')
+ return {}
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ })
+
+ profile(['enable-2fa', 'auth-only'], err => {
+ t.match(
+ err.message,
+ 'Your registry https://registry.npmjs.org/ does ' +
+ 'not seem to support bearer tokens. Bearer tokens ' +
+ 'are required for two-factor authentication',
+ 'should throw no support msg'
+ )
+ })
+ })
+
+ t.test('from basic username/password auth', t => {
+ // mock legacy basic auth style with user/pass
+ npm.config.getCredentialsByURI = () => {
+ return { username: 'foo', password: 'bar' }
+ }
+
+ const npmProfile = {
+ async createToken (pass) {
+ return {}
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ })
+
+ profile(['enable-2fa', 'auth-only'], err => {
+ t.match(
+ err.message,
+ 'Your registry https://registry.npmjs.org/ does ' +
+ 'not seem to support bearer tokens. Bearer tokens ' +
+ 'are required for two-factor authentication',
+ 'should throw no support msg'
+ )
+ t.end()
+ })
+ })
+
+ t.test('no auth found', t => {
+ npm.config.getCredentialsByURI = () => ({})
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ })
+
+ profile(['enable-2fa', 'auth-only'], err => {
+ t.match(
+ err.message,
+ 'You need to be logged in to registry ' +
+ 'https://registry.npmjs.org/ in order to enable 2fa'
+ )
+ t.end()
+ })
+ })
+
+ t.test('from basic auth, asks for otp', t => {
+ t.plan(10)
+
+ // mock legacy basic auth style
+ npm.config = {
+ getCredentialsByURI (reg) {
+ t.equal(reg, flatOptions.registry, 'should use expected registry')
+ return { auth: Buffer.from('foo:bar').toString('base64') }
+ },
+ setCredentialsByURI (registry, { token }) {
+ t.equal(registry, flatOptions.registry, 'should set expected registry')
+ t.equal(token, 'token', 'should set expected token')
+ },
+ save (type) {
+ t.equal(type, 'user', 'should save to user config')
+ },
+ }
+
+ const npmProfile = {
+ async createToken (pass) {
+ t.match(pass, 'bar', 'should use password for basic auth')
+ return { token: 'token' }
+ },
+ async get () {
+ return userProfile
+ },
+ async set (newProfile, conf) {
+ t.match(
+ newProfile,
+ {
+ tfa: {
+ mode: 'auth-only',
+ },
+ },
+ 'should set tfa mode'
+ )
+ t.match(
+ conf,
+ {
+ ...npm.flatOptions,
+ otp: '123456',
+ },
+ 'should forward flatOptions config'
+ )
+ return {
+ ...userProfile,
+ tfa: null,
+ }
+ },
+ }
+
+ const readUserInfo = {
+ async password () {
+ t.ok('should interactively ask for password confirmation')
+ return 'password1234'
+ },
+ async otp (label) {
+ t.equal(
+ label,
+ 'Enter one-time password from your authenticator app: ',
+ 'should ask for otp confirmation'
+ )
+ return '123456'
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ '../../lib/utils/read-user-info.js': readUserInfo,
+ })
+
+ profile(['enable-2fa', 'auth-only'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'Two factor authentication mode changed to: auth-only',
+ 'should output success msg'
+ )
+ })
+ })
+
+ t.test('from token and set otp, retries on pending and verifies with qrcode', t => {
+ t.plan(4)
+
+ npm.flatOptions.otp = '1234'
+
+ npm.config = {
+ getCredentialsByURI () {
+ return { token: 'token' }
+ },
+ }
+
+ let setCount = 0
+ const npmProfile = {
+ async get () {
+ return {
+ ...userProfile,
+ tfa: {
+ pending: true,
+ },
+ }
+ },
+ async set (newProfile, conf) {
+ setCount++
+
+ // when profile response shows that 2fa is pending the
+ // first time calling npm-profile.set should reset 2fa
+ if (setCount === 1) {
+ t.match(
+ newProfile,
+ {
+ tfa: {
+ password: 'password1234',
+ mode: 'disable',
+ },
+ },
+ 'should reset 2fa'
+ )
+ } else if (setCount === 2) {
+ t.match(
+ newProfile,
+ {
+ tfa: {
+ mode: 'auth-only',
+ },
+ },
+ 'should set tfa mode approprietly in follow-up call'
+ )
+ } else if (setCount === 3) {
+ t.match(
+ newProfile,
+ {
+ tfa: ['123456'],
+ },
+ 'should set tfa as otp code?'
+ )
+ return {
+ ...userProfile,
+ tfa: [
+ '123456',
+ '789101',
+ ],
+ }
+ }
+
+ return {
+ ...userProfile,
+ tfa: 'otpauth://foo?secret=1234',
+ }
+ },
+ }
+
+ const readUserInfo = {
+ async password () {
+ return 'password1234'
+ },
+ async otp (label) {
+ return '123456'
+ },
+ }
+
+ const qrcode = {
+ // eslint-disable-next-line standard/no-callback-literal
+ generate: (url, cb) => cb('qrcode'),
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ 'qrcode-terminal': qrcode,
+ '../../lib/utils/read-user-info.js': readUserInfo,
+ })
+
+ profile(['enable-2fa', 'auth-only'], err => {
+ if (err)
+ throw err
+
+ t.matchSnapshot(
+ result,
+ 'should output 2fa enablement success msgs'
+ )
+ })
+ })
+
+ t.test('from token and set otp, retrieves invalid otp', t => {
+ npm.flatOptions.otp = '1234'
+
+ npm.config = {
+ getCredentialsByURI () {
+ return { token: 'token' }
+ },
+ }
+
+ const npmProfile = {
+ async get () {
+ return {
+ ...userProfile,
+ tfa: {
+ pending: true,
+ },
+ }
+ },
+ async set (newProfile, conf) {
+ return {
+ ...userProfile,
+ tfa: 'http://foo?secret=1234',
+ }
+ },
+ }
+
+ const readUserInfo = {
+ async password () {
+ return 'password1234'
+ },
+ async otp (label) {
+ return '123456'
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ '../../lib/utils/read-user-info.js': readUserInfo,
+ })
+
+ profile(['enable-2fa', 'auth-only'], err => {
+ t.match(
+ err,
+ /Unknown error enabling two-factor authentication./,
+ 'should throw invalid 2fa auth url error'
+ )
+ t.end()
+ })
+ })
+
+ t.test('from token auth provides --otp config arg', t => {
+ npm.flatOptions.otp = '123456'
+
+ npm.config = {
+ getCredentialsByURI (reg) {
+ return { token: 'token' }
+ },
+ }
+
+ const npmProfile = {
+ async get () {
+ return userProfile
+ },
+ async set (newProfile, conf) {
+ return {
+ ...userProfile,
+ tfa: null,
+ }
+ },
+ }
+
+ const readUserInfo = {
+ async password () {
+ return 'password1234'
+ },
+ async otp () {
+ throw new Error('should not ask for otp')
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ '../../lib/utils/read-user-info.js': readUserInfo,
+ })
+
+ profile(['enable-2fa', 'auth-and-writes'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'Two factor authentication mode changed to: auth-and-writes',
+ 'should output success msg'
+ )
+ t.end()
+ })
+ })
+
+ t.test('missing tfa from user profile', t => {
+ npm.config = {
+ getCredentialsByURI (reg) {
+ return { token: 'token' }
+ },
+ }
+
+ const npmProfile = {
+ async get () {
+ return {
+ ...userProfile,
+ tfa: undefined,
+ }
+ },
+ async set (newProfile, conf) {
+ return {
+ ...userProfile,
+ tfa: null,
+ }
+ },
+ }
+
+ const readUserInfo = {
+ async password () {
+ return 'password1234'
+ },
+ async otp () {
+ return '123456'
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ '../../lib/utils/read-user-info.js': readUserInfo,
+ })
+
+ profile(['enable-2fa', 'auth-only'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'Two factor authentication mode changed to: auth-only',
+ 'should output success msg'
+ )
+ t.end()
+ })
+ })
+
+ t.test('defaults to auth-and-writes permission if no mode specified', t => {
+ npm.config = {
+ getCredentialsByURI (reg) {
+ return { token: 'token' }
+ },
+ }
+
+ const npmProfile = {
+ async get () {
+ return {
+ ...userProfile,
+ tfa: undefined,
+ }
+ },
+ async set (newProfile, conf) {
+ return {
+ ...userProfile,
+ tfa: null,
+ }
+ },
+ }
+
+ const readUserInfo = {
+ async password () {
+ return 'password1234'
+ },
+ async otp () {
+ return '123456'
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ '../../lib/utils/read-user-info.js': readUserInfo,
+ })
+
+ profile(['enable-2fa'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'Two factor authentication mode changed to: auth-and-writes',
+ 'should enable 2fa with auth-and-writes permission'
+ )
+ t.end()
+ })
+ })
+
+ t.end()
+})
+
+t.test('disable-2fa', t => {
+ t.test('no tfa enabled', t => {
+ const npmProfile = {
+ async get () {
+ return {
+ ...userProfile,
+ tfa: null,
+ }
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ })
+
+ profile(['disable-2fa'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'Two factor authentication not enabled.',
+ 'should output already disalbed msg'
+ )
+ t.end()
+ })
+ })
+
+ t.test('requests otp', t => {
+ const npmProfile = t => ({
+ async get () {
+ return userProfile
+ },
+ async set (newProfile, conf) {
+ t.deepEqual(
+ newProfile,
+ {
+ tfa: {
+ password: 'password1234',
+ mode: 'disable',
+ },
+ },
+ 'should send the new info for setting in profile'
+ )
+ t.match(
+ conf,
+ {
+ ...npm.flatOptions,
+ otp: '1234',
+ },
+ 'should forward flatOptions config'
+ )
+ },
+ })
+
+ const readUserInfo = t => ({
+ async password () {
+ t.ok('should interactively ask for password confirmation')
+ return 'password1234'
+ },
+ async otp (label) {
+ t.equal(
+ label,
+ 'Enter one-time password from your authenticator app: ',
+ 'should ask for otp confirmation'
+ )
+ return '1234'
+ },
+ })
+
+ t.test('default output', t => {
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile(t),
+ '../../lib/utils/read-user-info.js': readUserInfo(t),
+ })
+
+ profile(['disable-2fa'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'Two factor authentication disabled.',
+ 'should output already disabled msg'
+ )
+ t.end()
+ })
+ })
+
+ t.test('--json', t => {
+ npm.flatOptions.json = true
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile(t),
+ '../../lib/utils/read-user-info.js': readUserInfo(t),
+ })
+
+ profile(['disable-2fa'], err => {
+ if (err)
+ throw err
+
+ t.deepEqual(
+ JSON.parse(result),
+ { tfa: false },
+ 'should output json already disabled msg'
+ )
+ t.end()
+ })
+ })
+
+ t.test('--parseable', t => {
+ npm.flatOptions.parseable = true
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile(t),
+ '../../lib/utils/read-user-info.js': readUserInfo(t),
+ })
+
+ profile(['disable-2fa'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'tfa\tfalse',
+ 'should output parseable already disabled msg'
+ )
+ t.end()
+ })
+ })
+
+ t.end()
+ })
+
+ t.test('--otp config already set', t => {
+ t.plan(3)
+
+ npm.flatOptions.otp = '123456'
+
+ const npmProfile = {
+ async get () {
+ return userProfile
+ },
+ async set (newProfile, conf) {
+ t.deepEqual(
+ newProfile,
+ {
+ tfa: {
+ password: 'password1234',
+ mode: 'disable',
+ },
+ },
+ 'should send the new info for setting in profile'
+ )
+ t.match(
+ conf,
+ {
+ ...npm.flatOptions,
+ otp: '123456',
+ },
+ 'should forward flatOptions config'
+ )
+ },
+ }
+
+ const readUserInfo = {
+ async password () {
+ return 'password1234'
+ },
+ async otp (label) {
+ throw new Error('should not ask for otp')
+ },
+ }
+
+ const profile = requireInject('../../lib/profile.js', {
+ ...mocks,
+ 'npm-profile': npmProfile,
+ '../../lib/utils/read-user-info.js': readUserInfo,
+ })
+
+ profile(['disable-2fa'], err => {
+ if (err)
+ throw err
+
+ t.equal(
+ result,
+ 'Two factor authentication disabled.',
+ 'should output already disalbed msg'
+ )
+ })
+ })
+
+ t.end()
+})
+
+t.test('unknown subcommand', t => {
+ profile(['asfd'], err => {
+ t.match(
+ err,
+ /Unknown profile command: asfd/,
+ 'should throw unknown cmd error'
+ )
+ t.end()
+ })
+})
+
+t.test('completion', t => {
+ const { completion } = profile
+
+ const testComp = ({ t, argv, expect, title }) => {
+ completion({ conf: { argv: { remain: argv } } }, (err, res) => {
+ if (err)
+ throw err
+
+ t.strictSame(res, expect, title)
+ })
+ }
+
+ t.test('npm profile autocomplete', t => {
+ testComp({
+ t,
+ argv: ['npm', 'profile'],
+ expect: ['enable-2fa', 'disable-2fa', 'get', 'set'],
+ title: 'should auto complete with subcommands',
+ })
+
+ t.end()
+ })
+
+ t.test('npm profile enable autocomplete', t => {
+ testComp({
+ t,
+ argv: ['npm', 'profile', 'enable-2fa'],
+ expect: ['auth-and-writes', 'auth-only'],
+ title: 'should auto complete with auth types',
+ })
+
+ t.end()
+ })
+
+ t.test('npm profile <subcmd> no autocomplete', t => {
+ const noAutocompleteCmds = ['disable-2fa', 'disable-tfa', 'get', 'set']
+ for (const subcmd of noAutocompleteCmds) {
+ testComp({
+ t,
+ argv: ['npm', 'profile', subcmd],
+ expect: [],
+ title: `${subcmd} should have no autocomplete`,
+ })
+ }
+
+ t.end()
+ })
+
+ t.test('npm profile unknown subcommand autocomplete', t => {
+ completion({
+ conf: {
+ argv: {
+ remain: ['npm', 'profile', 'asdf'],
+ },
+ },
+ }, (err, res) => {
+ t.match(
+ err,
+ /asdf not recognized/,
+ 'should throw unknown cmd error'
+ )
+
+ t.end()
+ })
+ })
+
+ t.end()
+})
diff --git a/deps/npm/test/lib/publish.js b/deps/npm/test/lib/publish.js
index 14e2179816..c1f353f6fd 100644
--- a/deps/npm/test/lib/publish.js
+++ b/deps/npm/test/lib/publish.js
@@ -3,7 +3,14 @@ const requireInject = require('require-inject')
// mock config
const {defaults} = require('../../lib/utils/config.js')
-const config = { list: [defaults] }
+const credentials = {
+ token: 'asdfasdf',
+ alwaysAuth: false,
+}
+const config = {
+ list: [defaults],
+ getCredentialsByURI: () => credentials,
+}
const fs = require('fs')
t.test('should publish with libnpmpublish, respecting publishConfig', (t) => {
@@ -23,6 +30,7 @@ t.test('should publish with libnpmpublish, respecting publishConfig', (t) => {
flatOptions: {
json: true,
defaultTag: 'latest',
+ registry: 'https://registry.npmjs.org',
},
config,
},
@@ -55,7 +63,7 @@ t.test('should publish with libnpmpublish, respecting publishConfig', (t) => {
},
})
- publish([testDir], (er) => {
+ return publish([testDir], (er) => {
if (er)
throw er
t.pass('got to callback')
@@ -77,6 +85,7 @@ t.test('re-loads publishConfig if added during script process', (t) => {
flatOptions: {
json: true,
defaultTag: 'latest',
+ registry: 'https://registry.npmjs.org/',
},
config,
},
@@ -108,7 +117,7 @@ t.test('re-loads publishConfig if added during script process', (t) => {
},
})
- publish([testDir], (er) => {
+ return publish([testDir], (er) => {
if (er)
throw er
t.pass('got to callback')
@@ -131,6 +140,7 @@ t.test('should not log if silent', (t) => {
json: false,
defaultTag: 'latest',
dryRun: true,
+ registry: 'https://registry.npmjs.org/',
},
config,
},
@@ -159,7 +169,7 @@ t.test('should not log if silent', (t) => {
},
})
- publish([testDir], (er) => {
+ return publish([testDir], (er) => {
if (er)
throw er
t.pass('got to callback')
@@ -181,6 +191,7 @@ t.test('should log tarball contents', (t) => {
json: false,
defaultTag: 'latest',
dryRun: true,
+ registry: 'https://registry.npmjs.org/',
},
config,
},
@@ -206,7 +217,7 @@ t.test('should log tarball contents', (t) => {
},
})
- publish([testDir], (er) => {
+ return publish([testDir], (er) => {
if (er)
throw er
t.pass('got to callback')
@@ -220,12 +231,13 @@ t.test('shows usage with wrong set of arguments', (t) => {
flatOptions: {
json: false,
defaultTag: '0.0.13',
+ registry: 'https://registry.npmjs.org/',
},
config,
},
})
- publish(['a', 'b', 'c'], (er) => t.matchSnapshot(er, 'should print usage'))
+ return publish(['a', 'b', 'c'], (er) => t.matchSnapshot(er, 'should print usage'))
})
t.test('throws when invalid tag', (t) => {
@@ -235,12 +247,13 @@ t.test('throws when invalid tag', (t) => {
flatOptions: {
json: false,
defaultTag: '0.0.13',
+ registry: 'https://registry.npmjs.org/',
},
config,
},
})
- publish([], (err) => {
+ return publish([], (err) => {
t.match(err, {
message: /Tag name must not be a valid SemVer range: /,
}, 'throws when tag name is a valid SemVer range')
@@ -274,6 +287,7 @@ t.test('can publish a tarball', t => {
flatOptions: {
json: true,
defaultTag: 'latest',
+ registry: 'https://registry.npmjs.org/',
},
config,
},
@@ -298,9 +312,56 @@ t.test('can publish a tarball', t => {
},
})
- publish([`${testDir}/package.tgz`], (er) => {
+ return publish([`${testDir}/package.tgz`], (er) => {
if (er)
throw er
t.pass('got to callback')
})
})
+
+t.test('throw if no registry', async t => {
+ t.plan(1)
+ const publish = requireInject('../../lib/publish.js', {
+ '../../lib/npm.js': {
+ flatOptions: {
+ json: false,
+ defaultTag: '0.0.13',
+ registry: null,
+ },
+ config,
+ },
+ })
+
+ return publish([], (err) => {
+ t.match(err, {
+ message: 'No registry specified.',
+ code: 'ENOREGISTRY',
+ }, 'throws when registry unset')
+ })
+})
+
+t.test('throw if not logged in', async t => {
+ t.plan(1)
+ const publish = requireInject('../../lib/publish.js', {
+ '../../lib/npm.js': {
+ flatOptions: {
+ json: false,
+ defaultTag: '0.0.13',
+ registry: 'https://registry.npmjs.org/',
+ },
+ config: {
+ ...config,
+ getCredentialsByURI: () => ({
+ email: 'me@example.com',
+ }),
+ },
+ },
+ })
+
+ return publish([], (err) => {
+ t.match(err, {
+ message: 'This command requires you to be logged in.',
+ code: 'ENEEDAUTH',
+ }, 'throws when not logged in')
+ })
+})
diff --git a/deps/npm/test/lib/utils/error-handler.js b/deps/npm/test/lib/utils/error-handler.js
index 2dc116a4d3..0b896fee4f 100644
--- a/deps/npm/test/lib/utils/error-handler.js
+++ b/deps/npm/test/lib/utils/error-handler.js
@@ -78,10 +78,6 @@ const npmlog = {
},
}
-const metrics = {
- stop: () => null,
-}
-
// overrides OS type/release for cross platform snapshots
const os = require('os')
os.type = () => 'Foo'
@@ -124,7 +120,6 @@ const mocks = {
summary: [['ERR', err.message]],
detail: [['ERR', err.message]],
}),
- '../../../lib/utils/metrics.js': metrics,
'../../../lib/utils/cache-file.js': cacheFile,
}
diff --git a/deps/npm/test/lib/utils/flat-options.js b/deps/npm/test/lib/utils/flat-options.js
index ee7620fa78..6f580fabc4 100644
--- a/deps/npm/test/lib/utils/flat-options.js
+++ b/deps/npm/test/lib/utils/flat-options.js
@@ -34,8 +34,6 @@ class MockConfig {
cache: 'cache',
'node-version': '1.2.3',
global: 'global',
- 'metrics-registry': 'metrics-registry',
- 'send-metrics': 'send-metrics',
registry: 'registry',
access: 'access',
'always-auth': 'always-auth',
@@ -299,15 +297,12 @@ t.test('various default values and falsey fallbacks', t => {
const npm = new Mocknpm({
'script-shell': false,
registry: 'http://example.com',
- 'metrics-registry': null,
searchlimit: 0,
'save-exact': false,
'save-prefix': '>=',
})
const opts = flatOptions(npm)
t.equal(opts.scriptShell, undefined, 'scriptShell is undefined if falsey')
- t.equal(opts.metricsRegistry, 'http://example.com',
- 'metricsRegistry defaults to registry')
t.equal(opts.search.limit, 20, 'searchLimit defaults to 20')
t.equal(opts.savePrefix, '>=', 'save-prefix respected if no save-exact')
t.equal(opts.scope, '', 'scope defaults to empty string')
diff --git a/deps/npm/test/lib/utils/reify-output.js b/deps/npm/test/lib/utils/reify-output.js
index f7fd96ee87..f88f072e1e 100644
--- a/deps/npm/test/lib/utils/reify-output.js
+++ b/deps/npm/test/lib/utils/reify-output.js
@@ -245,7 +245,10 @@ t.test('packages changed message', t => {
settings.json = json
npmock.command = command
const mock = {
- actualTree: { inventory: { size: audited, has: () => true }, children: [] },
+ actualTree: {
+ inventory: { size: audited, has: () => true },
+ children: [],
+ },
auditReport: audited ? {
toJSON: () => mock.auditReport,
vulnerabilities: {},
diff --git a/deps/npm/test/lib/utils/replace-info.js b/deps/npm/test/lib/utils/replace-info.js
index f5e1246f1c..ea9f06520d 100644
--- a/deps/npm/test/lib/utils/replace-info.js
+++ b/deps/npm/test/lib/utils/replace-info.js
@@ -46,7 +46,7 @@ t.equal(
t.equal(
replaceInfo('Something https://user:pass@registry.npmjs.org/ foo bar'),
'Something https://user:***@registry.npmjs.org/ foo bar',
- 'should replace single item withing a phrase'
+ 'should replace single item within a phrase'
)
t.deepEqual(