Skip to content

Commit

Permalink
chore(tests): expose real mock npm object
Browse files Browse the repository at this point in the history
Consolidates existing "real npm" mocks, labels it real. We can now
migrate tests to this one at a time instead of trying to make one giant
PR that does it all at once.

PR-URL: #3458
Credit: @wraithgar
Close: #3458
Reviewed-by: @nlf
  • Loading branch information
wraithgar committed Jun 23, 2021
1 parent d0f50b1 commit 87f67d9
Show file tree
Hide file tree
Showing 41 changed files with 160 additions and 166 deletions.
59 changes: 53 additions & 6 deletions test/fixtures/mock-npm.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,52 @@
// Basic npm fixture that you can give a config object that acts like
// npm.config You still need a separate flatOptions but this is the first step
// to eventually just using npm itself
const npmlog = require('npmlog')
const perf = require('../../lib/utils/perf.js')
perf.reset()
const procLog = require('../../lib/utils/proc-log-listener.js')
procLog.reset()

const realLog = {}
for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error'])
realLog[level] = npmlog[level]

const { title, execPath } = process

const RealMockNpm = (t, otherMocks = {}) => {
t.teardown(() => {
for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error'])
npmlog[level] = realLog[level]
perf.reset()
procLog.reset()
process.title = title
process.execPath = execPath
delete process.env.npm_command
delete process.env.COLOR
})
const logs = []
const outputs = []
const npm = t.mock('../../lib/npm.js', otherMocks)
const command = async (command, args = []) => {
return new Promise((resolve, reject) => {
npm.commands[command](args, err => {
if (err)
return reject(err)
return resolve()
})
})
}
for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error']) {
npmlog[level] = (...msg) => {
logs.push([level, ...msg])
}
}
npm.output = (...msg) => outputs.push(msg)
return { npm, logs, outputs, command }
}

const realConfig = require('../../lib/utils/config')

