From 3a159d27e976933098ec18fa9c3e474c85b5b332 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 10 Feb 2021 16:10:41 -0800 Subject: [PATCH] fix(tests): rewrite doctor tests This decouples our tests from depending on the node version being right, and allows us to run in all of the environments we need to during CI. PR-URL: https://github.com/npm/cli/pull/2681 Credit: @ljharb Close: #2681 Reviewed-by: @wraithgar --- test/lib/doctor.js | 1640 ++++++++++++++++++++++---------------------- 1 file changed, 833 insertions(+), 807 deletions(-) diff --git a/test/lib/doctor.js b/test/lib/doctor.js index db41fc8e5dd56..f5e6fd062a331 100644 --- a/test/lib/doctor.js +++ b/test/lib/doctor.js @@ -22,6 +22,13 @@ const ping = async () => { throw pingError } +let whichError = null +const which = async () => { + if (whichError) + throw whichError + return '/path/to/git' +} + const nodeVersions = [ { version: 'v14.0.0', lts: false }, { version: 'v13.0.0', lts: false }, @@ -106,13 +113,6 @@ const pacote = { }, } -let whichError = null -const which = async () => { - if (whichError) - throw whichError - return '/path/to/git' -} - let verifyResponse = { verifiedCount: 1, verifiedContent: 1 } const cacache = { verify: async () => { @@ -133,811 +133,837 @@ const doctor = requireInject('../../lib/doctor.js', { which, }) -test('npm doctor checks ok', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - clearLogs() - }) - - doctor([], (err) => { - if (err) { - t.fail(output) - return t.end() - } - - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*ok/, 'ping output is ok') - t.match(output, /npm -v\s*ok/, 'npm -v output is ok') - t.match(output, /node -v\s*ok/, 'node -v output is ok') - t.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') - t.match(output, /which git\s*ok/, 'which git output is ok') - t.match(output, /cached files\s*ok/, 'cached files are ok') - t.match(output, /local node_modules\s*ok/, 'local node_modules are ok') - t.match(output, /global node_modules\s*ok/, 'global node_modules are ok') - t.match(output, /local bin folder\s*ok/, 'local bin is ok') - t.match(output, /global bin folder\s*ok/, 'global bin is ok') - t.match(output, /cache contents\s*ok/, 'cache contents is ok') - t.end() - }) -}) - -test('npm doctor supports silent', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - npm.log.level = 'info' - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - npm.log.level = 'error' - clearLogs() - }) - - doctor([], (err) => { - if (err) { - t.fail(err) - return t.end() - } - - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.strictSame(output, [], 'did not print output') - t.end() - }) -}) - -test('npm doctor supports color', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - npm.color = true - pingError = { message: 'generic error' } - const _consoleError = console.error - console.error = () => {} - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - delete npm.color - pingError = null - console.error = _consoleError - clearLogs() - }) - - doctor([], (err) => { - t.match(err, /Some problems found/, 'detected the ping error') - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping.*not ok/, 'ping output is ok') - t.match(output, /npm -v.*ok/, 'npm -v output is ok') - t.match(output, /node -v.*ok/, 'node -v output is ok') - t.match(output, /npm config get registry.*ok.*using default/, 'npm config get registry output is ok') - t.match(output, /which git.*ok/, 'which git output is ok') - t.match(output, /cached files.*ok/, 'cached files are ok') - t.match(output, /local node_modules.*ok/, 'local node_modules are ok') - t.match(output, /global node_modules.*ok/, 'global node_modules are ok') - t.match(output, /local bin folder.*ok/, 'local bin is ok') - t.match(output, /global bin folder.*ok/, 'global bin is ok') - t.match(output, /cache contents.*ok/, 'cache contents is ok') - t.notEqual(output[0], ansiTrim(output[0]), 'output should contain color codes') - t.end() - }) -}) - -test('npm doctor skips some tests in windows', t => { - const winDoctor = requireInject('../../lib/doctor.js', { - '../../lib/utils/is-windows.js': true, - '../../lib/utils/ping.js': ping, - '../../lib/utils/output.js': (data) => { - output.push(data) - }, - '../../lib/npm.js': npm, - cacache, - pacote, - 'make-fetch-happen': fetch, - which, - }) - - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - clearLogs() - }) - - winDoctor([], (err) => { - if (err) { - t.fail(output) - return t.end() - } - - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: undefined, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*ok/, 'ping output is ok') - t.match(output, /npm -v\s*ok/, 'npm -v output is ok') - t.match(output, /node -v\s*ok/, 'node -v output is ok') - t.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') - t.match(output, /which git\s*ok/, 'which git output is ok') - t.match(output, /cache contents\s*ok/, 'cache contents is ok') - t.end() +const origVersion = process.version +test('node versions', t => { + t.plan(nodeVersions.length) + + nodeVersions.forEach(({ version }) => { + t.test(`${version}:`, vt => { + Object.defineProperty(process, 'version', { value: version }) + vt.teardown(() => { + Object.defineProperty(process, 'version', { value: origVersion }) + }) + + vt.test(`${version}: npm doctor checks ok`, st => { + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + clearLogs() + }) + + doctor([], (err) => { + if (err) { + st.fail(output) + return st.end() + } + + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*ok/, 'ping output is ok') + st.match(output, /npm -v\s*ok/, 'npm -v output is ok') + st.match(output, /node -v\s*ok/, 'node -v output is ok') + st.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') + st.match(output, /which git\s*ok/, 'which git output is ok') + st.match(output, /cached files\s*ok/, 'cached files are ok') + st.match(output, /local node_modules\s*ok/, 'local node_modules are ok') + st.match(output, /global node_modules\s*ok/, 'global node_modules are ok') + st.match(output, /local bin folder\s*ok/, 'local bin is ok') + st.match(output, /global bin folder\s*ok/, 'global bin is ok') + st.match(output, /cache contents\s*ok/, 'cache contents is ok') + st.end() + }) + }) + + vt.test('npm doctor supports silent', st => { + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + npm.log.level = 'info' + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + npm.log.level = 'error' + clearLogs() + }) + + doctor([], (err) => { + if (err) { + st.fail(err) + return st.end() + } + + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.strictSame(output, [], 'did not print output') + st.end() + }) + }) + + vt.test('npm doctor supports color', st => { + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + npm.color = true + pingError = { message: 'generic error' } + const _consoleError = console.error + console.error = () => {} + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + delete npm.color + pingError = null + console.error = _consoleError + clearLogs() + }) + + doctor([], (err) => { + st.match(err, /Some problems found/, 'detected the ping error') + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping.*not ok/, 'ping output is ok') + st.match(output, /npm -v.*ok/, 'npm -v output is ok') + st.match(output, /node -v.*ok/, 'node -v output is ok') + st.match(output, /npm config get registry.*ok.*using default/, 'npm config get registry output is ok') + st.match(output, /which git.*ok/, 'which git output is ok') + st.match(output, /cached files.*ok/, 'cached files are ok') + st.match(output, /local node_modules.*ok/, 'local node_modules are ok') + st.match(output, /global node_modules.*ok/, 'global node_modules are ok') + st.match(output, /local bin folder.*ok/, 'local bin is ok') + st.match(output, /global bin folder.*ok/, 'global bin is ok') + st.match(output, /cache contents.*ok/, 'cache contents is ok') + st.notEqual(output[0], ansiTrim(output[0]), 'output should contain color codes') + st.end() + }) + }) + + vt.test('npm doctor skips some tests in windows', st => { + const winDoctor = requireInject('../../lib/doctor.js', { + '../../lib/utils/is-windows.js': true, + '../../lib/utils/ping.js': ping, + '../../lib/utils/output.js': (data) => { + output.push(data) + }, + '../../lib/npm.js': npm, + cacache, + pacote, + 'make-fetch-happen': fetch, + which, + }) + + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + clearLogs() + }) + + winDoctor([], (err) => { + if (err) { + st.fail(output) + return st.end() + } + + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: undefined, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*ok/, 'ping output is ok') + st.match(output, /npm -v\s*ok/, 'npm -v output is ok') + st.match(output, /node -v\s*ok/, 'node -v output is ok') + st.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') + st.match(output, /which git\s*ok/, 'which git output is ok') + st.match(output, /cache contents\s*ok/, 'cache contents is ok') + st.end() + }) + }) + + vt.test('npm doctor ping error E{3}', st => { + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + pingError = { code: 'E111', message: 'this error is 111' } + const consoleError = console.error + // we just print an empty line here, so swallow it and ignore + console.error = () => {} + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + pingError = null + console.error = consoleError + clearLogs() + }) + + doctor([], (err) => { + st.match(err, /Some problems found/, 'detected the ping error') + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*not ok\s*111 this error is 111/, 'ping output contains trimmed error') + st.match(output, /npm -v\s*ok/, 'npm -v output is ok') + st.match(output, /node -v\s*ok/, 'node -v output is ok') + st.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') + st.match(output, /which git\s*ok/, 'which git output is ok') + st.match(output, /cached files\s*ok/, 'cached files are ok') + st.match(output, /local node_modules\s*ok/, 'local node_modules are ok') + st.match(output, /global node_modules\s*ok/, 'global node_modules are ok') + st.match(output, /local bin folder\s*ok/, 'local bin is ok') + st.match(output, /global bin folder\s*ok/, 'global bin is ok') + st.match(output, /cache contents\s*ok/, 'cache contents is ok') + st.end() + }) + }) + + vt.test('npm doctor generic ping error', st => { + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + pingError = { message: 'generic error' } + const consoleError = console.error + // we just print an empty line here, so swallow it and ignore + console.error = () => {} + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + pingError = null + console.error = consoleError + clearLogs() + }) + + doctor([], (err) => { + st.match(err, /Some problems found/, 'detected the ping error') + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*not ok\s*generic error/, 'ping output contains trimmed error') + st.match(output, /npm -v\s*ok/, 'npm -v output is ok') + st.match(output, /node -v\s*ok/, 'node -v output is ok') + st.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') + st.match(output, /which git\s*ok/, 'which git output is ok') + st.match(output, /cached files\s*ok/, 'cached files are ok') + st.match(output, /local node_modules\s*ok/, 'local node_modules are ok') + st.match(output, /global node_modules\s*ok/, 'global node_modules are ok') + st.match(output, /local bin folder\s*ok/, 'local bin is ok') + st.match(output, /global bin folder\s*ok/, 'global bin is ok') + st.match(output, /cache contents\s*ok/, 'cache contents is ok') + st.end() + }) + }) + + vt.test('npm doctor outdated npm version', st => { + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + latestNpm = '7.1.1' + const consoleError = console.error + // we just print an empty line here, so swallow it and ignore + console.error = () => {} + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + latestNpm = npm.version + console.error = consoleError + clearLogs() + }) + + doctor([], (err) => { + st.match(err, /Some problems found/, 'detected the out of date npm') + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*ok/, 'ping output is ok') + st.match(output, /npm -v\s*not ok/, 'npm -v output is not ok') + st.match(output, /node -v\s*ok/, 'node -v output is ok') + st.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') + st.match(output, /which git\s*ok/, 'which git output is ok') + st.match(output, /cached files\s*ok/, 'cached files are ok') + st.match(output, /local node_modules\s*ok/, 'local node_modules are ok') + st.match(output, /global node_modules\s*ok/, 'global node_modules are ok') + st.match(output, /local bin folder\s*ok/, 'local bin is ok') + st.match(output, /global bin folder\s*ok/, 'global bin is ok') + st.match(output, /cache contents\s*ok/, 'cache contents is ok') + st.end() + }) + }) + + vt.test('npm doctor file permission checks', st => { + const dir = st.testdir({ + cache: { + one: 'one', + link: st.fixture('symlink', './one'), + unreadable: 'unreadable', + baddir: {}, + }, + local: { + two: 'two', + notmine: 'notmine', + }, + global: { + three: 'three', + broken: 'broken', + }, + localBin: { + four: 'four', + five: 'five', + }, + globalBin: { + six: 'six', + seven: 'seven', + }, + }) + + const _fsLstat = fs.lstat + fs.lstat = (p, cb) => { + let err = null + let stat = null + + try { + stat = fs.lstatSync(p) + } catch (err) { + return cb(err) + } + + switch (p) { + case join(dir, 'local', 'notmine'): + stat.uid += 1 + stat.gid += 1 + break + case join(dir, 'global', 'broken'): + err = new Error('broken') + break + } + + return cb(err, stat) + } + + const _fsReaddir = fs.readdir + fs.readdir = (p, cb) => { + let err = null + let result = null + + try { + result = fs.readdirSync(p) + } catch (err) { + return cb(err) + } + + if (p === join(dir, 'cache', 'baddir')) + err = new Error('broken') + + return cb(err, result) + } + + const _fsAccess = fs.access + fs.access = (p, mask, cb) => { + const err = new Error('failed') + switch (p) { + case join(dir, 'cache', 'unreadable'): + case join(dir, 'localBin', 'four'): + case join(dir, 'globalBin', 'six'): + return cb(err) + default: + return cb(null) + } + } + + const doctor = requireInject('../../lib/doctor.js', { + '../../lib/utils/is-windows.js': false, + '../../lib/utils/ping.js': ping, + '../../lib/utils/output.js': (data) => { + output.push(data) + }, + '../../lib/npm.js': npm, + cacache, + pacote, + 'make-fetch-happen': fetch, + which, + fs, + }) + // it's necessary to allow tests in node 10.x to not mark 12.x as lted + + npm.cache = npm.flatOptions.cache = join(dir, 'cache') + npm.localDir = join(dir, 'local') + npm.globalDir = join(dir, 'global') + npm.localBin = join(dir, 'localBin') + npm.globalBin = join(dir, 'globalBin') + const _consoleError = console.error + console.error = () => {} + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + console.error = _consoleError + fs.lstat = _fsLstat + fs.readdir = _fsReaddir + fs.access = _fsAccess + clearLogs() + }) + + doctor([], (err) => { + st.match(err, /Some problems found/, 'identified problems') + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [join(dir, 'cache')]: { finished: true }, + [join(dir, 'local')]: { finished: true }, + [join(dir, 'global')]: { finished: true }, + [join(dir, 'localBin')]: { finished: true }, + [join(dir, 'globalBin')]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*ok/, 'ping output is ok') + st.match(output, /npm -v\s*ok/, 'npm -v output is ok') + st.match(output, /node -v\s*ok/, 'node -v output is ok') + st.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') + st.match(output, /which git\s*ok/, 'which git output is ok') + st.match(output, /cached files\s*not ok/, 'cached files are not ok') + st.match(output, /local node_modules\s*not ok/, 'local node_modules are not ok') + st.match(output, /global node_modules\s*not ok/, 'global node_modules are not ok') + st.match(output, /local bin folder\s*not ok/, 'local bin is not ok') + st.match(output, /global bin folder\s*not ok/, 'global bin is not ok') + st.match(output, /cache contents\s*ok/, 'cache contents is ok') + st.end() + }) + }) + + vt.test('npm doctor missing git', st => { + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + whichError = new Error('boom') + const consoleError = console.error + // we just print an empty line here, so swallow it and ignore + console.error = () => {} + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + whichError = null + console.error = consoleError + clearLogs() + }) + + doctor([], (err) => { + st.match(err, /Some problems found/, 'detected the missing git') + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*ok/, 'ping output is ok') + st.match(output, /npm -v\s*ok/, 'npm -v output is ok') + st.match(output, /node -v\s*ok/, 'node -v output is ok') + st.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') + st.match(output, /which git\s*not ok/, 'which git output is not ok') + st.match(output, /cached files\s*ok/, 'cached files are ok') + st.match(output, /local node_modules\s*ok/, 'local node_modules are ok') + st.match(output, /global node_modules\s*ok/, 'global node_modules are ok') + st.match(output, /local bin folder\s*ok/, 'local bin is ok') + st.match(output, /global bin folder\s*ok/, 'global bin is ok') + st.match(output, /cache contents\s*ok/, 'cache contents is ok') + st.end() + }) + }) + + vt.test('npm doctor cache verification showed bad content', st => { + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + const _verifyResponse = verifyResponse + verifyResponse = { + ...verifyResponse, + badContentCount: 1, + } + const consoleError = console.error + // we just print an empty line here, so swallow it and ignore + console.error = () => {} + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + verifyResponse = _verifyResponse + console.error = consoleError + clearLogs() + }) + + doctor([], (err) => { + // cache verification problems get fixed and so do not throw an error + if (err) { + st.fail(output) + return st.end() + } + + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*ok/, 'ping output is ok') + st.match(output, /npm -v\s*ok/, 'npm -v output is ok') + st.match(output, /node -v\s*ok/, 'node -v output is ok') + st.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') + st.match(output, /which git\s*ok/, 'which git output is ok') + st.match(output, /cached files\s*ok/, 'cached files are ok') + st.match(output, /local node_modules\s*ok/, 'local node_modules are ok') + st.match(output, /global node_modules\s*ok/, 'global node_modules are ok') + st.match(output, /local bin folder\s*ok/, 'local bin is ok') + st.match(output, /global bin folder\s*ok/, 'global bin is ok') + st.match(output, /cache contents\s*ok/, 'cache contents is not ok') + st.end() + }) + }) + + vt.test('npm doctor cache verification showed reclaimed content', st => { + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + const _verifyResponse = verifyResponse + verifyResponse = { + ...verifyResponse, + reclaimedCount: 1, + reclaimedSize: 100, + } + const consoleError = console.error + // we just print an empty line here, so swallow it and ignore + console.error = () => {} + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + verifyResponse = _verifyResponse + console.error = consoleError + clearLogs() + }) + + doctor([], (err) => { + // cache verification problems get fixed and so do not throw an error + if (err) { + st.fail(output) + return st.end() + } + + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*ok/, 'ping output is ok') + st.match(output, /npm -v\s*ok/, 'npm -v output is ok') + st.match(output, /node -v\s*ok/, 'node -v output is ok') + st.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') + st.match(output, /which git\s*ok/, 'which git output is ok') + st.match(output, /cached files\s*ok/, 'cached files are ok') + st.match(output, /local node_modules\s*ok/, 'local node_modules are ok') + st.match(output, /global node_modules\s*ok/, 'global node_modules are ok') + st.match(output, /local bin folder\s*ok/, 'local bin is ok') + st.match(output, /global bin folder\s*ok/, 'global bin is ok') + st.match(output, /cache contents\s*ok/, 'cache contents is not ok') + st.end() + }) + }) + + vt.test('npm doctor cache verification showed missing content', st => { + const dir = t.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + const _verifyResponse = verifyResponse + verifyResponse = { + ...verifyResponse, + missingContent: 1, + } + const consoleError = console.error + // we just print an empty line here, so swallow it and ignore + console.error = () => {} + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + verifyResponse = _verifyResponse + console.error = consoleError + clearLogs() + }) + + doctor([], (err) => { + // cache verification problems get fixed and so do not throw an error + if (err) { + st.fail(output) + return st.end() + } + + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*ok/, 'ping output is ok') + st.match(output, /npm -v\s*ok/, 'npm -v output is ok') + st.match(output, /node -v\s*ok/, 'node -v output is ok') + st.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') + st.match(output, /which git\s*ok/, 'which git output is ok') + st.match(output, /cached files\s*ok/, 'cached files are ok') + st.match(output, /local node_modules\s*ok/, 'local node_modules are ok') + st.match(output, /global node_modules\s*ok/, 'global node_modules are ok') + st.match(output, /local bin folder\s*ok/, 'local bin is ok') + st.match(output, /global bin folder\s*ok/, 'global bin is ok') + st.match(output, /cache contents\s*ok/, 'cache contents is not ok') + st.end() + }) + }) + + vt.test('npm doctor not using default registry', st => { + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + const _currentRegistry = npm.flatOptions.registry + npm.flatOptions.registry = 'https://google.com' + const consoleError = console.error + // we just print an empty line here, so swallow it and ignore + console.error = () => {} + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + npm.flatOptions.registry = _currentRegistry + console.error = consoleError + clearLogs() + }) + + doctor([], (err) => { + // cache verification problems get fixed and so do not throw an error + st.match(err, /Some problems found/, 'detected the non-default registry') + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*ok/, 'ping output is ok') + st.match(output, /npm -v\s*ok/, 'npm -v output is ok') + st.match(output, /node -v\s*ok/, 'node -v output is ok') + st.match(output, /npm config get registry\s*not ok/, 'npm config get registry output is not ok') + st.match(output, /which git\s*ok/, 'which git output is ok') + st.match(output, /cached files\s*ok/, 'cached files are ok') + st.match(output, /local node_modules\s*ok/, 'local node_modules are ok') + st.match(output, /global node_modules\s*ok/, 'global node_modules are ok') + st.match(output, /local bin folder\s*ok/, 'local bin is ok') + st.match(output, /global bin folder\s*ok/, 'global bin is ok') + st.match(output, /cache contents\s*ok/, 'cache contents is ok') + st.end() + }) + }) + + vt.end() + }) }) }) -test('npm doctor ping error E{3}', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - pingError = { code: 'E111', message: 'this error is 111' } - const consoleError = console.error - // we just print an empty line here, so swallow it and ignore - console.error = () => {} - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - pingError = null - console.error = consoleError - clearLogs() - }) - - doctor([], (err) => { - t.match(err, /Some problems found/, 'detected the ping error') - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*not ok\s*111 this error is 111/, 'ping output contains trimmed error') - t.match(output, /npm -v\s*ok/, 'npm -v output is ok') - t.match(output, /node -v\s*ok/, 'node -v output is ok') - t.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') - t.match(output, /which git\s*ok/, 'which git output is ok') - t.match(output, /cached files\s*ok/, 'cached files are ok') - t.match(output, /local node_modules\s*ok/, 'local node_modules are ok') - t.match(output, /global node_modules\s*ok/, 'global node_modules are ok') - t.match(output, /local bin folder\s*ok/, 'local bin is ok') - t.match(output, /global bin folder\s*ok/, 'global bin is ok') - t.match(output, /cache contents\s*ok/, 'cache contents is ok') - t.end() - }) -}) - -test('npm doctor generic ping error', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - pingError = { message: 'generic error' } - const consoleError = console.error - // we just print an empty line here, so swallow it and ignore - console.error = () => {} - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - pingError = null - console.error = consoleError - clearLogs() - }) - - doctor([], (err) => { - t.match(err, /Some problems found/, 'detected the ping error') - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*not ok\s*generic error/, 'ping output contains trimmed error') - t.match(output, /npm -v\s*ok/, 'npm -v output is ok') - t.match(output, /node -v\s*ok/, 'node -v output is ok') - t.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') - t.match(output, /which git\s*ok/, 'which git output is ok') - t.match(output, /cached files\s*ok/, 'cached files are ok') - t.match(output, /local node_modules\s*ok/, 'local node_modules are ok') - t.match(output, /global node_modules\s*ok/, 'global node_modules are ok') - t.match(output, /local bin folder\s*ok/, 'local bin is ok') - t.match(output, /global bin folder\s*ok/, 'global bin is ok') - t.match(output, /cache contents\s*ok/, 'cache contents is ok') - t.end() - }) -}) - -test('npm doctor outdated npm version', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - latestNpm = '7.1.1' - const consoleError = console.error - // we just print an empty line here, so swallow it and ignore - console.error = () => {} - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - latestNpm = npm.version - console.error = consoleError - clearLogs() - }) - - doctor([], (err) => { - t.match(err, /Some problems found/, 'detected the out of date npm') - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*ok/, 'ping output is ok') - t.match(output, /npm -v\s*not ok/, 'npm -v output is not ok') - t.match(output, /node -v\s*ok/, 'node -v output is ok') - t.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') - t.match(output, /which git\s*ok/, 'which git output is ok') - t.match(output, /cached files\s*ok/, 'cached files are ok') - t.match(output, /local node_modules\s*ok/, 'local node_modules are ok') - t.match(output, /global node_modules\s*ok/, 'global node_modules are ok') - t.match(output, /local bin folder\s*ok/, 'local bin is ok') - t.match(output, /global bin folder\s*ok/, 'global bin is ok') - t.match(output, /cache contents\s*ok/, 'cache contents is ok') - t.end() - }) -}) - -test('npm doctor outdated nodejs version', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - nodeVersions.push({ version: process.version.replace(/\d+(-.*)?$/, '999'), lts: false }) - const consoleError = console.error - // we just print an empty line here, so swallow it and ignore - console.error = () => {} - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - nodeVersions.pop() - console.error = consoleError - clearLogs() - }) - - doctor([], (err) => { - t.match(err, /Some problems found/, 'detected the out of date nodejs') - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*ok/, 'ping output is ok') - t.match(output, /npm -v\s*ok/, 'npm -v output is ok') - t.match(output, /node -v\s*not ok/, 'node -v output is not ok') - t.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') - t.match(output, /which git\s*ok/, 'which git output is ok') - t.match(output, /cached files\s*ok/, 'cached files are ok') - t.match(output, /local node_modules\s*ok/, 'local node_modules are ok') - t.match(output, /global node_modules\s*ok/, 'global node_modules are ok') - t.match(output, /local bin folder\s*ok/, 'local bin is ok') - t.match(output, /global bin folder\s*ok/, 'global bin is ok') - t.match(output, /cache contents\s*ok/, 'cache contents is ok') - t.end() - }) -}) - -test('npm doctor file permission checks', t => { - const dir = t.testdir({ - cache: { - one: 'one', - link: t.fixture('symlink', './one'), - unreadable: 'unreadable', - baddir: {}, - }, - local: { - two: 'two', - notmine: 'notmine', - }, - global: { - three: 'three', - broken: 'broken', - }, - localBin: { - four: 'four', - five: 'five', - }, - globalBin: { - six: 'six', - seven: 'seven', - }, - }) - - const _fsLstat = fs.lstat - fs.lstat = (p, cb) => { - let err = null - let stat = null - - try { - stat = fs.lstatSync(p) - } catch (err) { - return cb(err) - } - - switch (p) { - case join(dir, 'local', 'notmine'): - stat.uid += 1 - stat.gid += 1 - break - case join(dir, 'global', 'broken'): - err = new Error('broken') - break - } - - return cb(err, stat) - } - - const _fsReaddir = fs.readdir - fs.readdir = (p, cb) => { - let err = null - let result = null - - try { - result = fs.readdirSync(p) - } catch (err) { - return cb(err) - } - - if (p === join(dir, 'cache', 'baddir')) - err = new Error('broken') - - return cb(err, result) - } - - const _fsAccess = fs.access - fs.access = (p, mask, cb) => { - const err = new Error('failed') - switch (p) { - case join(dir, 'cache', 'unreadable'): - case join(dir, 'localBin', 'four'): - case join(dir, 'globalBin', 'six'): - return cb(err) - default: - return cb(null) - } - } - - const doctor = requireInject('../../lib/doctor.js', { - '../../lib/utils/is-windows.js': false, - '../../lib/utils/ping.js': ping, - '../../lib/utils/output.js': (data) => { - output.push(data) - }, - '../../lib/npm.js': npm, - cacache, - pacote, - 'make-fetch-happen': fetch, - which, - fs, - }) - // it's necessary to allow tests in node 10.x to not mark 12.x as lted - - npm.cache = npm.flatOptions.cache = join(dir, 'cache') - npm.localDir = join(dir, 'local') - npm.globalDir = join(dir, 'global') - npm.localBin = join(dir, 'localBin') - npm.globalBin = join(dir, 'globalBin') - const _consoleError = console.error - console.error = () => {} - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - console.error = _consoleError - fs.lstat = _fsLstat - fs.readdir = _fsReaddir - fs.access = _fsAccess - clearLogs() - }) - - doctor([], (err) => { - t.match(err, /Some problems found/, 'identified problems') - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [join(dir, 'cache')]: { finished: true }, - [join(dir, 'local')]: { finished: true }, - [join(dir, 'global')]: { finished: true }, - [join(dir, 'localBin')]: { finished: true }, - [join(dir, 'globalBin')]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*ok/, 'ping output is ok') - t.match(output, /npm -v\s*ok/, 'npm -v output is ok') - t.match(output, /node -v\s*ok/, 'node -v output is ok') - t.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') - t.match(output, /which git\s*ok/, 'which git output is ok') - t.match(output, /cached files\s*not ok/, 'cached files are not ok') - t.match(output, /local node_modules\s*not ok/, 'local node_modules are not ok') - t.match(output, /global node_modules\s*not ok/, 'global node_modules are not ok') - t.match(output, /local bin folder\s*not ok/, 'local bin is not ok') - t.match(output, /global bin folder\s*not ok/, 'global bin is not ok') - t.match(output, /cache contents\s*ok/, 'cache contents is ok') - t.end() - }) -}) - -test('npm doctor missing git', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - whichError = new Error('boom') - const consoleError = console.error - // we just print an empty line here, so swallow it and ignore - console.error = () => {} - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - whichError = null - console.error = consoleError - clearLogs() - }) - - doctor([], (err) => { - t.match(err, /Some problems found/, 'detected the missing git') - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*ok/, 'ping output is ok') - t.match(output, /npm -v\s*ok/, 'npm -v output is ok') - t.match(output, /node -v\s*ok/, 'node -v output is ok') - t.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') - t.match(output, /which git\s*not ok/, 'which git output is not ok') - t.match(output, /cached files\s*ok/, 'cached files are ok') - t.match(output, /local node_modules\s*ok/, 'local node_modules are ok') - t.match(output, /global node_modules\s*ok/, 'global node_modules are ok') - t.match(output, /local bin folder\s*ok/, 'local bin is ok') - t.match(output, /global bin folder\s*ok/, 'global bin is ok') - t.match(output, /cache contents\s*ok/, 'cache contents is ok') - t.end() - }) -}) - -test('npm doctor cache verification showed bad content', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - const _verifyResponse = verifyResponse - verifyResponse = { - ...verifyResponse, - badContentCount: 1, - } - const consoleError = console.error - // we just print an empty line here, so swallow it and ignore - console.error = () => {} - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - verifyResponse = _verifyResponse - console.error = consoleError - clearLogs() - }) - - doctor([], (err) => { - // cache verification problems get fixed and so do not throw an error - if (err) { - t.fail(output) - return t.end() - } - - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*ok/, 'ping output is ok') - t.match(output, /npm -v\s*ok/, 'npm -v output is ok') - t.match(output, /node -v\s*ok/, 'node -v output is ok') - t.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') - t.match(output, /which git\s*ok/, 'which git output is ok') - t.match(output, /cached files\s*ok/, 'cached files are ok') - t.match(output, /local node_modules\s*ok/, 'local node_modules are ok') - t.match(output, /global node_modules\s*ok/, 'global node_modules are ok') - t.match(output, /local bin folder\s*ok/, 'local bin is ok') - t.match(output, /global bin folder\s*ok/, 'global bin is ok') - t.match(output, /cache contents\s*ok/, 'cache contents is not ok') - t.end() - }) -}) - -test('npm doctor cache verification showed reclaimed content', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - const _verifyResponse = verifyResponse - verifyResponse = { - ...verifyResponse, - reclaimedCount: 1, - reclaimedSize: 100, - } - const consoleError = console.error - // we just print an empty line here, so swallow it and ignore - console.error = () => {} - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - verifyResponse = _verifyResponse - console.error = consoleError - clearLogs() - }) - - doctor([], (err) => { - // cache verification problems get fixed and so do not throw an error - if (err) { - t.fail(output) - return t.end() - } - - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*ok/, 'ping output is ok') - t.match(output, /npm -v\s*ok/, 'npm -v output is ok') - t.match(output, /node -v\s*ok/, 'node -v output is ok') - t.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') - t.match(output, /which git\s*ok/, 'which git output is ok') - t.match(output, /cached files\s*ok/, 'cached files are ok') - t.match(output, /local node_modules\s*ok/, 'local node_modules are ok') - t.match(output, /global node_modules\s*ok/, 'global node_modules are ok') - t.match(output, /local bin folder\s*ok/, 'local bin is ok') - t.match(output, /global bin folder\s*ok/, 'global bin is ok') - t.match(output, /cache contents\s*ok/, 'cache contents is not ok') - t.end() - }) -}) - -test('npm doctor cache verification showed missing content', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - const _verifyResponse = verifyResponse - verifyResponse = { - ...verifyResponse, - missingContent: 1, - } - const consoleError = console.error - // we just print an empty line here, so swallow it and ignore - console.error = () => {} - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - verifyResponse = _verifyResponse - console.error = consoleError - clearLogs() - }) - - doctor([], (err) => { - // cache verification problems get fixed and so do not throw an error - if (err) { - t.fail(output) - return t.end() - } - - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*ok/, 'ping output is ok') - t.match(output, /npm -v\s*ok/, 'npm -v output is ok') - t.match(output, /node -v\s*ok/, 'node -v output is ok') - t.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') - t.match(output, /which git\s*ok/, 'which git output is ok') - t.match(output, /cached files\s*ok/, 'cached files are ok') - t.match(output, /local node_modules\s*ok/, 'local node_modules are ok') - t.match(output, /global node_modules\s*ok/, 'global node_modules are ok') - t.match(output, /local bin folder\s*ok/, 'local bin is ok') - t.match(output, /global bin folder\s*ok/, 'global bin is ok') - t.match(output, /cache contents\s*ok/, 'cache contents is not ok') - t.end() - }) -}) +test('outdated node version', vt => { + vt.plan(1) + const version = 'v10.0.0' -test('npm doctor not using default registry', t => { - const dir = t.testdir() - npm.cache = npm.flatOptions.cache = dir - npm.localDir = dir - npm.globalDir = dir - npm.localBin = dir - npm.globalBin = dir - const _currentRegistry = npm.flatOptions.registry - npm.flatOptions.registry = 'https://google.com' - const consoleError = console.error - // we just print an empty line here, so swallow it and ignore - console.error = () => {} - - t.teardown(() => { - delete npm.cache - delete npm.flatOptions.cache - delete npm.localDir - delete npm.globalDir - delete npm.localBin - delete npm.globalBin - npm.flatOptions.registry = _currentRegistry - console.error = consoleError - clearLogs() + Object.defineProperty(process, 'version', { value: version }) + vt.teardown(() => { + Object.defineProperty(process, 'version', { value: origVersion }) }) - doctor([], (err) => { - // cache verification problems get fixed and so do not throw an error - t.match(err, /Some problems found/, 'detected the non-default registry') - t.match(logs, { - checkPing: { finished: true }, - getLatestNpmVersion: { finished: true }, - getLatestNodejsVersion: { finished: true }, - getGitPath: { finished: true }, - [dir]: { finished: true }, - verifyCachedFiles: { finished: true }, - }, 'trackers all finished') - t.match(output, /npm ping\s*ok/, 'ping output is ok') - t.match(output, /npm -v\s*ok/, 'npm -v output is ok') - t.match(output, /node -v\s*ok/, 'node -v output is ok') - t.match(output, /npm config get registry\s*not ok/, 'npm config get registry output is not ok') - t.match(output, /which git\s*ok/, 'which git output is ok') - t.match(output, /cached files\s*ok/, 'cached files are ok') - t.match(output, /local node_modules\s*ok/, 'local node_modules are ok') - t.match(output, /global node_modules\s*ok/, 'global node_modules are ok') - t.match(output, /local bin folder\s*ok/, 'local bin is ok') - t.match(output, /global bin folder\s*ok/, 'global bin is ok') - t.match(output, /cache contents\s*ok/, 'cache contents is ok') - t.end() + vt.test('npm doctor outdated nodejs version', st => { + const dir = st.testdir() + npm.cache = npm.flatOptions.cache = dir + npm.localDir = dir + npm.globalDir = dir + npm.localBin = dir + npm.globalBin = dir + nodeVersions.push({ version: process.version.replace(/\d+(-.*)?$/, '999'), lts: false }) + const consoleError = console.error + // we just print an empty line here, so swallow it and ignore + console.error = () => {} + + st.teardown(() => { + delete npm.cache + delete npm.flatOptions.cache + delete npm.localDir + delete npm.globalDir + delete npm.localBin + delete npm.globalBin + nodeVersions.pop() + console.error = consoleError + clearLogs() + }) + + doctor([], (err) => { + st.match(err, /Some problems found/, 'detected the out of date nodejs') + st.match(logs, { + checkPing: { finished: true }, + getLatestNpmVersion: { finished: true }, + getLatestNodejsVersion: { finished: true }, + getGitPath: { finished: true }, + [dir]: { finished: true }, + verifyCachedFiles: { finished: true }, + }, 'trackers all finished') + st.match(output, /npm ping\s*ok/, 'ping output is ok') + st.match(output, /npm -v\s*ok/, 'npm -v output is ok') + st.match(output, /node -v\s*not ok/, 'node -v output is not ok') + st.match(output, /npm config get registry\s*ok\s*using default/, 'npm config get registry output is ok') + st.match(output, /which git\s*ok/, 'which git output is ok') + st.match(output, /cached files\s*ok/, 'cached files are ok') + st.match(output, /local node_modules\s*ok/, 'local node_modules are ok') + st.match(output, /global node_modules\s*ok/, 'global node_modules are ok') + st.match(output, /local bin folder\s*ok/, 'local bin is ok') + st.match(output, /global bin folder\s*ok/, 'global bin is ok') + st.match(output, /cache contents\s*ok/, 'cache contents is ok') + st.end() + }) }) })