diff options
Diffstat (limited to 'test/lib/commands')
43 files changed, 1162 insertions, 1202 deletions
diff --git a/test/lib/commands/access.js b/test/lib/commands/access.js index fdf132aff..298897e4f 100644 --- a/test/lib/commands/access.js +++ b/test/lib/commands/access.js @@ -1,18 +1,9 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm.js') - -const { Npm } = mockNpm(t) -const npm = new Npm() - -const prefix = t.testdir({}) - -t.before(async () => { - await npm.load() - npm.prefix = prefix -}) +const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') t.test('completion', async t => { + const { npm } = await loadMockNpm(t) const access = await npm.cmd('access') const testComp = (argv, expect) => { const res = access.completion({ conf: { argv: { remain: argv } } }) @@ -42,6 +33,7 @@ t.test('completion', async t => { }) t.test('subcommand required', async t => { + const { npm } = await loadMockNpm(t) const access = await npm.cmd('access') await t.rejects( npm.exec('access', []), @@ -50,6 +42,7 @@ t.test('subcommand required', async t => { }) t.test('unrecognized subcommand', async t => { + const { npm } = await loadMockNpm(t) await t.rejects( npm.exec('access', ['blerg']), /Usage: blerg is not a recognized subcommand/, @@ -58,6 +51,7 @@ t.test('unrecognized subcommand', async t => { }) t.test('edit', async t => { + const { npm } = await loadMockNpm(t) await t.rejects( npm.exec('access', ['edit', '@scoped/another']), /edit subcommand is not implemented yet/, @@ -66,15 +60,13 @@ t.test('edit', async t => { }) t.test('access public on unscoped package', async t => { - t.teardown(() => { - npm.prefix = prefix - }) - const testdir = t.testdir({ - 'package.json': JSON.stringify({ - name: 'npm-access-public-pkg', - }), + const { npm } = await loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify({ + name: 'npm-access-public-pkg', + }), + }, }) - npm.prefix = testdir await t.rejects( npm.exec('access', ['public']), /Usage: This command is only available for scoped packages/, @@ -84,30 +76,30 @@ t.test('access public on unscoped package', async t => { t.test('access public on scoped package', async t => { t.plan(2) - const { Npm } = mockNpm(t, { - libnpmaccess: { - public: (pkg, { registry }) => { - t.equal(pkg, name, 'should use pkg name ref') - t.equal( - registry, - 'https://registry.npmjs.org/', - 'should forward correct options' - ) - return true + const name = '@scoped/npm-access-public-pkg' + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmaccess: { + public: (pkg, { registry }) => { + t.equal(pkg, name, 'should use pkg name ref') + t.equal( + registry, + 'https://registry.npmjs.org/', + 'should forward correct options' + ) + return true + }, }, }, + testdir: { + 'package.json': JSON.stringify({ name }), + }, }) - const npm = new Npm() - await npm.load() - const name = '@scoped/npm-access-public-pkg' - const testdir = t.testdir({ - 'package.json': JSON.stringify({ name }), - }) - npm.prefix = testdir await npm.exec('access', ['public']) }) t.test('access public on missing package.json', async t => { + const { npm } = await loadMockNpm(t) await t.rejects( npm.exec('access', ['public']), /no package name passed to command and no package.json found/, @@ -116,14 +108,12 @@ t.test('access public on missing package.json', async t => { }) t.test('access public on invalid package.json', async t => { - t.teardown(() => { - npm.prefix = prefix - }) - const testdir = t.testdir({ - 'package.json': '{\n', - node_modules: {}, + const { npm } = await loadMockNpm(t, { + testdir: { + 'package.json': '{\n', + node_modules: {}, + }, }) - npm.prefix = testdir await t.rejects( npm.exec('access', ['public']), { code: 'EJSONPARSE' }, @@ -132,15 +122,13 @@ t.test('access public on invalid package.json', async t => { }) t.test('access restricted on unscoped package', async t => { - t.teardown(() => { - npm.prefix = prefix - }) - const testdir = t.testdir({ - 'package.json': JSON.stringify({ - name: 'npm-access-restricted-pkg', - }), + const { npm } = await loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify({ + name: 'npm-access-restricted-pkg', + }), + }, }) - npm.prefix = testdir await t.rejects( npm.exec('access', ['public']), /Usage: This command is only available for scoped packages/, @@ -150,30 +138,30 @@ t.test('access restricted on unscoped package', async t => { t.test('access restricted on scoped package', async t => { t.plan(2) - const { Npm } = mockNpm(t, { - libnpmaccess: { - restricted: (pkg, { registry }) => { - t.equal(pkg, name, 'should use pkg name ref') - t.equal( - registry, - 'https://registry.npmjs.org/', - 'should forward correct options' - ) - return true + const name = '@scoped/npm-access-restricted-pkg' + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmaccess: { + restricted: (pkg, { registry }) => { + t.equal(pkg, name, 'should use pkg name ref') + t.equal( + registry, + 'https://registry.npmjs.org/', + 'should forward correct options' + ) + return true + }, }, }, + testdir: { + 'package.json': JSON.stringify({ name }), + }, }) - const npm = new Npm() - await npm.load() - const name = '@scoped/npm-access-restricted-pkg' - const testdir = t.testdir({ - 'package.json': JSON.stringify({ name }), - }) - npm.prefix = testdir await npm.exec('access', ['restricted']) }) t.test('access restricted on missing package.json', async t => { + const { npm } = await loadMockNpm(t) await t.rejects( npm.exec('access', ['restricted']), /no package name passed to command and no package.json found/, @@ -182,14 +170,12 @@ t.test('access restricted on missing package.json', async t => { }) t.test('access restricted on invalid package.json', async t => { - t.teardown(() => { - npm.prefix = prefix - }) - const testdir = t.testdir({ - 'package.json': '{\n', - node_modules: {}, + const { npm } = await loadMockNpm(t, { + testdir: { + 'package.json': '{\n', + node_modules: {}, + }, }) - npm.prefix = testdir await t.rejects( npm.exec('access', ['restricted']), { code: 'EJSONPARSE' }, @@ -199,17 +185,18 @@ t.test('access restricted on invalid package.json', async t => { t.test('access grant read-only', async t => { t.plan(3) - const { Npm } = mockNpm(t, { - libnpmaccess: { - grant: (spec, team, permissions) => { - t.equal(spec, '@scoped/another', 'should use expected spec') - t.equal(team, 'myorg:myteam', 'should use expected team') - t.equal(permissions, 'read-only', 'should forward permissions') - return true + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmaccess: { + grant: (spec, team, permissions) => { + t.equal(spec, '@scoped/another', 'should use expected spec') + t.equal(team, 'myorg:myteam', 'should use expected team') + t.equal(permissions, 'read-only', 'should forward permissions') + return true + }, }, }, }) - const npm = new Npm() await npm.exec('access', [ 'grant', 'read-only', @@ -220,17 +207,18 @@ t.test('access grant read-only', async t => { t.test('access grant read-write', async t => { t.plan(3) - const { Npm } = mockNpm(t, { - libnpmaccess: { - grant: (spec, team, permissions) => { - t.equal(spec, '@scoped/another', 'should use expected spec') - t.equal(team, 'myorg:myteam', 'should use expected team') - t.equal(permissions, 'read-write', 'should forward permissions') - return true + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmaccess: { + grant: (spec, team, permissions) => { + t.equal(spec, '@scoped/another', 'should use expected spec') + t.equal(team, 'myorg:myteam', 'should use expected team') + t.equal(permissions, 'read-write', 'should forward permissions') + return true + }, }, }, }) - const npm = new Npm() await npm.exec('access', [ 'grant', 'read-write', @@ -241,24 +229,23 @@ t.test('access grant read-write', async t => { t.test('access grant current cwd', async t => { t.plan(3) - const testdir = t.testdir({ - 'package.json': JSON.stringify({ - name: 'yargs', - }), - }) - const { Npm } = mockNpm(t, { - libnpmaccess: { - grant: (spec, team, permissions) => { - t.equal(spec, 'yargs', 'should use expected spec') - t.equal(team, 'myorg:myteam', 'should use expected team') - t.equal(permissions, 'read-write', 'should forward permissions') - return true + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmaccess: { + grant: (spec, team, permissions) => { + t.equal(spec, 'yargs', 'should use expected spec') + t.equal(team, 'myorg:myteam', 'should use expected team') + t.equal(permissions, 'read-write', 'should forward permissions') + return true + }, }, }, + testdir: { + 'package.json': JSON.stringify({ + name: 'yargs', + }), + }, }) - const npm = new Npm() - await npm.load() - npm.prefix = testdir await npm.exec('access', [ 'grant', 'read-write', @@ -267,6 +254,7 @@ t.test('access grant current cwd', async t => { }) t.test('access grant others', async t => { + const { npm } = await loadMockNpm(t) await t.rejects( npm.exec('access', [ 'grant', @@ -280,6 +268,7 @@ t.test('access grant others', async t => { }) t.test('access grant missing team args', async t => { + const { npm } = await loadMockNpm(t) await t.rejects( npm.exec('access', [ 'grant', @@ -293,6 +282,7 @@ t.test('access grant missing team args', async t => { }) t.test('access grant malformed team arg', async t => { + const { npm } = await loadMockNpm(t) await t.rejects( npm.exec('access', [ 'grant', @@ -307,36 +297,37 @@ t.test('access grant malformed team arg', async t => { t.test('access 2fa-required/2fa-not-required', async t => { t.plan(2) - const { Npm } = mockNpm(t, { - libnpmaccess: { - tfaRequired: (spec) => { - t.equal(spec, '@scope/pkg', 'should use expected spec') - return true - }, - tfaNotRequired: (spec) => { - t.equal(spec, 'unscoped-pkg', 'should use expected spec') - return true + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmaccess: { + tfaRequired: (spec) => { + t.equal(spec, '@scope/pkg', 'should use expected spec') + return true + }, + tfaNotRequired: (spec) => { + t.equal(spec, 'unscoped-pkg', 'should use expected spec') + return true + }, }, }, }) - const npm = new Npm() - await npm.exec('access', ['2fa-required', '@scope/pkg']) await npm.exec('access', ['2fa-not-required', 'unscoped-pkg']) }) t.test('access revoke', async t => { t.plan(2) - const { Npm } = mockNpm(t, { - libnpmaccess: { - revoke: (spec, team) => { - t.equal(spec, '@scoped/another', 'should use expected spec') - t.equal(team, 'myorg:myteam', 'should use expected team') - return true + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmaccess: { + revoke: (spec, team) => { + t.equal(spec, '@scoped/another', 'should use expected spec') + t.equal(team, 'myorg:myteam', 'should use expected team') + return true + }, }, }, }) - const npm = new Npm() await npm.exec('access', [ 'revoke', 'myorg:myteam', @@ -345,6 +336,7 @@ t.test('access revoke', async t => { }) t.test('access revoke missing team args', async t => { + const { npm } = await loadMockNpm(t) await t.rejects( npm.exec('access', [ 'revoke', @@ -357,6 +349,7 @@ t.test('access revoke missing team args', async t => { }) t.test('access revoke malformed team arg', async t => { + const { npm } = await loadMockNpm(t) await t.rejects( npm.exec('access', [ 'revoke', @@ -370,30 +363,32 @@ t.test('access revoke malformed team arg', async t => { t.test('npm access ls-packages with no team', async t => { t.plan(1) - const { Npm } = mockNpm(t, { - libnpmaccess: { - lsPackages: (entity) => { - t.equal(entity, 'foo', 'should use expected entity') - return {} + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmaccess: { + lsPackages: (entity) => { + t.equal(entity, 'foo', 'should use expected entity') + return {} + }, }, + '../../lib/utils/get-identity.js': () => Promise.resolve('foo'), }, - '../../lib/utils/get-identity.js': () => Promise.resolve('foo'), }) - const npm = new Npm() await npm.exec('access', ['ls-packages']) }) t.test('access ls-packages on team', async t => { t.plan(1) - const { Npm } = mockNpm(t, { - libnpmaccess: { - lsPackages: (entity) => { - t.equal(entity, 'myorg:myteam', 'should use expected entity') - return {} + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmaccess: { + lsPackages: (entity) => { + t.equal(entity, 'myorg:myteam', 'should use expected entity') + return {} + }, }, }, }) - const npm = new Npm() await npm.exec('access', [ 'ls-packages', 'myorg:myteam', @@ -402,36 +397,36 @@ t.test('access ls-packages on team', async t => { t.test('access ls-collaborators on current', async t => { t.plan(1) - const testdir = t.testdir({ - 'package.json': JSON.stringify({ - name: 'yargs', - }), - }) - const { Npm } = mockNpm(t, { - libnpmaccess: { - lsCollaborators: (spec) => { - t.equal(spec, 'yargs', 'should use expected spec') - return {} + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmaccess: { + lsCollaborators: (spec) => { + t.equal(spec, 'yargs', 'should use expected spec') + return {} + }, }, }, + testdir: { + 'package.json': JSON.stringify({ + name: 'yargs', + }), + }, }) - const npm = new Npm() - await npm.load() - npm.prefix = testdir await npm.exec('access', ['ls-collaborators']) }) t.test('access ls-collaborators on spec', async t => { t.plan(1) - const { Npm } = mockNpm(t, { - libnpmaccess: { - lsCollaborators: (spec) => { - t.equal(spec, 'yargs', 'should use expected spec') - return {} + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmaccess: { + lsCollaborators: (spec) => { + t.equal(spec, 'yargs', 'should use expected spec') + return {} + }, }, }, }) - const npm = new Npm() await npm.exec('access', [ 'ls-collaborators', 'yargs', diff --git a/test/lib/commands/adduser.js b/test/lib/commands/adduser.js index 71d79ea93..8a9358f9a 100644 --- a/test/lib/commands/adduser.js +++ b/test/lib/commands/adduser.js @@ -20,6 +20,13 @@ 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: { @@ -71,6 +78,8 @@ const AddUser = t.mock('../../../lib/commands/adduser.js', { npmlog: { clearProgress: () => null, disableProgress: () => null, + }, + 'proc-log': { notice: (_, msg) => { registryOutput = msg }, diff --git a/test/lib/commands/audit.js b/test/lib/commands/audit.js index 3c87c76a8..05f268d6b 100644 --- a/test/lib/commands/audit.js +++ b/test/lib/commands/audit.js @@ -1,5 +1,5 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: _loadMockNpm } = require('../../fixtures/mock-npm') t.test('should audit using Arborist', async t => { let ARB_ARGS = null @@ -8,36 +8,35 @@ t.test('should audit using Arborist', async t => { let AUDIT_REPORT_CALLED = false let ARB_OBJ = null - const { Npm, outputs } = mockNpm(t, { - 'npm-audit-report': () => { - AUDIT_REPORT_CALLED = true - return { - report: 'there are vulnerabilities', - exitCode: 0, - } - }, - '@npmcli/arborist': function (args) { - ARB_ARGS = args - ARB_OBJ = this - this.audit = () => { - AUDIT_CALLED = true - this.auditReport = {} - } - }, - '../../lib/utils/reify-finish.js': (npm, arb) => { - if (arb !== ARB_OBJ) { - throw new Error('got wrong object passed to reify-output') - } + const loadMockNpm = (t) => _loadMockNpm(t, { + mocks: { + 'npm-audit-report': () => { + AUDIT_REPORT_CALLED = true + return { + report: 'there are vulnerabilities', + exitCode: 0, + } + }, + '@npmcli/arborist': function (args) { + ARB_ARGS = args + ARB_OBJ = this + this.audit = () => { + AUDIT_CALLED = true + this.auditReport = {} + } + }, + '../../lib/utils/reify-finish.js': (npm, arb) => { + if (arb !== ARB_OBJ) { + throw new Error('got wrong object passed to reify-output') + } - REIFY_FINISH_CALLED = true + REIFY_FINISH_CALLED = true + }, }, }) - const npm = new Npm() - await npm.load() - npm.prefix = t.testdir() - t.test('audit', async t => { + const { npm, outputs } = await loadMockNpm(t) await npm.exec('audit', []) t.match(ARB_ARGS, { audit: true, path: npm.prefix }) t.equal(AUDIT_CALLED, true, 'called audit') @@ -46,6 +45,7 @@ t.test('should audit using Arborist', async t => { }) t.test('audit fix', async t => { + const { npm } = await loadMockNpm(t) await npm.exec('audit', ['fix']) t.equal(REIFY_FINISH_CALLED, true, 'called reify output') }) @@ -53,69 +53,67 @@ t.test('should audit using Arborist', async t => { t.test('should audit - json', async t => { t.plan(1) - const { Npm } = mockNpm(t, { - 'npm-audit-report': (_, opts) => { - t.match(opts.reporter, 'json') - return { - report: 'there are vulnerabilities', - exitCode: 0, - } + const { npm } = await _loadMockNpm(t, { + mocks: { + 'npm-audit-report': (_, opts) => { + t.match(opts.reporter, 'json') + return { + report: 'there are vulnerabilities', + exitCode: 0, + } + }, + '@npmcli/arborist': function () { + this.audit = () => { + this.auditReport = {} + } + }, + '../../lib/utils/reify-output.js': () => {}, }, - '@npmcli/arborist': function () { - this.audit = () => { - this.auditReport = {} - } + config: { + json: true, }, - '../../lib/utils/reify-output.js': () => {}, }) - const npm = new Npm() - await npm.load() - npm.prefix = t.testdir() - npm.config.set('json', true) await npm.exec('audit', []) }) t.test('report endpoint error', async t => { - const { Npm, outputs, filteredLogs } = mockNpm(t, { - 'npm-audit-report': () => { - throw new Error('should not call audit report when there are errors') - }, - '@npmcli/arborist': function () { - this.audit = () => { - this.auditReport = { - error: { - message: 'hello, this didnt work', - method: 'POST', - uri: 'https://example.com/', - headers: { - head: ['ers'], + const loadMockNpm = (t, options) => _loadMockNpm(t, { + mocks: { + 'npm-audit-report': () => { + throw new Error('should not call audit report when there are errors') + }, + '@npmcli/arborist': function () { + this.audit = () => { + this.auditReport = { + error: { + message: 'hello, this didnt work', + method: 'POST', + uri: 'https://example.com/', + headers: { + head: ['ers'], + }, + statusCode: 420, + body: 'this is a string', }, - statusCode: 420, - body: 'this is a string', - // body: json ? { nope: 'lol' } : Buffer.from('i had a vuln but i eated it lol'), - }, + } } - } + }, + '../../lib/utils/reify-output.js': () => {}, }, - '../../lib/utils/reify-output.js': () => {}, + ...options, }) - const npm = new Npm() - await npm.load() - npm.prefix = t.testdir() - // npm.config.set('json', ) + t.test('json=false', async t => { + const { npm, outputs, logs } = await loadMockNpm(t, { config: { json: false } }) await t.rejects(npm.exec('audit', []), 'audit endpoint returned an error') - t.match(filteredLogs('warn'), ['hello, this didnt work']) + t.match(logs.warn, [['audit', 'hello, this didnt work']]) t.strictSame(outputs, [['this is a string']]) }) t.test('json=true', async t => { - t.teardown(() => { - npm.config.set('json', false) - }) - npm.config.set('json', true) + const { npm, outputs, logs } = await loadMockNpm(t, { config: { json: true } }) await t.rejects(npm.exec('audit', []), 'audit endpoint returned an error') - t.match(filteredLogs('warn'), ['hello, this didnt work']) + t.match(logs.warn, [['audit', 'hello, this didnt work']]) t.strictSame(outputs, [[ '{\n' + ' "message": "hello, this didnt work",\n' + @@ -135,8 +133,7 @@ t.test('report endpoint error', async t => { }) t.test('completion', async t => { - const { Npm } = mockNpm(t) - const npm = new Npm() + const { npm } = await _loadMockNpm(t) const audit = await npm.cmd('audit') t.test('fix', async t => { await t.resolveMatch( diff --git a/test/lib/commands/birthday.js b/test/lib/commands/birthday.js index 8c95dd57b..9156d3df0 100644 --- a/test/lib/commands/birthday.js +++ b/test/lib/commands/birthday.js @@ -1,14 +1,15 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') t.test('birthday', async t => { t.plan(2) - const { Npm } = mockNpm(t, { - libnpmexec: ({ args, yes }) => { - t.ok(yes) - t.match(args, ['@npmcli/npm-birthday']) + const { npm } = await loadMockNpm(t, { + mocks: { + libnpmexec: ({ args, yes }) => { + t.ok(yes) + t.match(args, ['@npmcli/npm-birthday']) + }, }, }) - const npm = new Npm() await npm.exec('birthday', []) }) diff --git a/test/lib/commands/cache.js b/test/lib/commands/cache.js index 70a8ba1b2..fc92facff 100644 --- a/test/lib/commands/cache.js +++ b/test/lib/commands/cache.js @@ -12,11 +12,6 @@ const rimraf = (path, cb) => { } let logOutput = [] -const npmlog = { - silly: (...args) => { - logOutput.push(['silly', ...args]) - }, -} let tarballStreamSpec = '' let tarballStreamOpts = {} @@ -141,9 +136,16 @@ const cacache = { const Cache = t.mock('../../../lib/commands/cache.js', { cacache, - npmlog, pacote, rimraf, + 'proc-log': { + silly: (...args) => { + logOutput.push(['silly', ...args]) + }, + warn: (...args) => { + logOutput.push(['warn', ...args]) + }, + }, }) const npm = mockNpm({ @@ -153,11 +155,6 @@ const npm = mockNpm({ output: (msg) => { outputOutput.push(msg) }, - log: { - warn: (...args) => { - logOutput.push(['warn', ...args]) - }, - }, }) const cache = new Cache(npm) diff --git a/test/lib/commands/ci.js b/test/lib/commands/ci.js index 1091f9125..537d0784f 100644 --- a/test/lib/commands/ci.js +++ b/test/lib/commands/ci.js @@ -159,7 +159,7 @@ t.test('should throw if package-lock.json or npm-shrinkwrap missing', async t => const CI = t.mock('../../../lib/commands/ci.js', { '@npmcli/run-script': opts => {}, '../../../lib/utils/reify-finish.js': async () => {}, - npmlog: { + 'proc-log': { verbose: () => { t.ok(true, 'log fn called') }, diff --git a/test/lib/commands/completion.js b/test/lib/commands/completion.js index 51212f06d..dd571baf7 100644 --- a/test/lib/commands/completion.js +++ b/test/lib/commands/completion.js @@ -6,189 +6,153 @@ const completionScript = fs .readFileSync(path.resolve(__dirname, '../../../lib/utils/completion.sh'), { encoding: 'utf8' }) .replace(/^#!.*?\n/, '') -const { real: mockNpm } = require('../../fixtures/mock-npm') - -const { Npm, outputs } = mockNpm(t, { - '../../lib/utils/is-windows-shell.js': false, -}) -const npm = new Npm() +const { load: _loadMockNpm } = require('../../fixtures/mock-npm') +const mockGlobals = require('../../fixtures/mock-globals') + +const loadMockCompletion = async (t, o = {}) => { + const { globals, windows, ...options } = o + let resetGlobals = {} + if (globals) { + resetGlobals = mockGlobals(t, globals).reset + } + const res = await _loadMockNpm(t, { + mocks: { + '../../lib/utils/is-windows-shell.js': !!windows, + ...options.mocks, + }, + ...options, + }) + const completion = await res.npm.cmd('completion') + return { + resetGlobals, + completion, + ...res, + } +} + +const loadMockCompletionComp = async (t, word, line) => + loadMockCompletion(t, { + globals: { + 'process.env.COMP_CWORD': word, + 'process.env.COMP_LINE': line, + 'process.env.COMP_POINT': line.length, + }, + }) t.test('completion', async t => { - const completion = await npm.cmd('completion') t.test('completion completion', async t => { - const home = process.env.HOME - t.teardown(() => { - process.env.HOME = home - }) - - process.env.HOME = t.testdir({ - '.bashrc': '', - '.zshrc': '', + const { outputs, completion, prefix } = await loadMockCompletion(t, { + testdir: { + '.bashrc': 'aaa', + '.zshrc': 'aaa', + }, }) + mockGlobals(t, { 'process.env.HOME': prefix }) await completion.completion({ w: 2 }) t.matchSnapshot(outputs, 'both shells') }) t.test('completion completion no known shells', async t => { - const home = process.env.HOME - t.teardown(() => { - process.env.HOME = home - }) - - process.env.HOME = t.testdir() + const { outputs, completion, prefix } = await loadMockCompletion(t) + mockGlobals(t, { 'process.env.HOME': prefix }) await completion.completion({ w: 2 }) t.matchSnapshot(outputs, 'no responses') }) t.test('completion completion wrong word count', async t => { + const { outputs, completion } = await loadMockCompletion(t) + await completion.completion({ w: 3 }) t.matchSnapshot(outputs, 'no responses') }) t.test('dump script when completion is not being attempted', async t => { - const _write = process.stdout.write - const _on = process.stdout.on - t.teardown(() => { - process.stdout.write = _write - process.stdout.on = _on + let errorHandler, data + const { completion, resetGlobals } = await loadMockCompletion(t, { + globals: { + 'process.stdout.on': (event, handler) => { + errorHandler = handler + resetGlobals['process.stdout.on']() + }, + 'process.stdout.write': (chunk, callback) => { + data = chunk + process.nextTick(() => { + callback() + errorHandler({ errno: 'EPIPE' }) + }) + resetGlobals['process.stdout.write']() + }, + }, }) - let errorHandler - process.stdout.on = (event, handler) => { - errorHandler = handler - process.stdout.on = _on - } - - let data - process.stdout.write = (chunk, callback) => { - data = chunk - process.stdout.write = _write - process.nextTick(() => { - callback() - errorHandler({ errno: 'EPIPE' }) - }) - } - await completion.exec({}) - t.equal(data, completionScript, 'wrote the completion script') }) t.test('dump script exits correctly when EPIPE is emitted on stdout', async t => { - const _write = process.stdout.write - const _on = process.stdout.on - t.teardown(() => { - process.stdout.write = _write - process.stdout.on = _on + let errorHandler, data + const { completion, resetGlobals } = await loadMockCompletion(t, { + globals: { + 'process.stdout.on': (event, handler) => { + if (event === 'error') { + errorHandler = handler + } + resetGlobals['process.stdout.on']() + }, + 'process.stdout.write': (chunk, callback) => { + data = chunk + process.nextTick(() => { + errorHandler({ errno: 'EPIPE' }) + callback() + }) + resetGlobals['process.stdout.write']() + }, + }, }) - let errorHandler - process.stdout.on = (event, handler) => { - errorHandler = handler - process.stdout.on = _on - } - - let data - process.stdout.write = (chunk, callback) => { - data = chunk - process.stdout.write = _write - process.nextTick(() => { - errorHandler({ errno: 'EPIPE' }) - callback() - }) - } - await completion.exec({}) t.equal(data, completionScript, 'wrote the completion script') }) t.test('single command name', async t => { - process.env.COMP_CWORD = 1 - process.env.COMP_LINE = 'npm conf' - process.env.COMP_POINT = process.env.COMP_LINE.length - - t.teardown(() => { - delete process.env.COMP_CWORD - delete process.env.COMP_LINE - delete process.env.COMP_POINT - }) + const { outputs, completion } = await loadMockCompletionComp(t, 1, 'npm conf') await completion.exec(['npm', 'conf']) t.matchSnapshot(outputs, 'single command name') }) t.test('multiple command names', async t => { - process.env.COMP_CWORD = 1 - process.env.COMP_LINE = 'npm a' - process.env.COMP_POINT = process.env.COMP_LINE.length - - t.teardown(() => { - delete process.env.COMP_CWORD - delete process.env.COMP_LINE - delete process.env.COMP_POINT - }) + const { outputs, completion } = await loadMockCompletionComp(t, 1, 'npm a') await completion.exec(['npm', 'a']) t.matchSnapshot(outputs, 'multiple command names') }) t.test('completion of invalid command name does nothing', async t => { - process.env.COMP_CWORD = 1 - process.env.COMP_LINE = 'npm compute' - process.env.COMP_POINT = process.env.COMP_LINE.length - - t.teardown(() => { - delete process.env.COMP_CWORD - delete process.env.COMP_LINE - delete process.env.COMP_POINT - }) + const { outputs, completion } = await loadMockCompletionComp(t, 1, 'npm compute') await completion.exec(['npm', 'compute']) t.matchSnapshot(outputs, 'no results') }) t.test('subcommand completion', async t => { - process.env.COMP_CWORD = 2 - process.env.COMP_LINE = 'npm access ' - process.env.COMP_POINT = process.env.COMP_LINE.length - - t.teardown(() => { - delete process.env.COMP_CWORD - delete process.env.COMP_LINE - delete process.env.COMP_POINT - }) + const { outputs, completion } = await loadMockCompletionComp(t, 2, 'npm access ') await completion.exec(['npm', 'access', '']) t.matchSnapshot(outputs, 'subcommands') }) t.test('filtered subcommands', async t => { - process.env.COMP_CWORD = 2 - process.env.COMP_LINE = 'npm access p' - process.env.COMP_POINT = process.env.COMP_LINE.length - - t.teardown(() => { - delete process.env.COMP_CWORD - delete process.env.COMP_LINE - delete process.env.COMP_POINT - }) + const { outputs, completion } = await loadMockCompletionComp(t, 2, 'npm access p') await completion.exec(['npm', 'access', 'p']) t.matchSnapshot(outputs, 'filtered subcommands') }) t.test('commands with no completion', async t => { - process.env.COMP_CWORD = 2 - process.env.COMP_LINE = 'npm adduser ' - process.env.COMP_POINT = process.env.COMP_LINE.length - - t.teardown(() => { - delete process.env.COMP_CWORD - delete process.env.COMP_LINE - delete process.env.COMP_POINT - }) + const { outputs, completion } = await loadMockCompletionComp(t, 2, 'npm adduser ') // quotes around adduser are to ensure coverage when unescaping commands await completion.exec(['npm', "'adduser'", '']) @@ -196,63 +160,28 @@ t.test('completion', async t => { }) t.test('flags', async t => { - process.env.COMP_CWORD = 2 - process.env.COMP_LINE = 'npm install --v' - process.env.COMP_POINT = process.env.COMP_LINE.length - - t.teardown(() => { - delete process.env.COMP_CWORD - delete process.env.COMP_LINE - delete process.env.COMP_POINT - }) + const { outputs, completion } = await loadMockCompletionComp(t, 2, 'npm install --v') await completion.exec(['npm', 'install', '--v']) - t.matchSnapshot(outputs, 'flags') }) t.test('--no- flags', async t => { - process.env.COMP_CWORD = 2 - process.env.COMP_LINE = 'npm install --no-v' - process.env.COMP_POINT = process.env.COMP_LINE.length - - t.teardown(() => { - delete process.env.COMP_CWORD - delete process.env.COMP_LINE - delete process.env.COMP_POINT - }) + const { outputs, completion } = await loadMockCompletionComp(t, 2, 'npm install --no-v') await completion.exec(['npm', 'install', '--no-v']) - t.matchSnapshot(outputs, 'flags') }) t.test('double dashes escape from flag completion', async t => { - process.env.COMP_CWORD = 2 - process.env.COMP_LINE = 'npm -- install --' - process.env.COMP_POINT = process.env.COMP_LINE.length - - t.teardown(() => { - delete process.env.COMP_CWORD - delete process.env.COMP_LINE - delete process.env.COMP_POINT - }) + const { outputs, completion } = await loadMockCompletionComp(t, 2, 'npm -- install --') await completion.exec(['npm', '--', 'install', '--']) - t.matchSnapshot(outputs, 'full command list') }) t.test('completion cannot complete options that take a value in mid-command', async t => { - process.env.COMP_CWORD = 2 - process.env.COMP_LINE = 'npm --registry install' - process.env.COMP_POINT = process.env.COMP_LINE.length - - t.teardown(() => { - delete process.env.COMP_CWORD - delete process.env.COMP_LINE - delete process.env.COMP_POINT - }) + const { outputs, completion } = await loadMockCompletionComp(t, 2, 'npm --registry install') await completion.exec(['npm', '--registry', 'install']) t.matchSnapshot(outputs, 'does not try to complete option arguments in the middle of a command') @@ -260,11 +189,7 @@ t.test('completion', async t => { }) t.test('windows without bash', async t => { - const { Npm, outputs } = mockNpm(t, { - '../../lib/utils/is-windows-shell.js': true, - }) - const npm = new Npm() - const completion = await npm.cmd('completion') + const { outputs, completion } = await loadMockCompletion(t, { windows: true }) await t.rejects( completion.exec({}), { code: 'ENOTSUP', message: /completion supported only in MINGW/ }, diff --git a/test/lib/commands/dedupe.js b/test/lib/commands/dedupe.js index 8fc0be061..2e2fae238 100644 --- a/test/lib/commands/dedupe.js +++ b/test/lib/commands/dedupe.js @@ -1,11 +1,12 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') t.test('should throw in global mode', async (t) => { - const { Npm } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.config.set('global', true) + const { npm } = await loadMockNpm(t, { + config: { + global: true, + }, + }) t.rejects( npm.exec('dedupe', []), { code: 'EDEDUPEGLOBAL' }, @@ -15,39 +16,41 @@ t.test('should throw in global mode', async (t) => { t.test('should remove dupes using Arborist', async (t) => { t.plan(5) - const { Npm } = mockNpm(t, { - '@npmcli/arborist': function (args) { - t.ok(args, 'gets options object') - t.ok(args.path, 'gets path option') - t.ok(args.dryRun, 'gets dryRun from user') - this.dedupe = () => { - t.ok(true, 'dedupe is called') - } + const { npm } = await loadMockNpm(t, { + mocks: { + '@npmcli/arborist': function (args) { + t.ok(args, 'gets options object') + t.ok(args.path, 'gets path option') + t.ok(args.dryRun, 'gets dryRun from user') + this.dedupe = () => { + t.ok(true, 'dedupe is called') + } + }, + '../../lib/utils/reify-finish.js': (npm, arb) => { + t.ok(arb, 'gets arborist tree') + }, }, - '../../lib/utils/reify-finish.js': (npm, arb) => { - t.ok(arb, 'gets arborist tree') + config: { + 'dry-run': 'true', }, }) - const npm = new Npm() - await npm.load() - npm.config.set('prefix', 'foo') - npm.config.set('dry-run', 'true') await npm.exec('dedupe', []) }) t.test('should remove dupes using Arborist - no arguments', async (t) => { t.plan(1) - const { Npm } = mockNpm(t, { - '@npmcli/arborist': function (args) { - t.ok(args.dryRun, 'gets dryRun from config') - this.dedupe = () => {} + const { npm } = await loadMockNpm(t, { + mocks: { + '@npmcli/arborist': function (args) { + t.ok(args.dryRun, 'gets dryRun from config') + this.dedupe = () => {} + }, + '../../lib/utils/reify-output.js': () => {}, + '../../lib/utils/reify-finish.js': () => {}, + }, + config: { + 'dry-run': true, }, - '../../lib/utils/reify-output.js': () => {}, - '../../lib/utils/reify-finish.js': () => {}, }) - const npm = new Npm() - await npm.load() - npm.config.set('prefix', 'foo') - npm.config.set('dry-run', true) await npm.exec('dedupe', []) }) diff --git a/test/lib/commands/diff.js b/test/lib/commands/diff.js index 811936fe6..ed0702e37 100644 --- a/test/lib/commands/diff.js +++ b/test/lib/commands/diff.js @@ -31,7 +31,7 @@ const npm = mockNpm({ }) const mocks = { - npmlog: { info: noop, verbose: noop }, + 'proc-log': { info: noop, verbose: noop }, libnpmdiff: (...args) => libnpmdiff(...args), 'npm-registry-fetch': async () => ({}), '../../../lib/utils/usage.js': () => 'usage instructions', diff --git a/test/lib/commands/dist-tag.js b/test/lib/commands/dist-tag.js index 6b45dc116..756a09d7d 100644 --- a/test/lib/commands/dist-tag.js +++ b/test/lib/commands/dist-tag.js @@ -61,7 +61,7 @@ const logger = (...msgs) => { } const DistTag = t.mock('../../../lib/commands/dist-tag.js', { - npmlog: { + 'proc-log': { error: logger, info: logger, verbose: logger, diff --git a/test/lib/commands/doctor.js b/test/lib/commands/doctor.js index e3ad5cc72..51b6111a0 100644 --- a/test/lib/commands/doctor.js +++ b/test/lib/commands/doctor.js @@ -50,13 +50,13 @@ const logs = { info: [], } -const clearLogs = (obj = logs) => { +const clearLogs = () => { output.length = 0 - for (const key in obj) { - if (Array.isArray(obj[key])) { - obj[key].length = 0 + for (const key in logs) { + if (Array.isArray(logs[key])) { + logs[key].length = 0 } else { - delete obj[key] + delete logs[key] } } } @@ -65,13 +65,41 @@ const npm = { flatOptions: { registry: 'https://registry.npmjs.org/', }, - log: { + version: '7.1.0', + output: data => { + output.push(data) + }, +} + +let latestNpm = npm.version +const pacote = { + manifest: async () => { + return { version: latestNpm } + }, +} + +let verifyResponse = { verifiedCount: 1, verifiedContent: 1 } +const cacache = { + verify: async () => { + return verifyResponse + }, +} + +const mocks = { + '../../../lib/utils/is-windows.js': false, + '../../../lib/utils/ping.js': ping, + cacache, + pacote, + 'make-fetch-happen': fetch, + which, + 'proc-log': { info: msg => { logs.info.push(msg) }, + }, + npmlog: { newItem: name => { logs[name] = {} - return { info: (_, msg) => { if (!logs[name].info) { @@ -109,33 +137,11 @@ const npm = { error: 0, }, }, - version: '7.1.0', - output: data => { - output.push(data) - }, -} -let latestNpm = npm.version -const pacote = { - manifest: async () => { - return { version: latestNpm } - }, -} - -let verifyResponse = { verifiedCount: 1, verifiedContent: 1 } -const cacache = { - verify: async () => { - return verifyResponse - }, } const Doctor = t.mock('../../../lib/commands/doctor.js', { - '../../../lib/utils/is-windows.js': false, - '../../../lib/utils/ping.js': ping, - cacache, - pacote, - 'make-fetch-happen': fetch, - which, + ...mocks, }) const doctor = new Doctor(npm) @@ -205,7 +211,7 @@ t.test('node versions', t => { npm.globalDir = dir npm.localBin = dir npm.globalBin = dir - npm.log.level = 'info' + mocks.npmlog.level = 'info' st.teardown(() => { delete npm.cache @@ -214,7 +220,7 @@ t.test('node versions', t => { delete npm.globalDir delete npm.localBin delete npm.globalBin - npm.log.level = 'error' + mocks.npmlog.level = 'error' clearLogs() }) @@ -293,12 +299,8 @@ t.test('node versions', t => { vt.test('npm doctor skips some tests in windows', async st => { const WinDoctor = t.mock('../../../lib/commands/doctor.js', { + ...mocks, '../../../lib/utils/is-windows.js': true, - '../../../lib/utils/ping.js': ping, - cacache, - pacote, - 'make-fetch-happen': fetch, - which, }) const winDoctor = new WinDoctor(npm) @@ -592,12 +594,7 @@ t.test('node versions', t => { } const Doctor = t.mock('../../../lib/commands/doctor.js', { - '../../../lib/utils/is-windows.js': false, - '../../../lib/utils/ping.js': ping, - cacache, - pacote, - 'make-fetch-happen': fetch, - which, + ...mocks, fs, }) const doctor = new Doctor(npm) diff --git a/test/lib/commands/exec.js b/test/lib/commands/exec.js index 4ab26568f..3c75c1d8d 100644 --- a/test/lib/commands/exec.js +++ b/test/lib/commands/exec.js @@ -44,17 +44,6 @@ const npm = mockNpm({ localPrefix: 'local-prefix', localBin: 'local-bin', globalBin: 'global-bin', - log: { - disableProgress: () => { - PROGRESS_ENABLED = false - }, - enableProgress: () => { - PROGRESS_ENABLED = true - }, - warn: (...args) => { - LOG_WARN.push(args) - }, - }, }) const RUN_SCRIPTS = [] @@ -87,6 +76,23 @@ const PATH = require('../../../lib/utils/path.js') let CI_NAME = 'travis-ci' +const log = { + 'proc-log': { + warn: (...args) => { + LOG_WARN.push(args) + }, + }, + npmlog: { + disableProgress: () => { + PROGRESS_ENABLED = false + }, + enableProgress: () => { + PROGRESS_ENABLED = true + }, + clearProgress: () => {}, + }, +} + const mocks = { libnpmexec: t.mock('libnpmexec', { '@npmcli/arborist': Arborist, @@ -95,7 +101,9 @@ const mocks = { pacote, read, 'mkdirp-infer-owner': mkdirp, + ...log, }), + ...log, } const Exec = t.mock('../../../lib/commands/exec.js', mocks) const exec = new Exec(npm) diff --git a/test/lib/commands/explore.js b/test/lib/commands/explore.js index b2e7be213..d1355d767 100644 --- a/test/lib/commands/explore.js +++ b/test/lib/commands/explore.js @@ -51,14 +51,17 @@ const getExplore = (windows) => { path: require('path')[windows ? 'win32' : 'posix'], 'read-package-json-fast': mockRPJ, '@npmcli/run-script': mockRunScript, - }) - const npm = { - dir: windows ? 'c:\\npm\\dir' : '/npm/dir', - log: { + 'proc-log': { error: (...msg) => logs.push(msg), + warn: () => {}, + }, + npmlog: { disableProgress: () => {}, enableProgress: () => {}, }, + }) + const npm = { + dir: windows ? 'c:\\npm\\dir' : '/npm/dir', flatOptions: { shell: 'shell-command', }, diff --git a/test/lib/commands/find-dupes.js b/test/lib/commands/find-dupes.js index c1b9c71df..06bd097b6 100644 --- a/test/lib/commands/find-dupes.js +++ b/test/lib/commands/find-dupes.js @@ -1,27 +1,28 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') t.test('should run dedupe in dryRun mode', async (t) => { t.plan(5) - const { Npm } = mockNpm(t, { - '@npmcli/arborist': function (args) { - t.ok(args, 'gets options object') - t.ok(args.path, 'gets path option') - t.ok(args.dryRun, 'is called in dryRun mode') - this.dedupe = () => { - t.ok(true, 'dedupe is called') - } + const { npm } = await loadMockNpm(t, { + mocks: { + '@npmcli/arborist': function (args) { + t.ok(args, 'gets options object') + t.ok(args.path, 'gets path option') + t.ok(args.dryRun, 'is called in dryRun mode') + this.dedupe = () => { + t.ok(true, 'dedupe is called') + } + }, + '../../lib/utils/reify-finish.js': (npm, arb) => { + t.ok(arb, 'gets arborist tree') + }, }, - '../../lib/utils/reify-finish.js': (npm, arb) => { - t.ok(arb, 'gets arborist tree') + config: { + // explicitly set to false so we can be 100% sure it's always true when it + // hits arborist + 'dry-run': false, }, }) - const npm = new Npm() - await npm.load() - // explicitly set to false so we can be 100% sure it's always true when it - // hits arborist - npm.config.set('dry-run', false) - npm.config.set('prefix', 'foo') await npm.exec('find-dupes', []) }) diff --git a/test/lib/commands/get.js b/test/lib/commands/get.js index ba9e770e3..597cccc3f 100644 --- a/test/lib/commands/get.js +++ b/test/lib/commands/get.js @@ -1,12 +1,10 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') t.test('should retrieve values from config', async t => { - const { joinedOutput, Npm } = mockNpm(t) - const npm = new Npm() + const { joinedOutput, npm } = await loadMockNpm(t) const name = 'editor' const value = 'vigor' - await npm.load() npm.config.set(name, value) await npm.exec('get', [name]) t.equal( diff --git a/test/lib/commands/init.js b/test/lib/commands/init.js index 74b33168a..215ebc581 100644 --- a/test/lib/commands/init.js +++ b/test/lib/commands/init.js @@ -3,14 +3,6 @@ const fs = require('fs') const { resolve } = require('path') const { fake: mockNpm } = require('../../fixtures/mock-npm') -const npmLog = { - disableProgress: () => null, - enableProgress: () => null, - info: () => null, - pause: () => null, - resume: () => null, - silly: () => null, -} const config = { cache: 'bad-cache-dir', 'init-module': '~/.npm-init.js', @@ -23,10 +15,19 @@ const flatOptions = { const npm = mockNpm({ flatOptions, config, - log: npmLog, }) const mocks = { '../../../lib/utils/usage.js': () => 'usage instructions', + npmlog: { + disableProgress: () => null, + enableProgress: () => null, + }, + 'proc-log': { + info: () => null, + pause: () => null, + resume: () => null, + silly: () => null, + }, } const Init = t.mock('../../../lib/commands/init.js', mocks) const init = new Init(npm) @@ -37,7 +38,6 @@ const noop = () => {} t.afterEach(() => { config.yes = true config.package = undefined - npm.log = npmLog process.chdir(_cwd) console.log = _consolelog }) @@ -251,13 +251,15 @@ t.test('npm init cancel', async t => { 'init-package-json': (dir, initFile, config, cb) => cb( new Error('canceled') ), + 'proc-log': { + ...mocks['proc-log'], + warn: (title, msg) => { + t.equal(title, 'init', 'should have init title') + t.equal(msg, 'canceled', 'should log canceled') + }, + }, }) const init = new Init(npm) - npm.log = { ...npm.log } - npm.log.warn = (title, msg) => { - t.equal(title, 'init', 'should have init title') - t.equal(msg, 'canceled', 'should log canceled') - } process.chdir(npm.localPrefix) await init.exec([]) diff --git a/test/lib/commands/install.js b/test/lib/commands/install.js index 994684596..d5db3af67 100644 --- a/test/lib/commands/install.js +++ b/test/lib/commands/install.js @@ -1,7 +1,10 @@ const t = require('tap') const path = require('path') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: _loadMockNpm } = require('../../fixtures/mock-npm') + +// Make less churn in the test to pass in mocks only signature +const loadMockNpm = (t, mocks) => _loadMockNpm(t, { mocks }) t.test('with args, dev=true', async t => { const SCRIPTS = [] @@ -9,7 +12,7 @@ t.test('with args, dev=true', async t => { let REIFY_CALLED = false let ARB_OBJ = null - const { Npm, filteredLogs } = mockNpm(t, { + const { npm, logs } = await loadMockNpm(t, { '@npmcli/run-script': ({ event }) => { SCRIPTS.push(event) }, @@ -27,8 +30,6 @@ t.test('with args, dev=true', async t => { }, }) - const npm = new Npm() - await npm.load() // This is here because CI calls tests with `--ignore-scripts`, which config // picks up from argv npm.config.set('ignore-scripts', false) @@ -41,8 +42,8 @@ t.test('with args, dev=true', async t => { await npm.exec('install', ['fizzbuzz']) t.match( - filteredLogs('warn'), - ['Usage of the `--dev` option is deprecated. Use `--include=dev` instead.'] + logs.warn, + [['install', 'Usage of the `--dev` option is deprecated. Use `--include=dev` instead.']] ) t.match( ARB_ARGS, @@ -59,7 +60,7 @@ t.test('without args', async t => { let REIFY_CALLED = false let ARB_OBJ = null - const { Npm } = mockNpm(t, { + const { npm } = await loadMockNpm(t, { '@npmcli/run-script': ({ event }) => { SCRIPTS.push(event) }, @@ -77,8 +78,6 @@ t.test('without args', async t => { }, }) - const npm = new Npm() - await npm.load() npm.prefix = path.resolve(t.testdir({})) npm.config.set('ignore-scripts', false) await npm.exec('install', []) @@ -98,7 +97,7 @@ t.test('without args', async t => { t.test('should ignore scripts with --ignore-scripts', async t => { const SCRIPTS = [] let REIFY_CALLED = false - const { Npm } = mockNpm(t, { + const { npm } = await loadMockNpm(t, { '../../lib/utils/reify-finish.js': async () => {}, '@npmcli/run-script': ({ event }) => { SCRIPTS.push(event) @@ -109,8 +108,6 @@ t.test('should ignore scripts with --ignore-scripts', async t => { } }, }) - const npm = new Npm() - await npm.load() npm.config.set('ignore-scripts', true) npm.prefix = path.resolve(t.testdir({})) await npm.exec('install', []) @@ -122,7 +119,7 @@ t.test('should install globally using Arborist', async t => { const SCRIPTS = [] let ARB_ARGS = null let REIFY_CALLED - const { Npm } = mockNpm(t, { + const { npm } = await loadMockNpm(t, { '@npmcli/run-script': ({ event }) => { SCRIPTS.push(event) }, @@ -134,8 +131,6 @@ t.test('should install globally using Arborist', async t => { } }, }) - const npm = new Npm() - await npm.load() npm.config.set('global', true) npm.globalPrefix = path.resolve(t.testdir({})) await npm.exec('install', []) @@ -148,7 +143,7 @@ t.test('should install globally using Arborist', async t => { }) t.test('npm i -g npm engines check success', async t => { - const { Npm } = mockNpm(t, { + const { npm } = await loadMockNpm(t, { '../../lib/utils/reify-finish.js': async () => {}, '@npmcli/arborist': function () { this.reify = () => {} @@ -164,8 +159,6 @@ t.test('npm i -g npm engines check success', async t => { }, }, }) - const npm = new Npm() - await npm.load() npm.globalDir = t.testdir({}) npm.config.set('global', true) await npm.exec('install', ['npm']) @@ -173,7 +166,7 @@ t.test('npm i -g npm engines check success', async t => { }) t.test('npm i -g npm engines check failure', async t => { - const { Npm } = mockNpm(t, { + const { npm } = await loadMockNpm(t, { pacote: { manifest: () => { return { @@ -186,8 +179,6 @@ t.test('npm i -g npm engines check failure', async t => { }, }, }) - const npm = new Npm() - await npm.load() npm.globalDir = t.testdir({}) npm.config.set('global', true) await t.rejects( @@ -208,7 +199,7 @@ t.test('npm i -g npm engines check failure', async t => { }) t.test('npm i -g npm engines check failure forced override', async t => { - const { Npm } = mockNpm(t, { + const { npm } = await loadMockNpm(t, { '../../lib/utils/reify-finish.js': async () => {}, '@npmcli/arborist': function () { this.reify = () => {} @@ -225,8 +216,6 @@ t.test('npm i -g npm engines check failure forced override', async t => { }, }, }) - const npm = new Npm() - await npm.load() npm.globalDir = t.testdir({}) npm.config.set('global', true) npm.config.set('force', true) @@ -235,7 +224,7 @@ t.test('npm i -g npm engines check failure forced override', async t => { }) t.test('npm i -g npm@version engines check failure', async t => { - const { Npm } = mockNpm(t, { + const { npm } = await loadMockNpm(t, { pacote: { manifest: () => { return { @@ -248,8 +237,6 @@ t.test('npm i -g npm@version engines check failure', async t => { }, }, }) - const npm = new Npm() - await npm.load() npm.globalDir = t.testdir({}) npm.config.set('global', true) await t.rejects( @@ -283,8 +270,7 @@ t.test('completion', async t => { }) t.test('completion to folder - has a match', async t => { - const { Npm } = mockNpm(t) - const npm = new Npm() + const { npm } = await _loadMockNpm(t, { load: false }) const install = await npm.cmd('install') process.chdir(testdir) const res = await install.completion({ partialWord: './ar' }) @@ -292,16 +278,14 @@ t.test('completion', async t => { }) t.test('completion to folder - invalid dir', async t => { - const { Npm } = mockNpm(t) - const npm = new Npm() + const { npm } = await _loadMockNpm(t, { load: false }) const install = await npm.cmd('install') const res = await install.completion({ partialWord: '/does/not/exist' }) t.strictSame(res, [], 'invalid dir: no matching') }) t.test('completion to folder - no matches', async t => { - const { Npm } = mockNpm(t) - const npm = new Npm() + const { npm } = await _loadMockNpm(t, { load: false }) const install = await npm.cmd('install') process.chdir(testdir) const res = await install.completion({ partialWord: './pa' }) @@ -309,8 +293,7 @@ t.test('completion', async t => { }) t.test('completion to folder - match is not a package', async t => { - const { Npm } = mockNpm(t) - const npm = new Npm() + const { npm } = await _loadMockNpm(t, { load: false }) const install = await npm.cmd('install') process.chdir(testdir) const res = await install.completion({ partialWord: './othe' }) @@ -318,8 +301,7 @@ t.test('completion', async t => { }) t.test('completion to url', async t => { - const { Npm } = mockNpm(t) - const npm = new Npm() + const { npm } = await _loadMockNpm(t, { load: false }) const install = await npm.cmd('install') process.chdir(testdir) const res = await install.completion({ partialWord: 'http://path/to/url' }) @@ -327,8 +309,7 @@ t.test('completion', async t => { }) t.test('no /', async t => { - const { Npm } = mockNpm(t) - const npm = new Npm() + const { npm } = await _loadMockNpm(t, { load: false }) const install = await npm.cmd('install') process.chdir(testdir) const res = await install.completion({ partialWord: 'toto' }) @@ -336,8 +317,7 @@ t.test('completion', async t => { }) t.test('only /', async t => { - const { Npm } = mockNpm(t) - const npm = new Npm() + const { npm } = await _loadMockNpm(t, { load: false }) const install = await npm.cmd('install') process.chdir(testdir) const res = await install.completion({ partialWord: '/' }) diff --git a/test/lib/commands/logout.js b/test/lib/commands/logout.js index 39ef86c84..ee01e7500 100644 --- a/test/lib/commands/logout.js +++ b/test/lib/commands/logout.js @@ -10,45 +10,31 @@ const flatOptions = { scope: '', } const npm = mockNpm({ config, flatOptions }) - -const npmlog = {} - let result = null -const npmFetch = (url, opts) => { - result = { url, opts } -} -const mocks = { - npmlog, - 'npm-registry-fetch': npmFetch, +const mockLogout = (otherMocks) => { + const Logout = t.mock('../../../lib/commands/logout.js', { + 'npm-registry-fetch': (url, opts) => { + result = { url, opts } + }, + ...otherMocks, + }) + return new Logout(npm) } -const Logout = t.mock('../../../lib/commands/logout.js', mocks) -const logout = new Logout(npm) +t.afterEach(() => { + delete flatOptions.token + result = null + config.clearCredentialsByURI = null + config.delete = null + config.save = null +}) t.test('token logout', async t => { - t.teardown(() => { - delete flatOptions.token - result = null - mocks['npm-registry-fetch'] = null - config.clearCredentialsByURI = null - config.delete = null - config.save = null - npmlog.verbose = null - }) t.plan(5) flatOptions['//registry.npmjs.org/:_authToken'] = '@foo/' - npmlog.verbose = (title, msg) => { - t.equal(title, 'logout', 'should have correcct log prefix') - t.equal( - msg, - 'clearing token for https://registry.npmjs.org/', - 'should log message with correct registry' - ) - } - npm.config.clearCredentialsByURI = registry => { t.equal( registry, @@ -61,6 +47,19 @@ t.test('token logout', async t => { t.equal(type, 'user', 'should save to user config') } + const logout = mockLogout({ + 'proc-log': { + verbose: (title, msg) => { + t.equal(title, 'logout', 'should have correcct log prefix') + t.equal( + msg, + 'clearing token for https://registry.npmjs.org/', + 'should log message with correct registry' + ) + }, + }, + }) + await logout.exec([]) t.same( @@ -87,12 +86,11 @@ t.test('token scoped logout', async t => { delete config['@myscope:registry'] delete flatOptions.scope result = null - mocks['npm-registry-fetch'] = null config.clearCredentialsByURI = null config.delete = null config.save = null - npmlog.verbose = null }) + t.plan(7) flatOptions['//diff-registry.npmjs.com/:_authToken'] = '@bar/' @@ -102,15 +100,6 @@ t.test('token scoped logout', async t => { flatOptions.scope = '@myscope' flatOptions['@myscope:registry'] = 'https://diff-registry.npmjs.com/' - npmlog.verbose = (title, msg) => { - t.equal(title, 'logout', 'should have correcct log prefix') - t.equal( - msg, - 'clearing token for https://diff-registry.npmjs.com/', - 'should log message with correct registry' - ) - } - npm.config.clearCredentialsByURI = registry => { t.equal( registry, @@ -128,6 +117,19 @@ t.test('token scoped logout', async t => { t.equal(type, 'user', 'should save to user config') } + const logout = mockLogout({ + 'proc-log': { + verbose: (title, msg) => { + t.equal(title, 'logout', 'should have correcct log prefix') + t.equal( + msg, + 'clearing token for https://diff-registry.npmjs.com/', + 'should log message with correct registry' + ) + }, + }, + }) + await logout.exec([]) t.same( @@ -154,29 +156,34 @@ t.test('user/pass logout', async t => { delete flatOptions['//registry.npmjs.org/:_password'] npm.config.clearCredentialsByURI = null npm.config.save = null - npmlog.verbose = null }) t.plan(2) flatOptions['//registry.npmjs.org/:username'] = 'foo' flatOptions['//registry.npmjs.org/:_password'] = 'bar' - npmlog.verbose = (title, msg) => { - t.equal(title, 'logout', 'should have correct log prefix') - t.equal( - msg, - 'clearing user credentials for https://registry.npmjs.org/', - 'should log message with correct registry' - ) - } - npm.config.clearCredentialsByURI = () => null npm.config.save = () => null + const logout = mockLogout({ + 'proc-log': { + verbose: (title, msg) => { + t.equal(title, 'logout', 'should have correct log prefix') + t.equal( + msg, + 'clearing user credentials for https://registry.npmjs.org/', + 'should log message with correct registry' + ) + }, + }, + }) + await logout.exec([]) }) t.test('missing credentials', async t => { + const logout = mockLogout() + await t.rejects( logout.exec([]), { @@ -191,11 +198,9 @@ t.test('ignore invalid scoped registry config', async t => { t.teardown(() => { delete flatOptions.token result = null - mocks['npm-registry-fetch'] = null config.clearCredentialsByURI = null config.delete = null config.save = null - npmlog.verbose = null }) t.plan(4) @@ -203,15 +208,6 @@ t.test('ignore invalid scoped registry config', async t => { config.scope = '@myscope' flatOptions['@myscope:registry'] = '' - npmlog.verbose = (title, msg) => { - t.equal(title, 'logout', 'should have correcct log prefix') - t.equal( - msg, - 'clearing token for https://registry.npmjs.org/', - 'should log message with correct registry' - ) - } - npm.config.clearCredentialsByURI = registry => { t.equal( registry, @@ -223,6 +219,19 @@ t.test('ignore invalid scoped registry config', async t => { npm.config.delete = () => null npm.config.save = () => null + const logout = mockLogout({ + 'proc-log': { + verbose: (title, msg) => { + t.equal(title, 'logout', 'should have correcct log prefix') + t.equal( + msg, + 'clearing token for https://registry.npmjs.org/', + 'should log message with correct registry' + ) + }, + }, + }) + await logout.exec([]) t.same( diff --git a/test/lib/commands/owner.js b/test/lib/commands/owner.js index 8645b349f..b5d4d1584 100644 --- a/test/lib/commands/owner.js +++ b/test/lib/commands/owner.js @@ -14,11 +14,11 @@ const npm = mockNpm({ }) const npmFetch = { json: noop } -const npmlog = { error: noop, info: noop, verbose: noop } +const log = { error: noop, info: noop, verbose: noop } const pacote = { packument: noop } const mocks = { - npmlog, + 'proc-log': log, 'npm-registry-fetch': npmFetch, pacote, '../../../lib/utils/otplease.js': async (opts, fn) => fn({ otp: '123456', opts }), @@ -97,7 +97,7 @@ t.test('owner ls no args no cwd package', async t => { result = '' t.teardown(() => { result = '' - npmlog.error = noop + log.error = noop }) await t.rejects( @@ -114,14 +114,14 @@ t.test('owner ls fails to retrieve packument', async t => { pacote.packument = () => { throw new Error('ERR') } - npmlog.error = (title, msg, pkgName) => { + log.error = (title, msg, pkgName) => { t.equal(title, 'owner ls', 'should list npm owner ls title') t.equal(msg, "Couldn't get owner data", 'should use expected msg') t.equal(pkgName, '@npmcli/map-workspaces', 'should use pkg name') } t.teardown(() => { result = '' - npmlog.error = noop + log.error = noop pacote.packument = noop }) @@ -276,7 +276,7 @@ t.test('owner add <user> <pkg> already an owner', async t => { t.plan(2) result = '' - npmlog.info = (title, msg) => { + log.info = (title, msg) => { t.equal(title, 'owner add', 'should use expected title') t.equal( msg, @@ -304,7 +304,7 @@ t.test('owner add <user> <pkg> already an owner', async t => { } t.teardown(() => { result = '' - npmlog.info = noop + log.info = noop npmFetch.json = noop pacote.packument = noop }) @@ -385,7 +385,7 @@ t.test('owner add <user> <pkg> fails to retrieve user info', async t => { t.plan(3) result = '' - npmlog.error = (title, msg) => { + log.error = (title, msg) => { t.equal(title, 'owner mutate', 'should use expected title') t.equal(msg, 'Error getting user data for foo') } @@ -406,7 +406,7 @@ t.test('owner add <user> <pkg> fails to retrieve user info', async t => { }) t.teardown(() => { result = '' - npmlog.error = noop + log.error = noop npmFetch.json = noop pacote.packument = noop }) @@ -552,7 +552,7 @@ t.test('owner rm <user> <pkg> not a current owner', async t => { t.plan(2) result = '' - npmlog.info = (title, msg) => { + log.info = (title, msg) => { t.equal(title, 'owner rm', 'should log expected title') t.equal(msg, 'Not a package owner: foo', 'should log.info not a package owner msg') } @@ -578,7 +578,7 @@ t.test('owner rm <user> <pkg> not a current owner', async t => { } t.teardown(() => { result = '' - npmlog.info = noop + log.info = noop npmFetch.json = noop pacote.packument = noop }) diff --git a/test/lib/commands/pack.js b/test/lib/commands/pack.js index bc8877208..21057e207 100644 --- a/test/lib/commands/pack.js +++ b/test/lib/commands/pack.js @@ -1,5 +1,5 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') const path = require('path') const fs = require('fs') @@ -9,33 +9,31 @@ t.afterEach(t => { }) t.test('should pack current directory with no arguments', async t => { - const { Npm, outputs, filteredLogs } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.prefix = t.testdir({ - 'package.json': JSON.stringify({ - name: 'test-package', - version: '1.0.0', - }), + const { npm, outputs, logs } = await loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify({ + name: 'test-package', + version: '1.0.0', + }), + }, }) process.chdir(npm.prefix) await npm.exec('pack', []) const filename = 'test-package-1.0.0.tgz' t.strictSame(outputs, [[filename]]) - t.matchSnapshot(filteredLogs('notice'), 'logs pack contents') + t.matchSnapshot(logs.notice.map(([, m]) => m), 'logs pack contents') t.ok(fs.statSync(path.resolve(npm.prefix, filename))) }) t.test('follows pack-destination config', async t => { - const { Npm, outputs } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.prefix = t.testdir({ - 'package.json': JSON.stringify({ - name: 'test-package', - version: '1.0.0', - }), - 'tar-destination': {}, + const { npm, outputs } = await loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify({ + name: 'test-package', + version: '1.0.0', + }), + 'tar-destination': {}, + }, }) process.chdir(npm.prefix) npm.config.set('pack-destination', path.join(npm.prefix, 'tar-destination')) @@ -46,14 +44,13 @@ t.test('follows pack-destination config', async t => { }) t.test('should pack given directory for scoped package', async t => { - const { Npm, outputs } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.prefix = t.testdir({ - 'package.json': JSON.stringify({ - name: '@npm/test-package', - version: '1.0.0', - }), + const { npm, outputs } = await loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify({ + name: '@npm/test-package', + version: '1.0.0', + }), + }, }) process.chdir(npm.prefix) await npm.exec('pack', []) @@ -63,49 +60,46 @@ t.test('should pack given directory for scoped package', async t => { }) t.test('should log output as valid json', async t => { - const { Npm, outputs, filteredLogs } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.prefix = t.testdir({ - 'package.json': JSON.stringify({ - name: 'test-package', - version: '1.0.0', - }), + const { npm, outputs, logs } = await loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify({ + name: 'test-package', + version: '1.0.0', + }), + }, }) process.chdir(npm.prefix) npm.config.set('json', true) await npm.exec('pack', []) const filename = 'test-package-1.0.0.tgz' t.matchSnapshot(outputs.map(JSON.parse), 'outputs as json') - t.matchSnapshot(filteredLogs('notice'), 'logs pack contents') + t.matchSnapshot(logs.notice.map(([, m]) => m), 'logs pack contents') t.ok(fs.statSync(path.resolve(npm.prefix, filename))) }) t.test('dry run', async t => { - const { Npm, outputs, filteredLogs } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.prefix = t.testdir({ - 'package.json': JSON.stringify({ - name: 'test-package', - version: '1.0.0', - }), + const { npm, outputs, logs } = await loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify({ + name: 'test-package', + version: '1.0.0', + }), + }, }) npm.config.set('dry-run', true) process.chdir(npm.prefix) await npm.exec('pack', []) const filename = 'test-package-1.0.0.tgz' t.strictSame(outputs, [[filename]]) - t.matchSnapshot(filteredLogs('notice'), 'logs pack contents') + t.matchSnapshot(logs.notice.map(([, m]) => m), 'logs pack contents') t.throws(() => fs.statSync(path.resolve(npm.prefix, filename))) }) t.test('invalid packument', async t => { - const { Npm, outputs } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.prefix = t.testdir({ - 'package.json': '{}', + const { npm, outputs } = await loadMockNpm(t, { + testdir: { + 'package.json': '{}', + }, }) process.chdir(npm.prefix) await t.rejects( @@ -116,52 +110,58 @@ t.test('invalid packument', async t => { }) t.test('workspaces', async t => { - const { Npm, outputs } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.prefix = t.testdir({ - 'package.json': JSON.stringify( - { - name: 'workspaces-test', - version: '1.0.0', - workspaces: ['workspace-a', 'workspace-b'], + const loadWorkspaces = (t) => loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify( + { + name: 'workspaces-test', + version: '1.0.0', + workspaces: ['workspace-a', 'workspace-b'], + }, + null, + 2 + ), + 'workspace-a': { + 'package.json': JSON.stringify({ + name: 'workspace-a', + version: '1.0.0', + }), + }, + 'workspace-b': { + 'package.json': JSON.stringify({ + name: 'workspace-b', + version: '1.0.0', + }), }, - null, - 2 - ), - 'workspace-a': { - 'package.json': JSON.stringify({ - name: 'workspace-a', - version: '1.0.0', - }), }, - 'workspace-b': { - 'package.json': JSON.stringify({ - name: 'workspace-b', - version: '1.0.0', - }), + config: { + workspaces: true, }, }) - npm.config.set('workspaces', true) + t.test('all workspaces', async t => { + const { npm, outputs } = await loadWorkspaces(t) process.chdir(npm.prefix) await npm.exec('pack', []) t.strictSame(outputs, [['workspace-a-1.0.0.tgz'], ['workspace-b-1.0.0.tgz']]) }) t.test('all workspaces, `.` first arg', async t => { + const { npm, outputs } = await loadWorkspaces(t) process.chdir(npm.prefix) await npm.exec('pack', ['.']) t.strictSame(outputs, [['workspace-a-1.0.0.tgz'], ['workspace-b-1.0.0.tgz']]) }) t.test('one workspace', async t => { + const { npm, outputs } = await loadWorkspaces(t) process.chdir(npm.prefix) await npm.exec('pack', ['workspace-a']) t.strictSame(outputs, [['workspace-a-1.0.0.tgz']]) }) t.test('specific package', async t => { + const { npm, outputs } = await loadWorkspaces(t) process.chdir(npm.prefix) await npm.exec('pack', [npm.prefix]) t.strictSame(outputs, [['workspaces-test-1.0.0.tgz']]) diff --git a/test/lib/commands/ping.js b/test/lib/commands/ping.js index 7011c709b..f808e0ac3 100644 --- a/test/lib/commands/ping.js +++ b/test/lib/commands/ping.js @@ -11,7 +11,7 @@ t.test('pings', async t => { t.equal(spec.registry, registry, 'passes flatOptions') return {} }, - npmlog: { + 'proc-log': { notice: (type, spec) => { ++noticeCalls if (noticeCalls === 1) { @@ -45,7 +45,7 @@ t.test('pings and logs details', async t => { t.equal(spec.registry, registry, 'passes flatOptions') return details }, - npmlog: { + 'proc-log': { notice: (type, spec) => { ++noticeCalls if (noticeCalls === 1) { @@ -83,7 +83,7 @@ t.test('pings and returns json', async t => { t.equal(spec.registry, registry, 'passes flatOptions') return details }, - npmlog: { + 'proc-log': { notice: (type, spec) => { ++noticeCalls if (noticeCalls === 1) { diff --git a/test/lib/commands/prefix.js b/test/lib/commands/prefix.js index 6f059e73a..e8295cf6a 100644 --- a/test/lib/commands/prefix.js +++ b/test/lib/commands/prefix.js @@ -1,9 +1,8 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') t.test('prefix', async t => { - const { joinedOutput, Npm } = mockNpm(t) - const npm = new Npm() + const { joinedOutput, npm } = await loadMockNpm(t, { load: false }) await npm.exec('prefix', []) t.equal( joinedOutput(), diff --git a/test/lib/commands/profile.js b/test/lib/commands/profile.js index 6554ca89e..0f16c1db1 100644 --- a/test/lib/commands/profile.js +++ b/test/lib/commands/profile.js @@ -22,6 +22,8 @@ const mocks = { ansistyles: { bright: a => a }, npmlog: { gauge: { show () {} }, + }, + 'proc-log': { info () {}, notice () {}, warn () {}, @@ -489,23 +491,23 @@ t.test('profile set <key> <value>', t => { }, } - const npmlog = { - gauge: { - show () {}, - }, - warn (title, msg) { - t.equal(title, 'profile', 'should use expected profile') - t.equal( - msg, - 'Passwords do not match, please try again.', - 'should log password mismatch message' - ) - }, - } - const Profile = t.mock('../../../lib/commands/profile.js', { ...mocks, - npmlog, + npmlog: { + gauge: { + show () {}, + }, + }, + 'proc-log': { + warn (title, msg) { + t.equal(title, 'profile', 'should use expected profile') + t.equal( + msg, + 'Passwords do not match, please try again.', + 'should log password mismatch message' + ) + }, + }, 'npm-profile': npmProfile, '../../../lib/utils/read-user-info.js': readUserInfo, }) diff --git a/test/lib/commands/prune.js b/test/lib/commands/prune.js index 49d5ab9be..a7f56547b 100644 --- a/test/lib/commands/prune.js +++ b/test/lib/commands/prune.js @@ -1,20 +1,22 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') t.test('should prune using Arborist', async (t) => { t.plan(4) - const { Npm } = mockNpm(t, { - '@npmcli/arborist': function (args) { - t.ok(args, 'gets options object') - t.ok(args.path, 'gets path option') - this.prune = () => { - t.ok(true, 'prune is called') - } - }, - '../../lib/utils/reify-finish.js': (arb) => { - t.ok(arb, 'gets arborist tree') + const { npm } = await loadMockNpm(t, { + load: false, + mocks: { + '@npmcli/arborist': function (args) { + t.ok(args, 'gets options object') + t.ok(args.path, 'gets path option') + this.prune = () => { + t.ok(true, 'prune is called') + } + }, + '../../lib/utils/reify-finish.js': (arb) => { + t.ok(arb, 'gets arborist tree') + }, }, }) - const npm = new Npm() await npm.exec('prune', []) }) diff --git a/test/lib/commands/publish.js b/test/lib/commands/publish.js index 5f4fb4010..1178cd6ee 100644 --- a/test/lib/commands/publish.js +++ b/test/lib/commands/publish.js @@ -1,13 +1,15 @@ 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 log = require('npmlog') -log.level = 'silent' +const _level = log.level +t.beforeEach(() => (log.level = 'silent')) +t.teardown(() => (log.level = _level)) t.cleanSnapshot = data => { return data.replace(/^ *"gitHead": .*$\n/gm, '') @@ -19,8 +21,6 @@ const defaults = Object.entries(definitions).reduce((defaults, [key, def]) => { return defaults }, {}) -t.afterEach(() => (log.level = 'silent')) - t.test( /* eslint-disable-next-line max-len */ 'should publish with libnpmpublish, passing through flatOptions and respecting publishConfig.registry', @@ -147,7 +147,7 @@ t.test('if loglevel=info and json, should not output package contents', async t id: 'someid', }), logTar: () => { - t.pass('logTar is called') + t.fail('logTar is not called in json mode') }, }, libnpmpublish: { @@ -188,7 +188,6 @@ t.test( ), }) - log.level = 'silent' const Publish = t.mock('../../../lib/commands/publish.js', { '../../../lib/utils/tar.js': { getContents: () => ({ @@ -681,9 +680,12 @@ 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, - npmlog: { + 'proc-log': { notice () {}, verbose () {}, warn (title, msg) { @@ -707,9 +709,12 @@ 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, - npmlog: { + 'proc-log': { notice () {}, verbose () {}, warn (title, msg) { @@ -730,6 +735,8 @@ t.test('private workspaces', async t => { }) t.test('unexpected error', async t => { + t.plan(1) + const Publish = t.mock('../../../lib/commands/publish.js', { ...mocks, libnpmpublish: { @@ -741,7 +748,7 @@ t.test('private workspaces', async t => { publishes.push(manifest) }, }, - npmlog: { + 'proc-log': { notice () {}, verbose () {}, }, @@ -755,6 +762,8 @@ t.test('private workspaces', async t => { }) t.test('runs correct lifecycle scripts', async t => { + t.plan(5) + const testDir = t.testdir({ 'package.json': JSON.stringify( { @@ -773,6 +782,7 @@ 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) @@ -810,6 +820,8 @@ t.test('runs correct lifecycle scripts', async t => { }) t.test('does not run scripts on --ignore-scripts', async t => { + t.plan(4) + const testDir = t.testdir({ 'package.json': JSON.stringify( { @@ -821,6 +833,7 @@ 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') diff --git a/test/lib/commands/repo.js b/test/lib/commands/repo.js index 4e61047b4..93eb6d031 100644 --- a/test/lib/commands/repo.js +++ b/test/lib/commands/repo.js @@ -1,8 +1,8 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm.js') -const { join, sep } = require('path') +const { load: _loadMockNpm } = require('../../fixtures/mock-npm.js') +const { sep } = require('path') -const pkgDirs = t.testdir({ +const fixture = { 'package.json': JSON.stringify({ name: 'thispkg', version: '1.2.3', @@ -149,35 +149,36 @@ const pkgDirs = t.testdir({ }, }), }, - workspaces: { +} + +const workspaceFixture = { + 'package.json': JSON.stringify({ + name: 'workspaces-test', + version: '1.2.3-test', + workspaces: ['workspace-a', 'workspace-b', 'workspace-c'], + repository: 'https://github.com/npm/workspaces-test', + }), + 'workspace-a': { 'package.json': JSON.stringify({ - name: 'workspaces-test', - version: '1.2.3-test', - workspaces: ['workspace-a', 'workspace-b', 'workspace-c'], - repository: 'https://github.com/npm/workspaces-test', + name: 'workspace-a', + version: '1.2.3-a', + repository: 'http://repo.workspace-a/', }), - 'workspace-a': { - 'package.json': JSON.stringify({ - name: 'workspace-a', - version: '1.2.3-a', - repository: 'http://repo.workspace-a/', - }), - }, - 'workspace-b': { - 'package.json': JSON.stringify({ - name: 'workspace-b', - version: '1.2.3-n', - repository: 'https://github.com/npm/workspace-b', - }), - }, - 'workspace-c': JSON.stringify({ - 'package.json': { - name: 'workspace-n', - version: '1.2.3-n', - }, + }, + 'workspace-b': { + 'package.json': JSON.stringify({ + name: 'workspace-b', + version: '1.2.3-n', + repository: 'https://github.com/npm/workspace-b', }), }, -}) + 'workspace-c': JSON.stringify({ + 'package.json': { + name: 'workspace-n', + version: '1.2.3-n', + }, + }), +} // keep a tally of which urls got opened let opened = {} @@ -185,20 +186,18 @@ const openUrl = async (npm, url, errMsg) => { opened[url] = opened[url] || 0 opened[url]++ } - -const { Npm } = mockNpm(t, { - '../../lib/utils/open-url.js': openUrl, -}) -const npm = new Npm() - -t.before(async () => { - await npm.load() -}) - t.afterEach(() => opened = {}) -t.test('open repo urls', t => { - npm.localPrefix = pkgDirs +const loadMockNpm = async (t, prefix) => { + const res = await _loadMockNpm(t, { + mocks: { '../../lib/utils/open-url.js': openUrl }, + testdir: prefix, + }) + return res +} + +t.test('open repo urls', async t => { + const { npm } = await loadMockNpm(t, fixture) const expect = { hostedgit: 'https://github.com/foo/hostedgit', hostedgitat: 'https://github.com/foo/hostedgitat', @@ -239,8 +238,9 @@ t.test('open repo urls', t => { }) }) -t.test('fail if cannot figure out repo url', t => { - npm.localPrefix = pkgDirs +t.test('fail if cannot figure out repo url', async t => { + const { npm } = await loadMockNpm(t, fixture) + const cases = [ 'norepo', 'repoobbj-nourl', @@ -261,13 +261,13 @@ t.test('fail if cannot figure out repo url', t => { }) t.test('open default package if none specified', async t => { - npm.localPrefix = pkgDirs + const { npm } = await loadMockNpm(t, fixture) await npm.exec('repo', []) t.equal(opened['https://example.com/thispkg'], 1, 'opened expected url', { opened }) }) -t.test('workspaces', t => { - npm.localPrefix = join(pkgDirs, 'workspaces') +t.test('workspaces', async t => { + const { npm } = await loadMockNpm(t, workspaceFixture) t.afterEach(() => { npm.config.set('workspaces', null) @@ -311,5 +311,4 @@ t.test('workspaces', t => { ) t.match({}, opened, 'opened no repo urls') }) - t.end() }) diff --git a/test/lib/commands/restart.js b/test/lib/commands/restart.js index 608de0331..7730f1a30 100644 --- a/test/lib/commands/restart.js +++ b/test/lib/commands/restart.js @@ -1,6 +1,6 @@ const t = require('tap') const spawk = require('spawk') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') spawk.preventUnmatched() t.teardown(() => { @@ -12,24 +12,24 @@ t.teardown(() => { // pretty specific internals of runScript const makeSpawnArgs = require('@npmcli/run-script/lib/make-spawn-args.js') -t.test('should run stop script from package.json', async t => { - const prefix = t.testdir({ - 'package.json': JSON.stringify({ - name: 'x', - version: '1.2.3', - scripts: { - restart: 'node ./test-restart.js', - }, - }), +t.test('should run restart script from package.json', async t => { + const { npm } = await loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify({ + name: 'x', + version: '1.2.3', + scripts: { + restart: 'node ./test-restart.js', + }, + }), + }, + config: { + loglevel: 'silent', + }, }) - const { Npm } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.log.level = 'silent' - npm.localPrefix = prefix - const [scriptShell] = makeSpawnArgs({ path: prefix }) + const [scriptShell] = makeSpawnArgs({ path: npm.prefix }) const script = spawk.spawn(scriptShell, (args) => { - t.ok(args.includes('node ./test-restart.js "foo"'), 'ran stop script with extra args') + t.ok(args.includes('node ./test-restart.js "foo"'), 'ran restart script with extra args') return true }) await npm.exec('restart', ['foo']) diff --git a/test/lib/commands/root.js b/test/lib/commands/root.js index 9871ddb25..a886b30c3 100644 --- a/test/lib/commands/root.js +++ b/test/lib/commands/root.js @@ -1,9 +1,8 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') t.test('prefix', async (t) => { - const { joinedOutput, Npm } = mockNpm(t) - const npm = new Npm() + const { joinedOutput, npm } = await loadMockNpm(t, { load: false }) await npm.exec('root', []) t.equal( joinedOutput(), diff --git a/test/lib/commands/run-script.js b/test/lib/commands/run-script.js index e421c655e..ea0227cda 100644 --- a/test/lib/commands/run-script.js +++ b/test/lib/commands/run-script.js @@ -31,13 +31,16 @@ const output = [] const npmlog = { disableProgress: () => null, level: 'warn', +} + +const log = { error: () => null, } t.afterEach(() => { npm.color = false npmlog.level = 'warn' - npmlog.error = () => null + log.error = () => null output.length = 0 RUN_SCRIPTS.length = 0 config['if-present'] = false @@ -56,6 +59,7 @@ const getRS = windows => { } ), npmlog, + 'proc-log': log, '../../../lib/utils/is-windows-shell.js': windows, }) return new RunScript(npm) @@ -758,7 +762,7 @@ t.test('workspaces', t => { t.test('missing scripts in all workspaces', async t => { const LOG = [] - npmlog.error = err => { + log.error = err => { LOG.push(String(err)) } await t.rejects( @@ -805,7 +809,7 @@ t.test('workspaces', t => { t.test('missing scripts in some workspaces', async t => { const LOG = [] - npmlog.error = err => { + log.error = err => { LOG.push(String(err)) } await runScript.execWorkspaces(['test'], ['a', 'b', 'c', 'd']) @@ -857,6 +861,7 @@ t.test('workspaces', t => { throw new Error('err') }, npmlog, + 'proc-log': log, '../../../lib/utils/is-windows-shell.js': false, }) const runScript = new RunScript(npm) @@ -875,6 +880,7 @@ t.test('workspaces', t => { RUN_SCRIPTS.push(opts) }, npmlog, + 'proc-log': log, '../../../lib/utils/is-windows-shell.js': false, }) const runScript = new RunScript(npm) diff --git a/test/lib/commands/set-script.js b/test/lib/commands/set-script.js index 592a2431c..2c4fe57d6 100644 --- a/test/lib/commands/set-script.js +++ b/test/lib/commands/set-script.js @@ -10,7 +10,7 @@ const npm = mockNpm(flatOptions) const ERROR_OUTPUT = [] const WARN_OUTPUT = [] const SetScript = t.mock('../../../lib/commands/set-script.js', { - npmlog: { + 'proc-log': { error: (...args) => { ERROR_OUTPUT.push(args) }, diff --git a/test/lib/commands/set.js b/test/lib/commands/set.js index a57ea1a54..feeb90157 100644 --- a/test/lib/commands/set.js +++ b/test/lib/commands/set.js @@ -2,6 +2,7 @@ const t = require('tap') // can't run this until npm set can save to project level npmrc t.skip('npm set', async t => { + // XXX: convert to loadMockNpm const { real: mockNpm } = require('../../fixtures/mock-npm') const { joinedOutput, Npm } = mockNpm(t) const npm = new Npm() diff --git a/test/lib/commands/shrinkwrap.js b/test/lib/commands/shrinkwrap.js index db4021abd..2b9e46c70 100644 --- a/test/lib/commands/shrinkwrap.js +++ b/test/lib/commands/shrinkwrap.js @@ -1,7 +1,7 @@ const t = require('tap') const fs = require('fs') const { resolve } = require('path') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') // Attempt to parse json values in snapshots before // stringifying to remove escaped values like \\" @@ -13,7 +13,7 @@ t.formatSnapshot = obj => (k, v) => { try { return JSON.parse(v) - } catch (_) {} + } catch {} return v }, 2 @@ -23,33 +23,25 @@ t.formatSnapshot = obj => // and make some assertions that should always be true. Sets // the results on t.context for use in child tests const shrinkwrap = async (t, testdir = {}, config = {}, mocks = {}) => { - const { Npm, filteredLogs } = mockNpm(t, mocks) - const npm = new Npm() - await npm.load() - - npm.localPrefix = t.testdir(testdir) - if (config.lockfileVersion) { - npm.config.set('lockfile-version', config.lockfileVersion) - } - if (config.global) { - npm.config.set('global', config.global) - } + const { npm, logs } = await loadMockNpm(t, { + mocks, + config, + testdir, + }) await npm.exec('shrinkwrap', []) - const newFile = resolve(npm.localPrefix, 'npm-shrinkwrap.json') - const oldFile = resolve(npm.localPrefix, 'package-lock.json') - const notices = filteredLogs('notice') - const warnings = filteredLogs('warn') + const newFile = resolve(npm.prefix, 'npm-shrinkwrap.json') + const oldFile = resolve(npm.prefix, 'package-lock.json') t.notOk(fs.existsSync(oldFile), 'package-lock is always deleted') - t.same(warnings, [], 'no warnings') + t.same(logs.warn, [], 'no warnings') t.teardown(() => delete t.context) t.context = { localPrefix: testdir, config, shrinkwrap: JSON.parse(fs.readFileSync(newFile)), - logs: notices, + logs: logs.notice.map(([, m]) => m), } } @@ -58,8 +50,8 @@ const shrinkwrap = async (t, testdir = {}, config = {}, mocks = {}) => { const shrinkwrapMatrix = async (t, file, assertions) => { const ancient = JSON.stringify({ lockfileVersion: 1 }) const existing = JSON.stringify({ lockfileVersion: 2 }) - const upgrade = { lockfileVersion: 3 } - const downgrade = { lockfileVersion: 1 } + const upgrade = { 'lockfile-version': 3 } + const downgrade = { 'lockfile-version': 1 } let ancientDir = {} let existingDir = null diff --git a/test/lib/commands/star.js b/test/lib/commands/star.js index 13838bb10..9a4903642 100644 --- a/test/lib/commands/star.js +++ b/test/lib/commands/star.js @@ -15,9 +15,9 @@ const npm = mockNpm({ }, }) const npmFetch = { json: noop } -const npmlog = { error: noop, info: noop, verbose: noop } +const log = { error: noop, info: noop, verbose: noop } const mocks = { - npmlog, + 'proc-log': log, 'npm-registry-fetch': npmFetch, '../../../lib/utils/get-identity.js': async () => 'foo', '../../../lib/utils/usage.js': () => 'usage instructions', @@ -29,7 +29,7 @@ const star = new Star(npm) t.afterEach(() => { config.unicode = false config['star.unstar'] = false - npmlog.info = noop + log.info = noop result = '' }) @@ -53,7 +53,7 @@ t.test('star a package', async t => { : {} ), }) - npmlog.info = (title, msg, id) => { + log.info = (title, msg, id) => { t.equal(title, 'star', 'should use expected title') t.equal(msg, 'starring', 'should use expected msg') t.equal(id, pkgName, 'should use expected id') @@ -78,7 +78,7 @@ t.test('unstar a package', async t => { : { foo: true } ), }) - npmlog.info = (title, msg, id) => { + log.info = (title, msg, id) => { t.equal(title, 'unstar', 'should use expected title') t.equal(msg, 'unstarring', 'should use expected msg') t.equal(id, pkgName, 'should use expected id') diff --git a/test/lib/commands/stars.js b/test/lib/commands/stars.js index 4ed643858..959739653 100644 --- a/test/lib/commands/stars.js +++ b/test/lib/commands/stars.js @@ -11,9 +11,9 @@ const npm = { }, } const npmFetch = { json: noop } -const npmlog = { warn: noop } +const log = { warn: noop } const mocks = { - npmlog, + 'proc-log': log, 'npm-registry-fetch': npmFetch, '../../../lib/utils/get-identity.js': async () => 'foo', '../../../lib/utils/usage.js': () => 'usage instructions', @@ -24,7 +24,7 @@ const stars = new Stars(npm) t.afterEach(() => { npm.config = { get () {} } - npmlog.warn = noop + log.warn = noop result = '' }) @@ -81,7 +81,7 @@ t.test('unauthorized request', async t => { ) } - npmlog.warn = (title, msg) => { + log.warn = (title, msg) => { t.equal(title, 'stars', 'should use expected title') t.equal( msg, @@ -108,7 +108,7 @@ t.test('unexpected error', async t => { throw new Error('ERROR') } - npmlog.warn = (title, msg) => { + log.warn = (title, msg) => { throw new Error('Should not output extra warning msgs') } @@ -123,7 +123,7 @@ t.test('no pkg starred', async t => { t.plan(2) npmFetch.json = async (uri, opts) => ({ rows: [] }) - npmlog.warn = (title, msg) => { + log.warn = (title, msg) => { t.equal(title, 'stars', 'should use expected title') t.equal( msg, diff --git a/test/lib/commands/start.js b/test/lib/commands/start.js index 1f26f38ea..4f7dc366d 100644 --- a/test/lib/commands/start.js +++ b/test/lib/commands/start.js @@ -1,6 +1,6 @@ const t = require('tap') const spawk = require('spawk') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') spawk.preventUnmatched() t.teardown(() => { @@ -12,22 +12,23 @@ t.teardown(() => { // pretty specific internals of runScript const makeSpawnArgs = require('@npmcli/run-script/lib/make-spawn-args.js') -t.test('should run stop script from package.json', async t => { - const prefix = t.testdir({ - 'package.json': JSON.stringify({ - name: 'x', - version: '1.2.3', - scripts: { - start: 'node ./test-start.js', - }, - }), +t.test('should run start script from package.json', async t => { + t.plan(2) + const { npm } = await loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify({ + name: 'x', + version: '1.2.3', + scripts: { + start: 'node ./test-start.js', + }, + }), + }, + config: { + loglevel: 'silent', + }, }) - const { Npm } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.log.level = 'silent' - npm.localPrefix = prefix - const [scriptShell] = makeSpawnArgs({ path: prefix }) + const [scriptShell] = makeSpawnArgs({ path: npm.prefix }) const script = spawk.spawn(scriptShell, (args) => { t.ok(args.includes('node ./test-start.js "foo"'), 'ran start script with extra args') return true diff --git a/test/lib/commands/stop.js b/test/lib/commands/stop.js index 4f189449b..53d057b71 100644 --- a/test/lib/commands/stop.js +++ b/test/lib/commands/stop.js @@ -1,6 +1,6 @@ const t = require('tap') const spawk = require('spawk') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') spawk.preventUnmatched() t.teardown(() => { @@ -13,21 +13,21 @@ t.teardown(() => { const makeSpawnArgs = require('@npmcli/run-script/lib/make-spawn-args.js') t.test('should run stop script from package.json', async t => { - const prefix = t.testdir({ - 'package.json': JSON.stringify({ - name: 'x', - version: '1.2.3', - scripts: { - stop: 'node ./test-stop.js', - }, - }), + const { npm } = await loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify({ + name: 'x', + version: '1.2.3', + scripts: { + stop: 'node ./test-stop.js', + }, + }), + }, + config: { + loglevel: 'silent', + }, }) - const { Npm } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.log.level = 'silent' - npm.localPrefix = prefix - const [scriptShell] = makeSpawnArgs({ path: prefix }) + const [scriptShell] = makeSpawnArgs({ path: npm.prefix }) const script = spawk.spawn(scriptShell, (args) => { t.ok(args.includes('node ./test-stop.js "foo"'), 'ran stop script with extra args') return true diff --git a/test/lib/commands/test.js b/test/lib/commands/test.js index 4e5ce289b..a3dbd3ff4 100644 --- a/test/lib/commands/test.js +++ b/test/lib/commands/test.js @@ -1,6 +1,6 @@ const t = require('tap') const spawk = require('spawk') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm') spawk.preventUnmatched() t.teardown(() => { @@ -12,22 +12,22 @@ t.teardown(() => { // pretty specific internals of runScript const makeSpawnArgs = require('@npmcli/run-script/lib/make-spawn-args.js') -t.test('should run stop script from package.json', async t => { - const prefix = t.testdir({ - 'package.json': JSON.stringify({ - name: 'x', - version: '1.2.3', - scripts: { - test: 'node ./test-test.js', - }, - }), +t.test('should run test script from package.json', async t => { + const { npm } = await loadMockNpm(t, { + testdir: { + 'package.json': JSON.stringify({ + name: 'x', + version: '1.2.3', + scripts: { + test: 'node ./test-test.js', + }, + }), + }, + config: { + loglevel: 'silent', + }, }) - const { Npm } = mockNpm(t) - const npm = new Npm() - await npm.load() - npm.log.level = 'silent' - npm.localPrefix = prefix - const [scriptShell] = makeSpawnArgs({ path: prefix }) + const [scriptShell] = makeSpawnArgs({ path: npm.prefix }) const script = spawk.spawn(scriptShell, (args) => { t.ok(args.includes('node ./test-test.js "foo"'), 'ran test script with extra args') return true diff --git a/test/lib/commands/token.js b/test/lib/commands/token.js index 6d0dc9d7e..65a094a0b 100644 --- a/test/lib/commands/token.js +++ b/test/lib/commands/token.js @@ -3,25 +3,24 @@ const t = require('tap') const mocks = { profile: {}, output: () => {}, - log: {}, readUserInfo: {}, } const npm = { output: (...args) => mocks.output(...args), } -const Token = t.mock('../../../lib/commands/token.js', { +const mockToken = (otherMocks) => t.mock('../../../lib/commands/token.js', { '../../../lib/utils/otplease.js': (opts, fn) => { return Promise.resolve().then(() => fn(opts)) }, '../../../lib/utils/read-user-info.js': mocks.readUserInfo, 'npm-profile': mocks.profile, - npmlog: mocks.log, + ...otherMocks, }) -const token = new Token(npm) +const tokenWithMocks = (options = {}) => { + const { log, ...mockRequests } = options -const tokenWithMocks = mockRequests => { for (const mod in mockRequests) { if (mod === 'npm') { mockRequests.npm = { ...npm, ...mockRequests.npm } @@ -50,13 +49,24 @@ const tokenWithMocks = mockRequests => { } } - const token = new Token(mockRequests.npm || npm) + const MockedToken = mockToken(log ? { + 'proc-log': { + info: log.info, + }, + npmlog: { + gauge: log.gauge, + newItem: log.newItem, + }, + } : {}) + const token = new MockedToken(mockRequests.npm || npm) return [token, reset] } t.test('completion', t => { t.plan(5) + const [token] = tokenWithMocks() + const testComp = (argv, expect) => { t.resolveMatch(token.completion({ conf: { argv: { remain: argv } } }), expect, argv.join(' ')) } @@ -74,7 +84,7 @@ t.test('completion', t => { t.test('token foobar', async t => { t.plan(2) - const [, reset] = tokenWithMocks({ + const [token, reset] = tokenWithMocks({ log: { gauge: { show: name => { diff --git a/test/lib/commands/unpublish.js b/test/lib/commands/unpublish.js index 6ac206753..1424adf5c 100644 --- a/test/lib/commands/unpublish.js +++ b/test/lib/commands/unpublish.js @@ -17,7 +17,6 @@ const testDir = t.testdir({ const npm = mockNpm({ localPrefix: testDir, - log: { silly () {}, verbose () {} }, config, output: (...msg) => { result += msg.join('\n') @@ -30,10 +29,10 @@ const mocks = { 'npm-registry-fetch': { json: noop }, '../../../lib/utils/otplease.js': async (opts, fn) => fn(opts), '../../../lib/utils/get-identity.js': async () => 'foo', + 'proc-log': { silly () {}, verbose () {} }, } t.afterEach(() => { - npm.log = { silly () {}, verbose () {} } npm.localPrefix = testDir result = '' config['dry-run'] = false @@ -44,7 +43,7 @@ t.afterEach(() => { t.test('no args --force', async t => { config.force = true - npm.log = { + const log = { silly (title) { t.equal(title, 'unpublish', 'should silly log args') }, @@ -74,6 +73,7 @@ t.test('no args --force', async t => { const Unpublish = t.mock('../../../lib/commands/unpublish.js', { ...mocks, libnpmpublish, + 'proc-log': log, }) const unpublish = new Unpublish(npm) @@ -147,7 +147,7 @@ t.test('too many args', async t => { }) t.test('unpublish <pkg>@version', async t => { - npm.log = { + const log = { silly (title, key, value) { t.equal(title, 'unpublish', 'should silly log args') if (key === 'spec') { @@ -172,6 +172,7 @@ t.test('unpublish <pkg>@version', async t => { const Unpublish = t.mock('../../../lib/commands/unpublish.js', { ...mocks, libnpmpublish, + 'proc-log': log, }) const unpublish = new Unpublish(npm) diff --git a/test/lib/commands/update.js b/test/lib/commands/update.js index 6ca6dbc87..aecb2c32b 100644 --- a/test/lib/commands/update.js +++ b/test/lib/commands/update.js @@ -9,12 +9,10 @@ const config = { const noop = () => null const npm = mockNpm({ globalDir: '', - log: noop, config, prefix: '', }) const mocks = { - npmlog: { warn () {} }, '@npmcli/arborist': class { reify () {} }, @@ -29,22 +27,23 @@ t.afterEach(() => { }) t.test('no args', async t => { - t.plan(3) + t.plan(4) npm.prefix = '/project/a' class Arborist { constructor (args) { + const { log, ...rest } = args t.same( - args, + rest, { ...npm.flatOptions, path: npm.prefix, - log: noop, workspaces: null, }, 'should call arborist contructor with expected args' ) + t.match(log, {}, 'log is passed in') } reify ({ update }) { @@ -65,22 +64,23 @@ t.test('no args', async t => { }) t.test('with args', async t => { - t.plan(3) + t.plan(4) npm.prefix = '/project/a' class Arborist { constructor (args) { + const { log, ...rest } = args t.same( - args, + rest, { ...npm.flatOptions, path: npm.prefix, - log: noop, workspaces: null, }, 'should call arborist contructor with expected args' ) + t.match(log, {}, 'log is passed in') } reify ({ update }) { @@ -108,7 +108,7 @@ t.test('update --depth=<number>', async t => { const Update = t.mock('../../../lib/commands/update.js', { ...mocks, - npmlog: { + 'proc-log': { warn: (title, msg) => { t.equal(title, 'update', 'should print expected title') t.match( @@ -125,7 +125,7 @@ t.test('update --depth=<number>', async t => { }) t.test('update --global', async t => { - t.plan(2) + t.plan(3) const normalizePath = p => p.replace(/\\+/g, '/') const redactCwd = (path) => normalizePath(path) @@ -137,13 +137,15 @@ t.test('update --global', async t => { class Arborist { constructor (args) { - const { path, ...opts } = args + const { path, log, ...rest } = args t.same( - opts, - { ...npm.flatOptions, log: noop, workspaces: undefined }, + rest, + { ...npm.flatOptions, workspaces: undefined }, '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/commands/version.js b/test/lib/commands/version.js index 6603b5810..980353897 100644 --- a/test/lib/commands/version.js +++ b/test/lib/commands/version.js @@ -1,5 +1,6 @@ const t = require('tap') const { fake: mockNpm } = require('../../fixtures/mock-npm') +const mockGlobals = require('../../fixtures/mock-globals.js') let result = [] @@ -26,294 +27,301 @@ const mocks = { const Version = t.mock('../../../lib/commands/version.js', mocks) const version = new Version(npm) -const _processVersions = process.versions t.afterEach(() => { config.json = false npm.prefix = '' - process.versions = _processVersions result = [] }) -t.test('no args', async t => { - const prefix = t.testdir({ - 'package.json': JSON.stringify({ - name: 'test-version-no-args', - version: '3.2.1', - }), - }) - npm.prefix = prefix - Object.defineProperty(process, 'versions', { value: { node: '1.0.0' } }) - - await version.exec([]) - - t.same( - result, - [ - { - 'test-version-no-args': '3.2.1', - node: '1.0.0', - npm: '1.0.0', - }, - ], - 'should output expected values for various versions in npm' - ) -}) - -t.test('too many args', async t => { - await t.rejects( - version.exec(['foo', 'bar']), - /npm version/, - 'should throw usage instructions error' - ) -}) - -t.test('completion', async t => { - const testComp = async (argv, expect) => { - const res = await version.completion({ conf: { argv: { remain: argv } } }) - t.strictSame(res, expect, argv.join(' ')) - } - - await testComp( - ['npm', 'version'], - ['major', 'minor', 'patch', 'premajor', 'preminor', 'prepatch', 'prerelease', 'from-git'] - ) - await testComp(['npm', 'version', 'major'], []) - - t.end() -}) - -t.test('failure reading package.json', async t => { - const prefix = t.testdir({}) - npm.prefix = prefix - - await version.exec([]) - - t.same( - result, - [ - { - npm: '1.0.0', - node: '1.0.0', - }, - ], - 'should not have package name on returning object' - ) -}) - -t.test('--json option', async t => { - const prefix = t.testdir({}) - config.json = true - npm.prefix = prefix - Object.defineProperty(process, 'versions', { value: {} }) - - await version.exec([]) - t.same(result, ['{\n "npm": "1.0.0"\n}'], 'should return json stringified result') -}) +t.test('node@1', t => { + mockGlobals(t, { 'process.versions': { node: '1.0.0' } }, { replace: true }) -t.test('with one arg', async t => { - const Version = t.mock('../../../lib/commands/version.js', { - ...mocks, - libnpmversion: (arg, opts) => { - t.equal(arg, 'major', 'should forward expected value') - t.same( - opts, - { - path: '', - }, - 'should forward expected options' - ) - return '4.0.0' - }, - }) - const version = new Version(npm) - - await version.exec(['major']) - t.same(result, ['v4.0.0'], 'outputs the new version prefixed by the tagVersionPrefix') -}) + t.test('no args', async t => { + const prefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'test-version-no-args', + version: '3.2.1', + }), + }) + npm.prefix = prefix -t.test('workspaces', async t => { - t.teardown(() => { - npm.localPrefix = '' - npm.prefix = '' - }) + await version.exec([]) - t.test('no args, all workspaces', async t => { - const testDir = t.testdir({ - 'package.json': JSON.stringify( - { - name: 'workspaces-test', - version: '1.0.0', - workspaces: ['workspace-a', 'workspace-b'], - }, - null, - 2 - ), - 'workspace-a': { - 'package.json': JSON.stringify({ - name: 'workspace-a', - version: '1.0.0', - }), - }, - 'workspace-b': { - 'package.json': JSON.stringify({ - name: 'workspace-b', - version: '1.0.0', - }), - }, - }) - npm.localPrefix = testDir - npm.prefix = testDir - const version = new Version(npm) - await version.execWorkspaces([], []) t.same( result, [ { - 'workspaces-test': '1.0.0', - 'workspace-a': '1.0.0', - 'workspace-b': '1.0.0', + 'test-version-no-args': '3.2.1', + node: '1.0.0', npm: '1.0.0', }, ], - 'outputs includes main package and workspace versions' + 'should output expected values for various versions in npm' ) }) - t.test('no args, single workspaces', async t => { - const testDir = t.testdir({ - 'package.json': JSON.stringify( - { - name: 'workspaces-test', - version: '1.0.0', - workspaces: ['workspace-a', 'workspace-b'], - }, - null, - 2 - ), - 'workspace-a': { - 'package.json': JSON.stringify({ - name: 'workspace-a', - version: '1.0.0', - }), - }, - 'workspace-b': { - 'package.json': JSON.stringify({ - name: 'workspace-b', - version: '1.0.0', - }), - }, - }) - npm.localPrefix = testDir - npm.prefix = testDir - const version = new Version(npm) - await version.execWorkspaces([], ['workspace-a']) - t.same( - result, - [ - { - 'workspaces-test': '1.0.0', - 'workspace-a': '1.0.0', - npm: '1.0.0', - }, - ], - 'outputs includes main package and requested workspace versions' + t.test('too many args', async t => { + await t.rejects( + version.exec(['foo', 'bar']), + /npm version/, + 'should throw usage instructions error' ) }) - t.test('no args, all workspaces, workspace with missing name or version', async t => { - const testDir = t.testdir({ - 'package.json': JSON.stringify( - { - name: 'workspaces-test', - version: '1.0.0', - workspaces: ['workspace-a', 'workspace-b', 'workspace-c'], - }, - null, - 2 - ), - 'workspace-a': { - 'package.json': JSON.stringify({ - name: 'workspace-a', - version: '1.0.0', - }), - }, - 'workspace-b': { - 'package.json': JSON.stringify({ - name: 'workspace-b', - }), - }, - 'workspace-c': { - 'package.json': JSON.stringify({ - version: '1.0.0', - }), - }, - }) - npm.localPrefix = testDir - npm.prefix = testDir - const version = new Version(npm) - await version.execWorkspaces([], []) + t.test('completion', async t => { + const testComp = async (argv, expect) => { + const res = await version.completion({ conf: { argv: { remain: argv } } }) + t.strictSame(res, expect, argv.join(' ')) + } + + await testComp( + ['npm', 'version'], + ['major', 'minor', 'patch', 'premajor', 'preminor', 'prepatch', 'prerelease', 'from-git'] + ) + await testComp(['npm', 'version', 'major'], []) + + t.end() + }) + + t.test('failure reading package.json', async t => { + const prefix = t.testdir({}) + npm.prefix = prefix + + await version.exec([]) + t.same( result, [ { - 'workspaces-test': '1.0.0', - 'workspace-a': '1.0.0', npm: '1.0.0', + node: '1.0.0', }, ], - 'outputs includes main package and valid workspace versions' + 'should not have package name on returning object' ) }) + t.end() +}) - t.test('with one arg, all workspaces', async t => { - const libNpmVersionArgs = [] - const testDir = t.testdir({ - 'package.json': JSON.stringify( - { - name: 'workspaces-test', - version: '1.0.0', - workspaces: ['workspace-a', 'workspace-b'], - }, - null, - 2 - ), - 'workspace-a': { - 'package.json': JSON.stringify({ - name: 'workspace-a', - version: '1.0.0', - }), - }, - 'workspace-b': { - 'package.json': JSON.stringify({ - name: 'workspace-b', - version: '1.0.0', - }), - }, - }) +t.test('empty versions', t => { + mockGlobals(t, { 'process.versions': {} }, { replace: true }) + + t.test('--json option', async t => { + const prefix = t.testdir({}) + config.json = true + npm.prefix = prefix + + await version.exec([]) + t.same(result, ['{\n "npm": "1.0.0"\n}'], 'should return json stringified result') + }) + + t.test('with one arg', async t => { const Version = t.mock('../../../lib/commands/version.js', { ...mocks, libnpmversion: (arg, opts) => { - libNpmVersionArgs.push([arg, opts]) - return '2.0.0' + t.equal(arg, 'major', 'should forward expected value') + t.same( + opts, + { + path: '', + }, + 'should forward expected options' + ) + return '4.0.0' }, }) - npm.localPrefix = testDir - npm.prefix = testDir const version = new Version(npm) - await version.execWorkspaces(['major'], []) - t.same( - result, - ['workspace-a', 'v2.0.0', 'workspace-b', 'v2.0.0'], - 'outputs the new version for only the workspaces prefixed by the tagVersionPrefix' - ) + await version.exec(['major']) + t.same(result, ['v4.0.0'], 'outputs the new version prefixed by the tagVersionPrefix') }) - t.test('too many args', async t => { - await t.rejects( - version.execWorkspaces(['foo', 'bar'], []), - /npm version/, - 'should throw usage instructions error' - ) + t.test('workspaces', async t => { + t.teardown(() => { + npm.localPrefix = '' + npm.prefix = '' + }) + + t.test('no args, all workspaces', async t => { + const testDir = t.testdir({ + 'package.json': JSON.stringify( + { + name: 'workspaces-test', + version: '1.0.0', + workspaces: ['workspace-a', 'workspace-b'], + }, + null, + 2 + ), + 'workspace-a': { + 'package.json': JSON.stringify({ + name: 'workspace-a', + version: '1.0.0', + }), + }, + 'workspace-b': { + 'package.json': JSON.stringify({ + name: 'workspace-b', + version: '1.0.0', + }), + }, + }) + npm.localPrefix = testDir + npm.prefix = testDir + const version = new Version(npm) + await version.execWorkspaces([], []) + t.same( + result, + [ + { + 'workspaces-test': '1.0.0', + 'workspace-a': '1.0.0', + 'workspace-b': '1.0.0', + npm: '1.0.0', + }, + ], + 'outputs includes main package and workspace versions' + ) + }) + + t.test('no args, single workspaces', async t => { + const testDir = t.testdir({ + 'package.json': JSON.stringify( + { + name: 'workspaces-test', + version: '1.0.0', + workspaces: ['workspace-a', 'workspace-b'], + }, + null, + 2 + ), + 'workspace-a': { + 'package.json': JSON.stringify({ + name: 'workspace-a', + version: '1.0.0', + }), + }, + 'workspace-b': { + 'package.json': JSON.stringify({ + name: 'workspace-b', + version: '1.0.0', + }), + }, + }) + npm.localPrefix = testDir + npm.prefix = testDir + const version = new Version(npm) + await version.execWorkspaces([], ['workspace-a']) + t.same( + result, + [ + { + 'workspaces-test': '1.0.0', + 'workspace-a': '1.0.0', + npm: '1.0.0', + }, + ], + 'outputs includes main package and requested workspace versions' + ) + }) + + t.test('no args, all workspaces, workspace with missing name or version', async t => { + const testDir = t.testdir({ + 'package.json': JSON.stringify( + { + name: 'workspaces-test', + version: '1.0.0', + workspaces: ['workspace-a', 'workspace-b', 'workspace-c'], + }, + null, + 2 + ), + 'workspace-a': { + 'package.json': JSON.stringify({ + name: 'workspace-a', + version: '1.0.0', + }), + }, + 'workspace-b': { + 'package.json': JSON.stringify({ + name: 'workspace-b', + }), + }, + 'workspace-c': { + 'package.json': JSON.stringify({ + version: '1.0.0', + }), + }, + }) + npm.localPrefix = testDir + npm.prefix = testDir + const version = new Version(npm) + await version.execWorkspaces([], []) + t.same( + result, + [ + { + 'workspaces-test': '1.0.0', + 'workspace-a': '1.0.0', + npm: '1.0.0', + }, + ], + 'outputs includes main package and valid workspace versions' + ) + }) + + t.test('with one arg, all workspaces', async t => { + const libNpmVersionArgs = [] + const testDir = t.testdir({ + 'package.json': JSON.stringify( + { + name: 'workspaces-test', + version: '1.0.0', + workspaces: ['workspace-a', 'workspace-b'], + }, + null, + 2 + ), + 'workspace-a': { + 'package.json': JSON.stringify({ + name: 'workspace-a', + version: '1.0.0', + }), + }, + 'workspace-b': { + 'package.json': JSON.stringify({ + name: 'workspace-b', + version: '1.0.0', + }), + }, + }) + const Version = t.mock('../../../lib/commands/version.js', { + ...mocks, + libnpmversion: (arg, opts) => { + libNpmVersionArgs.push([arg, opts]) + return '2.0.0' + }, + }) + npm.localPrefix = testDir + npm.prefix = testDir + const version = new Version(npm) + + await version.execWorkspaces(['major'], []) + t.same( + result, + ['workspace-a', 'v2.0.0', 'workspace-b', 'v2.0.0'], + 'outputs the new version for only the workspaces prefixed by the tagVersionPrefix' + ) + }) + + t.test('too many args', async t => { + await t.rejects( + version.execWorkspaces(['foo', 'bar'], []), + /npm version/, + 'should throw usage instructions error' + ) + }) }) + + t.end() }) diff --git a/test/lib/commands/view.js b/test/lib/commands/view.js index 728787ec4..035490a79 100644 --- a/test/lib/commands/view.js +++ b/test/lib/commands/view.js @@ -1,6 +1,7 @@ const t = require('tap') -t.cleanSnapshot = str => str.replace(/published .*? ago/g, 'published {TIME} ago') +t.cleanSnapshot = str => str + .replace(/(published ).*?( ago)/g, '$1{TIME}$2') // run the same as tap does when running directly with node process.stdout.columns = undefined @@ -17,8 +18,8 @@ const cleanLogs = () => { console.log = fn } -// 25 hours ago -const yesterday = new Date(Date.now() - 1000 * 60 * 60 * 25) +// 3 days. its never yesterday and never a week ago +const yesterday = new Date(Date.now() - 1000 * 60 * 60 * 24 * 3) const packument = (nv, opts) => { if (!opts.fullMetadata) { @@ -564,6 +565,12 @@ t.test('workspaces', async t => { pacote: { packument, }, + 'proc-log': { + warn: (msg) => { + warnMsg = msg + }, + silly: () => {}, + }, }) const config = { unicode: false, @@ -571,11 +578,6 @@ t.test('workspaces', async t => { } let warnMsg const npm = mockNpm({ - log: { - warn: (msg) => { - warnMsg = msg - }, - }, config, localPrefix: testDir, }) diff --git a/test/lib/commands/whoami.js b/test/lib/commands/whoami.js index dc6144ec1..66c3f0c6b 100644 --- a/test/lib/commands/whoami.js +++ b/test/lib/commands/whoami.js @@ -1,26 +1,24 @@ const t = require('tap') -const { real: mockNpm } = require('../../fixtures/mock-npm') +const { load: _loadMockNpm } = require('../../fixtures/mock-npm') const username = 'foo' -const { joinedOutput, Npm } = mockNpm(t, { - '../../lib/utils/get-identity.js': () => Promise.resolve(username), -}) -const npm = new Npm() - -t.before(async () => { - await npm.load() +const loadMockNpm = (t, options) => _loadMockNpm(t, { + mocks: { + '../../lib/utils/get-identity.js': () => Promise.resolve(username), + }, + ...options, }) t.test('npm whoami', async (t) => { + const { npm, joinedOutput } = await loadMockNpm(t) await npm.exec('whoami', []) t.equal(joinedOutput(), username, 'should print username') }) t.test('npm whoami --json', async (t) => { - t.teardown(() => { - npm.config.set('json', false) + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { json: true }, }) - npm.config.set('json', true) await npm.exec('whoami', []) t.equal(JSON.parse(joinedOutput()), username, 'should print username') }) |