diff options
author | npm CLI robot <npm-cli+bot@github.com> | 2023-03-31 06:38:48 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-31 13:38:48 +0000 |
commit | 0517e19310281bb8ab95afa8a29d02cd0de07354 (patch) | |
tree | 3f037182eae8eab9ae361dc92e1bce51d2d0bae9 /deps/npm/test/lib/utils | |
parent | b74b9ddb7b0161e7090a9ec2fd2b1358b17b0e23 (diff) | |
download | node-new-0517e19310281bb8ab95afa8a29d02cd0de07354.tar.gz |
deps: upgrade npm to 9.6.3
PR-URL: https://github.com/nodejs/node/pull/47325
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Luke Karrys <luke@lukekarrys.com>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Diffstat (limited to 'deps/npm/test/lib/utils')
-rw-r--r-- | deps/npm/test/lib/utils/display.js | 2 | ||||
-rw-r--r-- | deps/npm/test/lib/utils/error-message.js | 31 | ||||
-rw-r--r-- | deps/npm/test/lib/utils/exit-handler.js | 33 | ||||
-rw-r--r-- | deps/npm/test/lib/utils/explain-dep.js | 15 | ||||
-rw-r--r-- | deps/npm/test/lib/utils/explain-eresolve.js | 28 | ||||
-rw-r--r-- | deps/npm/test/lib/utils/log-file.js | 14 | ||||
-rw-r--r-- | deps/npm/test/lib/utils/update-notifier.js | 324 |
7 files changed, 223 insertions, 224 deletions
diff --git a/deps/npm/test/lib/utils/display.js b/deps/npm/test/lib/utils/display.js index cfe0181e23..7a99dcb679 100644 --- a/deps/npm/test/lib/utils/display.js +++ b/deps/npm/test/lib/utils/display.js @@ -58,7 +58,7 @@ t.test('can log', async (t) => { display.log('warn', 'ERESOLVE', 'hello', { some: 'object' }) t.match(logs.warn, [['ERESOLVE', 'hello']]) - t.match(explains, [[{ some: 'object' }, false, 2]]) + t.match(explains, [[{ some: 'object' }, null, 2]]) }) t.test('handles log throwing', async (t) => { diff --git a/deps/npm/test/lib/utils/error-message.js b/deps/npm/test/lib/utils/error-message.js index 9d07693989..37b3bc6afe 100644 --- a/deps/npm/test/lib/utils/error-message.js +++ b/deps/npm/test/lib/utils/error-message.js @@ -384,6 +384,27 @@ t.test('bad platform', async t => { t.matchSnapshot(errorMessage(er)) t.end() }) + t.test('omits keys with no required value', t => { + const er = Object.assign(new Error('a bad plat'), { + pkgid: 'lodash@1.0.0', + current: { + os: 'posix', + cpu: 'x64', + libc: 'musl', + }, + required: { + os: ['!yours', 'mine'], + libc: [], // empty arrays should also lead to a key being removed + cpu: undefined, // XXX npm-install-checks sets unused keys to undefined + }, + code: 'EBADPLATFORM', + }) + const msg = errorMessage(er) + t.matchSnapshot(msg) + t.notMatch(msg, /Valid cpu/, 'omits cpu from message') + t.notMatch(msg, /Valid libc/, 'omits libc from message') + t.end() + }) }) t.test('explain ERESOLVE errors', async t => { @@ -393,11 +414,14 @@ t.test('explain ERESOLVE errors', async t => { errorMocks: { '{LIB}/utils/explain-eresolve.js': { report: (...args) => { - EXPLAIN_CALLED.push(args) + EXPLAIN_CALLED.push(...args) return { explanation: 'explanation', file: 'report' } }, }, }, + config: { + color: 'always', + }, }) const er = Object.assign(new Error('could not resolve'), { @@ -405,5 +429,8 @@ t.test('explain ERESOLVE errors', async t => { }) t.matchSnapshot(errorMessage(er)) - t.match(EXPLAIN_CALLED, [[er, false]]) + t.equal(EXPLAIN_CALLED.length, 3) + t.match(EXPLAIN_CALLED, [er, Function, Function]) + t.not(EXPLAIN_CALLED[1].level, 0, 'color chalk level is not 0') + t.equal(EXPLAIN_CALLED[2].level, 0, 'colorless chalk level is 0') }) diff --git a/deps/npm/test/lib/utils/exit-handler.js b/deps/npm/test/lib/utils/exit-handler.js index 76d5fec4c0..969bd05a98 100644 --- a/deps/npm/test/lib/utils/exit-handler.js +++ b/deps/npm/test/lib/utils/exit-handler.js @@ -27,6 +27,9 @@ t.formatSnapshot = (obj) => { t.cleanSnapshot = (path) => cleanDate(cleanCwd(path)) // Config loading is dependent on env so strip those from snapshots .replace(/.*timing config:load:.*\n/gm, '') + // logfile cleaning is not awaited so it races with the process.exit + // in this test and can cause snapshot failures so we always remove them + .replace(/.*silly logfile.*cleaning.*\n/gm, '') .replace(/(Completed in )\d+(ms)/g, '$1{TIME}$2') .replace(/(removing )\d+( files)/g, '$1${NUM}2') @@ -106,13 +109,11 @@ const mockExitHandler = async (t, { init, load, testdir, config, mocks, files } errors, npm, // Make it async to make testing ergonomics a little easier so we dont need - // to t.plan() every test to make sure we get process.exit called. Also - // introduce a small artificial delay so the logs are consistently finished - // by the time the exit handler forces process.exit - exitHandler: (...args) => new Promise(res => setTimeout(() => { + // to t.plan() every test to make sure we get process.exit called. + exitHandler: (...args) => new Promise(res => { process.once('exit', res) exitHandler(...args) - }, 50)), + }), } } @@ -134,30 +135,32 @@ t.test('handles unknown error with logs and debug file', async (t) => { await exitHandler(err('Unknown error', 'ECODE')) - const debugContent = await debugFile() + const fileLogs = await debugFile() + const fileLines = fileLogs.split('\n') + + const lineNumber = /^(\d+)\s/ + const lastLog = fileLines[fileLines.length - 1].match(lineNumber)[1] t.equal(process.exitCode, 1) + logs.forEach((logItem, i) => { const logLines = format(i, ...logItem).trim().split(os.EOL) logLines.forEach((line) => { - t.match(debugContent.trim(), line, 'log appears in debug file') + t.match(fileLogs.trim(), line, 'log appears in debug file') }) }) - const lastLog = debugContent - .split('\n') - .reduce((__, l) => parseInt(l.match(/^(\d+)\s/)[1])) - t.equal(logs.length, lastLog + 1) + t.equal(logs.length, parseInt(lastLog) + 1) t.match(logs.error, [ ['code', 'ECODE'], ['ERR SUMMARY', 'Unknown error'], ['ERR DETAIL', 'Unknown error'], ]) - t.match(debugContent, /\d+ error code ECODE/) - t.match(debugContent, /\d+ error ERR SUMMARY Unknown error/) - t.match(debugContent, /\d+ error ERR DETAIL Unknown error/) + t.match(fileLogs, /\d+ error code ECODE/) + t.match(fileLogs, /\d+ error ERR SUMMARY Unknown error/) + t.match(fileLogs, /\d+ error ERR DETAIL Unknown error/) t.matchSnapshot(logs, 'logs') - t.matchSnapshot(debugContent, 'debug file contents') + t.matchSnapshot(fileLines.map(l => l.replace(lineNumber, 'XX ')), 'debug file contents') }) t.test('exit handler never called - loglevel silent', async (t) => { diff --git a/deps/npm/test/lib/utils/explain-dep.js b/deps/npm/test/lib/utils/explain-dep.js index 514f28d125..e5389fd26d 100644 --- a/deps/npm/test/lib/utils/explain-dep.js +++ b/deps/npm/test/lib/utils/explain-dep.js @@ -1,9 +1,12 @@ const { resolve } = require('path') const t = require('tap') +const Chalk = require('chalk') const { explainNode, printNode } = require('../../../lib/utils/explain-dep.js') const { cleanCwd } = require('../../fixtures/clean-snapshot') const testdir = t.testdirName +const color = new Chalk.Instance({ level: Chalk.level }) +const noColor = new Chalk.Instance({ level: 0 }) t.cleanSnapshot = (str) => cleanCwd(str) @@ -250,10 +253,10 @@ cases.workspaces = { for (const [name, expl] of Object.entries(cases)) { t.test(name, t => { - t.matchSnapshot(printNode(expl, true), 'print color') - t.matchSnapshot(printNode(expl, false), 'print nocolor') - t.matchSnapshot(explainNode(expl, Infinity, true), 'explain color deep') - t.matchSnapshot(explainNode(expl, 2, false), 'explain nocolor shallow') + t.matchSnapshot(printNode(expl, color), 'print color') + t.matchSnapshot(printNode(expl, noColor), 'print nocolor') + t.matchSnapshot(explainNode(expl, Infinity, color), 'explain color deep') + t.matchSnapshot(explainNode(expl, 2, noColor), 'explain nocolor shallow') t.end() }) } @@ -261,6 +264,6 @@ for (const [name, expl] of Object.entries(cases)) { // make sure that we show the last one if it's the only one that would // hit the ... cases.manyDeps.dependents.pop() -t.matchSnapshot(explainNode(cases.manyDeps, 2, false), 'ellipses test one') +t.matchSnapshot(explainNode(cases.manyDeps, 2, noColor), 'ellipses test one') cases.manyDeps.dependents.pop() -t.matchSnapshot(explainNode(cases.manyDeps, 2, false), 'ellipses test two') +t.matchSnapshot(explainNode(cases.manyDeps, 2, noColor), 'ellipses test two') diff --git a/deps/npm/test/lib/utils/explain-eresolve.js b/deps/npm/test/lib/utils/explain-eresolve.js index 2c1fed7789..0f60556ef2 100644 --- a/deps/npm/test/lib/utils/explain-eresolve.js +++ b/deps/npm/test/lib/utils/explain-eresolve.js @@ -1,9 +1,11 @@ const t = require('tap') -const { resolve } = require('path') +const Chalk = require('chalk') const { explain, report } = require('../../../lib/utils/explain-eresolve.js') const cases = require('../../fixtures/eresolve-explanations.js') -const { cleanDate } = require('../../fixtures/clean-snapshot.js') + +const color = new Chalk.Instance({ level: Chalk.level }) +const noColor = new Chalk.Instance({ level: 0 }) for (const [name, expl] of Object.entries(cases)) { // no sense storing the whole contents of each object in the snapshot @@ -11,22 +13,16 @@ for (const [name, expl] of Object.entries(cases)) { expl.toJSON = () => ({ name, json: true }) t.test(name, t => { - const dir = t.testdir() - const fileReport = resolve(dir, 'eresolve-report.txt') - const opts = { file: fileReport, date: new Date().toISOString() } - - t.cleanSnapshot = str => cleanDate(str.split(fileReport).join('${REPORT}')) - - const color = report(expl, true, opts) - t.matchSnapshot(color.explanation, 'report with color') - t.matchSnapshot(color.file, 'report from color') + const colorReport = report(expl, color, noColor) + t.matchSnapshot(colorReport.explanation, 'report with color') + t.matchSnapshot(colorReport.file, 'report from color') - const noColor = report(expl, false, opts) - t.matchSnapshot(noColor.explanation, 'report with no color') - t.equal(noColor.file, color.file, 'same report written for object') + const noColorReport = report(expl, noColor, noColor) + t.matchSnapshot(noColorReport.explanation, 'report with no color') + t.equal(noColorReport.file, colorReport.file, 'same report written for object') - t.matchSnapshot(explain(expl, true, 2), 'explain with color, depth of 2') - t.matchSnapshot(explain(expl, false, 6), 'explain with no color, depth of 6') + t.matchSnapshot(explain(expl, color, 2), 'explain with color, depth of 2') + t.matchSnapshot(explain(expl, noColor, 6), 'explain with no color, depth of 6') t.end() }) diff --git a/deps/npm/test/lib/utils/log-file.js b/deps/npm/test/lib/utils/log-file.js index e134fe8790..fde17dee96 100644 --- a/deps/npm/test/lib/utils/log-file.js +++ b/deps/npm/test/lib/utils/log-file.js @@ -255,6 +255,20 @@ t.test('glob error', async t => { t.match(last(logs).content, /error cleaning log files .* bad glob/) }) +t.test('do not log cleaning errors when logging is disabled', async t => { + const { readLogs } = await loadLogFile(t, { + logsMax: 0, + mocks: { + glob: () => { + throw new Error('should not be logged') + }, + }, + }) + + const logs = await readLogs() + t.equal(logs.length, 0) +}) + t.test('cleans old style logs too', async t => { const logsMax = 5 const oldLogs = 10 diff --git a/deps/npm/test/lib/utils/update-notifier.js b/deps/npm/test/lib/utils/update-notifier.js index e7830e6d9d..9c12433a2d 100644 --- a/deps/npm/test/lib/utils/update-notifier.js +++ b/deps/npm/test/lib/utils/update-notifier.js @@ -1,10 +1,8 @@ const t = require('tap') +const { basename } = require('path') const tmock = require('../../fixtures/tmock') +const mockNpm = require('../../fixtures/mock-npm') -let ciMock = {} -const flatOptions = { global: false, cache: t.testdir() + '/_cacache' } - -const MANIFEST_REQUEST = [] const CURRENT_VERSION = '123.420.69' const CURRENT_MAJOR = '122.420.69' const CURRENT_MINOR = '123.419.69' @@ -15,238 +13,196 @@ const NEXT_PATCH = '123.421.69' const CURRENT_BETA = '124.0.0-beta.99999' const HAVE_BETA = '124.0.0-beta.0' -let PACOTE_ERROR = null -const pacote = { - manifest: async (spec, opts) => { - if (!spec.match(/^npm@/)) { - process.exit(1) - } - MANIFEST_REQUEST.push(spec) - if (PACOTE_ERROR) { - throw PACOTE_ERROR - } - - return { - version: - spec === 'npm@latest' - ? CURRENT_VERSION - : /-/.test(spec) - ? CURRENT_BETA - : NEXT_VERSION, - } - }, -} - -const defaultNpm = { - flatOptions, - version: CURRENT_VERSION, - config: { get: k => k !== 'global' }, - command: 'view', - argv: ['npm'], -} - -const { basename } = require('path') - -let STAT_ERROR = null -let STAT_MTIME = null -let WRITE_ERROR = null -const fs = { - ...require('fs'), - stat: (path, cb) => { - if (basename(path) !== '_update-notifier-last-checked') { - process.exit(1) - } - process.nextTick(() => cb(STAT_ERROR, { mtime: new Date(STAT_MTIME) })) - }, - writeFile: (path, content, cb) => { - if (content !== '') { - process.exit(1) - } - if (basename(path) !== '_update-notifier-last-checked') { - process.exit(1) - } - process.nextTick(() => cb(WRITE_ERROR)) - }, +const runUpdateNotifier = async (t, { + STAT_ERROR, + WRITE_ERROR, + PACOTE_ERROR, + STAT_MTIME = 0, + mocks: _mocks = {}, + command = 'view', + version = CURRENT_VERSION, + argv = [], + ...config +} = {}) => { + const mockFs = { + ...require('fs/promises'), + stat: async (path) => { + if (basename(path) !== '_update-notifier-last-checked') { + t.fail('no stat allowed for non upate notifier files') + } + if (STAT_ERROR) { + throw STAT_ERROR + } + return { mtime: new Date(STAT_MTIME) } + }, + writeFile: async (path, content) => { + if (content !== '') { + t.fail('no write file content allowed') + } + if (basename(path) !== '_update-notifier-last-checked') { + t.fail('no writefile allowed for non upate notifier files') + } + if (WRITE_ERROR) { + throw WRITE_ERROR + } + }, + } + + const MANIFEST_REQUEST = [] + const mockPacote = { + manifest: async (spec) => { + if (!spec.match(/^npm@/)) { + t.fail('no pacote manifest allowed for non npm packages') + } + MANIFEST_REQUEST.push(spec) + if (PACOTE_ERROR) { + throw PACOTE_ERROR + } + const manifestV = spec === 'npm@latest' ? CURRENT_VERSION + : /-/.test(spec) ? CURRENT_BETA : NEXT_VERSION + return { version: manifestV } + }, + } + + const mocks = { + pacote: mockPacote, + 'fs/promises': mockFs, + '{ROOT}/package.json': { version }, + 'ci-info': { isCI: false, name: null }, + ..._mocks, + } + + const mock = await mockNpm(t, { + command, + mocks, + config, + argv, + }) + const updateNotifier = tmock(t, '{LIB}/utils/update-notifier.js', mocks) + + const result = await updateNotifier(mock.npm) + + return { + result, + MANIFEST_REQUEST, + } } -t.afterEach(() => { - MANIFEST_REQUEST.length = 0 - STAT_ERROR = null - PACOTE_ERROR = null - STAT_MTIME = null - WRITE_ERROR = null +t.test('does not notify by default', async t => { + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t) + t.not(result) + t.equal(MANIFEST_REQUEST.length, 1) }) -const runUpdateNotifier = async ({ color = true, ...npmOptions } = {}) => { - const _npm = { ...defaultNpm, ...npmOptions, logColor: color } - return tmock(t, '{LIB}/utils/update-notifier.js', { - 'ci-info': ciMock, - pacote, - fs, - })(_npm) -} - t.test('situations in which we do not notify', t => { t.test('nothing to do if notifier disabled', async t => { - t.equal( - await runUpdateNotifier({ - config: { get: k => k !== 'update-notifier' }, - }), - null - ) + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t, { + 'update-notifier': false, + }) + t.equal(result, null) t.strictSame(MANIFEST_REQUEST, [], 'no requests for manifests') }) t.test('do not suggest update if already updating', async t => { - t.equal( - await runUpdateNotifier({ - flatOptions: { ...flatOptions, global: true }, - command: 'install', - argv: ['npm'], - }), - null - ) + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t, { + command: 'install', + argv: ['npm'], + global: true, + }) + t.equal(result, null) t.strictSame(MANIFEST_REQUEST, [], 'no requests for manifests') }) t.test('do not suggest update if already updating with spec', async t => { - t.equal( - await runUpdateNotifier({ - flatOptions: { ...flatOptions, global: true }, - command: 'install', - argv: ['npm@latest'], - }), - null - ) + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t, { + command: 'install', + argv: ['npm@latest'], + global: true, + }) + t.equal(result, null) t.strictSame(MANIFEST_REQUEST, [], 'no requests for manifests') }) t.test('do not update if same as latest', async t => { - t.equal(await runUpdateNotifier(), null) + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t) + t.equal(result, null) t.strictSame(MANIFEST_REQUEST, ['npm@latest'], 'requested latest version') }) t.test('check if stat errors (here for coverage)', async t => { - STAT_ERROR = new Error('blorg') - t.equal(await runUpdateNotifier(), null) + const STAT_ERROR = new Error('blorg') + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t, { STAT_ERROR }) + t.equal(result, null) t.strictSame(MANIFEST_REQUEST, ['npm@latest'], 'requested latest version') }) t.test('ok if write errors (here for coverage)', async t => { - WRITE_ERROR = new Error('grolb') - t.equal(await runUpdateNotifier(), null) + const WRITE_ERROR = new Error('grolb') + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t, { WRITE_ERROR }) + t.equal(result, null) t.strictSame(MANIFEST_REQUEST, ['npm@latest'], 'requested latest version') }) t.test('ignore pacote failures (here for coverage)', async t => { - PACOTE_ERROR = new Error('pah-KO-tchay') - t.equal(await runUpdateNotifier(), null) + const PACOTE_ERROR = new Error('pah-KO-tchay') + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t, { PACOTE_ERROR }) + t.equal(result, null) t.strictSame(MANIFEST_REQUEST, ['npm@latest'], 'requested latest version') }) t.test('do not update if newer than latest, but same as next', async t => { - t.equal(await runUpdateNotifier({ version: NEXT_VERSION }), null) + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t, { version: NEXT_VERSION }) + t.equal(result, null) const reqs = ['npm@latest', `npm@^${NEXT_VERSION}`] t.strictSame(MANIFEST_REQUEST, reqs, 'requested latest and next versions') }) t.test('do not update if on the latest beta', async t => { - t.equal(await runUpdateNotifier({ version: CURRENT_BETA }), null) + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t, { version: CURRENT_BETA }) + t.equal(result, null) const reqs = [`npm@^${CURRENT_BETA}`] t.strictSame(MANIFEST_REQUEST, reqs, 'requested latest and next versions') }) t.test('do not update in CI', async t => { - t.teardown(() => { - ciMock = {} - }) - ciMock = { isCI: true, name: 'something' } - t.equal(await runUpdateNotifier(), null) + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t, { mocks: { + 'ci-info': { isCI: true, name: 'something' }, + } }) + t.equal(result, null) t.strictSame(MANIFEST_REQUEST, [], 'no requests for manifests') }) t.test('only check weekly for GA releases', async t => { // One week (plus five minutes to account for test environment fuzziness) - STAT_MTIME = Date.now() - 1000 * 60 * 60 * 24 * 7 + 1000 * 60 * 5 - t.equal(await runUpdateNotifier(), null) + const STAT_MTIME = Date.now() - 1000 * 60 * 60 * 24 * 7 + 1000 * 60 * 5 + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t, { STAT_MTIME }) + t.equal(result, null) t.strictSame(MANIFEST_REQUEST, [], 'no requests for manifests') }) t.test('only check daily for betas', async t => { // One day (plus five minutes to account for test environment fuzziness) - STAT_MTIME = Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 5 - t.equal(await runUpdateNotifier({ version: HAVE_BETA }), null) - t.strictSame(MANIFEST_REQUEST, [], 'no requests for manifests') + const STAT_MTIME = Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 5 + const res = await runUpdateNotifier(t, { STAT_MTIME, version: HAVE_BETA }) + t.equal(res.result, null) + t.strictSame(res.MANIFEST_REQUEST, [], 'no requests for manifests') }) t.end() }) -t.test('notification situations', t => { - t.test('new beta available', async t => { - const version = HAVE_BETA - t.matchSnapshot(await runUpdateNotifier({ version }), 'color') - t.matchSnapshot( - await runUpdateNotifier({ version, color: false }), - 'no color' - ) - t.strictSame(MANIFEST_REQUEST, [`npm@^${version}`, `npm@^${version}`]) - }) - - t.test('patch to next version', async t => { - const version = NEXT_PATCH - t.matchSnapshot(await runUpdateNotifier({ version }), 'color') - t.matchSnapshot( - await runUpdateNotifier({ version, color: false }), - 'no color' - ) - t.strictSame(MANIFEST_REQUEST, [ - 'npm@latest', - `npm@^${version}`, - 'npm@latest', - `npm@^${version}`, - ]) - }) - - t.test('minor to next version', async t => { - const version = NEXT_MINOR - t.matchSnapshot(await runUpdateNotifier({ version }), 'color') - t.matchSnapshot( - await runUpdateNotifier({ version, color: false }), - 'no color' - ) - t.strictSame(MANIFEST_REQUEST, [ - 'npm@latest', - `npm@^${version}`, - 'npm@latest', - `npm@^${version}`, - ]) - }) - - t.test('patch to current', async t => { - const version = CURRENT_PATCH - t.matchSnapshot(await runUpdateNotifier({ version }), 'color') - t.matchSnapshot( - await runUpdateNotifier({ version, color: false }), - 'no color' - ) - t.strictSame(MANIFEST_REQUEST, ['npm@latest', 'npm@latest']) - }) - - t.test('minor to current', async t => { - const version = CURRENT_MINOR - t.matchSnapshot(await runUpdateNotifier({ version }), 'color') - t.matchSnapshot( - await runUpdateNotifier({ version, color: false }), - 'no color' - ) - t.strictSame(MANIFEST_REQUEST, ['npm@latest', 'npm@latest']) - }) - - t.test('major to current', async t => { - const version = CURRENT_MAJOR - t.matchSnapshot(await runUpdateNotifier({ version }), 'color') - t.matchSnapshot( - await runUpdateNotifier({ version, color: false }), - 'no color' - ) - t.strictSame(MANIFEST_REQUEST, ['npm@latest', 'npm@latest']) - }) - - t.end() +t.test('notification situations', async t => { + const cases = { + [HAVE_BETA]: [`^{V}`], + [NEXT_PATCH]: [`latest`, `^{V}`], + [NEXT_MINOR]: [`latest`, `^{V}`], + [CURRENT_PATCH]: ['latest'], + [CURRENT_MINOR]: ['latest'], + [CURRENT_MAJOR]: ['latest'], + } + + for (const [version, reqs] of Object.entries(cases)) { + for (const color of [false, 'always']) { + await t.test(`${version} - color=${color}`, async t => { + const { result, MANIFEST_REQUEST } = await runUpdateNotifier(t, { version, color }) + t.matchSnapshot(result) + t.strictSame(MANIFEST_REQUEST, reqs.map(r => `npm@${r.replace('{V}', version)}`)) + }) + } + } }) |