Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGar <gar+gh@danger.computer>2021-06-24 20:04:57 +0300
committerGar <gar+gh@danger.computer>2021-07-29 19:16:31 +0300
commit6a8086e258aa209b877e182db4b75f11de5b291d (patch)
treed24d982c63ba72e34acc32ff9b7ba99d9e6885d4 /test
parente7e1181702db2cf5d90b0c651ed5372b7ad13c74 (diff)
fix(tests): move more tests to use real npm
This moves a handful of the smaller tests to using the new npm mock that uses the real actual npm object. It also extends the testing surface area of a few tests back down into the actual `process.spawn` that results, instead of anything internal to the code. Some dead code in `lib/test.js` was found during this, as well as an instance of a module throwing a string instead of an error object. PR-URL: https://github.com/npm/cli/pull/3463 Credit: @wraithgar Close: #3463 Reviewed-by: @nlf
Diffstat (limited to 'test')
-rw-r--r--test/fixtures/mock-npm.js9
-rw-r--r--test/lib/find-dupes.js36
-rw-r--r--test/lib/get.js26
-rw-r--r--test/lib/load-all.js22
-rw-r--r--test/lib/prefix.js26
-rw-r--r--test/lib/prune.js20
-rw-r--r--test/lib/restart.js48
-rw-r--r--test/lib/root.js26
-rw-r--r--test/lib/set.js27
-rw-r--r--test/lib/start.js48
-rw-r--r--test/lib/stop.js48
-rw-r--r--test/lib/test.js60
-rw-r--r--test/lib/whoami.js50
13 files changed, 253 insertions, 193 deletions
diff --git a/test/fixtures/mock-npm.js b/test/fixtures/mock-npm.js
index e3be10b4b..3faf8d5cf 100644
--- a/test/fixtures/mock-npm.js
+++ b/test/fixtures/mock-npm.js
@@ -9,6 +9,10 @@ for (const level in npmlog.levels)
const { title, execPath } = process
const RealMockNpm = (t, otherMocks = {}) => {
+ t.afterEach(() => {
+ outputs.length = 0
+ logs.length = 0
+ })
t.teardown(() => {
npm.perfStop()
npmlog.record.length = 0
@@ -22,6 +26,9 @@ const RealMockNpm = (t, otherMocks = {}) => {
})
const logs = []
const outputs = []
+ const joinedOutput = () => {
+ return outputs.map(o => o.join(' ')).join('\n')
+ }
const npm = t.mock('../../lib/npm.js', otherMocks)
const command = async (command, args = []) => {
return new Promise((resolve, reject) => {
@@ -43,7 +50,7 @@ const RealMockNpm = (t, otherMocks = {}) => {
}
}
npm.output = (...msg) => outputs.push(msg)
- return { npm, logs, outputs, command }
+ return { npm, logs, outputs, command, joinedOutput }
}
const realConfig = require('../../lib/utils/config')
diff --git a/test/lib/find-dupes.js b/test/lib/find-dupes.js
index c7b33ceb6..17940764b 100644
--- a/test/lib/find-dupes.js
+++ b/test/lib/find-dupes.js
@@ -1,24 +1,26 @@
const t = require('tap')
-const FindDupes = require('../../lib/find-dupes.js')
+const { real: mockNpm } = require('../fixtures/mock-npm')
-t.test('should run dedupe in dryRun mode', (t) => {
- t.plan(3)
- const findDupesTest = new FindDupes({
- config: {
- set: (k, v) => {
- t.match(k, 'dry-run')
- t.match(v, true)
- },
+t.test('should run dedupe in dryRun mode', 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')
+ t.ok(args.dryRun, 'is called in dryRun mode')
+ this.dedupe = () => {
+ t.ok(true, 'dedupe is called')
+ }
},
- commands: {
- dedupe: (args, cb) => {
- t.match(args, [])
- cb()
- },
+ '../../lib/utils/reify-finish.js': (npm, arb) => {
+ t.ok(arb, 'gets arborist tree')
},
})
- findDupesTest.exec({}, () => {
- t.end()
- })
+ 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 command('find-dupes')
})
diff --git a/test/lib/get.js b/test/lib/get.js
index 9b77fbba3..30e26b745 100644
--- a/test/lib/get.js
+++ b/test/lib/get.js
@@ -1,16 +1,16 @@
const t = require('tap')
+const { real: mockNpm } = require('../fixtures/mock-npm')
-t.test('should retrieve values from npm.commands.config', (t) => {
- const Get = t.mock('../../lib/get.js')
- const get = new Get({
- commands: {
- config: ([action, arg]) => {
- t.equal(action, 'get', 'should use config get action')
- t.equal(arg, 'foo', 'should use expected key')
- t.end()
- },
- },
- })
-
- get.exec(['foo'])
+t.test('should retrieve values from config', async t => {
+ const { joinedOutput, command, npm } = mockNpm(t)
+ const name = 'editor'
+ const value = 'vigor'
+ await npm.load()
+ npm.config.set(name, value)
+ await command('get', [name])
+ t.equal(
+ joinedOutput(),
+ value,
+ 'outputs config item'
+ )
})
diff --git a/test/lib/load-all.js b/test/lib/load-all.js
index e6e407805..c38c24493 100644
--- a/test/lib/load-all.js
+++ b/test/lib/load-all.js
@@ -1,15 +1,24 @@
const t = require('tap')
const glob = require('glob')
const { resolve } = require('path')
+const { real: mockNpm } = require('../fixtures/mock-npm')
const full = process.env.npm_lifecycle_event === 'check-coverage'
if (!full)
t.pass('nothing to do here, not checking for full coverage')
else {
- // some files do config.get() on load, so have to load npm first
- const npm = require('../../lib/npm.js')
- t.test('load npm first', t => npm.load(t.end))
+ const { npm } = mockNpm(t)
+
+ t.teardown(() => {
+ const exitHandler = require('../../lib/utils/exit-handler.js')
+ exitHandler.setNpm(npm)
+ exitHandler()
+ })
+
+ t.test('load npm first', async t => {
+ await npm.load()
+ })
t.test('load all the files', t => {
// just load all the files so we measure coverage for the missing tests
@@ -21,11 +30,4 @@ else {
t.pass('loaded all files')
t.end()
})
-
- t.test('call the exit handler so we dont freak out', t => {
- const exitHandler = require('../../lib/utils/exit-handler.js')
- exitHandler.setNpm(npm)
- exitHandler()
- t.end()
- })
}
diff --git a/test/lib/prefix.js b/test/lib/prefix.js
index 526631388..18a37f3cc 100644
--- a/test/lib/prefix.js
+++ b/test/lib/prefix.js
@@ -1,19 +1,13 @@
const t = require('tap')
+const { real: mockNpm } = require('../fixtures/mock-npm')
-t.test('prefix', (t) => {
- t.plan(3)
- const dir = '/prefix/dir'
-
- const Prefix = require('../../lib/prefix.js')
- const prefix = new Prefix({
- prefix: dir,
- output: (output) => {
- t.equal(output, dir, 'prints the correct directory')
- },
- })
-
- prefix.exec([], (err) => {
- t.error(err, 'npm prefix')
- t.ok('should have printed directory')
- })
+t.test('prefix', async (t) => {
+ const { joinedOutput, command, npm } = mockNpm(t)
+ await npm.load()
+ await command('prefix')
+ t.equal(
+ joinedOutput(),
+ npm.prefix,
+ 'outputs npm.prefix'
+ )
})
diff --git a/test/lib/prune.js b/test/lib/prune.js
index 87bb1370f..3e47feb46 100644
--- a/test/lib/prune.js
+++ b/test/lib/prune.js
@@ -1,7 +1,9 @@
const t = require('tap')
+const { real: mockNpm } = require('../fixtures/mock-npm')
-t.test('should prune using Arborist', (t) => {
- const Prune = t.mock('../../lib/prune.js', {
+t.test('should prune using Arborist', async (t) => {
+ t.plan(4)
+ const { command, npm } = mockNpm(t, {
'@npmcli/arborist': function (args) {
t.ok(args, 'gets options object')
t.ok(args.path, 'gets path option')
@@ -13,16 +15,6 @@ t.test('should prune using Arborist', (t) => {
t.ok(arb, 'gets arborist tree')
},
})
- const prune = new Prune({
- prefix: 'foo',
- flatOptions: {
- foo: 'bar',
- },
- })
- prune.exec(null, er => {
- if (er)
- throw er
- t.ok(true, 'callback is called')
- t.end()
- })
+ await npm.load()
+ await command('prune')
})
diff --git a/test/lib/restart.js b/test/lib/restart.js
index 9719476c4..153c31447 100644
--- a/test/lib/restart.js
+++ b/test/lib/restart.js
@@ -1,16 +1,36 @@
const t = require('tap')
-let runArgs
-const npm = {
- commands: {
- 'run-script': (args, cb) => {
- runArgs = args
- cb()
- },
- },
-}
-const Restart = require('../../lib/restart.js')
-const restart = new Restart(npm)
-restart.exec(['foo'], () => {
- t.match(runArgs, ['restart', 'foo'])
- t.end()
+const spawk = require('spawk')
+const { real: mockNpm } = require('../fixtures/mock-npm')
+
+spawk.preventUnmatched()
+t.teardown(() => {
+ spawk.unload()
+})
+
+// TODO this ... smells. npm "script-shell" config mentions defaults but those
+// are handled by run-script, not npm. So for now we have to tie tests to some
+// 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',
+ },
+ }),
+ })
+ const { command, npm } = mockNpm(t)
+ await npm.load()
+ npm.log.level = 'silent'
+ npm.localPrefix = prefix
+ const [scriptShell] = makeSpawnArgs({ path: prefix })
+ const script = spawk.spawn(scriptShell, (args) => {
+ t.ok(args.includes('node ./test-restart.js "foo"'), 'ran stop script with extra args')
+ return true
+ })
+ await command('restart', ['foo'])
+ t.ok(script.called, 'script ran')
})
diff --git a/test/lib/root.js b/test/lib/root.js
index 5460f3d49..7b91654c6 100644
--- a/test/lib/root.js
+++ b/test/lib/root.js
@@ -1,19 +1,13 @@
const t = require('tap')
+const { real: mockNpm } = require('../fixtures/mock-npm')
-t.test('root', (t) => {
- t.plan(3)
- const dir = '/root/dir'
-
- const Root = require('../../lib/root.js')
- const root = new Root({
- dir,
- output: (output) => {
- t.equal(output, dir, 'prints the correct directory')
- },
- })
-
- root.exec([], (err) => {
- t.error(err, 'npm root')
- t.ok('should have printed directory')
- })
+t.test('prefix', async (t) => {
+ const { joinedOutput, command, npm } = mockNpm(t)
+ await npm.load()
+ await command('root')
+ t.equal(
+ joinedOutput(),
+ npm.dir,
+ 'outputs npm.dir'
+ )
})
diff --git a/test/lib/set.js b/test/lib/set.js
index f51065a4b..14d094001 100644
--- a/test/lib/set.js
+++ b/test/lib/set.js
@@ -1,5 +1,32 @@
const t = require('tap')
+// can't run this until npm set can save to npm.localPrefix
+t.skip('npm set', async t => {
+ const { real: mockNpm } = require('../fixtures/mock-npm')
+ const { joinedOutput, command, npm } = mockNpm(t)
+ await npm.load()
+
+ t.test('no args', async t => {
+ t.rejects(
+ command('set'),
+ /Usage:/,
+ 'prints usage'
+ )
+ })
+
+ t.test('test-config-item', async t => {
+ npm.localPrefix = t.testdir({})
+ t.not(npm.config.get('test-config-item', 'project'), 'test config value', 'config is not already new value')
+ // This will write to ~/.npmrc!
+ // Don't unskip until we can write to project level
+ await command('set', ['test-config-item=test config value'])
+ t.equal(joinedOutput(), '', 'outputs nothing')
+ t.equal(npm.config.get('test-config-item', 'project'), 'test config value', 'config is set to new value')
+ })
+})
+
+// Everything after this can go away once the above test is unskipped
+
let configArgs = null
const npm = {
commands: {
diff --git a/test/lib/start.js b/test/lib/start.js
index 4e77f9691..5c38c71a9 100644
--- a/test/lib/start.js
+++ b/test/lib/start.js
@@ -1,16 +1,36 @@
const t = require('tap')
-let runArgs
-const npm = {
- commands: {
- 'run-script': (args, cb) => {
- runArgs = args
- cb()
- },
- },
-}
-const Start = require('../../lib/start.js')
-const start = new Start(npm)
-start.exec(['foo'], () => {
- t.match(runArgs, ['start', 'foo'])
- t.end()
+const spawk = require('spawk')
+const { real: mockNpm } = require('../fixtures/mock-npm')
+
+spawk.preventUnmatched()
+t.teardown(() => {
+ spawk.unload()
+})
+
+// TODO this ... smells. npm "script-shell" config mentions defaults but those
+// are handled by run-script, not npm. So for now we have to tie tests to some
+// 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',
+ },
+ }),
+ })
+ const { command, npm } = mockNpm(t)
+ await npm.load()
+ npm.log.level = 'silent'
+ npm.localPrefix = prefix
+ const [scriptShell] = makeSpawnArgs({ path: prefix })
+ const script = spawk.spawn(scriptShell, (args) => {
+ t.ok(args.includes('node ./test-start.js "foo"'), 'ran start script with extra args')
+ return true
+ })
+ await command('start', ['foo'])
+ t.ok(script.called, 'script ran')
})
diff --git a/test/lib/stop.js b/test/lib/stop.js
index 92ca84bd8..04cdb4e5e 100644
--- a/test/lib/stop.js
+++ b/test/lib/stop.js
@@ -1,16 +1,36 @@
const t = require('tap')
-let runArgs
-const npm = {
- commands: {
- 'run-script': (args, cb) => {
- runArgs = args
- cb()
- },
- },
-}
-const Stop = require('../../lib/stop.js')
-const stop = new Stop(npm)
-stop.exec(['foo'], () => {
- t.match(runArgs, ['stop', 'foo'])
- t.end()
+const spawk = require('spawk')
+const { real: mockNpm } = require('../fixtures/mock-npm')
+
+spawk.preventUnmatched()
+t.teardown(() => {
+ spawk.unload()
+})
+
+// TODO this ... smells. npm "script-shell" config mentions defaults but those
+// are handled by run-script, not npm. So for now we have to tie tests to some
+// 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: {
+ stop: 'node ./test-stop.js',
+ },
+ }),
+ })
+ const { command, npm } = mockNpm(t)
+ await npm.load()
+ npm.log.level = 'silent'
+ npm.localPrefix = prefix
+ const [scriptShell] = makeSpawnArgs({ path: prefix })
+ const script = spawk.spawn(scriptShell, (args) => {
+ t.ok(args.includes('node ./test-stop.js "foo"'), 'ran stop script with extra args')
+ return true
+ })
+ await command('stop', ['foo'])
+ t.ok(script.called, 'script ran')
})
diff --git a/test/lib/test.js b/test/lib/test.js
index c151b1e82..d597ba274 100644
--- a/test/lib/test.js
+++ b/test/lib/test.js
@@ -1,38 +1,36 @@
const t = require('tap')
-let RUN_ARGS = null
-const npm = {
- commands: {
- 'run-script': (args, cb) => {
- RUN_ARGS = args
- cb()
- },
- },
-}
-const Test = require('../../lib/test.js')
-const test = new Test(npm)
+const spawk = require('spawk')
+const { real: mockNpm } = require('../fixtures/mock-npm')
-t.test('run a test', t => {
- test.exec([], (er) => {
- t.strictSame(RUN_ARGS, ['test'], 'added "test" to the args')
- })
- test.exec(['hello', 'world'], (er) => {
- t.strictSame(RUN_ARGS, ['test', 'hello', 'world'], 'added positional args')
- })
+spawk.preventUnmatched()
+t.teardown(() => {
+ spawk.unload()
+})
- const lcErr = Object.assign(new Error('should not see this'), {
- code: 'ELIFECYCLE',
- })
- const otherErr = new Error('should see this')
+// TODO this ... smells. npm "script-shell" config mentions defaults but those
+// are handled by run-script, not npm. So for now we have to tie tests to some
+// pretty specific internals of runScript
+const makeSpawnArgs = require('@npmcli/run-script/lib/make-spawn-args.js')
- npm.commands['run-script'] = (args, cb) => cb(lcErr)
- test.exec([], (er) => {
- t.equal(er, 'Test failed. See above for more details.')
+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',
+ },
+ }),
})
-
- npm.commands['run-script'] = (args, cb) => cb(otherErr)
- test.exec([], (er) => {
- t.match(er, { message: 'should see this' })
+ const { command, npm } = mockNpm(t)
+ await npm.load()
+ npm.log.level = 'silent'
+ npm.localPrefix = prefix
+ const [scriptShell] = makeSpawnArgs({ path: prefix })
+ const script = spawk.spawn(scriptShell, (args) => {
+ t.ok(args.includes('node ./test-test.js "foo"'), 'ran test script with extra args')
+ return true
})
-
- t.end()
+ await command('test', ['foo'])
+ t.ok(script.called, 'script ran')
})
diff --git a/test/lib/whoami.js b/test/lib/whoami.js
index 9190e3858..c54ee2a5a 100644
--- a/test/lib/whoami.js
+++ b/test/lib/whoami.js
@@ -1,41 +1,25 @@
const t = require('tap')
-const { fake: mockNpm } = require('../fixtures/mock-npm')
+const { real: mockNpm } = require('../fixtures/mock-npm')
-t.test('whoami', (t) => {
- t.plan(3)
- const Whoami = t.mock('../../lib/whoami.js', {
- '../../lib/utils/get-identity.js': () => Promise.resolve('foo'),
- })
- const npm = mockNpm({
- config: { json: false },
- output: (output) => {
- t.equal(output, 'foo', 'should output the username')
- },
- })
-
- const whoami = new Whoami(npm)
+const username = 'foo'
+const { joinedOutput, command, npm } = mockNpm(t, {
+ '../../lib/utils/get-identity.js': () => Promise.resolve(username),
+})
- whoami.exec([], (err) => {
- t.error(err, 'npm whoami')
- t.ok('should successfully print username')
- })
+t.before(async () => {
+ await npm.load()
})
-t.test('whoami json', (t) => {
- t.plan(3)
- const Whoami = t.mock('../../lib/whoami.js', {
- '../../lib/utils/get-identity.js': () => Promise.resolve('foo'),
- })
- const npm = mockNpm({
- config: { json: true },
- output: (output) => {
- t.equal(output, '"foo"', 'should output the username')
- },
- })
- const whoami = new Whoami(npm)
+t.test('npm whoami', async (t) => {
+ await command('whoami')
+ t.equal(joinedOutput(), username, 'should print username')
+})
- whoami.exec([], (err) => {
- t.error(err, 'npm whoami')
- t.ok('should successfully print username as json')
+t.test('npm whoami --json', async (t) => {
+ t.teardown(() => {
+ npm.config.set('json', false)
})
+ npm.config.set('json', true)
+ await command('whoami')
+ t.equal(JSON.parse(joinedOutput()), username, 'should print username')
})