From 433ffca9d9689986ea22e99fac07385cfc8f262c Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Tue, 20 Oct 2020 14:12:57 -0400 Subject: [PATCH 1/2] test: add lib/config.js tests --- tap-snapshots/test-lib-config.js-TAP.test.js | 150 +++++ test/lib/config.js | 578 +++++++++++++++++++ 2 files changed, 728 insertions(+) create mode 100644 tap-snapshots/test-lib-config.js-TAP.test.js create mode 100644 test/lib/config.js diff --git a/tap-snapshots/test-lib-config.js-TAP.test.js b/tap-snapshots/test-lib-config.js-TAP.test.js new file mode 100644 index 0000000000000..1794dc4fadfb8 --- /dev/null +++ b/tap-snapshots/test-lib-config.js-TAP.test.js @@ -0,0 +1,150 @@ +/* IMPORTANT + * This snapshot file is auto-generated, but designed for humans. + * It should be checked into source control and tracked carefully. + * Re-generate by setting TAP_SNAPSHOT=1 and running tests. + * Make sure to inspect the output below. Do not ignore changes! + */ +'use strict' +exports[`test/lib/config.js TAP config edit --global > should write global config file 1`] = ` +;;;; +; npm globalconfig file: /etc/npmrc +; this is a simple ini-formatted file +; lines that start with semi-colons are comments +; run \`npm help 7 config\` for documentation of the various options +; +; Configs like \`@scope:registry\` map a scope to a given registry url. +; +; Configs like \`///:_authToken\` are auth that is restricted +; to the registry host specified. + +init.author.name=Foo + +;;;; +; all available options shown below with default values +;;;; + + +; init-author-name= +; init-version=1.0.0 +; init.author.name= +; init.version=1.0.0 + +` + +exports[`test/lib/config.js TAP config edit > should write config file 1`] = ` +;;;; +; npm userconfig file: ~/.npmrc +; this is a simple ini-formatted file +; lines that start with semi-colons are comments +; run \`npm help 7 config\` for documentation of the various options +; +; Configs like \`@scope:registry\` map a scope to a given registry url. +; +; Configs like \`///:_authToken\` are auth that is restricted +; to the registry host specified. + +//registry.npmjs.org/:_authToken=0000000 +init.author.name=Foo +sign-git-commit=true + +;;;; +; all available options shown below with default values +;;;; + + +; init-author-name= +; init-version=1.0.0 +; init.author.name= +; init.version=1.0.0 + +` + +exports[`test/lib/config.js TAP config edit > should write config file 2`] = ` +;;;; +; npm userconfig file: ~/.npmrc +; this is a simple ini-formatted file +; lines that start with semi-colons are comments +; run \`npm help 7 config\` for documentation of the various options +; +; Configs like \`@scope:registry\` map a scope to a given registry url. +; +; Configs like \`///:_authToken\` are auth that is restricted +; to the registry host specified. + + + +;;;; +; all available options shown below with default values +;;;; + + +; init-author-name= +; init-version=1.0.0 +; init.author.name= +; init.version=1.0.0 + +` + +exports[`test/lib/config.js TAP config get no args > should list configs on config get no args 1`] = ` +; "cli" config from command line options + +editor = "vi" +global = false +json = false +long = false + +; node bin location = /path/to/node +; cwd = {CWD} +; HOME = ~/ +; Run \`npm config ls -l\` to show all defaults. +` + +exports[`test/lib/config.js TAP config list --long > should list all configs 1`] = ` +; "default" config from default values + +init-author-name = "" +init-version = "1.0.0" +init.author.name = "" +init.version = "1.0.0" + +; "cli" config from command line options + +editor = "vi" +global = false +json = false +long = true +` + +exports[`test/lib/config.js TAP config list > should list configs 1`] = ` +; "cli" config from command line options + +editor = "vi" +global = false +json = false +long = false + +; node bin location = /path/to/node +; cwd = {CWD} +; HOME = ~/ +; Run \`npm config ls -l\` to show all defaults. +` + +exports[`test/lib/config.js TAP config list overrides > should list overriden configs 1`] = ` +; "cli" config from command line options + +editor = "vi" +global = false +init.author.name = "Bar" +json = false +long = false + +; "user" config from ~/.npmrc + +; //private-reg.npmjs.org/:_authThoken = (protected) ; overridden by cli +; init.author.name = "Foo" ; overridden by cli + +; node bin location = /path/to/node +; cwd = {CWD} +; HOME = ~/ +; Run \`npm config ls -l\` to show all defaults. +` diff --git a/test/lib/config.js b/test/lib/config.js new file mode 100644 index 0000000000000..d94af00cb1a00 --- /dev/null +++ b/test/lib/config.js @@ -0,0 +1,578 @@ +const t = require('tap') +const requireInject = require('require-inject') + +const redactCwd = (path) => { + const normalizePath = p => p + .replace(/\\+/g, '/') + .replace(/\r\n/g, '\n') + return normalizePath(path) + .replace(new RegExp(normalizePath(process.cwd()), 'g'), '{CWD}') + .replace(process.execPath, '/path/to/node') + .replace(process.env.HOME, '~/') +} + +t.cleanSnapshot = (str) => redactCwd(str) + +let result = '' +const types = { + 'init-author-name': String, + 'init-version': String, + 'init.author.name': String, + 'init.version': String +} +const defaults = { + 'init-author-name': '', + 'init-version': '1.0.0', + 'init.author.name': '', + 'init.version': '1.0.0' +} + +const flatOptions = { + editor: 'vi', + json: false, + long: false, + global: false +} + +const npm = { + flatOptions, + log: { + info: () => null, + enableProgress: () => null, + disableProgress: () => null + }, + config: { + data: new Map(Object.entries({ + default: { data: defaults, source: 'default values' }, + global: { data: {}, source: '/etc/npmrc' }, + cli: { data: flatOptions, source: 'command line options' } + })), + get (key) { return flatOptions[key] }, + validate () { return true } + } +} + +const usageUtil = () => 'usage instructions' + +const mocks = { + '../../lib/utils/config.js': { defaults, types }, + '../../lib/npm.js': npm, + '../../lib/utils/output.js': msg => { result = msg }, + '../../lib/utils/usage.js': usageUtil +} + +const config = requireInject('../../lib/config.js', mocks) + +t.test('config no args', t => { + config([], (err) => { + t.match(err, /usage instructions/, 'should not error out on empty locations') + t.end() + }) +}) + +t.test('config list', t => { + t.plan(2) + + npm.config.find = () => 'cli' + result = '' + t.teardown(() => { + result = '' + delete npm.config.find + }) + + config(['list'], (err) => { + t.ifError(err, 'npm config list') + t.matchSnapshot(result, 'should list configs') + }) +}) + +t.test('config list overrides', t => { + t.plan(2) + + npm.config.data.set('user', { + data: { + 'init.author.name': 'Foo', + '//private-reg.npmjs.org/:_authThoken': 'f00ba1' + }, + source: '~/.npmrc' + }) + flatOptions['init.author.name'] = 'Bar' + npm.config.find = () => 'cli' + result = '' + t.teardown(() => { + result = '' + npm.config.data.delete('user') + delete flatOptions['init.author.name'] + delete npm.config.find + }) + + config(['list'], (err) => { + t.ifError(err, 'npm config list') + t.matchSnapshot(result, 'should list overriden configs') + }) +}) + +t.test('config list --long', t => { + t.plan(2) + + npm.config.find = key => key in flatOptions ? 'cli' : 'default' + flatOptions.long = true + result = '' + t.teardown(() => { + delete npm.config.find + flatOptions.long = false + result = '' + }) + + config(['list'], (err) => { + t.ifError(err, 'npm config list --long') + t.matchSnapshot(result, 'should list all configs') + }) +}) + +t.test('config list --json', t => { + t.plan(2) + + flatOptions.json = true + result = '' + npm.config.list = [{ + '//private-reg.npmjs.org/:_authThoken': 'f00ba1', + ...npm.config.data.get('cli').data + }] + const npmConfigGet = npm.config.get + npm.config.get = key => npm.config.list[0][key] + + t.teardown(() => { + delete npm.config.list + flatOptions.json = false + npm.config.get = npmConfigGet + result = '' + }) + + config(['list'], (err) => { + t.ifError(err, 'npm config list --json') + t.deepEqual( + JSON.parse(result), + { + editor: 'vi', + json: true, + long: false, + global: false + }, + 'should list configs usin json' + ) + }) +}) + +t.test('config delete no args', t => { + config(['delete'], (err) => { + t.equal( + err, + 'usage instructions', + 'should throw usage error' + ) + t.end() + }) +}) + +t.test('config delete key', t => { + t.plan(4) + + npm.config.delete = (key, where) => { + t.equal(key, 'foo', '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'], (err) => { + t.ifError(err, 'npm config delete key') + }) + + t.teardown(() => { + delete npm.config.delete + delete npm.config.save + }) +}) + +t.test('config delete key --global', t => { + t.plan(4) + + npm.config.delete = (key, where) => { + t.equal(key, 'foo', 'should delete expected keyword from global configs') + t.equal(where, 'global', 'should delete key from global config by default') + } + + npm.config.save = where => { + t.equal(where, 'global', 'should save global config post-delete') + } + + flatOptions.global = true + config(['delete', 'foo'], (err) => { + t.ifError(err, 'npm config delete key --global') + }) + + t.teardown(() => { + flatOptions.global = false + delete npm.config.delete + delete npm.config.save + }) +}) + +t.test('config set no args', t => { + config(['set'], (err) => { + t.equal( + err, + 'usage instructions', + 'should throw usage error' + ) + t.end() + }) +}) + +t.test('config set key', t => { + t.plan(5) + + npm.config.set = (key, val, where) => { + t.equal(key, 'foo', 'should set expected key to user config') + t.equal(val, 'bar', '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', 'foo', 'bar'], (err) => { + t.ifError(err, 'npm config set key') + }) + + t.teardown(() => { + delete npm.config.set + delete npm.config.save + }) +}) + +t.test('config set key=val', t => { + t.plan(5) + + npm.config.set = (key, val, where) => { + t.equal(key, 'foo', 'should set expected key to user config') + t.equal(val, 'bar', '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', 'foo=bar'], (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(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', 'foo'], (err) => { + t.ifError(err, 'npm config set key to empty value') + }) + + t.teardown(() => { + delete npm.config.set + delete npm.config.save + }) +}) + +t.test('config set invalid key', t => { + t.plan(3) + + const npmConfigValidate = npm.config.validate + npm.config.save = () => null + npm.config.set = () => null + npm.config.validate = () => false + npm.log.warn = (title, msg) => { + t.equal(title, 'config', 'should warn with expected title') + t.equal(msg, 'omitting invalid config values', 'should use expected msg') + } + t.teardown(() => { + npm.config.validate = npmConfigValidate + delete npm.config.save + delete npm.config.set + delete npm.log.warn + }) + + config(['set', 'foo', 'bar'], (err) => { + t.ifError(err, 'npm config set invalid key') + }) +}) + +t.test('config set key --global', t => { + t.plan(5) + + npm.config.set = (key, val, where) => { + t.equal(key, 'foo', 'should set expected key to global config') + t.equal(val, 'bar', 'should set expected value to global config') + t.equal(where, 'global', 'should set key/val in global config') + } + + npm.config.save = where => { + t.equal(where, 'global', 'should save global config') + } + + flatOptions.global = true + config(['set', 'foo', 'bar'], (err) => { + t.ifError(err, 'npm config set key --global') + }) + + t.teardown(() => { + flatOptions.global = false + delete npm.config.set + delete npm.config.save + }) +}) + +t.test('config get no args', t => { + t.plan(2) + + npm.config.find = () => 'cli' + result = '' + t.teardown(() => { + result = '' + delete npm.config.find + }) + + config(['get'], (err) => { + t.ifError(err, 'npm config get no args') + t.matchSnapshot(result, 'should list configs on config get no args') + }) +}) + +t.test('config get key', t => { + t.plan(3) + + const npmConfigGet = npm.config.get + npm.config.get = (key, where) => { + t.equal(key, 'foo', 'should use expected key') + t.equal(where, 'user', 'should retrieve key from user config by default') + return 'bar' + } + + npm.config.save = where => { + throw new Error('should not save') + } + + config(['get', 'foo'], (err) => { + t.ifError(err, 'npm config get key') + }) + + t.teardown(() => { + npm.config.get = npmConfigGet + delete npm.config.save + }) +}) + +t.test('config get key --global', t => { + t.plan(3) + + flatOptions.global = true + const npmConfigGet = npm.config.get + npm.config.get = (key, where) => { + t.equal(key, 'foo', 'should use expected global key') + t.equal(where, 'global', 'should retrieve key from global config') + return 'bar' + } + + npm.config.save = where => { + throw new Error('should not save') + } + + config(['get', 'foo'], (err) => { + t.ifError(err, 'npm config get key --global') + }) + + t.teardown(() => { + flatOptions.global = false + 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( + err, + /The \/\/private-reg.npmjs.org\/:_authThoken option is protected, and cannot be retrieved in this way/, + 'should throw unable to retrieve error' + ) + t.end() + }) +}) + +t.test('config edit', t => { + t.plan(12) + const npmrc = `//registry.npmjs.org/:_authToken=0000000 +init.author.name=Foo +sign-git-commit=true` + npm.config.data.set('user', { + source: '~/.npmrc' + }) + npm.config.save = async where => { + t.equal(where, 'user', 'should save to user config by default') + } + const editMocks = { + ...mocks, + 'mkdirp-infer-owner': async () => null, + fs: { + readFile (path, encoding, cb) { cb(null, npmrc) }, + writeFile (file, data, encoding, cb) { + t.equal(file, '~/.npmrc', 'should save to expected file location') + t.matchSnapshot(data, 'should write config file') + cb() + } + }, + editor: (file, { editor }, cb) => { + t.equal(file, '~/.npmrc', 'should match user source data') + t.equal(editor, 'vi', 'should use default editor') + cb() + } + } + const config = requireInject('../../lib/config.js', editMocks) + config(['edit'], (err) => { + t.ifError(err, 'npm config edit') + + // test no config file result + editMocks.fs.readFile = (p, e, cb) => { cb(new Error('ERR')) } + const config = requireInject('../../lib/config.js', editMocks) + config(['edit'], (err) => { + t.ifError(err, 'npm config edit') + }) + }) + + t.teardown(() => { + npm.config.data.delete('user') + delete npm.config.save + }) +}) + +t.test('config edit --global', t => { + t.plan(6) + + flatOptions.global = true + const npmrc = 'init.author.name=Foo' + npm.config.data.set('global', { + source: '/etc/npmrc' + }) + npm.config.save = async where => { + t.equal(where, 'global', 'should save to global config') + } + const editMocks = { + ...mocks, + 'mkdirp-infer-owner': async () => null, + fs: { + readFile (path, encoding, cb) { cb(null, npmrc) }, + writeFile (file, data, encoding, cb) { + t.equal(file, '/etc/npmrc', 'should save to global file location') + t.matchSnapshot(data, 'should write global config file') + cb() + } + }, + editor: (file, { editor }, cb) => { + t.equal(file, '/etc/npmrc', 'should match global source data') + t.equal(editor, 'vi', 'should use default editor') + cb() + } + } + const config = requireInject('../../lib/config.js', editMocks) + config(['edit'], (err) => { + t.ifError(err, 'npm config edit --global') + }) + + t.teardown(() => { + flatOptions.global = false + npm.config.data.delete('user') + delete npm.config.save + }) +}) + +t.test('config edit no editor set', t => { + flatOptions.editor = undefined + config(['edit'], (err) => { + t.match( + err, + /No `editor` config or EDITOR environment variable set/, + 'should throw no available editor error' + ) + flatOptions.editor = 'vi' + t.end() + }) +}) + +t.test('completion', t => { + const { completion } = config + + const testComp = (argv, expect) => { + completion({ conf: { argv: { remain: argv } } }, (er, res) => { + t.ifError(er) + t.strictSame(res, expect, argv.join(' ')) + }) + } + + testComp(['npm', 'foo'], []) + testComp(['npm', 'config'], [ + 'get', + 'set', + 'delete', + 'ls', + 'rm', + 'edit', + 'list' + ]) + testComp(['npm', 'config', 'set', 'foo'], []) + const possibleConfigKeys = [...Object.keys(types)] + testComp(['npm', 'config', 'get'], possibleConfigKeys) + testComp(['npm', 'config', 'set'], possibleConfigKeys) + testComp(['npm', 'config', 'delete'], possibleConfigKeys) + testComp(['npm', 'config', 'rm'], possibleConfigKeys) + testComp(['npm', 'config', 'edit'], []) + testComp(['npm', 'config', 'list'], []) + testComp(['npm', 'config', 'ls'], []) + + completion({ + conf: { + argv: { + remain: ['npm', 'config'] + } + }, + partialWord: 'l' + }, (er, res) => { + t.ifError(er) + t.strictSame(res, [ + 'get', + 'set', + 'delete', + 'ls', + 'rm', + 'edit' + ], 'npm config') + }) + + t.end() +}) From b4972a7738c65d1c884fa10a77b128235a52ec86 Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Wed, 21 Oct 2020 00:24:43 -0400 Subject: [PATCH 2/2] fix: npm config - Small refactors such as line breaks and favor usage of flatOptions - Removes validBefore? console.error msg - Fix typos --- lib/config.js | 45 +++++++++++++++++++++++++----------------- test/lib/config.js | 49 ++++++++++++++-------------------------------- 2 files changed, 42 insertions(+), 52 deletions(-) diff --git a/lib/config.js b/lib/config.js index fd59152aad9e8..21f3ab693c42d 100644 --- a/lib/config.js +++ b/lib/config.js @@ -3,13 +3,13 @@ const { defaults, types } = require('./utils/config.js') const usageUtil = require('./utils/usage.js') const output = require('./utils/output.js') -const editor = require('editor') const mkdirp = require('mkdirp-infer-owner') const { dirname } = require('path') const { promisify } = require('util') const fs = require('fs') const readFile = promisify(fs.readFile) const writeFile = promisify(fs.writeFile) +const editor = promisify(require('editor')) const { EOL } = require('os') const ini = require('ini') @@ -28,10 +28,15 @@ const cmd = (args, cb) => config(args).then(() => cb()).catch(cb) const completion = (opts, cb) => { const argv = opts.conf.argv.remain - if (argv[1] !== 'config') argv.unshift('config') + if (argv[1] !== 'config') { + argv.unshift('config') + } + if (argv.length === 2) { const cmds = ['get', 'set', 'delete', 'ls', 'rm', 'edit'] - if (opts.partialWord !== 'l') cmds.push('list') + if (opts.partialWord !== 'l') { + cmds.push('list') + } return cb(null, cmds) } @@ -39,7 +44,9 @@ const completion = (opts, cb) => { switch (action) { case 'set': // todo: complete with valid values, if possible. - if (argv.length > 3) return cb(null, []) + if (argv.length > 3) { + return cb(null, []) + } // fallthrough /* eslint no-fallthrough:0 */ case 'get': @@ -49,12 +56,14 @@ const completion = (opts, cb) => { case 'edit': case 'list': case 'ls': - return cb(null, []) default: return cb(null, []) } } +const UsageError = () => + Object.assign(new Error(usage), { code: 'EUSAGE' }) + const config = async ([action, key, val]) => { npm.log.disableProgress() try { @@ -72,13 +81,13 @@ const config = async ([action, key, val]) => { break case 'list': case 'ls': - await (npm.config.get('json') ? listJson() : list()) + await (npm.flatOptions.json ? listJson() : list()) break case 'edit': await edit() break default: - throw usage + throw UsageError() } } finally { npm.log.enableProgress() @@ -87,7 +96,7 @@ const config = async ([action, key, val]) => { const set = async (key, val) => { if (key === undefined) { - throw usage + throw UsageError() } if (val === undefined) { @@ -103,9 +112,7 @@ const set = async (key, val) => { key = key.trim() val = val.trim() npm.log.info('config', 'set %j %j', key, val) - const where = npm.config.get('global') ? 'global' : 'user' - const validBefore = npm.config.data.get(where).valid - console.error('validBefore?', validBefore) + const where = npm.flatOptions.global ? 'global' : 'user' npm.config.set(key, val, where) if (!npm.config.validate(where)) { npm.log.warn('config', 'omitting invalid config values') @@ -127,10 +134,10 @@ const get = async key => { const del = async key => { if (!key) { - throw usage + throw UsageError() } - const where = npm.config.get('global') ? 'global' : 'user' + const where = npm.flatOptions.global ? 'global' : 'user' npm.config.delete(key, where) await npm.config.save(where) } @@ -138,7 +145,7 @@ const del = async key => { const edit = async () => { const { editor: e, global } = npm.flatOptions if (!e) { - throw new Error('No `editor` config or EDITOR envionment variable set') + throw new Error('No `editor` config or EDITOR environment variable set') } const where = global ? 'global' : 'user' @@ -147,10 +154,14 @@ const edit = async () => { // save first, just to make sure it's synced up // this also removes all the comments from the last time we edited it. await npm.config.save(where) - const data = (await readFile(file, 'utf8').catch(() => '')).replace(/\r\n/g, '\n') + + const data = ( + await readFile(file, 'utf8').catch(() => '') + ).replace(/\r\n/g, '\n') const defData = Object.entries(defaults).reduce((str, [key, val]) => { const obj = { [key]: val } const i = ini.stringify(obj) + .replace(/\r\n/g, '\n') // normalizes output from ini.stringify .replace(/\n$/m, '') .replace(/^/g, '; ') .replace(/\n/g, '\n; ') @@ -179,9 +190,7 @@ ${defData} `.split('\n').join(EOL) await mkdirp(dirname(file)) await writeFile(file, tmpData, 'utf8') - await new Promise((res, rej) => { - editor(file, { editor: e }, (er) => er ? rej(er) : res()) - }) + await editor(file, { editor: e }) } const publicVar = k => !/^(\/\/[^:]+:)?_/.test(k) diff --git a/test/lib/config.js b/test/lib/config.js index d94af00cb1a00..890d65731a88c 100644 --- a/test/lib/config.js +++ b/test/lib/config.js @@ -5,10 +5,17 @@ const redactCwd = (path) => { const normalizePath = p => p .replace(/\\+/g, '/') .replace(/\r\n/g, '\n') - return normalizePath(path) + const replaceCwd = p => p .replace(new RegExp(normalizePath(process.cwd()), 'g'), '{CWD}') - .replace(process.execPath, '/path/to/node') - .replace(process.env.HOME, '~/') + const cleanupWinPaths = p => p + .replace(normalizePath(process.execPath), '/path/to/node') + .replace(normalizePath(process.env.HOME), '~/') + + return cleanupWinPaths( + replaceCwd( + normalizePath(path) + ) + ) } t.cleanSnapshot = (str) => redactCwd(str) @@ -167,10 +174,11 @@ t.test('config list --json', t => { t.test('config delete no args', t => { config(['delete'], (err) => { t.equal( - err, + err.message, 'usage instructions', 'should throw usage error' ) + t.equal(err.code, 'EUSAGE', 'should throw expected error code') t.end() }) }) @@ -224,7 +232,7 @@ t.test('config delete key --global', t => { t.test('config set no args', t => { config(['set'], (err) => { t.equal( - err, + err.message, 'usage instructions', 'should throw usage error' ) @@ -366,12 +374,11 @@ t.test('config get no args', t => { }) t.test('config get key', t => { - t.plan(3) + t.plan(2) const npmConfigGet = npm.config.get - npm.config.get = (key, where) => { + npm.config.get = (key) => { t.equal(key, 'foo', 'should use expected key') - t.equal(where, 'user', 'should retrieve key from user config by default') return 'bar' } @@ -389,32 +396,6 @@ t.test('config get key', t => { }) }) -t.test('config get key --global', t => { - t.plan(3) - - flatOptions.global = true - const npmConfigGet = npm.config.get - npm.config.get = (key, where) => { - t.equal(key, 'foo', 'should use expected global key') - t.equal(where, 'global', 'should retrieve key from global config') - return 'bar' - } - - npm.config.save = where => { - throw new Error('should not save') - } - - config(['get', 'foo'], (err) => { - t.ifError(err, 'npm config get key --global') - }) - - t.teardown(() => { - flatOptions.global = false - 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(