// Basic npm fixture that you can give a config object that acts like
// npm.config You still need a separate flatOptions. Tests should migrate to
// using the real npm mock above
class MockNpm {
constructor (base = {}) {
this._mockOutputs = []
Expand Down Expand Up @@ -51,7 +94,11 @@ class MockNpm {
}
}

// TODO export MockNpm, and change tests to use new MockNpm()
module.exports = (base = {}) => {
return new MockNpm(base)
const FakeMockNpm = (base = {}) => {
return new MockNpm(base)
}

module.exports = {
fake: FakeMockNpm,
real: RealMockNpm
}
2 changes: 1 addition & 1 deletion test/lib/audit.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const t = require('tap')
const mockNpm = require('../fixtures/mock-npm')
const { fake: mockNpm } = require('../fixtures/mock-npm')

t.test('should audit using Arborist', t => {
let ARB_ARGS = null
Expand Down
2 changes: 1 addition & 1 deletion test/lib/bin.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const t = require('tap')
const mockNpm = require('../fixtures/mock-npm')
const { fake: mockNpm } = require('../fixtures/mock-npm')

t.test('bin', (t) => {
t.plan(4)
Expand Down
2 changes: 1 addition & 1 deletion test/lib/birthday.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const t = require('tap')
const mockNpm = require('../fixtures/mock-npm')
const { fake: mockNpm } = require('../fixtures/mock-npm')

const config = {
yes: false,
Expand Down
2 changes: 1 addition & 1 deletion test/lib/cache.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const t = require('tap')
const mockNpm = require('../fixtures/mock-npm')
const { fake: mockNpm } = require('../fixtures/mock-npm.js')
const path = require('path')

const usageUtil = () => 'usage instructions'
Expand Down
2 changes: 1 addition & 1 deletion test/lib/ci.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const readdir = util.promisify(fs.readdir)

const t = require('tap')

const mockNpm = require('../fixtures/mock-npm')
const { fake: mockNpm } = require('../fixtures/mock-npm')

t.test('should ignore scripts with --ignore-scripts', (t) => {
const SCRIPTS = []
Expand Down
32 changes: 11 additions & 21 deletions test/lib/cli.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
const t = require('tap')

// NOTE lib/npm.js is wrapped in t.mock() every time because it's currently a
// singleton. In the next semver major we will export the class and lib/cli.js
// can call `new` on it and then we won't have to do that anymore
const { real: mockNpm } = require('../fixtures/mock-npm.js')

const unsupportedMock = {
checkForBrokenNode: () => {},
Expand Down Expand Up @@ -36,13 +34,6 @@ const cliMock = (npm) => t.mock('../../lib/cli.js', {
npmlog: npmlogMock,
})

const npmOutputs = []
const npmMock = () => {
const npm = t.mock('../../lib/npm.js')
npm.output = (...msg) => npmOutputs.push(msg)
return npm
}

const processMock = (proc) => {
const mocked = {
...process,
Expand All @@ -59,7 +50,6 @@ const { argv } = process
t.afterEach(() => {
logs.length = 0
process.argv = argv
npmOutputs.length = 0
exitHandlerCalled = null
exitHandlerNpm = null
})
Expand All @@ -70,7 +60,7 @@ t.test('print the version, and treat npm_g as npm -g', async t => {
version: process.version,
})

const npm = npmMock()
const { npm, outputs } = mockNpm(t)
const cli = cliMock(npm)
await cli(proc)

Expand All @@ -82,15 +72,15 @@ t.test('print the version, and treat npm_g as npm -g', async t => {
['info', 'using', 'npm@%s', npm.version],
['info', 'using', 'node@%s', process.version],
])
t.strictSame(npmOutputs, [[npm.version]])
t.strictSame(outputs, [[npm.version]])
t.strictSame(exitHandlerCalled, [])
})

t.test('calling with --versions calls npm version with no args', async t => {
const proc = processMock({
argv: ['node', 'npm', 'install', 'or', 'whatever', '--versions'],
})
const npm = npmMock()
const { npm, outputs } = mockNpm(t)
const cli = cliMock(npm)

let versionArgs
Expand All @@ -110,7 +100,7 @@ t.test('calling with --versions calls npm version with no args', async t => {
['info', 'using', 'node@%s', process.version],
])

t.strictSame(npmOutputs, [])
t.strictSame(outputs, [])
t.strictSame(exitHandlerCalled, [])
})

Expand All @@ -119,10 +109,10 @@ t.test('print usage if no params provided', async t => {
argv: ['node', 'npm'],
})

const npm = npmMock()
const { npm, outputs } = mockNpm(t)
const cli = cliMock(npm)
await cli(proc)
t.match(npmOutputs[0][0], 'Usage:', 'outputs npm usage')
t.match(outputs[0][0], 'Usage:', 'outputs npm usage')
t.match(exitHandlerCalled, [], 'should call exitHandler with no args')
t.ok(exitHandlerNpm, 'exitHandler npm is set')
t.match(proc.exitCode, 1)
Expand All @@ -133,11 +123,11 @@ t.test('print usage if non-command param provided', async t => {
argv: ['node', 'npm', 'tset'],
})

const npm = npmMock()
const { npm, outputs } = mockNpm(t)
const cli = cliMock(npm)
await cli(proc)
t.match(npmOutputs[0][0], 'Unknown command: "tset"')
t.match(npmOutputs[0][0], 'Did you mean this?')
t.match(outputs[0][0], 'Unknown command: "tset"')
t.match(outputs[0][0], 'Did you mean this?')
t.match(exitHandlerCalled, [], 'should call exitHandler with no args')
t.ok(exitHandlerNpm, 'exitHandler npm is set')
t.match(proc.exitCode, 1)
Expand All @@ -148,7 +138,7 @@ t.test('load error calls error handler', async t => {
argv: ['node', 'npm', 'asdf'],
})

const npm = npmMock()
const { npm } = mockNpm(t)
const cli = cliMock(npm)
const er = new Error('test load error')
npm.load = () => Promise.reject(er)
Expand Down
64 changes: 25 additions & 39 deletions test/lib/dedupe.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
const t = require('tap')
const mockNpm = require('../fixtures/mock-npm')
const { real: mockNpm } = require('../fixtures/mock-npm')

t.test('should throw in global mode', (t) => {
const Dedupe = t.mock('../../lib/dedupe.js')
const npm = mockNpm({
config: { 'dry-run': false, global: true },
})
const dedupe = new Dedupe(npm)

dedupe.exec([], er => {
t.match(er, { code: 'EDEDUPEGLOBAL' }, 'throws EDEDUPEGLOBAL')
t.end()
})
t.test('should throw in global mode', async (t) => {
const { npm, command } = mockNpm(t)
await npm.load()
npm.config.set('global', true)
t.rejects(
command('dedupe'),
{ code: 'EDEDUPEGLOBAL' },
'throws EDEDUPEGLOBALE'
)
})

t.test('should remove dupes using Arborist', (t) => {
const Dedupe = t.mock('../../lib/dedupe.js', {
t.test('should remove dupes using Arborist', async (t) => {
t.plan(5)
const { npm, command } = mockNpm(t, {
'@npmcli/arborist': function (args) {
t.ok(args, 'gets options object')
t.ok(args.path, 'gets path option')
Expand All @@ -28,37 +27,24 @@ t.test('should remove dupes using Arborist', (t) => {
t.ok(arb, 'gets arborist tree')
},
})
const npm = mockNpm({
prefix: 'foo',
config: {
'dry-run': 'true',
},
})
const dedupe = new Dedupe(npm)
dedupe.exec([], er => {
if (er)
throw er
t.ok(true, 'callback is called')
t.end()
})
await npm.load()
npm.config.set('prefix', 'foo')
npm.config.set('dry-run', 'true')
await command('dedupe')
})

t.test('should remove dupes using Arborist - no arguments', (t) => {
const Dedupe = t.mock('../../lib/dedupe.js', {
t.test('should remove dupes using Arborist - no arguments', async (t) => {
t.plan(1)
const { npm, command } = mockNpm(t, {
'@npmcli/arborist': function (args) {
t.ok(args.dryRun, 'gets dryRun from config')
this.dedupe = () => {}
},
'../../lib/utils/reify-output.js': () => {},
'../../lib/utils/reify-finish.js': () => {},
})
const npm = mockNpm({
prefix: 'foo',
config: {
'dry-run': 'true',
},
})
const dedupe = new Dedupe(npm)
dedupe.exec(null, () => {
t.end()
})
await npm.load()
npm.config.set('prefix', 'foo')
npm.config.set('dry-run', true)
await command('dedupe')
})
4 changes: 2 additions & 2 deletions test/lib/diff.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { resolve, join } = require('path')
const t = require('tap')
const mockNpm = require('../fixtures/mock-npm')
const { resolve, join } = require('path')
const { fake: mockNpm } = require('../fixtures/mock-npm')

const noop = () => null
let libnpmdiff = noop
Expand Down
2 changes: 1 addition & 1 deletion test/lib/dist-tag.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const mockNpm = require('../fixtures/mock-npm')
const t = require('tap')
const { fake: mockNpm } = require('../fixtures/mock-npm')

let result = ''
let log = ''
Expand Down
2 changes: 1 addition & 1 deletion test/lib/docs.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const t = require('tap')
const mockNpm = require('../fixtures/mock-npm.js')
const { fake: mockNpm } = require('../fixtures/mock-npm.js')
const { join, sep } = require('path')

const pkgDirs = t.testdir({
Expand Down
2 changes: 1 addition & 1 deletion test/lib/exec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const t = require('tap')
const mockNpm = require('../fixtures/mock-npm')
const { fake: mockNpm } = require('../fixtures/mock-npm')
const { resolve, delimiter } = require('path')

const ARB_CTOR = []
Expand Down
2 changes: 1 addition & 1 deletion test/lib/fund.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const t = require('tap')
const mockNpm = require('../fixtures/mock-npm')
const { fake: mockNpm } = require('../fixtures/mock-npm')

const version = '1.0.0'
const funding = {
Expand Down
2 changes: 1 addition & 1 deletion test/lib/help-search.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const t = require('tap')
const { join } = require('path')
const mockNpm = require('../fixtures/mock-npm')
const { fake: mockNpm } = require('../fixtures/mock-npm')
const ansicolors = require('ansicolors')

const OUTPUT = []
Expand Down
4 changes: 2 additions & 2 deletions test/lib/init.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const t = require('tap')
const fs = require('fs')
const { resolve } = require('path')
const t = require('tap')
const mockNpm = require('../fixtures/mock-npm')
const { fake: mockNpm } = require('../fixtures/mock-npm')

const npmLog = {
disableProgress: () => null,
Expand Down
2 changes: 1 addition & 1 deletion test/lib/install.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const t = require('tap')

const Install = require('../../lib/install.js')
const mockNpm = require('../fixtures/mock-npm')
const { fake: mockNpm } = require('../fixtures/mock-npm')

t.test('should install using Arborist', (t) => {
const SCRIPTS = []
Expand Down
4 changes: 2 additions & 2 deletions test/lib/link.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const t = require('tap')
const { resolve } = require('path')
const fs = require('fs')

const Arborist = require('@npmcli/arborist')
const t = require('tap')
const mockNpm = require('../fixtures/mock-npm')
const { fake: mockNpm } = require('../fixtures/mock-npm')

const redactCwd = (path) => {
const normalizePath = p => p
Expand Down
Loading

0 comments on commit 87f67d9

Please sign in to comment.