Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(tests): expose real mock npm object #3458

Merged
merged 1 commit into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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