From ce1c2bf4bade53df66efff03415d29a828a3d47a Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 21 Feb 2022 21:58:12 -0700 Subject: [PATCH] chore(cli): remove log option from being passed anywhere --- lib/commands/access.js | 2 - lib/commands/adduser.js | 1 - lib/commands/ci.js | 3 +- lib/commands/dedupe.js | 2 - lib/commands/deprecate.js | 3 - lib/commands/diff.js | 2 - lib/commands/dist-tag.js | 1 - lib/commands/doctor.js | 3 +- lib/commands/exec.js | 2 - lib/commands/fund.js | 2 - lib/commands/hook.js | 10 ++-- lib/commands/init.js | 1 - lib/commands/install.js | 3 +- lib/commands/link.js | 6 -- lib/commands/logout.js | 1 - lib/commands/org.js | 8 +-- lib/commands/owner.js | 2 - lib/commands/ping.js | 2 +- lib/commands/profile.js | 8 +-- lib/commands/prune.js | 2 - lib/commands/publish.js | 6 +- lib/commands/run-script.js | 6 +- lib/commands/star.js | 4 +- lib/commands/team.js | 15 +++-- lib/commands/token.js | 2 +- lib/commands/uninstall.js | 2 - lib/commands/unpublish.js | 7 +-- lib/commands/update.js | 1 - lib/commands/whoami.js | 3 +- lib/npm.js | 6 +- lib/utils/config/definitions.js | 3 + lib/utils/display.js | 4 +- lib/utils/exit-handler.js | 6 +- lib/utils/reify-output.js | 6 +- lib/utils/update-notifier.js | 3 +- .../test/lib/utils/exit-handler.js.test.cjs | 8 +-- test/fixtures/mock-npm.js | 53 ++++++++++------ test/fixtures/sandbox.js | 45 +++++--------- test/lib/commands/access.js | 5 +- test/lib/commands/adduser.js | 7 --- test/lib/commands/deprecate.js | 7 --- test/lib/commands/diff.js | 3 +- test/lib/commands/dist-tag.js | 10 ---- test/lib/commands/doctor.js | 12 ++-- test/lib/commands/hook.js | 47 +++++---------- test/lib/commands/logout.js | 9 +-- test/lib/commands/org.js | 41 ++++--------- test/lib/commands/owner.js | 26 ++------ test/lib/commands/ping.js | 9 +-- test/lib/commands/publish.js | 60 ++++++------------- test/lib/commands/run-script.js | 28 ++++----- test/lib/commands/star.js | 6 +- test/lib/commands/team.js | 21 ++++--- test/lib/commands/unpublish.js | 7 +-- test/lib/commands/update.js | 10 +--- test/lib/utils/config/definitions.js | 9 +++ test/lib/utils/exit-handler.js | 6 +- test/lib/utils/reify-output.js | 11 ++-- test/lib/utils/update-notifier.js | 3 +- 59 files changed, 223 insertions(+), 358 deletions(-) diff --git a/lib/commands/access.js b/lib/commands/access.js index 7d3930dacbce9..206d6de9c22c4 100644 --- a/lib/commands/access.js +++ b/lib/commands/access.js @@ -3,7 +3,6 @@ const path = require('path') const libaccess = require('libnpmaccess') const readPackageJson = require('read-package-json-fast') -const log = require('../utils/log-shim.js') const otplease = require('../utils/otplease.js') const getIdentity = require('../utils/get-identity.js') const BaseCommand = require('../base-command.js') @@ -79,7 +78,6 @@ class Access extends BaseCommand { return this[cmd](args, { ...this.npm.flatOptions, - log, }) } diff --git a/lib/commands/adduser.js b/lib/commands/adduser.js index 1cf70fffbf541..cbeaaaf0f28be 100644 --- a/lib/commands/adduser.js +++ b/lib/commands/adduser.js @@ -31,7 +31,6 @@ class AddUser extends BaseCommand { creds, registry, scope, - log, }) await this.updateConfig({ diff --git a/lib/commands/ci.js b/lib/commands/ci.js index 5e862a473a70f..e054bee51679c 100644 --- a/lib/commands/ci.js +++ b/lib/commands/ci.js @@ -40,7 +40,6 @@ class CI extends ArboristWorkspaceCmd { ...this.npm.flatOptions, packageLock: true, // npm ci should never skip lock files path: where, - log, save: false, // npm ci should never modify the lockfile or package.json workspaces: this.workspaceNames, } @@ -101,7 +100,7 @@ class CI extends ArboristWorkspaceCmd { scriptShell, stdio: 'inherit', stdioString: true, - banner: log.level !== 'silent', + banner: !this.npm.silent, event, }) } diff --git a/lib/commands/dedupe.js b/lib/commands/dedupe.js index 1c270249adb3f..4662ce3241b24 100644 --- a/lib/commands/dedupe.js +++ b/lib/commands/dedupe.js @@ -1,7 +1,6 @@ // dedupe duplicated packages, or find them in the tree const Arborist = require('@npmcli/arborist') const reifyFinish = require('../utils/reify-finish.js') -const log = require('../utils/log-shim.js') const ArboristWorkspaceCmd = require('../arborist-cmd.js') @@ -40,7 +39,6 @@ class Dedupe extends ArboristWorkspaceCmd { const where = this.npm.prefix const opts = { ...this.npm.flatOptions, - log, path: where, dryRun, save, diff --git a/lib/commands/deprecate.js b/lib/commands/deprecate.js index 5505b9bf77cf7..839e974caf09b 100644 --- a/lib/commands/deprecate.js +++ b/lib/commands/deprecate.js @@ -1,5 +1,4 @@ const fetch = require('npm-registry-fetch') -const log = require('../utils/log-shim.js') const otplease = require('../utils/otplease.js') const npa = require('npm-package-arg') const semver = require('semver') @@ -51,7 +50,6 @@ class Deprecate extends BaseCommand { ...this.npm.flatOptions, spec: p, query: { write: true }, - log, }) Object.keys(packument.versions) @@ -66,7 +64,6 @@ class Deprecate extends BaseCommand { method: 'PUT', body: packument, ignoreBody: true, - log, })) } } diff --git a/lib/commands/diff.js b/lib/commands/diff.js index b3855aa08f3f1..d737a58dc43d8 100644 --- a/lib/commands/diff.js +++ b/lib/commands/diff.js @@ -61,7 +61,6 @@ class Diff extends BaseCommand { ...this.npm.flatOptions, diffFiles: args, where: this.top, - log, }) return this.npm.output(res) } @@ -194,7 +193,6 @@ class Diff extends BaseCommand { const packument = await pacote.packument(spec, { ...this.npm.flatOptions, preferOnline: true, - log, }) bSpec = pickManifest( packument, diff --git a/lib/commands/dist-tag.js b/lib/commands/dist-tag.js index e2b013206d3aa..bb36f3f72bfb2 100644 --- a/lib/commands/dist-tag.js +++ b/lib/commands/dist-tag.js @@ -31,7 +31,6 @@ class DistTag extends BaseCommand { async exec ([cmdName, pkg, tag]) { const opts = { ...this.npm.flatOptions, - log, } if (['add', 'a', 'set', 's'].includes(cmdName)) { diff --git a/lib/commands/doctor.js b/lib/commands/doctor.js index 47a522eb676d0..508faa57aa5e9 100644 --- a/lib/commands/doctor.js +++ b/lib/commands/doctor.js @@ -125,8 +125,7 @@ class Doctor extends BaseCommand { stringLength: s => ansiTrim(s).length, } - const silent = log.levels[log.level] > log.levels.error - if (!silent) { + if (!this.npm.silent) { this.npm.output(table(outTable, tableOpts)) if (!allOk) { console.error('') diff --git a/lib/commands/exec.js b/lib/commands/exec.js index 61a6d965954aa..52fb1f8eb7229 100644 --- a/lib/commands/exec.js +++ b/lib/commands/exec.js @@ -1,7 +1,6 @@ const libexec = require('libnpmexec') const BaseCommand = require('../base-command.js') const getLocationMsg = require('../exec/get-workspace-location-msg.js') -const log = require('../utils/log-shim') // it's like this: // @@ -77,7 +76,6 @@ class Exec extends BaseCommand { call, localBin, locationMsg, - log, globalBin, output, packages, diff --git a/lib/commands/fund.js b/lib/commands/fund.js index 47a51c33a6841..787a5193f0155 100644 --- a/lib/commands/fund.js +++ b/lib/commands/fund.js @@ -5,7 +5,6 @@ const pacote = require('pacote') const semver = require('semver') const npa = require('npm-package-arg') const { depth } = require('treeverse') -const log = require('../utils/log-shim.js') const { readTree: getFundingInfo, normalizeFunding, isValidFunding } = require('libnpmfund') const completion = require('../utils/completion/installed-deep.js') @@ -69,7 +68,6 @@ class Fund extends ArboristWorkspaceCmd { // TODO: add !workspacesEnabled option handling to libnpmfund const fundingInfo = getFundingInfo(tree, { ...this.flatOptions, - log, workspaces: this.workspaceNames, }) diff --git a/lib/commands/hook.js b/lib/commands/hook.js index c99a99585897a..2ff6ac01ce527 100644 --- a/lib/commands/hook.js +++ b/lib/commands/hook.js @@ -2,7 +2,6 @@ const hookApi = require('libnpmhook') const otplease = require('../utils/otplease.js') const relativeDate = require('tiny-relative-date') const Table = require('cli-table3') -const log = require('../utils/log-shim.js') const BaseCommand = require('../base-command.js') class Hook extends BaseCommand { @@ -23,7 +22,6 @@ class Hook extends BaseCommand { async exec (args) { return otplease({ ...this.npm.flatOptions, - log, }, (opts) => { switch (args[0]) { case 'add': @@ -48,7 +46,7 @@ class Hook extends BaseCommand { } else if (opts.parseable) { this.npm.output(Object.keys(hook).join('\t')) this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { this.npm.output(`+ ${this.hookName(hook)} ${ opts.unicode ? ' ➜ ' : ' -> ' } ${hook.endpoint}`) @@ -66,7 +64,7 @@ class Hook extends BaseCommand { }) } else if (!hooks.length) { this.npm.output("You don't have any hooks configured yet.") - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { if (hooks.length === 1) { this.npm.output('You have one hook configured.') } else { @@ -103,7 +101,7 @@ class Hook extends BaseCommand { } else if (opts.parseable) { this.npm.output(Object.keys(hook).join('\t')) this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { this.npm.output(`- ${this.hookName(hook)} ${ opts.unicode ? ' ✘ ' : ' X ' } ${hook.endpoint}`) @@ -117,7 +115,7 @@ class Hook extends BaseCommand { } else if (opts.parseable) { this.npm.output(Object.keys(hook).join('\t')) this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { this.npm.output(`+ ${this.hookName(hook)} ${ opts.unicode ? ' ➜ ' : ' -> ' } ${hook.endpoint}`) diff --git a/lib/commands/init.js b/lib/commands/init.js index 7e8a8f7a5c8ab..367533f8259f5 100644 --- a/lib/commands/init.js +++ b/lib/commands/init.js @@ -114,7 +114,6 @@ class Init extends BaseCommand { color, localBin, locationMsg, - log, globalBin, output, path, diff --git a/lib/commands/install.js b/lib/commands/install.js index a92a5edc5ebb7..61526abb7879b 100644 --- a/lib/commands/install.js +++ b/lib/commands/install.js @@ -147,7 +147,6 @@ class Install extends ArboristWorkspaceCmd { const opts = { ...this.npm.flatOptions, - log, auditLevel: null, path: where, add: args, @@ -173,7 +172,7 @@ class Install extends ArboristWorkspaceCmd { scriptShell, stdio: 'inherit', stdioString: true, - banner: log.level !== 'silent', + banner: !this.npm.silent, event, }) } diff --git a/lib/commands/link.js b/lib/commands/link.js index e8e2c6b349aa9..d656791469a64 100644 --- a/lib/commands/link.js +++ b/lib/commands/link.js @@ -7,7 +7,6 @@ const Arborist = require('@npmcli/arborist') const npa = require('npm-package-arg') const rpj = require('read-package-json-fast') const semver = require('semver') -const log = require('../utils/log-shim.js') const reifyFinish = require('../utils/reify-finish.js') @@ -69,7 +68,6 @@ class Link extends ArboristWorkspaceCmd { const globalOpts = { ...this.npm.flatOptions, path: globalTop, - log, global: true, prune: false, } @@ -118,7 +116,6 @@ class Link extends ArboristWorkspaceCmd { const localArb = new Arborist({ ...this.npm.flatOptions, prune: false, - log, path: this.npm.prefix, save, }) @@ -126,7 +123,6 @@ class Link extends ArboristWorkspaceCmd { ...this.npm.flatOptions, prune: false, path: this.npm.prefix, - log, add: names.map(l => `file:${resolve(globalTop, 'node_modules', l)}`), save, workspaces: this.workspaceNames, @@ -143,12 +139,10 @@ class Link extends ArboristWorkspaceCmd { const arb = new Arborist({ ...this.npm.flatOptions, path: globalTop, - log, global: true, }) await arb.reify({ add, - log, }) await reifyFinish(this.npm, arb) } diff --git a/lib/commands/logout.js b/lib/commands/logout.js index 34fbace583562..aea5e93652b0e 100644 --- a/lib/commands/logout.js +++ b/lib/commands/logout.js @@ -25,7 +25,6 @@ class Logout extends BaseCommand { ...this.npm.flatOptions, method: 'DELETE', ignoreBody: true, - log, }) } else if (auth.isBasicAuth) { log.verbose('logout', `clearing user credentials for ${reg}`) diff --git a/lib/commands/org.js b/lib/commands/org.js index 89859200fed6b..f3d344ca33e3d 100644 --- a/lib/commands/org.js +++ b/lib/commands/org.js @@ -2,7 +2,6 @@ const liborg = require('libnpmorg') const otplease = require('../utils/otplease.js') const Table = require('cli-table3') const BaseCommand = require('../base-command.js') -const log = require('../utils/log-shim.js') class Org extends BaseCommand { static description = 'Manage orgs' @@ -35,7 +34,6 @@ class Org extends BaseCommand { async exec ([cmd, orgname, username, role], cb) { return otplease({ ...this.npm.flatOptions, - log, }, opts => { switch (cmd) { case 'add': @@ -76,7 +74,7 @@ class Org extends BaseCommand { this.npm.output( [memDeets.org.name, memDeets.org.size, memDeets.user, memDeets.role].join('\t') ) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { this.npm.output( `Added ${memDeets.user} as ${memDeets.role} to ${memDeets.org.name}. You now have ${ memDeets.org.size @@ -118,7 +116,7 @@ class Org extends BaseCommand { } else if (opts.parseable) { this.npm.output(['user', 'org', 'userCount', 'deleted'].join('\t')) this.npm.output([user, org, userCount, true].join('\t')) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { this.npm.output( `Successfully removed ${user} from ${org}. You now have ${userCount} member${ userCount === 1 ? '' : 's' @@ -149,7 +147,7 @@ class Org extends BaseCommand { Object.keys(roster).forEach(user => { this.npm.output([user, roster[user]].join('\t')) }) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { const table = new Table({ head: ['user', 'role'] }) Object.keys(roster) .sort() diff --git a/lib/commands/owner.js b/lib/commands/owner.js index 7b76b7be42ec6..effaaa6a53d3a 100644 --- a/lib/commands/owner.js +++ b/lib/commands/owner.js @@ -59,7 +59,6 @@ class Owner extends BaseCommand { async exec ([action, ...args]) { const opts = { ...this.npm.flatOptions, - log, } switch (action) { case 'ls': @@ -198,7 +197,6 @@ class Owner extends BaseCommand { method: 'PUT', body, spec, - log, }) }) diff --git a/lib/commands/ping.js b/lib/commands/ping.js index 27089be4e1714..5a651c4a6ab09 100644 --- a/lib/commands/ping.js +++ b/lib/commands/ping.js @@ -10,7 +10,7 @@ class Ping extends BaseCommand { async exec (args) { log.notice('PING', this.npm.config.get('registry')) const start = Date.now() - const details = await pingUtil({ ...this.npm.flatOptions, log }) + const details = await pingUtil({ ...this.npm.flatOptions }) const time = Date.now() - start log.notice('PONG', `${time}ms`) if (this.npm.config.get('json')) { diff --git a/lib/commands/profile.js b/lib/commands/profile.js index 9786e9ba4d4cf..6b4d1407f7919 100644 --- a/lib/commands/profile.js +++ b/lib/commands/profile.js @@ -108,7 +108,7 @@ class Profile extends BaseCommand { async get (args) { const tfa = 'two-factor auth' const info = await pulseTillDone.withPromise( - npmProfile.get({ ...this.npm.flatOptions, log }) + npmProfile.get({ ...this.npm.flatOptions }) ) if (!info.cidr_whitelist) { @@ -170,7 +170,7 @@ class Profile extends BaseCommand { } async set (args) { - const conf = { ...this.npm.flatOptions, log } + const conf = { ...this.npm.flatOptions } const prop = (args[0] || '').toLowerCase().trim() let value = args.length > 1 ? args.slice(1).join(' ') : null @@ -285,7 +285,7 @@ class Profile extends BaseCommand { if (auth.basic) { log.info('profile', 'Updating authentication to bearer token') const result = await npmProfile.createToken( - auth.basic.password, false, [], { ...this.npm.flatOptions, log } + auth.basic.password, false, [], { ...this.npm.flatOptions } ) if (!result.token) { @@ -309,7 +309,7 @@ class Profile extends BaseCommand { log.info('profile', 'Determine if tfa is pending') const userInfo = await pulseTillDone.withPromise( - npmProfile.get({ ...this.npm.flatOptions, log }) + npmProfile.get({ ...this.npm.flatOptions }) ) const conf = { ...this.npm.flatOptions } diff --git a/lib/commands/prune.js b/lib/commands/prune.js index 5831df62859c2..16c8b6d4329ac 100644 --- a/lib/commands/prune.js +++ b/lib/commands/prune.js @@ -1,6 +1,5 @@ // prune extraneous packages const Arborist = require('@npmcli/arborist') -const log = require('../utils/log-shim.js') const reifyFinish = require('../utils/reify-finish.js') const ArboristWorkspaceCmd = require('../arborist-cmd.js') @@ -15,7 +14,6 @@ class Prune extends ArboristWorkspaceCmd { const opts = { ...this.npm.flatOptions, path: where, - log, workspaces: this.workspaceNames, } const arb = new Arborist(opts) diff --git a/lib/commands/publish.js b/lib/commands/publish.js index 63106c520bd58..d1f0ee743cfcc 100644 --- a/lib/commands/publish.js +++ b/lib/commands/publish.js @@ -55,13 +55,13 @@ class Publish extends BaseCommand { const json = this.npm.config.get('json') const defaultTag = this.npm.config.get('tag') const ignoreScripts = this.npm.config.get('ignore-scripts') - const silent = log.level === 'silent' + const { silent } = this.npm if (semver.validRange(defaultTag)) { throw new Error('Tag name must not be a valid SemVer range: ' + defaultTag.trim()) } - const opts = { ...this.npm.flatOptions, log } + const opts = { ...this.npm.flatOptions } // you can publish name@version, ./foo.tgz, etc. // even though the default is the 'file:.' cwd. @@ -152,7 +152,7 @@ class Publish extends BaseCommand { const results = {} const json = this.npm.config.get('json') - const silent = log.level === 'silent' + const { silent } = this.npm const noop = a => a const color = this.npm.color ? chalk : { green: noop, bold: noop } await this.setWorkspaces(filters) diff --git a/lib/commands/run-script.js b/lib/commands/run-script.js index cd877e0b3dfa4..edba95821b44c 100644 --- a/lib/commands/run-script.js +++ b/lib/commands/run-script.js @@ -116,7 +116,7 @@ class RunScript extends BaseCommand { stdio: 'inherit', stdioString: true, pkg, - banner: log.level !== 'silent', + banner: !this.npm.silent, } for (const [event, args] of events) { @@ -139,7 +139,7 @@ class RunScript extends BaseCommand { } const allScripts = Object.keys(scripts) - if (log.level === 'silent') { + if (this.npm.silent) { return allScripts } @@ -233,7 +233,7 @@ class RunScript extends BaseCommand { async listWorkspaces (args, filters) { await this.setWorkspaces(filters) - if (log.level === 'silent') { + if (this.npm.silent) { return } diff --git a/lib/commands/star.js b/lib/commands/star.js index 4974c39883e43..2d08747aa7719 100644 --- a/lib/commands/star.js +++ b/lib/commands/star.js @@ -29,13 +29,12 @@ class Star extends BaseCommand { const pkgs = args.map(npa) for (const pkg of pkgs) { const [username, fullData] = await Promise.all([ - getIdentity(this.npm, { ...this.npm.flatOptions, log }), + getIdentity(this.npm, { ...this.npm.flatOptions }), fetch.json(pkg.escapedName, { ...this.npm.flatOptions, spec: pkg, query: { write: true }, preferOnline: true, - log, }), ]) @@ -64,7 +63,6 @@ class Star extends BaseCommand { spec: pkg, method: 'PUT', body, - log, }) this.npm.output(show + ' ' + pkg.name) diff --git a/lib/commands/team.js b/lib/commands/team.js index e3fb9b83c5a27..1e13a83f52b09 100644 --- a/lib/commands/team.js +++ b/lib/commands/team.js @@ -1,7 +1,6 @@ const columns = require('cli-columns') const libteam = require('libnpmteam') -const log = require('../utils/log-shim.js') const otplease = require('../utils/otplease.js') const BaseCommand = require('../base-command.js') @@ -43,7 +42,7 @@ class Team extends BaseCommand { // XXX: "description" option to libnpmteam is used as a description of the // team, but in npm's options, this is a boolean meaning "show the // description in npm search output". Hence its being set to null here. - await otplease({ ...this.npm.flatOptions, log }, opts => { + await otplease({ ...this.npm.flatOptions }, opts => { entity = entity.replace(/^@/, '') switch (cmd) { case 'create': return this.create(entity, opts) @@ -73,7 +72,7 @@ class Team extends BaseCommand { })) } else if (opts.parseable) { this.npm.output(`${entity}\tcreated`) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { this.npm.output(`+@${entity}`) } } @@ -87,7 +86,7 @@ class Team extends BaseCommand { })) } else if (opts.parseable) { this.npm.output(`${entity}\tdeleted`) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { this.npm.output(`-@${entity}`) } } @@ -102,7 +101,7 @@ class Team extends BaseCommand { })) } else if (opts.parseable) { this.npm.output(`${user}\t${entity}\tadded`) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { this.npm.output(`${user} added to @${entity}`) } } @@ -117,7 +116,7 @@ class Team extends BaseCommand { })) } else if (opts.parseable) { this.npm.output(`${user}\t${entity}\tremoved`) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { this.npm.output(`${user} removed from @${entity}`) } } @@ -128,7 +127,7 @@ class Team extends BaseCommand { this.npm.output(JSON.stringify(users, null, 2)) } else if (opts.parseable) { this.npm.output(users.join('\n')) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { const plural = users.length === 1 ? '' : 's' const more = users.length === 0 ? '' : ':\n' this.npm.output(`\n@${entity} has ${users.length} user${plural}${more}`) @@ -142,7 +141,7 @@ class Team extends BaseCommand { this.npm.output(JSON.stringify(teams, null, 2)) } else if (opts.parseable) { this.npm.output(teams.join('\n')) - } else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!this.npm.silent) { const plural = teams.length === 1 ? '' : 's' const more = teams.length === 0 ? '' : ':\n' this.npm.output(`\n@${entity} has ${teams.length} team${plural}${more}`) diff --git a/lib/commands/token.js b/lib/commands/token.js index cfb5ab666565a..df80f1afec44e 100644 --- a/lib/commands/token.js +++ b/lib/commands/token.js @@ -168,7 +168,7 @@ class Token extends BaseCommand { } config () { - const conf = { ...this.npm.flatOptions, log } + const conf = { ...this.npm.flatOptions } const creds = this.npm.config.getCredentialsByURI(conf.registry) if (creds.token) { conf.auth = { token: creds.token } diff --git a/lib/commands/uninstall.js b/lib/commands/uninstall.js index b40c59bda4419..587968e3bbba9 100644 --- a/lib/commands/uninstall.js +++ b/lib/commands/uninstall.js @@ -1,5 +1,4 @@ const { resolve } = require('path') -const log = require('../utils/log-shim.js') const Arborist = require('@npmcli/arborist') const rpj = require('read-package-json-fast') @@ -49,7 +48,6 @@ class Uninstall extends ArboristWorkspaceCmd { const opts = { ...this.npm.flatOptions, path, - log, rm: args, workspaces: this.workspaceNames, } diff --git a/lib/commands/unpublish.js b/lib/commands/unpublish.js index d8410cc13481b..c848b6389d1b8 100644 --- a/lib/commands/unpublish.js +++ b/lib/commands/unpublish.js @@ -32,7 +32,7 @@ class Unpublish extends BaseCommand { return [] } - const opts = { ...this.npm.flatOptions, log } + const opts = { ...this.npm.flatOptions } const username = await getIdentity(this.npm, { ...opts }).catch(() => null) if (!username) { return [] @@ -68,8 +68,7 @@ class Unpublish extends BaseCommand { const spec = args.length && npa(args[0]) const force = this.npm.config.get('force') - const loglevel = this.npm.config.get('loglevel') - const silent = loglevel === 'silent' + const { silent } = this.npm const dryRun = this.npm.config.get('dry-run') let pkgName let pkgVersion @@ -84,7 +83,7 @@ class Unpublish extends BaseCommand { ) } - const opts = { ...this.npm.flatOptions, log } + const opts = { ...this.npm.flatOptions } if (!spec || path.resolve(spec.name) === this.npm.localPrefix) { // if there's a package.json in the current folder, then // read the package name and version out of that. diff --git a/lib/commands/update.js b/lib/commands/update.js index c55d7cf575d88..025ebbaf815f0 100644 --- a/lib/commands/update.js +++ b/lib/commands/update.js @@ -54,7 +54,6 @@ class Update extends ArboristWorkspaceCmd { const opts = { ...this.npm.flatOptions, - log, path: where, save, workspaces: this.workspaceNames, diff --git a/lib/commands/whoami.js b/lib/commands/whoami.js index 07ebe2e244753..154cc870391ba 100644 --- a/lib/commands/whoami.js +++ b/lib/commands/whoami.js @@ -1,5 +1,4 @@ const getIdentity = require('../utils/get-identity.js') -const log = require('../utils/log-shim.js') const BaseCommand = require('../base-command.js') class Whoami extends BaseCommand { @@ -8,7 +7,7 @@ class Whoami extends BaseCommand { static params = ['registry'] async exec (args) { - const username = await getIdentity(this.npm, { ...this.npm.flatOptions, log }) + const username = await getIdentity(this.npm, { ...this.npm.flatOptions }) this.npm.output( this.npm.config.get('json') ? JSON.stringify(username) : username ) diff --git a/lib/npm.js b/lib/npm.js index 4d22b531a4662..ce8f6aee8f575 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -52,7 +52,6 @@ class Npm extends EventEmitter { definitions, flatten, shorthands, - log, }) this[_title] = process.title this.updateNotification = null @@ -251,6 +250,7 @@ class Npm extends EventEmitter { // Use logColor since that is based on stderr color: this.logColor, progress: this.flatOptions.progress, + silent: this.silent, timing: this.config.get('timing'), loglevel: this.config.get('loglevel'), unicode: this.config.get('unicode'), @@ -300,6 +300,10 @@ class Npm extends EventEmitter { return this.flatOptions.logColor } + get silent () { + return this.flatOptions.silent + } + get lockfileVersion () { return 2 } diff --git a/lib/utils/config/definitions.js b/lib/utils/config/definitions.js index 79e686ca75134..c5c129eb3d495 100644 --- a/lib/utils/config/definitions.js +++ b/lib/utils/config/definitions.js @@ -1222,6 +1222,9 @@ define('loglevel', { See also the \`foreground-scripts\` config. `, + flatten (key, obj, flatOptions) { + flatOptions.silent = obj[key] === 'silent' + }, }) define('logs-max', { diff --git a/lib/utils/display.js b/lib/utils/display.js index aae51e8806f8a..a19f72297e838 100644 --- a/lib/utils/display.js +++ b/lib/utils/display.js @@ -35,6 +35,7 @@ class Display { loglevel, unicode, progress, + silent, heading = 'npm', } = config @@ -59,8 +60,7 @@ class Display { log.disableUnicode() } - // if it's more than error, don't show progress - const silent = log.levels[log.level] > log.levels.error + // if it's silent, don't show progress if (progress && !silent) { log.enableProgress() } else { diff --git a/lib/utils/exit-handler.js b/lib/utils/exit-handler.js index 22c774101751b..6186ea81dcc02 100644 --- a/lib/utils/exit-handler.js +++ b/lib/utils/exit-handler.js @@ -49,8 +49,8 @@ process.on('exit', code => { // npm must be loaded to know where the log file was written if (showLogFileMessage && hasLoadedNpm) { - // just a line break - if (log.levels[log.level] <= log.levels.error) { + // just a line break if not in silent mode + if (!npm.silent) { console.error('') } @@ -175,7 +175,7 @@ const exitHandler = err => { log.verbose('exit', exitCode || 0) - showLogFileMessage = log.level === 'silent' || noLogMessage + showLogFileMessage = (hasLoadedNpm && npm.silent) || noLogMessage ? false : !!exitCode diff --git a/lib/utils/reify-output.js b/lib/utils/reify-output.js index b4114c1b2fe04..b5c3a593b8db0 100644 --- a/lib/utils/reify-output.js +++ b/lib/utils/reify-output.js @@ -27,7 +27,7 @@ const reifyOutput = (npm, arb) => { // don't print any info in --silent mode, but we still need to // set the exitCode properly from the audit report, if we have one. - if (log.levels[log.level] > log.levels.error) { + if (npm.silent) { getAuditReport(npm, auditReport) return } @@ -88,7 +88,7 @@ const reifyOutput = (npm, arb) => { // at the end if there's still stuff, because it's silly for `npm audit` // to tell you to run `npm audit` for details. otherwise, use the summary // report. if we get here, we know it's not quiet or json. -// If the loglevel is set higher than 'error', then we just run the report +// If the loglevel is silent, then we just run the report // to get the exitCode set appropriately. const printAuditReport = (npm, report) => { const res = getAuditReport(npm, report) @@ -105,7 +105,7 @@ const getAuditReport = (npm, report) => { // when in silent mode, we print nothing. the JSON output is // going to just JSON.stringify() the report object. - const reporter = log.levels[log.level] > log.levels.error ? 'quiet' + const reporter = npm.silent ? 'quiet' : npm.flatOptions.json ? 'quiet' : npm.command !== 'audit' ? 'install' : 'detail' diff --git a/lib/utils/update-notifier.js b/lib/utils/update-notifier.js index 44b6a5433c09a..875c3a99a2579 100644 --- a/lib/utils/update-notifier.js +++ b/lib/utils/update-notifier.js @@ -10,7 +10,6 @@ const { promisify } = require('util') const stat = promisify(require('fs').stat) const writeFile = promisify(require('fs').writeFile) const { resolve } = require('path') -const log = require('./log-shim.js') const isGlobalNpmUpdate = npm => { return npm.flatOptions.global && @@ -62,7 +61,7 @@ const updateNotifier = async (npm, spec = 'latest') => { // if they're currently using a prerelease, nudge to the next prerelease // otherwise, nudge to latest. - const useColor = log.useColor() + const useColor = npm.logColor const mani = await pacote.manifest(`npm@${spec}`, { // always prefer latest, even if doing --tag=whatever on the cmd diff --git a/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs b/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs index 523aabca29b50..0aaf235fd14b6 100644 --- a/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs +++ b/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs @@ -26,10 +26,10 @@ exports[`test/lib/utils/exit-handler.js TAP handles unknown error with logs and 32 error ERR SUMMARY Unknown error 33 error ERR DETAIL Unknown error 34 verbose exit 1 -35 timing npm Completed in {TIME}ms -36 verbose code 1 -37 error A complete log of this run can be found in: -37 error {CWD}/test/lib/utils/tap-testdir-exit-handler-handles-unknown-error-with-logs-and-debug-file/cache/_logs/{DATE}-debug-0.log +36 timing npm Completed in {TIME}ms +37 verbose code 1 +38 error A complete log of this run can be found in: +38 error {CWD}/test/lib/utils/tap-testdir-exit-handler-handles-unknown-error-with-logs-and-debug-file/cache/_logs/{DATE}-debug-0.log ` exports[`test/lib/utils/exit-handler.js TAP handles unknown error with logs and debug file > logs 1`] = ` diff --git a/test/fixtures/mock-npm.js b/test/fixtures/mock-npm.js index c3dc47f5dde4f..4846d9a485841 100644 --- a/test/fixtures/mock-npm.js +++ b/test/fixtures/mock-npm.js @@ -31,6 +31,18 @@ const RealMockNpm = (t, otherMocks = {}) => { return mock } +const setLoglevel = (t, loglevel, reset = true) => { + if (t && reset) { + const _level = log.level + t.teardown(() => log.level = _level) + } + + if (loglevel) { + // Set log level on the npmlog singleton and shared across everything + log.level = loglevel + } +} + // Resolve some options to a function call with supplied args const result = (fn, ...args) => typeof fn === 'function' ? fn(...args) : fn @@ -62,14 +74,8 @@ const LoadMockNpm = async (t, { throw new Error('cant `load` without `init`') } - const _level = log.level - t.teardown(() => log.level = _level) - - if (config.loglevel) { - // Set log level as early as possible since it is set - // on the npmlog singleton and shared across everything - log.level = config.loglevel - } + // Set log level as early as possible since + setLoglevel(t, config.loglevel) const dir = t.testdir({ root: testdir, cache: {} }) const prefix = path.join(dir, 'root') @@ -93,11 +99,9 @@ const LoadMockNpm = async (t, { for (const [k, v] of Object.entries(result(config, { npm, prefix, cache }))) { npm.config.set(k, v) } - if (config.loglevel) { - // Set global loglevel *again* since it possibly got reset during load - // XXX: remove with npmlog - log.level = config.loglevel - } + // Set global loglevel *again* since it possibly got reset during load + // XXX: remove with npmlog + setLoglevel(t, config.loglevel, false) npm.prefix = prefix npm.cache = cache } @@ -129,7 +133,7 @@ const realConfig = require('../../lib/utils/config') // npm.config You still need a separate flatOptions. Tests should migrate to // using the real npm mock above class MockNpm { - constructor (base = {}) { + constructor (base = {}, t) { this._mockOutputs = [] this.isMockNpm = true this.base = base @@ -150,9 +154,24 @@ class MockNpm { // for now isDefault is going to just return false if a value was defined isDefault: (k) => !Object.prototype.hasOwnProperty.call(config, k), get: (k) => ({ ...realConfig.defaults, ...config })[k], - set: (k, v) => config[k] = v, + set: (k, v) => { + config[k] = v + // mock how real npm derives silent + if (k === 'loglevel') { + this.flatOptions.silent = v === 'silent' + this.silent = v === 'silent' + } + }, list: [{ ...realConfig.defaults, ...config }], } + + if (t && config.loglevel) { + setLoglevel(t, config.loglevel) + } + + if (config.loglevel) { + this.config.set('loglevel', config.loglevel) + } } output (...msg) { @@ -163,8 +182,8 @@ class MockNpm { } } -const FakeMockNpm = (base = {}) => { - return new MockNpm(base) +const FakeMockNpm = (base = {}, t) => { + return new MockNpm(base, t) } module.exports = { diff --git a/test/fixtures/sandbox.js b/test/fixtures/sandbox.js index 701d9cea72397..d51281d41d104 100644 --- a/test/fixtures/sandbox.js +++ b/test/fixtures/sandbox.js @@ -193,6 +193,8 @@ class Sandbox extends EventEmitter { // test.teardown hook teardown () { if (this[_parent]) { + const sandboxProcess = sandboxes.get(this[_parent]) + sandboxProcess.removeAllListeners('log') sandboxes.delete(this[_parent]) } if (this[_npm]) { @@ -211,20 +213,7 @@ class Sandbox extends EventEmitter { return Reflect.get(this, prop, this) } - const actual = Reflect.get(target, prop, receiver) - if (typeof actual === 'function') { - // in node 10.1 there's an interesting bug where if a function on process - // is called without explicitly forcing the 'this' arg to something, we - // get 'Illegal invocation' errors. wrapping function properties in their - // own proxy so that we can make sure the context is right fixes it - return new Proxy(actual, { - apply: (target, context, args) => { - return Reflect.apply(target, _process, args) - }, - }) - } - - return actual + return Reflect.get(target, prop, receiver) } // proxy set handler @@ -278,17 +267,15 @@ class Sandbox extends EventEmitter { ...this[_mocks], ...mockedLogs.logMocks, }) + this.process.on('log', (l, ...args) => { + if (l !== 'pause' && l !== 'resume') { + this[_logs].push([l, ...args]) + } + }) + this[_npm] = new Npm() this[_npm].output = (...args) => this[_output].push(args) await this[_npm].load() - // in some node versions (later 10.x) our executionAsyncId at this point - // will for some reason appear to have been triggered by a different parent - // so immediately after load, if we can see that we lost our ancestry, we - // fix it here with a hammer - if (chain.get(executionAsyncId()) !== this[_parent]) { - chain.set(executionAsyncId(), this[_parent]) - process = this[_proxy] - } const cmd = this[_npm].argv.shift() return this[_npm].exec(cmd, this[_npm].argv) @@ -330,17 +317,15 @@ class Sandbox extends EventEmitter { ...this[_mocks], ...mockedLogs.logMocks, }) + this.process.on('log', (l, ...args) => { + if (l !== 'pause' && l !== 'resume') { + this[_logs].push([l, ...args]) + } + }) + this[_npm] = new Npm() this[_npm].output = (...args) => this[_output].push(args) await this[_npm].load() - // in some node versions (later 10.x) our executionAsyncId at this point - // will for some reason appear to have been triggered by a different parent - // so immediately after load, if we can see that we lost our ancestry, we - // fix it here with a hammer - if (chain.get(executionAsyncId()) !== this[_parent]) { - chain.set(executionAsyncId(), this[_parent]) - process = this[_proxy] - } const impl = await this[_npm].cmd(command) return impl.completion({ diff --git a/test/lib/commands/access.js b/test/lib/commands/access.js index c4e6f3167aa01..298897e4f5ffc 100644 --- a/test/lib/commands/access.js +++ b/test/lib/commands/access.js @@ -75,13 +75,12 @@ t.test('access public on unscoped package', async t => { }) t.test('access public on scoped package', async t => { - t.plan(3) + t.plan(2) const name = '@scoped/npm-access-public-pkg' const { npm } = await loadMockNpm(t, { mocks: { libnpmaccess: { - public: (pkg, { registry, log }) => { - t.ok(log, 'should pass a logger') + public: (pkg, { registry }) => { t.equal(pkg, name, 'should use pkg name ref') t.equal( registry, diff --git a/test/lib/commands/adduser.js b/test/lib/commands/adduser.js index 8a9358f9ab21a..f88508d15a6fe 100644 --- a/test/lib/commands/adduser.js +++ b/test/lib/commands/adduser.js @@ -20,13 +20,6 @@ const authDummy = (npm, options) => { throw new Error('did not pass full flatOptions to auth function') } - if (!options.log) { - // A quick to test to make sure a log gets passed to auth - // XXX: should be refactored with change to real mock npm - // https://github.com/npm/statusboard/issues/411 - throw new Error('pass log to auth') - } - return Promise.resolve({ message: 'success', newCreds: { diff --git a/test/lib/commands/deprecate.js b/test/lib/commands/deprecate.js index aa158cca3a1a1..180629a7488f9 100644 --- a/test/lib/commands/deprecate.js +++ b/test/lib/commands/deprecate.js @@ -2,15 +2,12 @@ const t = require('tap') let getIdentityImpl = () => 'someperson' let npmFetchBody = null -let npmFetchLog = null const npmFetch = async (uri, opts) => { npmFetchBody = opts.body - npmFetchLog = opts.log } npmFetch.json = async (uri, opts) => { - npmFetchLog = opts.log return { versions: { '1.0.0': {}, @@ -87,10 +84,8 @@ t.test('invalid semver range', async t => { t.test('undeprecate', async t => { t.teardown(() => { npmFetchBody = null - npmFetchLog = null }) await deprecate.exec(['foo', '']) - t.ok(npmFetchLog, 'was passed a logger') t.match(npmFetchBody, { versions: { '1.0.0': { deprecated: '' }, @@ -103,11 +98,9 @@ t.test('undeprecate', async t => { t.test('deprecates given range', async t => { t.teardown(() => { npmFetchBody = null - npmFetchLog = null }) await deprecate.exec(['foo@1.0.0', 'this version is deprecated']) - t.ok(npmFetchLog, 'was passed a logger') t.match(npmFetchBody, { versions: { '1.0.0': { diff --git a/test/lib/commands/diff.js b/test/lib/commands/diff.js index f73a543cb4c51..ed0702e3784a6 100644 --- a/test/lib/commands/diff.js +++ b/test/lib/commands/diff.js @@ -61,10 +61,9 @@ const diff = new Diff(npm) t.test('no args', t => { t.test('in a project dir', async t => { - t.plan(4) + t.plan(3) libnpmdiff = async ([a, b], opts) => { - t.ok(opts.log, 'should be passed a logger') t.equal(a, 'foo@latest', 'should have default spec comparison') t.equal(b, `file:${fooPath}`, 'should compare to cwd') t.match(opts, npm.flatOptions, 'should forward flat options') diff --git a/test/lib/commands/dist-tag.js b/test/lib/commands/dist-tag.js index b83c30e9c64ea..eb13c7ff02fbe 100644 --- a/test/lib/commands/dist-tag.js +++ b/test/lib/commands/dist-tag.js @@ -43,7 +43,6 @@ const routeMap = { // XXX overriding this does not appear to do anything, adding t.plan to things // that use it fails the test let npmRegistryFetchMock = (url, opts) => { - npmRegistryFetchLog = opts.log if (url === '/-/package/foo/dist-tags') { throw new Error('no package found') } @@ -51,9 +50,7 @@ let npmRegistryFetchMock = (url, opts) => { return routeMap[url] } -let npmRegistryFetchLog npmRegistryFetchMock.json = async (url, opts) => { - npmRegistryFetchLog = opts.log return routeMap[url] } @@ -86,10 +83,6 @@ const npm = mockNpm({ }) const distTag = new DistTag(npm) -t.afterEach(() => { - npmRegistryFetchLog = null -}) - t.test('ls in current package', async t => { npm.prefix = t.testdir({ 'package.json': JSON.stringify({ @@ -97,7 +90,6 @@ t.test('ls in current package', async t => { }), }) await distTag.exec(['ls']) - t.ok(npmRegistryFetchLog, 'is passed a logger') t.matchSnapshot( result, 'should list available tags for current package' @@ -299,7 +291,6 @@ t.test('add new tag', async t => { }) npmRegistryFetchMock = async (url, opts) => { - t.ok(opts.log, 'is passed a logger') t.equal(opts.method, 'PUT', 'should trigger request to add new tag') t.equal(opts.body, '7.7.7', 'should point to expected version') } @@ -366,7 +357,6 @@ t.test('remove existing tag', async t => { } npm.prefix = t.testdir({}) await distTag.exec(['rm', '@scoped/another', 'c']) - t.ok(npmRegistryFetchLog, 'is passed a logger') t.matchSnapshot(log, 'should log remove info') t.matchSnapshot(result, 'should return success msg') }) diff --git a/test/lib/commands/doctor.js b/test/lib/commands/doctor.js index 51b6111a0ae70..dee2110ff3c89 100644 --- a/test/lib/commands/doctor.js +++ b/test/lib/commands/doctor.js @@ -4,6 +4,7 @@ const { join } = require('path') const fs = require('fs') const ansiTrim = require('../../../lib/utils/ansi-trim.js') const isWindows = require('../../../lib/utils/is-windows.js') +const { fake: mockNpm } = require('../../fixtures/mock-npm') // getuid and getgid do not exist in windows, so we shim them // to return 0, as that is the value that lstat will assign the @@ -61,15 +62,18 @@ const clearLogs = () => { } } -const npm = { +const npm = mockNpm({ flatOptions: { registry: 'https://registry.npmjs.org/', }, + config: { + loglevel: 'info', + }, version: '7.1.0', output: data => { output.push(data) }, -} +}) let latestNpm = npm.version const pacote = { @@ -211,7 +215,7 @@ t.test('node versions', t => { npm.globalDir = dir npm.localBin = dir npm.globalBin = dir - mocks.npmlog.level = 'info' + npm.config.set('loglevel', 'silent') st.teardown(() => { delete npm.cache @@ -220,7 +224,7 @@ t.test('node versions', t => { delete npm.globalDir delete npm.localBin delete npm.globalBin - mocks.npmlog.level = 'error' + npm.config.set('loglevel', 'info') clearLogs() }) diff --git a/test/lib/commands/hook.js b/test/lib/commands/hook.js index a4eee711fe8e0..60a59a3fe7a3b 100644 --- a/test/lib/commands/hook.js +++ b/test/lib/commands/hook.js @@ -1,18 +1,20 @@ const t = require('tap') +const { fake: mockNpm } = require('../../fixtures/mock-npm') const output = [] -const npm = { +const npm = mockNpm({ flatOptions: { json: false, parseable: false, - silent: false, - loglevel: 'info', unicode: false, }, + config: { + loglevel: 'info', + }, output: msg => { output.push(msg) }, -} +}) const pkgTypes = { semver: 'package', @@ -78,7 +80,6 @@ t.test('npm hook add', async t => { await hook.exec(['add', 'semver', 'https://google.com', 'some-secret']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -102,7 +103,6 @@ t.test('npm hook add - unicode output', async t => { await hook.exec(['add', 'semver', 'https://google.com', 'some-secret']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -126,7 +126,6 @@ t.test('npm hook add - json output', async t => { await hook.exec(['add', '@npmcli', 'https://google.com', 'some-secret']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -159,7 +158,6 @@ t.test('npm hook add - parseable output', async t => { await hook.exec(['add', '@npmcli', 'https://google.com', 'some-secret']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -183,16 +181,15 @@ t.test('npm hook add - parseable output', async t => { }) t.test('npm hook add - silent output', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') t.teardown(() => { - npm.flatOptions.silent = false + npm.config.set('loglevel', 'info') hookArgs = null output.length = 0 }) await hook.exec(['add', '@npmcli', 'https://google.com', 'some-secret']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -214,7 +211,6 @@ t.test('npm hook ls', async t => { await hook.exec(['ls']) - t.ok(hookArgs.log, 'is passed a logger') t.match( hookArgs, { @@ -240,7 +236,6 @@ t.test('npm hook ls, no results', async t => { await hook.exec(['ls']) - t.ok(hookArgs.log, 'is passed a logger') t.match( hookArgs, { @@ -270,7 +265,6 @@ t.test('npm hook ls, single result', async t => { await hook.exec(['ls']) - t.ok(hookArgs.log, 'is passed a logger') t.match( hookArgs, { @@ -294,7 +288,6 @@ t.test('npm hook ls - json output', async t => { await hook.exec(['ls']) - t.ok(hookArgs.log, 'is passed a logger') t.match( hookArgs, { @@ -340,7 +333,6 @@ t.test('npm hook ls - parseable output', async t => { await hook.exec(['ls']) - t.ok(hookArgs.log, 'is passed a logger') t.match( hookArgs, { @@ -362,16 +354,15 @@ t.test('npm hook ls - parseable output', async t => { }) t.test('npm hook ls - silent output', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') t.teardown(() => { - npm.flatOptions.silent = false + npm.config.set('loglevel', 'info') hookArgs = null output.length = 0 }) await hook.exec(['ls']) - t.ok(hookArgs.log, 'is passed a logger') t.match( hookArgs, { @@ -391,7 +382,6 @@ t.test('npm hook rm', async t => { await hook.exec(['rm', '1']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -413,7 +403,6 @@ t.test('npm hook rm - unicode output', async t => { await hook.exec(['rm', '1']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -426,16 +415,15 @@ t.test('npm hook rm - unicode output', async t => { }) t.test('npm hook rm - silent output', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') t.teardown(() => { - npm.flatOptions.silent = false + npm.config.set('loglevel', 'info') hookArgs = null output.length = 0 }) await hook.exec(['rm', '1']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -457,7 +445,6 @@ t.test('npm hook rm - json output', async t => { await hook.exec(['rm', '1']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -488,7 +475,6 @@ t.test('npm hook rm - parseable output', async t => { await hook.exec(['rm', '1']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -515,7 +501,6 @@ t.test('npm hook update', async t => { await hook.exec(['update', '1', 'https://google.com', 'some-secret']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -539,7 +524,6 @@ t.test('npm hook update - unicode', async t => { await hook.exec(['update', '1', 'https://google.com', 'some-secret']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -563,7 +547,6 @@ t.test('npm hook update - json output', async t => { await hook.exec(['update', '1', 'https://google.com', 'some-secret']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -596,7 +579,6 @@ t.test('npm hook update - parseable output', async t => { await hook.exec(['update', '1', 'https://google.com', 'some-secret']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { @@ -618,16 +600,15 @@ t.test('npm hook update - parseable output', async t => { }) t.test('npm hook update - silent output', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') t.teardown(() => { - npm.flatOptions.silent = false + npm.config.set('loglevel', 'info') hookArgs = null output.length = 0 }) await hook.exec(['update', '1', 'https://google.com', 'some-secret']) - t.ok(hookArgs.opts.log, 'is passed a logger') t.match( hookArgs, { diff --git a/test/lib/commands/logout.js b/test/lib/commands/logout.js index 1a1fbb785c808..73fe8028c7853 100644 --- a/test/lib/commands/logout.js +++ b/test/lib/commands/logout.js @@ -31,7 +31,7 @@ t.afterEach(() => { }) t.test('token logout', async t => { - t.plan(6) + t.plan(5) flatOptions['//registry.npmjs.org/:_authToken'] = '@foo/' @@ -62,7 +62,6 @@ t.test('token logout', async t => { await logout.exec([]) - t.ok(result.opts.log, 'should pass a logger') t.match( result, { @@ -92,7 +91,7 @@ t.test('token scoped logout', async t => { config.save = null }) - t.plan(8) + t.plan(7) flatOptions['//diff-registry.npmjs.com/:_authToken'] = '@bar/' flatOptions['//registry.npmjs.org/:_authToken'] = '@foo/' @@ -133,7 +132,6 @@ t.test('token scoped logout', async t => { await logout.exec([]) - t.ok(result.opts.log, 'should pass a logger') t.match( result, { @@ -204,7 +202,7 @@ t.test('ignore invalid scoped registry config', async t => { config.delete = null config.save = null }) - t.plan(5) + t.plan(4) flatOptions['//registry.npmjs.org/:_authToken'] = '@foo/' config.scope = '@myscope' @@ -236,7 +234,6 @@ t.test('ignore invalid scoped registry config', async t => { await logout.exec([]) - t.ok(result.opts.log, 'should pass a logger') t.match( result, { diff --git a/test/lib/commands/org.js b/test/lib/commands/org.js index b716adc097523..3ae951dd5c453 100644 --- a/test/lib/commands/org.js +++ b/test/lib/commands/org.js @@ -1,18 +1,20 @@ const t = require('tap') const ansiTrim = require('../../../lib/utils/ansi-trim.js') +const { fake: mockNpm } = require('../../fixtures/mock-npm') const output = [] -const npm = { +const npm = mockNpm({ flatOptions: { json: false, parseable: false, - silent: false, + }, + config: { loglevel: 'info', }, output: msg => { output.push(msg) }, -} +}) let orgSize = 1 let orgSetArgs = null @@ -83,7 +85,6 @@ t.test('npm org add', async t => { await org.exec(['add', 'orgname', 'username']) - t.ok(orgSetArgs.opts.log, 'got passed a logger') t.match( orgSetArgs, { @@ -149,7 +150,6 @@ t.test('npm org add - more users', async t => { }) await org.exec(['add', 'orgname', 'username']) - t.ok(orgSetArgs.opts.log, 'got passed a logger') t.match( orgSetArgs, { @@ -177,7 +177,6 @@ t.test('npm org add - json output', async t => { await org.exec(['add', 'orgname', 'username']) - t.ok(orgSetArgs.opts.log, 'got passed a logger') t.match( orgSetArgs, { @@ -212,7 +211,6 @@ t.test('npm org add - parseable output', async t => { await org.exec(['add', 'orgname', 'username']) - t.ok(orgSetArgs.opts.log, 'got passed a logger') t.match( orgSetArgs, { @@ -234,16 +232,15 @@ t.test('npm org add - parseable output', async t => { }) t.test('npm org add - silent output', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') t.teardown(() => { - npm.flatOptions.silent = false + npm.config.set('loglevel', 'info') orgSetArgs = null output.length = 0 }) await org.exec(['add', 'orgname', 'username']) - t.ok(orgSetArgs.opts.log, 'got passed a logger') t.match( orgSetArgs, { @@ -266,7 +263,6 @@ t.test('npm org rm', async t => { await org.exec(['rm', 'orgname', 'username']) - t.ok(orgRmArgs.opts.log, 'got passed a logger') t.match( orgRmArgs, { @@ -276,7 +272,6 @@ t.test('npm org rm', async t => { }, 'libnpmorg.rm received the correct args' ) - t.ok(orgLsArgs.opts.log, 'got passed a logger') t.match( orgLsArgs, { @@ -330,7 +325,6 @@ t.test('npm org rm - one user left', async t => { await org.exec(['rm', 'orgname', 'username']) - t.ok(orgRmArgs.opts.log, 'got passed a logger') t.match( orgRmArgs, { @@ -340,7 +334,6 @@ t.test('npm org rm - one user left', async t => { }, 'libnpmorg.rm received the correct args' ) - t.ok(orgLsArgs.opts.log, 'got passed a logger') t.match( orgLsArgs, { @@ -367,7 +360,6 @@ t.test('npm org rm - json output', async t => { await org.exec(['rm', 'orgname', 'username']) - t.ok(orgRmArgs.opts.log, 'got passed a logger') t.match( orgRmArgs, { @@ -377,7 +369,6 @@ t.test('npm org rm - json output', async t => { }, 'libnpmorg.rm received the correct args' ) - t.ok(orgLsArgs.opts.log, 'got passed a logger') t.match( orgLsArgs, { @@ -409,7 +400,6 @@ t.test('npm org rm - parseable output', async t => { await org.exec(['rm', 'orgname', 'username']) - t.ok(orgRmArgs.opts.log, 'got passed a logger') t.match( orgRmArgs, { @@ -419,7 +409,6 @@ t.test('npm org rm - parseable output', async t => { }, 'libnpmorg.rm received the correct args' ) - t.ok(orgLsArgs.opts.log, 'got passed a logger') t.match( orgLsArgs, { @@ -439,9 +428,9 @@ t.test('npm org rm - parseable output', async t => { }) t.test('npm org rm - silent output', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') t.teardown(() => { - npm.flatOptions.silent = false + npm.config.set('loglevel', 'info') orgRmArgs = null orgLsArgs = null output.length = 0 @@ -449,7 +438,6 @@ t.test('npm org rm - silent output', async t => { await org.exec(['rm', 'orgname', 'username']) - t.ok(orgRmArgs.opts.log, 'got passed a logger') t.match( orgRmArgs, { @@ -459,7 +447,6 @@ t.test('npm org rm - silent output', async t => { }, 'libnpmorg.rm received the correct args' ) - t.ok(orgLsArgs.opts.log, 'got passed a logger') t.match( orgLsArgs, { @@ -485,7 +472,6 @@ t.test('npm org ls', async t => { await org.exec(['ls', 'orgname']) - t.ok(orgLsArgs.opts.log, 'got passed a logger') t.match( orgLsArgs, { @@ -513,7 +499,6 @@ t.test('npm org ls - user filter', async t => { await org.exec(['ls', 'orgname', 'username']) - t.ok(orgLsArgs.opts.log, 'got passed a logger') t.match( orgLsArgs, { @@ -539,7 +524,6 @@ t.test('npm org ls - user filter, missing user', async t => { await org.exec(['ls', 'orgname', 'username']) - t.ok(orgLsArgs.opts.log, 'got passed a logger') t.match( orgLsArgs, { @@ -578,7 +562,6 @@ t.test('npm org ls - json output', async t => { await org.exec(['ls', 'orgname']) - t.ok(orgLsArgs.opts.log, 'got passed a logger') t.match( orgLsArgs, { @@ -606,7 +589,6 @@ t.test('npm org ls - parseable output', async t => { await org.exec(['ls', 'orgname']) - t.ok(orgLsArgs.opts.log, 'got passed a logger') t.match( orgLsArgs, { @@ -628,14 +610,14 @@ t.test('npm org ls - parseable output', async t => { }) t.test('npm org ls - silent output', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') orgList = { one: 'developer', two: 'admin', three: 'owner', } t.teardown(() => { - npm.flatOptions.silent = false + npm.config.set('loglevel', 'info') orgList = {} orgLsArgs = null output.length = 0 @@ -643,7 +625,6 @@ t.test('npm org ls - silent output', async t => { await org.exec(['ls', 'orgname']) - t.ok(orgLsArgs.opts.log, 'got passed a logger') t.match( orgLsArgs, { diff --git a/test/lib/commands/owner.js b/test/lib/commands/owner.js index a32a3df9b7dde..b5d4d1584289d 100644 --- a/test/lib/commands/owner.js +++ b/test/lib/commands/owner.js @@ -51,14 +51,13 @@ t.test('owner no args', async t => { }) t.test('owner ls no args', async t => { - t.plan(5) + t.plan(4) result = '' readPackageNameResponse = '@npmcli/map-workspaces' pacote.packument = async (spec, opts) => { t.equal(spec.name, '@npmcli/map-workspaces', 'should use expect pkg name') - t.ok(opts.log, 'is passed a logger') t.match( opts, { @@ -173,11 +172,10 @@ t.test('owner ls no maintainers', async t => { }) t.test('owner add ', async t => { - t.plan(11) + t.plan(8) result = '' npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:foo') { t.ok('should request user info') @@ -218,7 +216,6 @@ t.test('owner add ', async t => { } } pacote.packument = async (spec, opts) => { - t.ok(opts.log, 'is passed a logger') t.equal(spec.name, '@npmcli/map-workspaces', 'should use expect pkg name') t.match( opts, @@ -247,7 +244,6 @@ t.test('owner add cwd package', async t => { result = '' readPackageNameResponse = '@npmcli/map-workspaces' npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:foo') { return { @@ -277,7 +273,7 @@ t.test('owner add cwd package', async t => { }) t.test('owner add already an owner', async t => { - t.plan(3) + t.plan(2) result = '' log.info = (title, msg) => { @@ -289,7 +285,6 @@ t.test('owner add already an owner', async t => { ) } npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:ruyadorno') { return { @@ -321,7 +316,6 @@ t.test('owner add fails to retrieve user', async t => { result = '' readPackageNameResponse = npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') // retrieve borked user info from couchdb request if (uri === '/-/user/org.couchdb.user:foo') { return { ok: false } @@ -352,7 +346,6 @@ t.test('owner add fails to retrieve user', async t => { t.test('owner add fails to PUT updates', async t => { result = '' npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:foo') { return { @@ -389,7 +382,7 @@ t.test('owner add fails to PUT updates', async t => { }) t.test('owner add fails to retrieve user info', async t => { - t.plan(4) + t.plan(3) result = '' log.error = (title, msg) => { @@ -397,7 +390,6 @@ t.test('owner add fails to retrieve user info', async t => { t.equal(msg, 'Error getting user data for foo') } npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:foo') { throw Object.assign( @@ -429,7 +421,6 @@ t.test('owner add fails to retrieve user info', async t => { t.test('owner add no previous maintainers property from server', async t => { result = '' npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:foo') { return { @@ -496,11 +487,10 @@ t.test('owner add no cwd package', async t => { }) t.test('owner rm ', async t => { - t.plan(11) + t.plan(8) result = '' npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:ruyadorno') { t.ok('should request user info') @@ -534,7 +524,6 @@ t.test('owner rm ', async t => { } } pacote.packument = async (spec, opts) => { - t.ok(opts.log, 'is passed a logger') t.equal(spec.name, '@npmcli/map-workspaces', 'should use expect pkg name') t.match( opts, @@ -560,7 +549,7 @@ t.test('owner rm ', async t => { }) t.test('owner rm not a current owner', async t => { - t.plan(3) + t.plan(2) result = '' log.info = (title, msg) => { @@ -568,7 +557,6 @@ t.test('owner rm not a current owner', async t => { t.equal(msg, 'Not a package owner: foo', 'should log.info not a package owner msg') } npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:foo') { return { @@ -602,7 +590,6 @@ t.test('owner rm cwd package', async t => { result = '' readPackageNameResponse = '@npmcli/map-workspaces' npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:ruyadorno') { return { @@ -635,7 +622,6 @@ t.test('owner rm only user', async t => { result = '' readPackageNameResponse = 'ipt' npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:ruyadorno') { return { diff --git a/test/lib/commands/ping.js b/test/lib/commands/ping.js index 19ba9d586b763..f808e0ac3ba2a 100644 --- a/test/lib/commands/ping.js +++ b/test/lib/commands/ping.js @@ -2,13 +2,12 @@ const t = require('tap') const { fake: mockNpm } = require('../../fixtures/mock-npm') t.test('pings', async t => { - t.plan(7) + t.plan(6) const registry = 'https://registry.npmjs.org' let noticeCalls = 0 const Ping = t.mock('../../../lib/commands/ping.js', { '../../../lib/utils/ping.js': function (spec) { - t.ok(spec.log, 'is passed a logger') t.equal(spec.registry, registry, 'passes flatOptions') return {} }, @@ -36,14 +35,13 @@ t.test('pings', async t => { }) t.test('pings and logs details', async t => { - t.plan(9) + t.plan(8) const registry = 'https://registry.npmjs.org' const details = { extra: 'data' } let noticeCalls = 0 const Ping = t.mock('../../../lib/commands/ping.js', { '../../../lib/utils/ping.js': function (spec) { - t.ok(spec.log, 'is passed a logger') t.equal(spec.registry, registry, 'passes flatOptions') return details }, @@ -75,14 +73,13 @@ t.test('pings and logs details', async t => { }) t.test('pings and returns json', async t => { - t.plan(10) + t.plan(9) const registry = 'https://registry.npmjs.org' const details = { extra: 'data' } let noticeCalls = 0 const Ping = t.mock('../../../lib/commands/ping.js', { '../../../lib/utils/ping.js': function (spec) { - t.ok(spec.log, 'is passed a logger') t.equal(spec.registry, registry, 'passes flatOptions') return details }, diff --git a/test/lib/commands/publish.js b/test/lib/commands/publish.js index 52d4c1b342908..0a7f961bfbdc9 100644 --- a/test/lib/commands/publish.js +++ b/test/lib/commands/publish.js @@ -1,15 +1,6 @@ const t = require('tap') const { fake: mockNpm } = require('../../fixtures/mock-npm') const fs = require('fs') -const log = require('../../../lib/utils/log-shim') - -// The way we set loglevel is kind of convoluted, and there is no way to affect -// it from these tests, which only interact with lib/publish.js, which assumes -// that the code that is requiring and calling lib/publish.js has already -// taken care of the loglevel -const _level = log.level -t.beforeEach(() => (log.level = 'silent')) -t.teardown(() => (log.level = _level)) t.cleanSnapshot = data => { return data.replace(/^ *"gitHead": .*$\n/gm, '') @@ -25,7 +16,7 @@ t.test( /* eslint-disable-next-line max-len */ 'should publish with libnpmpublish, passing through flatOptions and respecting publishConfig.registry', async t => { - t.plan(7) + t.plan(6) const registry = 'https://some.registry' const publishConfig = { registry } @@ -59,7 +50,6 @@ t.test( t.match(manifest, { name: 'my-cool-pkg', version: '1.0.0' }, 'gets manifest') t.type(tarData, Buffer, 'tarData is a buffer') t.ok(opts, 'gets opts object') - t.ok(opts.log, 'gets passed a logger') t.same(opts.customValue, true, 'flatOptions values are passed through') t.same(opts.registry, registry, 'publishConfig.registry is passed through') }, @@ -82,7 +72,7 @@ t.test( ) t.test('re-loads publishConfig.registry if added during script process', async t => { - t.plan(6) + t.plan(5) const registry = 'https://some.registry' const publishConfig = { registry } const testDir = t.testdir({ @@ -113,7 +103,6 @@ t.test('re-loads publishConfig.registry if added during script process', async t t.match(manifest, { name: 'my-cool-pkg', version: '1.0.0' }, 'gets manifest') t.type(tarData, Buffer, 'tarData is a buffer') t.ok(opts, 'gets opts object') - t.ok(opts.log, 'gets passed a logger') t.same(opts.registry, registry, 'publishConfig.registry is passed through') }, }, @@ -142,7 +131,6 @@ t.test('if loglevel=info and json, should not output package contents', async t ), }) - log.level = 'info' const Publish = t.mock('../../../lib/commands/publish.js', { '../../../lib/utils/tar.js': { getContents: () => ({ @@ -159,11 +147,11 @@ t.test('if loglevel=info and json, should not output package contents', async t }, }) const npm = mockNpm({ - config: { json: true }, + config: { json: true, loglevel: 'info' }, output: () => { t.pass('output is called') }, - }) + }, t) npm.config.getCredentialsByURI = uri => { t.same(uri, npm.config.get('registry'), 'gets credentials for expected registry') return { token: 'some.registry.token' } @@ -206,11 +194,11 @@ t.test( }, }) const npm = mockNpm({ - config: { 'dry-run': true }, + config: { 'dry-run': true, loglevel: 'silent' }, output: () => { throw new Error('should not output in dry run mode') }, - }) + }, t) npm.config.getCredentialsByURI = () => { throw new Error('should not call getCredentialsByURI in dry run') } @@ -238,7 +226,6 @@ t.test( ), }) - log.level = 'info' const Publish = t.mock('../../../lib/commands/publish.js', { '../../../lib/utils/tar.js': { getContents: () => ({ @@ -255,11 +242,11 @@ t.test( }, }) const npm = mockNpm({ - config: { 'dry-run': true }, + config: { 'dry-run': true, loglevel: 'info' }, output: () => { t.pass('output fn is called') }, - }) + }, t) npm.config.getCredentialsByURI = () => { throw new Error('should not call getCredentialsByURI in dry run') } @@ -294,7 +281,7 @@ t.test('throws when invalid tag', async t => { }) t.test('can publish a tarball', async t => { - t.plan(4) + t.plan(3) const testDir = t.testdir({ tarball: {}, @@ -319,7 +306,6 @@ t.test('can publish a tarball', async t => { const Publish = t.mock('../../../lib/commands/publish.js', { libnpmpublish: { publish: (manifest, tarData, opts) => { - t.ok(opts.log, 'gets passed a logger') t.match( manifest, { @@ -415,7 +401,7 @@ t.test('should check auth for scope specific registry', async t => { }) t.test('should use auth for scope specific registry', async t => { - t.plan(4) + t.plan(3) const registry = 'https://some.registry' const testDir = t.testdir({ 'package.json': JSON.stringify( @@ -432,7 +418,6 @@ t.test('should use auth for scope specific registry', async t => { libnpmpublish: { publish: (manifest, tarData, opts) => { t.ok(opts, 'gets opts object') - t.ok(opts.log, 'gets passed a logger') t.same(opts['@npm:registry'], registry, 'scope specific registry is passed through') }, }, @@ -450,7 +435,7 @@ t.test('should use auth for scope specific registry', async t => { }) t.test('read registry only from publishConfig', async t => { - t.plan(4) + t.plan(3) const registry = 'https://some.registry' const publishConfig = { registry } @@ -469,7 +454,6 @@ t.test('read registry only from publishConfig', async t => { const Publish = t.mock('../../../lib/commands/publish.js', { libnpmpublish: { publish: (manifest, tarData, opts) => { - t.ok(opts.log, 'gets passed a logger') t.match(manifest, { name: 'my-cool-pkg', version: '1.0.0' }, 'gets manifest') t.same(opts.registry, registry, 'publishConfig is passed through') }, @@ -486,7 +470,7 @@ t.test('read registry only from publishConfig', async t => { }) t.test('able to publish after if encountered multiple configs', async t => { - t.plan(3) + t.plan(2) const registry = 'https://some.registry' const tag = 'better-tag' @@ -515,7 +499,6 @@ t.test('able to publish after if encountered multiple configs', async t => { const Publish = t.mock('../../../lib/commands/publish.js', { libnpmpublish: { publish: (manifest, tarData, opts) => { - t.ok(opts.log, 'gets passed a logger') t.same(opts.defaultTag, tag, 'gets option for expected tag') }, }, @@ -526,6 +509,7 @@ t.test('able to publish after if encountered multiple configs', async t => { defaultTag: 'better-tag', registry: 'https://other.registry', }, + output () {}, config: { get: key => configList[0][key], list: configList, @@ -604,14 +588,12 @@ t.test('workspaces', t => { const publish = new Publish(npm) t.test('all workspaces', async t => { - log.level = 'info' await publish.execWorkspaces([], []) t.matchSnapshot(publishes, 'should publish all workspaces') t.matchSnapshot(outputs, 'should output all publishes') }) t.test('one workspace', async t => { - log.level = 'info' await publish.execWorkspaces([], ['workspace-a']) t.matchSnapshot(publishes, 'should publish given workspace') t.matchSnapshot(outputs, 'should output one publish') @@ -623,7 +605,6 @@ t.test('workspaces', t => { }) t.test('json', async t => { - log.level = 'info' npm.config.set('json', true) await publish.execWorkspaces([], []) t.matchSnapshot(publishes, 'should publish all workspaces') @@ -680,10 +661,11 @@ t.test('private workspaces', async t => { }, } const npm = mockNpm({ + config: { loglevel: 'info' }, output: o => { outputs.push(o) }, - }) + }, t) npm.localPrefix = testDir npm.config.getCredentialsByURI = uri => { return { token: 'some.registry.token' } @@ -692,7 +674,6 @@ t.test('private workspaces', async t => { t.test('with color', async t => { t.plan(4) - log.level = 'info' const Publish = t.mock('../../../lib/commands/publish.js', { ...mocks, 'proc-log': { @@ -721,7 +702,6 @@ t.test('private workspaces', async t => { t.test('colorless', async t => { t.plan(4) - log.level = 'info' const Publish = t.mock('../../../lib/commands/publish.js', { ...mocks, 'proc-log': { @@ -754,7 +734,6 @@ t.test('private workspaces', async t => { if (manifest.private) { throw new Error('ERR') } - t.ok(opts.log, 'gets passed a logger') publishes.push(manifest) }, }, @@ -794,7 +773,6 @@ t.test('runs correct lifecycle scripts', async t => { }) const scripts = [] - log.level = 'info' const Publish = t.mock('../../../lib/commands/publish.js', { '@npmcli/run-script': args => { scripts.push(args) @@ -814,10 +792,11 @@ t.test('runs correct lifecycle scripts', async t => { }, }) const npm = mockNpm({ + config: { loglevel: 'info' }, output: () => { t.pass('output is called') }, - }) + }, t) npm.config.getCredentialsByURI = uri => { t.same(uri, npm.config.get('registry'), 'gets credentials for expected registry') return { token: 'some.registry.token' } @@ -845,7 +824,6 @@ t.test('does not run scripts on --ignore-scripts', async t => { ), }) - log.level = 'info' const Publish = t.mock('../../../lib/commands/publish.js', { '@npmcli/run-script': () => { t.fail('should not call run-script') @@ -865,11 +843,11 @@ t.test('does not run scripts on --ignore-scripts', async t => { }, }) const npm = mockNpm({ - config: { 'ignore-scripts': true }, + config: { 'ignore-scripts': true, loglevel: 'info' }, output: () => { t.pass('output is called') }, - }) + }, t) npm.config.getCredentialsByURI = uri => { t.same(uri, npm.config.get('registry'), 'gets credentials for expected registry') return { token: 'some.registry.token' } diff --git a/test/lib/commands/run-script.js b/test/lib/commands/run-script.js index ea0227cda08ca..834b61e7474c4 100644 --- a/test/lib/commands/run-script.js +++ b/test/lib/commands/run-script.js @@ -10,10 +10,12 @@ const RUN_SCRIPTS = [] const flatOptions = { scriptShell: undefined, } +const defaultLoglevel = 'info' const config = { json: false, parseable: false, 'if-present': false, + loglevel: defaultLoglevel, } const npm = mockNpm({ @@ -26,20 +28,21 @@ const npm = mockNpm({ output: (...msg) => output.push(msg), }) -const output = [] - -const npmlog = { - disableProgress: () => null, - level: 'warn', +const setLoglevel = (t, level) => { + npm.config.set('loglevel', level) + t.teardown(() => { + npm.config.set('loglevel', defaultLoglevel) + }) } +const output = [] + const log = { error: () => null, } t.afterEach(() => { npm.color = false - npmlog.level = 'warn' log.error = () => null output.length = 0 RUN_SCRIPTS.length = 0 @@ -58,7 +61,6 @@ const getRS = windows => { isServerPackage: require('@npmcli/run-script').isServerPackage, } ), - npmlog, 'proc-log': log, '../../../lib/utils/is-windows-shell.js': windows, }) @@ -359,10 +361,7 @@ t.test('skip pre/post hooks when using ignoreScripts', async t => { }) t.test('run silent', async t => { - npmlog.level = 'silent' - t.teardown(() => { - npmlog.level = 'warn' - }) + setLoglevel(t, 'silent') npm.localPrefix = t.testdir({ 'package.json': JSON.stringify({ @@ -440,12 +439,11 @@ t.test('list scripts', t => { }) t.test('silent', async t => { - npmlog.level = 'silent' + setLoglevel(t, 'silent') await runScript.exec([]) t.strictSame(output, []) }) t.test('warn json', async t => { - npmlog.level = 'warn' config.json = true await runScript.exec([]) t.strictSame(output, [[JSON.stringify(scripts, 0, 2)]], 'json report') @@ -723,7 +721,7 @@ t.test('workspaces', t => { }) t.test('list no scripts --loglevel=silent', async t => { - npmlog.level = 'silent' + setLoglevel(t, 'silent') await runScript.execWorkspaces([], []) t.strictSame(output, []) }) @@ -860,7 +858,6 @@ t.test('workspaces', t => { '@npmcli/run-script': () => { throw new Error('err') }, - npmlog, 'proc-log': log, '../../../lib/utils/is-windows-shell.js': false, }) @@ -879,7 +876,6 @@ t.test('workspaces', t => { RUN_SCRIPTS.push(opts) }, - npmlog, 'proc-log': log, '../../../lib/utils/is-windows-shell.js': false, }) diff --git a/test/lib/commands/star.js b/test/lib/commands/star.js index 2f4ddc9dc6439..4d19b32e1d258 100644 --- a/test/lib/commands/star.js +++ b/test/lib/commands/star.js @@ -42,10 +42,9 @@ t.test('no args', async t => { }) t.test('star a package', async t => { - t.plan(6) + t.plan(4) const pkgName = '@npmcli/arborist' npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') return { _id: pkgName, _rev: 'hash', @@ -70,11 +69,10 @@ t.test('star a package', async t => { }) t.test('unstar a package', async t => { - t.plan(6) + t.plan(4) const pkgName = '@npmcli/arborist' config['star.unstar'] = true npmFetch.json = async (uri, opts) => { - t.ok(opts.log, 'is passed a logger') return { _id: pkgName, _rev: 'hash', diff --git a/test/lib/commands/team.js b/test/lib/commands/team.js index 96260835fa2b6..0d5378b530647 100644 --- a/test/lib/commands/team.js +++ b/test/lib/commands/team.js @@ -1,4 +1,5 @@ const t = require('tap') +const { fake: mockNpm } = require('../../fixtures/mock-npm') let result = '' const libnpmteam = { @@ -9,12 +10,15 @@ const libnpmteam = { async lsUsers () {}, async rm () {}, } -const npm = { +const npm = mockNpm({ flatOptions: {}, + config: { + loglevel: 'info', + }, output: (...msg) => { result += msg.join('\n') }, -} +}) const mocks = { libnpmteam, 'cli-columns': a => a.join(' '), @@ -25,6 +29,7 @@ const mocks = { t.afterEach(() => { result = '' npm.flatOptions = {} + npm.config.set('loglevel', 'info') }) const Team = t.mock('../../../lib/commands/team.js', mocks) @@ -73,7 +78,7 @@ t.test('team add ', async t => { }) t.test('--silent', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') await team.exec(['add', '@npmcli:developers', 'foo']) @@ -115,7 +120,7 @@ t.test('team create ', async t => { }) t.test('--silent', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') await team.exec(['create', '@npmcli:newteam']) @@ -149,7 +154,7 @@ t.test('team destroy ', async t => { }) t.test('--silent', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') await team.exec(['destroy', '@npmcli:newteam']) t.same(result, '', 'should not output destroy if silent') }) @@ -198,7 +203,7 @@ t.test('team ls ', async t => { }) t.test('--silent', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') await team.exec(['ls', '@npmcli']) t.same(result, '', 'should not list teams if silent') }) @@ -278,7 +283,7 @@ t.test('team ls ', async t => { }) t.test('--silent', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') await team.exec(['ls', '@npmcli:developers']) t.same(result, '', 'should not output users if silent') }) @@ -345,7 +350,7 @@ t.test('team rm ', async t => { }) t.test('--silent', async t => { - npm.flatOptions.silent = true + npm.config.set('loglevel', 'silent') await team.exec(['rm', '@npmcli:newteam', 'foo']) t.same(result, '', 'should not output rm result if silent') }) diff --git a/test/lib/commands/unpublish.js b/test/lib/commands/unpublish.js index 99d55294fbacf..b9c94e5d5265f 100644 --- a/test/lib/commands/unpublish.js +++ b/test/lib/commands/unpublish.js @@ -22,7 +22,6 @@ const singleVersion = async () => { const config = { force: false, - loglevel: 'silly', } const testDir = t.testdir({ @@ -54,7 +53,7 @@ t.afterEach(() => { result = '' config['dry-run'] = false config.force = false - config.loglevel = 'silly' + npm.config.set('loglevel', 'info') }) t.test('no args --force', async t => { @@ -76,7 +75,6 @@ t.test('no args --force', async t => { const libnpmpublish = { unpublish (spec, opts) { - t.ok(opts.log, 'gets passed a logger') t.equal(spec.raw, 'pkg@1.0.0', 'should unpublish expected spec') t.match( opts, @@ -178,7 +176,6 @@ t.test('unpublish @version', async t => { const libnpmpublish = { unpublish (spec, opts) { - t.ok(opts.log, 'gets passed a logger') t.equal(spec.raw, 'pkg@1.0.0', 'should unpublish expected parsed spec') }, } @@ -240,7 +237,7 @@ t.test('unpublish --force no version set', async t => { }) t.test('silent', async t => { - config.loglevel = 'silent' + npm.config.set('loglevel', 'silent') const Unpublish = t.mock('../../../lib/commands/unpublish.js', { ...mocks, diff --git a/test/lib/commands/update.js b/test/lib/commands/update.js index 2b464bfabbfcd..ae9376466128a 100644 --- a/test/lib/commands/update.js +++ b/test/lib/commands/update.js @@ -27,7 +27,7 @@ t.afterEach(() => { }) t.test('no args', async t => { - t.plan(5) + t.plan(4) npm.prefix = '/project/a' @@ -44,7 +44,6 @@ t.test('no args', async t => { }, 'should call arborist contructor with expected args' ) - t.match(log, {}, 'log is passed in') } reify ({ save, update }) { @@ -66,7 +65,7 @@ t.test('no args', async t => { }) t.test('with args', async t => { - t.plan(5) + t.plan(4) npm.prefix = '/project/a' config.save = true @@ -84,7 +83,6 @@ t.test('with args', async t => { }, 'should call arborist contructor with expected args' ) - t.match(log, {}, 'log is passed in') } reify ({ save, update }) { @@ -130,7 +128,7 @@ t.test('update --depth=', async t => { }) t.test('update --global', async t => { - t.plan(3) + t.plan(2) const normalizePath = p => p.replace(/\\+/g, '/') const redactCwd = (path) => normalizePath(path) @@ -149,8 +147,6 @@ t.test('update --global', async t => { 'should call arborist contructor with expected options' ) - t.match(log, {}, 'log is passed in') - t.equal( redactCwd(path), '{CWD}/global/lib', diff --git a/test/lib/utils/config/definitions.js b/test/lib/utils/config/definitions.js index bf4b48709ae7b..a5b34a7499fbe 100644 --- a/test/lib/utils/config/definitions.js +++ b/test/lib/utils/config/definitions.js @@ -929,3 +929,12 @@ t.test('lockfile version', t => { t.match(flat.lockfileVersion, 3, 'flattens to a number') t.end() }) + +t.test('loglevel silent', t => { + const flat = {} + definitions.loglevel.flatten('loglevel', { + loglevel: 'silent', + }, flat) + t.match(flat.silent, true, 'flattens to assign silent') + t.end() +}) diff --git a/test/lib/utils/exit-handler.js b/test/lib/utils/exit-handler.js index 54bf48f89b0dd..6a96d92ddb250 100644 --- a/test/lib/utils/exit-handler.js +++ b/test/lib/utils/exit-handler.js @@ -89,9 +89,9 @@ const mockExitHandler = async (t, { init, load, testdir, config } = {}) => { ...rest, errors, npm, - // // Make it async to make testing ergonomics a little - // // easier so we dont need to t.plan() every test to - // // make sure we get process.exit called + // Make it async to make testing ergonomics a little + // easier so we dont need to t.plan() every test to + // make sure we get process.exit called exitHandler: (...args) => new Promise(resolve => { process.once('exit', resolve) exitHandler(...args) diff --git a/test/lib/utils/reify-output.js b/test/lib/utils/reify-output.js index 4e9ed7133c18c..b38a14de33909 100644 --- a/test/lib/utils/reify-output.js +++ b/test/lib/utils/reify-output.js @@ -1,9 +1,4 @@ const t = require('tap') -const log = require('../../../lib/utils/log-shim') - -const _level = log.level -t.beforeEach(() => log.level = 'warn') -t.teardown(() => log.level = _level) t.cleanSnapshot = str => str.replace(/in [0-9]+m?s/g, 'in {TIME}') @@ -13,6 +8,7 @@ const settings = { const npm = { started: Date.now(), flatOptions: settings, + silent: false, } const reifyOutput = require('../../../lib/utils/reify-output.js') t.test('missing info', (t) => { @@ -236,10 +232,13 @@ t.test('showing and not showing audit report', async t => { } t.test('no output when silent', t => { + t.teardown(() => { + delete npm.silent + }) + npm.silent = true npm.output = out => { t.fail('should not get output when silent', { actual: out }) } - log.level = 'silent' reifyOutput(npm, { actualTree: { inventory: { size: 999 }, children: [] }, auditReport, diff --git a/test/lib/utils/update-notifier.js b/test/lib/utils/update-notifier.js index a7a800c602fd6..fa4af29476f12 100644 --- a/test/lib/utils/update-notifier.js +++ b/test/lib/utils/update-notifier.js @@ -84,12 +84,11 @@ t.afterEach(() => { }) const runUpdateNotifier = async ({ color = true, ...npmOptions } = {}) => { - const _npm = { ...defaultNpm, ...npmOptions } + const _npm = { ...defaultNpm, ...npmOptions, logColor: color } await t.mock('../../../lib/utils/update-notifier.js', { '@npmcli/ci-detect': () => ciMock, pacote, fs, - npmlog: { useColor: () => color }, })(_npm) return _npm.updateNotification }