diff options
author | npm-cli+bot@github.com <npm CLI robot> | 2022-05-25 21:26:36 +0000 |
---|---|---|
committer | Ruy Adorno <ruyadorno@hotmail.com> | 2022-05-27 11:13:35 -0400 |
commit | 6375b13de86d0e993e0e2798ce77c5812598b953 (patch) | |
tree | 9e286e5d7164cbf78bab3b4c66762f977100171d /deps/npm/test | |
parent | 331088f4a450e29f3ea8a28a9f98ccc9f8951386 (diff) | |
download | node-new-6375b13de86d0e993e0e2798ce77c5812598b953.tar.gz |
deps: upgrade npm to 8.11.0
PR-URL: https://github.com/nodejs/node/pull/43210
Reviewed-By: Ruy Adorno <ruyadorno@github.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
Reviewed-By: Beth Griggs <bgriggs@redhat.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Diffstat (limited to 'deps/npm/test')
-rw-r--r-- | deps/npm/test/fixtures/mock-npm.js | 4 | ||||
-rw-r--r-- | deps/npm/test/fixtures/mock-registry.js | 19 | ||||
-rw-r--r-- | deps/npm/test/lib/commands/cache.js | 557 | ||||
-rw-r--r-- | deps/npm/test/lib/commands/ci.js | 451 | ||||
-rw-r--r-- | deps/npm/test/lib/commands/deprecate.js | 2 | ||||
-rw-r--r-- | deps/npm/test/lib/commands/exec.js | 2 | ||||
-rw-r--r-- | deps/npm/test/lib/commands/outdated.js | 12 | ||||
-rw-r--r-- | deps/npm/test/lib/commands/ping.js | 154 | ||||
-rw-r--r-- | deps/npm/test/lib/commands/set-script.js | 2 | ||||
-rw-r--r-- | deps/npm/test/lib/commands/whoami.js | 24 | ||||
-rw-r--r-- | deps/npm/test/lib/npm.js | 58 | ||||
-rw-r--r-- | deps/npm/test/lib/utils/get-identity.js | 103 | ||||
-rw-r--r-- | deps/npm/test/lib/utils/is-windows.js | 39 | ||||
-rw-r--r-- | deps/npm/test/lib/utils/npm-usage.js | 60 | ||||
-rw-r--r-- | deps/npm/test/lib/utils/ping.js | 35 |
15 files changed, 544 insertions, 978 deletions
diff --git a/deps/npm/test/fixtures/mock-npm.js b/deps/npm/test/fixtures/mock-npm.js index c9701ebc23..a79812fb71 100644 --- a/deps/npm/test/fixtures/mock-npm.js +++ b/deps/npm/test/fixtures/mock-npm.js @@ -224,6 +224,10 @@ class MockNpm { } } + get global () { + return this.config.get('global') || this.config.get('location') === 'global' + } + output (...msg) { if (this.base.output) { return this.base.output(msg) diff --git a/deps/npm/test/fixtures/mock-registry.js b/deps/npm/test/fixtures/mock-registry.js index a62890b72e..8fb5a055ff 100644 --- a/deps/npm/test/fixtures/mock-registry.js +++ b/deps/npm/test/fixtures/mock-registry.js @@ -192,6 +192,10 @@ class MockRegistry { }).reply(200, { ...manifest, users }) } + ping ({ body = {}, responseCode = 200 } = {}) { + this.nock = this.nock.get('/-/ping?write=true').reply(responseCode, body) + } + async package ({ manifest, times = 1, query, tarballs }) { let nock = this.nock const spec = npa(manifest.name) @@ -202,16 +206,21 @@ class MockRegistry { nock = nock.reply(200, manifest) if (tarballs) { for (const version in tarballs) { - // for (const version in manifest.versions) { - const packument = manifest.versions[version] - const dist = new URL(packument.dist.tarball) - const tarball = await pacote.tarball(tarballs[version]) - nock.get(dist.pathname).reply(200, tarball) + const m = manifest.versions[version] + nock = await this.tarball({ manifest: m, tarball: tarballs[version] }) } } this.nock = nock } + async tarball ({ manifest, tarball }) { + const nock = this.nock + const dist = new URL(manifest.dist.tarball) + const tar = await pacote.tarball(tarball) + nock.get(dist.pathname).reply(200, tar) + return nock + } + // either pass in packuments if you need to set specific attributes besides version, // or an array of versions // the last packument in the packuments or versions array will be tagged latest diff --git a/deps/npm/test/lib/commands/cache.js b/deps/npm/test/lib/commands/cache.js index 6023127691..72a7ce96aa 100644 --- a/deps/npm/test/lib/commands/cache.js +++ b/deps/npm/test/lib/commands/cache.js @@ -1,442 +1,309 @@ const t = require('tap') -const { fake: mockNpm } = require('../../fixtures/mock-npm.js') -const path = require('path') -const npa = require('npm-package-arg') - -let outputOutput = [] - -let rimrafPath = '' -const rimraf = (path, cb) => { - rimrafPath = path - return cb() -} - -let logOutput = [] - -let tarballStreamSpec = '' -let tarballStreamOpts = {} -const pacote = { - tarball: { - stream: (spec, handler, opts) => { - tarballStreamSpec = spec - tarballStreamOpts = opts - return handler({ - resume: () => {}, - promise: () => Promise.resolve(), - }) - }, - }, -} - -let cacacheEntries = {} -let cacacheContent = {} - -const setupCacacheFixture = () => { - cacacheEntries = {} - cacacheContent = {} - const pkgs = [ - ['webpack@4.44.1', 'https://registry.npmjs.org', true], - ['npm@1.2.0', 'https://registry.npmjs.org', true], - ['webpack@4.47.0', 'https://registry.npmjs.org', true], - ['foo@1.2.3-beta', 'https://registry.npmjs.org', true], - ['ape-ecs@2.1.7', 'https://registry.npmjs.org', true], - ['@fritzy/staydown@3.1.1', 'https://registry.npmjs.org', true], - ['@gar/npm-expansion@2.1.0', 'https://registry.npmjs.org', true], - ['@gar/npm-expansion@3.0.0-beta', 'https://registry.npmjs.org', true], - ['extemporaneously@44.2.2', 'https://somerepo.github.org', false], - ['corrupted@3.1.0', 'https://registry.npmjs.org', true], - ['missing-dist@23.0.0', 'https://registry.npmjs.org', true], - ['missing-version@16.2.0', 'https://registry.npmjs.org', true], - ] - pkgs.forEach(pkg => addCacachePkg(...pkg)) - // corrupt the packument - cacacheContent[ - /* eslint-disable-next-line max-len */ - [cacacheEntries['make-fetch-happen:request-cache:https://registry.npmjs.org/corrupted'].integrity] - ].data = Buffer.from('<>>>}"') - // nuke the version dist - cacacheContent[ - /* eslint-disable-next-line max-len */ - [cacacheEntries['make-fetch-happen:request-cache:https://registry.npmjs.org/missing-dist'].integrity] - ].data = Buffer.from(JSON.stringify({ versions: { '23.0.0': {} } })) - // make the version a non-object - cacacheContent[ - /* eslint-disable-next-line max-len */ - [cacacheEntries['make-fetch-happen:request-cache:https://registry.npmjs.org/missing-version'].integrity] - ].data = Buffer.from(JSON.stringify({ versions: 'hello' })) -} - -const packuments = {} +const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') +const MockRegistry = require('../../fixtures/mock-registry.js') +const mockGlobals = require('../../fixtures/mock-globals') -let contentId = 0 -const cacacheVerifyStats = { - keptSize: 100, - verifiedContent: 1, - totalEntries: 1, - runTime: { total: 2000 }, -} +const cacache = require('cacache') +const fs = require('@npmcli/fs') +const path = require('path') -const addCacacheKey = (key, content) => { - contentId++ - cacacheEntries[key] = { integrity: `${contentId}` } - cacacheContent[`${contentId}`] = {} -} -const addCacachePkg = (spec, registry, publicURL) => { - const parts = npa(spec) - const ver = parts.rawSpec || '1.0.0' - let url = `${registry}/${parts.name}/-/${parts.name}-${ver}.tgz` - if (!publicURL) { - url = `${registry}/aabbcc/${contentId}` - } - const key = `make-fetch-happen:request-cache:${url}` - const pkey = `make-fetch-happen:request-cache:${registry}/${parts.escapedName}` - if (!packuments[parts.escapedName]) { - packuments[parts.escapedName] = { - versions: {}, - } - addCacacheKey(pkey) - } - packuments[parts.escapedName].versions[ver] = { - dist: { - tarball: url, - }, - } - addCacacheKey(key) - cacacheContent[cacacheEntries[pkey].integrity] = { - data: Buffer.from(JSON.stringify(packuments[parts.escapedName])), - } -} +const pkg = 'test-package' -const cacache = { - verify: (path) => { - return cacacheVerifyStats - }, - get: (path, key) => { - if (cacacheEntries[key] === undefined - || cacacheContent[cacacheEntries[key].integrity] === undefined) { - throw new Error() - } - return cacacheContent[cacacheEntries[key].integrity] - }, - rm: { - entry: (path, key) => { - if (cacacheEntries[key] === undefined) { - throw new Error() - } - delete cacacheEntries[key] - }, - content: (path, sha) => { - delete cacacheContent[sha] - }, - }, - ls: (path) => { - return cacacheEntries - }, +t.cleanSnapshot = str => { + return str + .replace(/Finished in [0-9.s]+/g, 'Finished in xxxs') + .replace(/Cache verified and compressed (.*)/, 'Cache verified and compressed ({PATH})') } -const Cache = t.mock('../../../lib/commands/cache.js', { - cacache, - pacote, - rimraf, - 'proc-log': { - silly: (...args) => { - logOutput.push(['silly', ...args]) - }, - warn: (...args) => { - logOutput.push(['warn', ...args]) - }, - }, -}) - -const npm = mockNpm({ - cache: '/fake/path', - flatOptions: { force: false }, - config: { force: false }, - output: (msg) => { - outputOutput.push(msg) - }, -}) -const cache = new Cache(npm) - t.test('cache no args', async t => { + const { npm } = await loadMockNpm(t) await t.rejects( - cache.exec([]), + npm.exec('cache', []), { code: 'EUSAGE' }, 'should throw usage instructions' ) }) t.test('cache clean', async t => { + const { npm } = await loadMockNpm(t) await t.rejects( - cache.exec(['clean']), - 'the npm cache self-heals', + npm.exec('cache', ['clean']), + /the npm cache self-heals/, 'should throw warning' ) }) t.test('cache clean (force)', async t => { - npm.config.set('force', true) - npm.flatOptions.force = true - t.teardown(() => { - rimrafPath = '' - npm.config.force = false - npm.flatOptions.force = false + const { npm } = await loadMockNpm(t, { + cacheDir: { _cacache: {} }, + config: { force: true }, }) - - await cache.exec(['clear']) - t.equal(rimrafPath, path.join(npm.cache, '_cacache')) + const cache = path.join(npm.cache, '_cacache') + await npm.exec('cache', ['clean']) + t.notOk(fs.existsSync(cache), 'cache dir was removed') }) t.test('cache add no arg', async t => { - t.teardown(() => { - logOutput = [] - }) - + const { npm } = await loadMockNpm(t) await t.rejects( - cache.exec(['add']), + npm.exec('cache', ['add']), { code: 'EUSAGE', message: 'First argument to `add` is required', }, 'throws usage error' ) - t.strictSame(logOutput, [ - ['silly', 'cache add', 'args', []], - ], 'logs correctly') }) -t.test('cache add pkg only', async t => { - t.teardown(() => { - logOutput = [] - tarballStreamSpec = '' - tarballStreamOpts = {} +t.test('cache add single pkg', async t => { + const { npm, joinedOutput } = await loadMockNpm(t, { + prefixDir: { + package: { + 'package.json': JSON.stringify({ + name: pkg, + version: '1.0.0', + }), + }, + }, }) - - await cache.exec(['add', 'mypkg']) - t.strictSame(logOutput, [ - ['silly', 'cache add', 'args', ['mypkg']], - ['silly', 'cache add', 'spec', 'mypkg'], - ], 'logs correctly') - t.equal(tarballStreamSpec, 'mypkg', 'passes the correct spec to pacote') - t.same(tarballStreamOpts, npm.flatOptions, 'passes the correct options to pacote') + const cache = path.join(npm.cache, '_cacache') + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + }) + const manifest = registry.manifest({ name: pkg }) + await registry.package({ manifest, tarballs: { '1.0.0': path.join(npm.prefix, 'package') } }) + await npm.exec('cache', ['add', pkg]) + t.equal(joinedOutput(), '') + // eslint-disable-next-line max-len + t.resolves(cacache.get(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package/-/test-package-1.0.0.tgz')) + // eslint-disable-next-line max-len + t.resolves(cacache.get(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package')) }) t.test('cache add multiple pkgs', async t => { - t.teardown(() => { - outputOutput = [] - tarballStreamSpec = '' - tarballStreamOpts = {} + const pkg2 = 'test-package-two' + const { npm, joinedOutput } = await loadMockNpm(t, { + prefixDir: { + package: { + 'package.json': JSON.stringify({ + name: pkg, + version: '1.0.0', + }), + }, + }, }) - - await cache.exec(['add', 'mypkg', 'anotherpkg']) - t.strictSame(logOutput, [ - ['silly', 'cache add', 'args', ['mypkg', 'anotherpkg']], - ['silly', 'cache add', 'spec', 'mypkg'], - ['silly', 'cache add', 'spec', 'anotherpkg'], - ], 'logs correctly') - t.equal(tarballStreamSpec, 'anotherpkg', 'passes the correct spec to pacote') - t.same(tarballStreamOpts, npm.flatOptions, 'passes the correct options to pacote') + const cache = path.join(npm.cache, '_cacache') + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + }) + const manifest = registry.manifest({ name: pkg }) + const manifest2 = registry.manifest({ name: pkg2 }) + await registry.package({ manifest, tarballs: { '1.0.0': path.join(npm.prefix, 'package') } }) + await registry.package({ + manifest: manifest2, tarballs: { '1.0.0': path.join(npm.prefix, 'package') }, + }) + await npm.exec('cache', ['add', pkg, pkg2]) + t.equal(joinedOutput(), '') + // eslint-disable-next-line max-len + t.resolves(cacache.get(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package/-/test-package-1.0.0.tgz')) + // eslint-disable-next-line max-len + t.resolves(cacache.get(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package')) + // eslint-disable-next-line max-len + t.resolves(cacache.get(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package-two/-/test-package-two-1.0.0.tgz')) + // eslint-disable-next-line max-len + t.resolves(cacache.get(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package-two')) }) t.test('cache ls', async t => { - t.teardown(() => { - outputOutput = [] - logOutput = [] - }) - setupCacacheFixture() - await cache.exec(['ls']) - t.strictSame(outputOutput, [ - /* eslint-disable-next-line max-len */ - 'make-fetch-happen:request-cache:https://registry.npmjs.org/@fritzy/staydown/-/@fritzy/staydown-3.1.1.tgz', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/@fritzy%2fstaydown', - /* eslint-disable-next-line max-len */ - 'make-fetch-happen:request-cache:https://registry.npmjs.org/@gar/npm-expansion/-/@gar/npm-expansion-2.1.0.tgz', - /* eslint-disable-next-line max-len */ - 'make-fetch-happen:request-cache:https://registry.npmjs.org/@gar/npm-expansion/-/@gar/npm-expansion-3.0.0-beta.tgz', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/@gar%2fnpm-expansion', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/ape-ecs', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/ape-ecs/-/ape-ecs-2.1.7.tgz', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/corrupted', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/corrupted/-/corrupted-3.1.0.tgz', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/foo', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/foo/-/foo-1.2.3-beta.tgz', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/missing-dist', - /* eslint-disable-next-line max-len */ - 'make-fetch-happen:request-cache:https://registry.npmjs.org/missing-dist/-/missing-dist-23.0.0.tgz', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/missing-version', - /* eslint-disable-next-line max-len */ - 'make-fetch-happen:request-cache:https://registry.npmjs.org/missing-version/-/missing-version-16.2.0.tgz', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/npm', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/npm/-/npm-1.2.0.tgz', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/webpack', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/webpack/-/webpack-4.47.0.tgz', - 'make-fetch-happen:request-cache:https://somerepo.github.org/aabbcc/14', - 'make-fetch-happen:request-cache:https://somerepo.github.org/extemporaneously', - ]) + const keys = [ + 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package', + // eslint-disable-next-line max-len + 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package/-/test-package-1.0.0.tgz', + ] + const { npm, joinedOutput } = await loadMockNpm(t) + const cache = path.join(npm.cache, '_cacache') + for (const key of keys) { + await cacache.put(cache, key, 'test data') + } + await npm.exec('cache', ['ls']) + t.matchSnapshot(joinedOutput(), 'logs cache entries') }) t.test('cache ls pkgs', async t => { - t.teardown(() => { - outputOutput = [] - }) - await cache.exec(['ls', 'webpack@>4.44.1', 'npm']) - t.strictSame(outputOutput, [ + const keys = [ 'make-fetch-happen:request-cache:https://registry.npmjs.org/npm', 'make-fetch-happen:request-cache:https://registry.npmjs.org/npm/-/npm-1.2.0.tgz', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/webpack', 'make-fetch-happen:request-cache:https://registry.npmjs.org/webpack/-/webpack-4.47.0.tgz', - ]) + 'make-fetch-happen:request-cache:https://registry.npmjs.org/webpack/-/webpack-4.40.0.tgz', + ] + const { npm, joinedOutput } = await loadMockNpm(t) + const cache = path.join(npm.cache, '_cacache') + for (const key of keys) { + await cacache.put(cache, key, 'test data') + } + await cacache.put(cache, + 'make-fetch-happen:request-cache:https://registry.npmjs.org/webpack', + JSON.stringify({ versions: { + '4.40.0': { dist: { tarball: 'https://registry.npmjs.org/webpack/-/webpack-4.40.0.tgz' } }, + '4.47.0': { dist: { tarball: 'https://registry.npmjs.org/webpack/-/webpack-4.47.0.tgz' } }, + } }) + ) + await npm.exec('cache', ['ls', 'webpack@>4.44.1', 'npm']) + t.matchSnapshot(joinedOutput(), 'logs cache entries for npm and webpack and one webpack tgz') }) t.test('cache ls special', async t => { - t.teardown(() => { - outputOutput = [] - }) - await cache.exec(['ls', 'foo@1.2.3-beta']) - t.strictSame(outputOutput, [ + const { npm, joinedOutput } = await loadMockNpm(t) + const cache = path.join(npm.cache, '_cacache') + await cacache.put(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/foo', + JSON.stringify({ versions: { '1.2.3-beta': {} } }) + ) + await cacache.put(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/foo/-/foo-1.2.3-beta.tgz', - ]) + 'test-data' + ) + await npm.exec('cache', ['ls', 'foo@1.2.3-beta']) + t.matchSnapshot(joinedOutput(), 'logs cache entries for foo') }) t.test('cache ls nonpublic registry', async t => { - t.teardown(() => { - outputOutput = [] - }) - await cache.exec(['ls', 'extemporaneously']) - t.strictSame(outputOutput, [ - 'make-fetch-happen:request-cache:https://somerepo.github.org/aabbcc/14', + const { npm, joinedOutput } = await loadMockNpm(t) + const cache = path.join(npm.cache, '_cacache') + await cacache.put(cache, 'make-fetch-happen:request-cache:https://somerepo.github.org/extemporaneously', - ]) + JSON.stringify({ + versions: { '1.0.0': { dist: { tarball: 'https://somerepo.github.org/aabbcc/' } } }, + }) + ) + await cacache.put(cache, + 'make-fetch-happen:request-cache:https://somerepo.github.org/aabbcc/', + 'test data' + ) + await npm.exec('cache', ['ls', 'extemporaneously']) + t.matchSnapshot(joinedOutput(), 'logs cache entry for extemporaneously and its tarball') }) t.test('cache ls tagged', async t => { - t.teardown(() => { - outputOutput = [] - }) + const { npm } = await loadMockNpm(t) await t.rejects( - cache.exec(['ls', 'webpack@latest']), - 'tagged package', - 'should throw warning' + npm.exec('cache', ['ls', 'webpack@latest']), + { code: 'EUSAGE' }, + 'should throw usage error' ) }) t.test('cache ls scoped and scoped slash', async t => { - t.teardown(() => { - outputOutput = [] - }) - await cache.exec(['ls', '@fritzy/staydown', '@gar/npm-expansion']) - t.strictSame(outputOutput, [ - /* eslint-disable-next-line max-len */ + const keys = [ + // eslint-disable-next-line max-len 'make-fetch-happen:request-cache:https://registry.npmjs.org/@fritzy/staydown/-/@fritzy/staydown-3.1.1.tgz', 'make-fetch-happen:request-cache:https://registry.npmjs.org/@fritzy%2fstaydown', - /* eslint-disable-next-line max-len */ + // eslint-disable-next-line max-len 'make-fetch-happen:request-cache:https://registry.npmjs.org/@gar/npm-expansion/-/@gar/npm-expansion-2.1.0.tgz', 'make-fetch-happen:request-cache:https://registry.npmjs.org/@gar%2fnpm-expansion', - ]) + ] + const { npm, joinedOutput } = await loadMockNpm(t) + const cache = path.join(npm.cache, '_cacache') + for (const key of keys) { + await cacache.put(cache, key, 'test data') + } + await npm.exec('cache', ['ls', '@fritzy/staydown', '@gar/npm-expansion']) + t.matchSnapshot(joinedOutput(), 'logs cache entries for @gar and @fritzy') }) t.test('cache ls corrupted', async t => { - t.teardown(() => { - outputOutput = [] - }) - await cache.exec(['ls', 'corrupted']) - t.strictSame(outputOutput, [ + const keys = [ 'make-fetch-happen:request-cache:https://registry.npmjs.org/corrupted', 'make-fetch-happen:request-cache:https://registry.npmjs.org/corrupted/-/corrupted-3.1.0.tgz', - ]) -}) - -t.test('cache ls missing packument dist', async t => { - t.teardown(() => { - outputOutput = [] - }) - await cache.exec(['ls', 'missing-dist']) - t.strictSame(outputOutput, [ - 'make-fetch-happen:request-cache:https://registry.npmjs.org/missing-dist', - /* eslint-disable-next-line max-len */ - 'make-fetch-happen:request-cache:https://registry.npmjs.org/missing-dist/-/missing-dist-23.0.0.tgz', - ]) + ] + const { npm, joinedOutput } = await loadMockNpm(t) + const cache = path.join(npm.cache, '_cacache') + for (const key of keys) { + await cacache.put(cache, key, Buffer.from('<>>>}"')) + } + await npm.exec('cache', ['ls', 'corrupted']) + t.matchSnapshot(joinedOutput(), 'logs cache entries with bad data') }) t.test('cache ls missing packument version not an object', async t => { - t.teardown(() => { - outputOutput = [] - }) - await cache.exec(['ls', 'missing-version']) - t.strictSame(outputOutput, [ + const { npm, joinedOutput } = await loadMockNpm(t) + const cache = path.join(npm.cache, '_cacache') + await cacache.put(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/missing-version', - /* eslint-disable-next-line max-len */ - 'make-fetch-happen:request-cache:https://registry.npmjs.org/missing-version/-/missing-version-16.2.0.tgz', - ]) + JSON.stringify({ versions: 'not an object' }) + ) + await npm.exec('cache', ['ls', 'missing-version']) + t.matchSnapshot(joinedOutput(), 'logs cache entry for packument') }) t.test('cache rm', async t => { - t.teardown(() => { - outputOutput = [] - }) - await cache.exec(['rm', - 'make-fetch-happen:request-cache:https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz']) - t.strictSame(outputOutput, [ - /* eslint-disable-next-line max-len */ - 'Deleted: make-fetch-happen:request-cache:https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz', - ]) + const { npm, joinedOutput } = await loadMockNpm(t) + const cache = path.join(npm.cache, '_cacache') + // eslint-disable-next-line max-len + await cacache.put(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package', '{}') + // eslint-disable-next-line max-len + await cacache.put(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package/-/test-package-1.0.0.tgz', 'test data') + // eslint-disable-next-line max-len + await npm.exec('cache', ['rm', 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package/-/test-package-1.0.0.tgz']) + t.matchSnapshot(joinedOutput(), 'logs deleting single entry') + // eslint-disable-next-line max-len + t.resolves(cacache.get(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package')) + // eslint-disable-next-line max-len + t.rejects(cacache.get(cache, 'make-fetch-happen:request-cache:https://registry.npmjs.org/test-package/-/test-package-1.0.0.tgz')) }) t.test('cache rm unfound', async t => { - t.teardown(() => { - outputOutput = [] - logOutput = [] - }) - await cache.exec(['rm', 'made-up-key']) - t.strictSame(logOutput, [ - ['warn', 'Not Found: made-up-key'], - ], 'logs correctly') + const { npm, joinedOutput } = await loadMockNpm(t) + await npm.exec('cache', ['rm', 'made-up-key']) + t.same(joinedOutput(), '', 'no errors, no output') }) t.test('cache verify', async t => { - t.teardown(() => { - outputOutput = [] - }) + const { npm, joinedOutput } = await loadMockNpm(t) + await npm.exec('cache', ['verify']) + t.matchSnapshot(joinedOutput(), 'shows verified cache output') +}) - await cache.exec(['verify']) - t.match(outputOutput, [ - `Cache verified and compressed (${path.join(npm.cache, '_cacache')})`, - 'Content verified: 1 (100 bytes)', - 'Index entries: 1', - 'Finished in 2s', - ], 'prints correct output') +t.test('cache verify as part of home', async t => { + const { npm, joinedOutput, prefix } = await loadMockNpm(t) + mockGlobals(t, { 'process.env.HOME': path.dirname(prefix) }) + await npm.exec('cache', ['verify']) + t.match(joinedOutput(), 'Cache verified and compressed (~', 'contains ~ shorthand') }) t.test('cache verify w/ extra output', async t => { - npm.cache = `${process.env.HOME}/fake/path` - cacacheVerifyStats.badContentCount = 1 - cacacheVerifyStats.reclaimedCount = 2 - cacacheVerifyStats.reclaimedSize = 200 - cacacheVerifyStats.missingContent = 3 - t.teardown(() => { - npm.cache = '/fake/path' - outputOutput = [] - delete cacacheVerifyStats.badContentCount - delete cacacheVerifyStats.reclaimedCount - delete cacacheVerifyStats.reclaimedSize - delete cacacheVerifyStats.missingContent + const verify = { + runTime: { + markStartTime: 0, + fixPerms: 3, + garbageCollect: 54982, + rebuildIndex: 62779, + cleanTmp: 62781, + writeVerifile: 62783, + markEndTime: 62783, + total: 62783, + }, + verifiedContent: 17057, + reclaimedCount: 1144, + reclaimedSize: 248164665, + badContentCount: 12345, + keptSize: 1644485260, + missingContent: 92, + rejectedEntries: 92, + totalEntries: 20175, + } + const { npm, joinedOutput } = await loadMockNpm(t, { + mocks: { cacache: { verify: () => verify } }, }) - - await cache.exec(['check']) - t.match(outputOutput, [ - `Cache verified and compressed (~${path.join('/fake/path', '_cacache')})`, - 'Content verified: 1 (100 bytes)', - 'Corrupted content removed: 1', - 'Content garbage-collected: 2 (200 bytes)', - 'Missing content: 3', - 'Index entries: 1', - 'Finished in 2s', - ], 'prints correct output') + await npm.exec('cache', ['verify']) + t.matchSnapshot(joinedOutput(), 'shows extra output') }) t.test('cache completion', async t => { + const { npm } = await loadMockNpm(t) + const cache = await npm.cmd('cache') const { completion } = cache const testComp = (argv, expect) => { diff --git a/deps/npm/test/lib/commands/ci.js b/deps/npm/test/lib/commands/ci.js index 978cd03b87..179cee6c9b 100644 --- a/deps/npm/test/lib/commands/ci.js +++ b/deps/npm/test/lib/commands/ci.js @@ -1,316 +1,201 @@ -const fs = require('fs') -const util = require('util') -const readdir = util.promisify(fs.readdir) - const t = require('tap') - -const { fake: mockNpm } = require('../../fixtures/mock-npm') - -t.test('should ignore scripts with --ignore-scripts', async t => { - const SCRIPTS = [] - let REIFY_CALLED = false - const CI = t.mock('../../../lib/commands/ci.js', { - '../../../lib/utils/reify-finish.js': async () => {}, - '@npmcli/run-script': ({ event }) => { - SCRIPTS.push(event) - }, - '@npmcli/arborist': function () { - this.loadVirtual = async () => {} - this.reify = () => { - REIFY_CALLED = true - } - this.buildIdealTree = () => {} - this.virtualTree = { - inventory: new Map([ - ['foo', { name: 'foo', version: '1.0.0' }], - ]), - } - this.idealTree = { - inventory: new Map([ - ['foo', { name: 'foo', version: '1.0.0' }], - ]), - } +const { load: _loadMockNpm } = require('../../fixtures/mock-npm') +const MockRegistry = require('../../fixtures/mock-registry.js') + +const path = require('path') +const fs = require('@npmcli/fs') + +// t.cleanSnapshot = str => str.replace(/ in [0-9ms]+/g, ' in {TIME}') + +const loadMockNpm = async (t, opts) => { + const mock = await _loadMockNpm(t, opts) + const registry = new MockRegistry({ + tap: t, + registry: mock.npm.config.get('registry'), + }) + return { registry, ...mock } +} + +const packageJson = { + name: 'test-package', + version: '1.0.0', + dependencies: { + abbrev: '^1.0.0', + }, +} +const packageLock = { + name: 'test-package', + version: '1.0.0', + lockfileVersion: 2, + requires: true, + packages: { + '': { + name: 'test-package', + version: '1.0.0', + dependencies: { + abbrev: '^1.0.0', + }, }, - }) + 'node_modules/abbrev': { + version: '1.0.0', + resolved: 'https://registry.npmjs.org/abbrev/-/abbrev-1.0.0.tgz', + // integrity changes w/ each test cause the path is different? + }, + }, + dependencies: { + abbrev: { + version: '1.0.0', + resolved: 'https://registry.npmjs.org/abbrev/-/abbrev-1.0.0.tgz', + // integrity changes w/ each test cause the path is different? + }, + }, +} + +const abbrev = { + 'package.json': '{"name": "abbrev", "version": "1.0.0"}', + test: 'test file', +} + +t.test('reifies, audits, removes node_modules', async t => { + const { npm, joinedOutput, registry } = await loadMockNpm(t, { + prefixDir: { + abbrev: abbrev, + 'package.json': JSON.stringify(packageJson), + 'package-lock.json': JSON.stringify(packageLock), + node_modules: { test: 'test file that will be removed' }, + }, + }) + const manifest = registry.manifest({ name: 'abbrev' }) + await registry.tarball({ + manifest: manifest.versions['1.0.0'], + tarball: path.join(npm.prefix, 'abbrev'), + }) + registry.nock.post('/-/npm/v1/security/advisories/bulk').reply(200, {}) + await npm.exec('ci', []) + t.match(joinedOutput(), 'added 1 package, and audited 2 packages in') + await t.resolveMatch( + fs.exists(path.join(npm.prefix, 'node_modules', 'test')), + false, + 'existing node_modules is removed' + ) + await t.resolveMatch( + fs.exists(path.join(npm.prefix, 'node_modules', 'abbrev')), + true, + 'installs abbrev' + ) +}) - const npm = mockNpm({ - globalDir: 'path/to/node_modules/', - prefix: 'foo', +t.test('--no-audit and --ignore-scripts', async t => { + const { npm, joinedOutput, registry } = await loadMockNpm(t, { config: { - global: false, 'ignore-scripts': true, + audit: false, }, - }) - const ci = new CI(npm) - - await ci.exec([]) - t.equal(REIFY_CALLED, true, 'called reify') - t.strictSame(SCRIPTS, [], 'no scripts when running ci') -}) - -t.test('should use Arborist and run-script', async t => { - const scripts = [ - 'preinstall', - 'install', - 'postinstall', - 'prepublish', // XXX should we remove this finally?? - 'preprepare', - 'prepare', - 'postprepare', - ] - - // set to true when timer starts, false when it ends - // when the test is done, we assert that all timers ended - const timers = {} - const onTime = msg => { - if (timers[msg]) { - throw new Error(`saw duplicate timer: ${msg}`) - } - timers[msg] = true - } - const onTimeEnd = msg => { - if (!timers[msg]) { - throw new Error(`ended timer that was not started: ${msg}`) - } - timers[msg] = false - } - process.on('time', onTime) - process.on('timeEnd', onTimeEnd) - t.teardown(() => { - process.removeListener('time', onTime) - process.removeListener('timeEnd', onTimeEnd) - }) - - const path = t.testdir({ - node_modules: { - foo: { - 'package.json': JSON.stringify({ - name: 'foo', - version: '1.2.3', - }), + prefixDir: { + abbrev: { + 'package.json': '{"name": "abbrev", "version": "1.0.0"}', + test: 'test-file', }, - '.dotdir': {}, - '.dotfile': 'a file with a dot', + 'package.json': JSON.stringify({ + ...packageJson, + // Would make install fail + scripts: { install: 'echo "SHOULD NOT RUN" && exit 1' }, + }), + 'package-lock.json': JSON.stringify(packageLock), }, }) - const expectRimrafs = 3 - let actualRimrafs = 0 - - const CI = t.mock('../../../lib/commands/ci.js', { - '../../../lib/utils/reify-finish.js': async () => {}, - '@npmcli/run-script': opts => { - t.match(opts, { event: scripts.shift() }) - }, - '@npmcli/arborist': function (args) { - t.ok(args, 'gets options object') - this.loadVirtual = () => { - t.ok(true, 'loadVirtual is called') - return Promise.resolve(true) - } - this.reify = () => { - t.ok(true, 'reify is called') - } - this.buildIdealTree = () => {} - this.virtualTree = { - inventory: new Map([ - ['foo', { name: 'foo', version: '1.0.0' }], - ]), - } - this.idealTree = { - inventory: new Map([ - ['foo', { name: 'foo', version: '1.0.0' }], - ]), - } - }, - rimraf: (path, ...args) => { - actualRimrafs++ - t.ok(path, 'rimraf called with path') - // callback is always last arg - args.pop()() - }, - '../../../lib/utils/reify-output.js': function (arb) { - t.ok(arb, 'gets arborist tree') - }, + require('nock').emitter.on('no match', req => { + t.fail('Should not audit') }) - - const npm = mockNpm({ - prefix: path, - config: { - global: false, - }, + const manifest = registry.manifest({ name: 'abbrev' }) + await registry.tarball({ + manifest: manifest.versions['1.0.0'], + tarball: path.join(npm.prefix, 'abbrev'), }) - const ci = new CI(npm) - - await ci.exec(null) - for (const [msg, result] of Object.entries(timers)) { - t.notOk(result, `properly resolved ${msg} timer`) - } - t.match(timers, { 'npm-ci:rm': false }, 'saw the rimraf timer') - t.equal(actualRimrafs, expectRimrafs, 'removed the right number of things') - t.strictSame(scripts, [], 'called all scripts') + await npm.exec('ci', []) + t.match(joinedOutput(), 'added 1 package in', 'would fail if install script ran') }) -t.test('should pass flatOptions to Arborist.reify', async t => { - t.plan(1) - const CI = t.mock('../../../lib/commands/ci.js', { - '../../../lib/utils/reify-finish.js': async () => {}, - '@npmcli/run-script': opts => {}, - '@npmcli/arborist': function () { - this.loadVirtual = () => Promise.resolve(true) - this.reify = async (options) => { - t.equal(options.production, true, 'should pass flatOptions to Arborist.reify') - } - this.buildIdealTree = () => {} - this.virtualTree = { - inventory: new Map([ - ['foo', { name: 'foo', version: '1.0.0' }], - ]), - } - this.idealTree = { - inventory: new Map([ - ['foo', { name: 'foo', version: '1.0.0' }], - ]), - } +t.test('lifecycle scripts', async t => { + const scripts = [] + const { npm, registry } = await loadMockNpm(t, { + prefixDir: { + abbrev: abbrev, + 'package.json': JSON.stringify(packageJson), + 'package-lock.json': JSON.stringify(packageLock), + }, + mocks: { + '@npmcli/run-script': (opts) => { + t.ok(opts.banner) + scripts.push(opts.event) + }, }, }) - const npm = mockNpm({ - prefix: 'foo', - flatOptions: { - production: true, - }, + const manifest = registry.manifest({ name: 'abbrev' }) + await registry.tarball({ + manifest: manifest.versions['1.0.0'], + tarball: path.join(npm.prefix, 'abbrev'), }) - const ci = new CI(npm) - await ci.exec(null) + registry.nock.post('/-/npm/v1/security/advisories/bulk').reply(200, {}) + await npm.exec('ci', []) + t.same(scripts, [ + 'preinstall', + 'install', + 'postinstall', + 'prepublish', + 'preprepare', + 'prepare', + 'postprepare', + ], 'runs appropriate scripts, in order') }) t.test('should throw if package-lock.json or npm-shrinkwrap missing', async t => { - const testDir = t.testdir({ - 'index.js': 'some contents', - 'package.json': 'some info', - }) - - const CI = t.mock('../../../lib/commands/ci.js', { - '@npmcli/run-script': opts => {}, - '../../../lib/utils/reify-finish.js': async () => {}, - 'proc-log': { - verbose: () => { - t.ok(true, 'log fn called') + const { npm } = await loadMockNpm(t, { + prefixDir: { + 'package.json': JSON.stringify(packageJson), + node_modules: { + 'test-file': 'should not be removed', }, }, }) - const npm = mockNpm({ - prefix: testDir, - config: { - global: false, - }, - }) - const ci = new CI(npm) - await t.rejects( - ci.exec(null), - /package-lock.json/, - 'throws error when there is no package-lock' + await t.rejects(npm.exec('ci', []), { code: 'EUSAGE', message: /package-lock.json/ }) + await t.resolveMatch( + fs.exists(path.join(npm.prefix, 'node_modules', 'test-file')), + true, + 'does not remove node_modules' ) }) t.test('should throw ECIGLOBAL', async t => { - const CI = t.mock('../../../lib/commands/ci.js', { - '@npmcli/run-script': opts => {}, - '../../../lib/utils/reify-finish.js': async () => {}, - }) - const npm = mockNpm({ - prefix: 'foo', - config: { - global: true, - }, - }) - const ci = new CI(npm) - await t.rejects( - ci.exec(null), - { code: 'ECIGLOBAL' }, - 'throws error with global packages' - ) -}) - -t.test('should remove existing node_modules before installing', async t => { - t.plan(3) - const testDir = t.testdir({ - node_modules: { - 'some-file': 'some contents', - }, + const { npm } = await loadMockNpm(t, { + config: { global: true }, }) - - const CI = t.mock('../../../lib/commands/ci.js', { - '@npmcli/run-script': opts => {}, - '../../../lib/utils/reify-finish.js': async () => {}, - '@npmcli/arborist': function () { - this.loadVirtual = () => Promise.resolve(true) - this.reify = async (options) => { - t.equal(options.packageLock, true, 'npm ci should never ignore lock') - t.equal(options.save, false, 'npm ci should never save') - // check if node_modules was removed before reifying - const contents = await readdir(testDir) - const nodeModules = contents.filter((path) => path.startsWith('node_modules')) - t.same(nodeModules, ['node_modules'], 'should only have the node_modules directory') - } - this.buildIdealTree = () => {} - this.virtualTree = { - inventory: new Map([ - ['foo', { name: 'foo', version: '1.0.0' }], - ]), - } - this.idealTree = { - inventory: new Map([ - ['foo', { name: 'foo', version: '1.0.0' }], - ]), - } - }, - }) - - const npm = mockNpm({ - prefix: testDir, - config: { - global: false, - }, - }) - const ci = new CI(npm) - - await ci.exec(null) + await t.rejects(npm.exec('ci', []), { code: 'ECIGLOBAL' }) }) t.test('should throw error when ideal inventory mismatches virtual', async t => { - const CI = t.mock('../../../lib/commands/ci.js', { - '../../../lib/utils/reify-finish.js': async () => {}, - '@npmcli/run-script': ({ event }) => {}, - '@npmcli/arborist': function () { - this.loadVirtual = async () => {} - this.reify = () => {} - this.buildIdealTree = () => {} - this.virtualTree = { - inventory: new Map([ - ['foo', { name: 'foo', version: '1.0.0' }], - ]), - } - this.idealTree = { - inventory: new Map([ - ['foo', { name: 'foo', version: '2.0.0' }], - ]), - } - }, - }) - - const npm = mockNpm({ - globalDir: 'path/to/node_modules/', - prefix: 'foo', - config: { - global: false, - 'ignore-scripts': true, + const { npm, registry } = await loadMockNpm(t, { + prefixDir: { + abbrev: abbrev, + 'package.json': JSON.stringify({ + ...packageJson, + dependencies: { notabbrev: '^1.0.0' }, + }), + 'package-lock.json': JSON.stringify(packageLock), + node_modules: { + 'test-file': 'should not be removed', + }, }, }) - const ci = new CI(npm) - - try { - await ci.exec([]) - } catch (err) { - t.matchSnapshot(err.message) - } + const manifest = registry.manifest({ name: 'notabbrev' }) + await registry.package({ manifest }) + await t.rejects( + npm.exec('ci', []), + { code: 'EUSAGE', message: /in sync/ } + ) + await t.resolveMatch( + fs.exists(path.join(npm.prefix, 'node_modules', 'test-file')), + true, + 'does not remove node_modules' + ) }) diff --git a/deps/npm/test/lib/commands/deprecate.js b/deps/npm/test/lib/commands/deprecate.js index 8a925fc2a6..3a610a703a 100644 --- a/deps/npm/test/lib/commands/deprecate.js +++ b/deps/npm/test/lib/commands/deprecate.js @@ -44,7 +44,7 @@ t.test('completion', async t => { registry.whoami({ statusCode: 404, body: {} }) - t.rejects(testComp([], []), { code: 'ENEEDAUTH' }) + t.rejects(testComp([], []), { code: 'EINVALIDTYPE' }) }) t.test('no args', async t => { diff --git a/deps/npm/test/lib/commands/exec.js b/deps/npm/test/lib/commands/exec.js index 1117885b91..049ed327c8 100644 --- a/deps/npm/test/lib/commands/exec.js +++ b/deps/npm/test/lib/commands/exec.js @@ -473,7 +473,7 @@ t.test('npm exec foo, not present locally but in central loc', async t => { await exec.exec(['foo', 'one arg', 'two arg']) t.strictSame(MKDIRPS, [installDir], 'need to make install dir') t.match(ARB_CTOR, [{ path }]) - t.match(ARB_REIFY, [], 'no need to install again, already there') + t.strictSame(ARB_REIFY, [], 'no need to install again, already there') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') const PATH = `${resolve(installDir, 'node_modules', '.bin')}${delimiter}${process.env.PATH}` t.match(RUN_SCRIPTS, [ diff --git a/deps/npm/test/lib/commands/outdated.js b/deps/npm/test/lib/commands/outdated.js index 14647ce6ce..4803c7e171 100644 --- a/deps/npm/test/lib/commands/outdated.js +++ b/deps/npm/test/lib/commands/outdated.js @@ -343,7 +343,9 @@ t.test('should return if no outdated deps', async t => { }) await outdated(testDir, { - global: false, + config: { + global: false, + }, }).exec([]) t.equal(logs.length, 0, 'no logs') }) @@ -369,7 +371,9 @@ t.test('throws if error with a dep', async t => { await t.rejects( outdated(testDir, { - global: false, + config: { + global: false, + }, }).exec([]), 'There is an error with this package.' ) @@ -388,7 +392,9 @@ t.test('should skip missing non-prod deps', async t => { }) await outdated(testDir, { - global: false, + config: { + global: false, + }, }).exec([]) t.equal(logs.length, 0, 'no logs') }) diff --git a/deps/npm/test/lib/commands/ping.js b/deps/npm/test/lib/commands/ping.js index f808e0ac3b..dd2f83de08 100644 --- a/deps/npm/test/lib/commands/ping.js +++ b/deps/npm/test/lib/commands/ping.js @@ -1,113 +1,67 @@ const t = require('tap') -const { fake: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') +const MockRegistry = require('../../fixtures/mock-registry.js') -t.test('pings', async t => { - t.plan(6) - - const registry = 'https://registry.npmjs.org' - let noticeCalls = 0 - const Ping = t.mock('../../../lib/commands/ping.js', { - '../../../lib/utils/ping.js': function (spec) { - t.equal(spec.registry, registry, 'passes flatOptions') - return {} - }, - 'proc-log': { - notice: (type, spec) => { - ++noticeCalls - if (noticeCalls === 1) { - t.equal(type, 'PING', 'should log a PING') - t.equal(spec, registry, 'should log the registry url') - } else { - t.equal(type, 'PONG', 'should log a PONG') - t.match(spec, /\d+ms/, 'should log the elapsed milliseconds') - } - }, - }, - }) - const npm = mockNpm({ - config: { registry }, - flatOptions: { registry }, +t.test('no details', async t => { + const { npm, logs, joinedOutput } = await loadMockNpm(t) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), }) - const ping = new Ping(npm) - - await ping.exec([]) - t.equal(noticeCalls, 2, 'should have logged 2 lines') + registry.ping() + await npm.exec('ping', []) + t.match(logs.notice, [['PING', 'https://registry.npmjs.org/'], ['PONG', /[0-9]+ms/]]) + t.equal(joinedOutput(), '') }) -t.test('pings and logs details', async t => { - t.plan(8) +t.test('with details', async t => { + const { npm, logs, joinedOutput } = await loadMockNpm(t) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + }) + registry.ping({ body: { test: true } }) + await npm.exec('ping', []) + t.match(logs.notice, [ + ['PING', 'https://registry.npmjs.org/'], + ['PONG', /[0-9]+ms/], + ['PONG', '{\n "test": true\n}'], + ]) + t.match(joinedOutput(), '') +}) - const registry = 'https://registry.npmjs.org' - const details = { extra: 'data' } - let noticeCalls = 0 - const Ping = t.mock('../../../lib/commands/ping.js', { - '../../../lib/utils/ping.js': function (spec) { - t.equal(spec.registry, registry, 'passes flatOptions') - return details - }, - 'proc-log': { - notice: (type, spec) => { - ++noticeCalls - if (noticeCalls === 1) { - t.equal(type, 'PING', 'should log a PING') - t.equal(spec, registry, 'should log the registry url') - } else if (noticeCalls === 2) { - t.equal(type, 'PONG', 'should log a PONG') - t.match(spec, /\d+ms/, 'should log the elapsed milliseconds') - } else { - t.equal(type, 'PONG', 'should log a PONG') - const parsed = JSON.parse(spec) - t.match(parsed, details, 'should log JSON stringified details') - } - }, - }, +t.test('valid json', async t => { + const { npm, logs, joinedOutput } = await loadMockNpm(t, { + config: { json: true }, }) - const npm = mockNpm({ - config: { registry }, - flatOptions: { registry }, + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + }) + registry.ping() + await npm.exec('ping', []) + t.match(logs.notice, [['PING', 'https://registry.npmjs.org/'], ['PONG', /[0-9]+ms/]]) + t.match(JSON.parse(joinedOutput()), { + registry: npm.config.get('registry'), + time: /[0-9]+/, + details: {}, }) - const ping = new Ping(npm) - - await ping.exec([]) - t.equal(noticeCalls, 3, 'should have logged 3 lines') }) -t.test('pings and returns json', async t => { - t.plan(9) - - const registry = 'https://registry.npmjs.org' - const details = { extra: 'data' } - let noticeCalls = 0 - const Ping = t.mock('../../../lib/commands/ping.js', { - '../../../lib/utils/ping.js': function (spec) { - t.equal(spec.registry, registry, 'passes flatOptions') - return details - }, - 'proc-log': { - notice: (type, spec) => { - ++noticeCalls - if (noticeCalls === 1) { - t.equal(type, 'PING', 'should log a PING') - t.equal(spec, registry, 'should log the registry url') - } else { - t.equal(type, 'PONG', 'should log a PONG') - t.match(spec, /\d+ms/, 'should log the elapsed milliseconds') - } - }, - }, +t.test('invalid json', async t => { + const { npm, logs, joinedOutput } = await loadMockNpm(t, { + config: { json: true }, }) - const npm = mockNpm({ - config: { registry, json: true }, - flatOptions: { registry }, - output: function (spec) { - const parsed = JSON.parse(spec) - t.equal(parsed.registry, registry, 'returns the correct registry url') - t.match(parsed.details, details, 'prints returned details') - t.type(parsed.time, 'number', 'returns time as a number') - }, + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + }) + registry.ping({ body: '{not: real"json]' }) + await npm.exec('ping', []) + t.match(logs.notice, [['PING', 'https://registry.npmjs.org/'], ['PONG', /[0-9]+ms/]]) + t.match(JSON.parse(joinedOutput()), { + registry: npm.config.get('registry'), + time: /[0-9]+/, + details: {}, }) - const ping = new Ping(npm) - - await ping.exec([]) - t.equal(noticeCalls, 2, 'should have logged 2 lines') }) diff --git a/deps/npm/test/lib/commands/set-script.js b/deps/npm/test/lib/commands/set-script.js index 2c4fe57d68..cf0df53af1 100644 --- a/deps/npm/test/lib/commands/set-script.js +++ b/deps/npm/test/lib/commands/set-script.js @@ -130,7 +130,7 @@ t.test('warns when overwriting', async t => { }) await setScript.exec(['arg1', 'arg2']) - t.hasStrict(WARN_OUTPUT[0], ['set-script', 'Script "arg1" was overwritten'], 'warning was logged') + t.hasStrict(WARN_OUTPUT[1], ['set-script', 'Script "arg1" was overwritten'], 'warning was logged') }) t.test('workspaces', async t => { diff --git a/deps/npm/test/lib/commands/whoami.js b/deps/npm/test/lib/commands/whoami.js index f483bd46d5..ad7c223888 100644 --- a/deps/npm/test/lib/commands/whoami.js +++ b/deps/npm/test/lib/commands/whoami.js @@ -5,7 +5,7 @@ const MockRegistry = require('../../fixtures/mock-registry.js') const username = 'foo' const auth = { '//registry.npmjs.org/:_authToken': 'test-auth-token' } -t.test('npm whoami', async (t) => { +t.test('npm whoami', async t => { const { npm, joinedOutput } = await loadMockNpm(t, { config: auth }) const registry = new MockRegistry({ tap: t, @@ -17,7 +17,7 @@ t.test('npm whoami', async (t) => { t.equal(joinedOutput(), username, 'should print username') }) -t.test('npm whoami --json', async (t) => { +t.test('npm whoami --json', async t => { const { npm, joinedOutput } = await loadMockNpm(t, { config: { json: true, @@ -33,3 +33,23 @@ t.test('npm whoami --json', async (t) => { await npm.exec('whoami', []) t.equal(JSON.parse(joinedOutput()), username, 'should print username') }) + +t.test('credentials from token', async t => { + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { + '//registry.npmjs.org/:username': username, + '//registry.npmjs.org/:_password': 'hunter2', + }, + }) + await npm.exec('whoami', []) + t.equal(joinedOutput(), username, 'should print username') +}) + +t.test('not logged in', async t => { + const { npm } = await loadMockNpm(t, { + config: { + json: true, + }, + }) + await t.rejects(npm.exec('whoami', []), { code: 'ENEEDAUTH' }) +}) diff --git a/deps/npm/test/lib/npm.js b/deps/npm/test/lib/npm.js index 566cbca20f..cd692a93f5 100644 --- a/deps/npm/test/lib/npm.js +++ b/deps/npm/test/lib/npm.js @@ -654,3 +654,61 @@ t.test('implicit workspace accept', async t => { }) await t.rejects(mock.npm.exec('org', []), /.*Usage/) }) + +t.test('usage', async t => { + const { npm } = await loadMockNpm(t) + t.afterEach(() => { + npm.config.set('viewer', null) + npm.config.set('long', false) + npm.config.set('userconfig', '/some/config/file/.npmrc') + }) + const { dirname } = require('path') + const basedir = dirname(dirname(__dirname)) + t.cleanSnapshot = str => str.split(basedir).join('{BASEDIR}') + .split(require('../../package.json').version).join('{VERSION}') + + npm.config.set('viewer', null) + npm.config.set('long', false) + npm.config.set('userconfig', '/some/config/file/.npmrc') + + t.test('basic usage', async t => { + t.matchSnapshot(await npm.usage) + t.end() + }) + + t.test('with browser', async t => { + npm.config.set('viewer', 'browser') + t.matchSnapshot(await npm.usage) + t.end() + }) + + t.test('with long', async t => { + npm.config.set('long', true) + t.matchSnapshot(await npm.usage) + t.end() + }) + + t.test('set process.stdout.columns', async t => { + const { columns } = process.stdout + t.teardown(() => { + Object.defineProperty(process.stdout, 'columns', { + value: columns, + enumerable: true, + configurable: true, + writable: true, + }) + }) + const cases = [0, 90] + for (const cols of cases) { + t.test(`columns=${cols}`, async t => { + Object.defineProperty(process.stdout, 'columns', { + value: cols, + enumerable: true, + configurable: true, + writable: true, + }) + t.matchSnapshot(await npm.usage) + }) + } + }) +}) diff --git a/deps/npm/test/lib/utils/get-identity.js b/deps/npm/test/lib/utils/get-identity.js deleted file mode 100644 index 5e6de9ca9c..0000000000 --- a/deps/npm/test/lib/utils/get-identity.js +++ /dev/null @@ -1,103 +0,0 @@ -const t = require('tap') - -t.test('throws ENOREGISTRY when no registry option is provided', async (t) => { - t.plan(2) - const getIdentity = t.mock('../../../lib/utils/get-identity.js') - - try { - await getIdentity({}) - } catch (err) { - t.equal(err.code, 'ENOREGISTRY', 'assigns the appropriate error code') - t.equal(err.message, 'No registry specified.', 'returns the correct error message') - } -}) - -t.test('returns username from uri when provided', async (t) => { - t.plan(1) - - const getIdentity = t.mock('../../../lib/utils/get-identity.js') - const npm = { - config: { - getCredentialsByURI: () => { - return { username: 'foo' } - }, - }, - } - - const identity = await getIdentity(npm, { registry: 'https://registry.npmjs.org' }) - t.equal(identity, 'foo', 'returns username from uri') -}) - -t.test('calls registry whoami when token is provided', async (t) => { - t.plan(3) - - const options = { - registry: 'https://registry.npmjs.org', - token: 'thisisnotreallyatoken', - } - - const getIdentity = t.mock('../../../lib/utils/get-identity.js', { - 'npm-registry-fetch': { - json: (path, opts) => { - t.equal(path, '/-/whoami', 'calls whoami') - t.same(opts, options, 'passes through provided options') - return { username: 'foo' } - }, - }, - }) - const npm = { - config: { - getCredentialsByURI: () => options, - }, - } - - const identity = await getIdentity(npm, options) - t.equal(identity, 'foo', 'fetched username from registry') -}) - -t.test('throws ENEEDAUTH when response does not include a username', async (t) => { - t.plan(3) - - const options = { - registry: 'https://registry.npmjs.org', - token: 'thisisnotreallyatoken', - } - - const getIdentity = t.mock('../../../lib/utils/get-identity.js', { - 'npm-registry-fetch': { - json: (path, opts) => { - t.equal(path, '/-/whoami', 'calls whoami') - t.same(opts, options, 'passes through provided options') - return {} - }, - }, - }) - const npm = { - config: { - getCredentialsByURI: () => options, - }, - } - - try { - await getIdentity(npm, options) - } catch (err) { - t.equal(err.code, 'ENEEDAUTH', 'throws correct error code') - } -}) - -t.test('throws ENEEDAUTH when neither username nor token is configured', async (t) => { - t.plan(1) - const getIdentity = t.mock('../../../lib/utils/get-identity.js', { - }) - const npm = { - config: { - getCredentialsByURI: () => ({}), - }, - } - - try { - await getIdentity(npm, { registry: 'https://registry.npmjs.org' }) - } catch (err) { - t.equal(err.code, 'ENEEDAUTH', 'throws correct error code') - } -}) diff --git a/deps/npm/test/lib/utils/is-windows.js b/deps/npm/test/lib/utils/is-windows.js deleted file mode 100644 index a1d520f062..0000000000 --- a/deps/npm/test/lib/utils/is-windows.js +++ /dev/null @@ -1,39 +0,0 @@ -const t = require('tap') - -const mockGlobals = require('../../fixtures/mock-globals') - -t.test('is not windows', async t => { - mockGlobals(t, { 'process.platform': 'posix' }) - t.match({ - isWindows: false, - isWindowsShell: false, - }, t.mock('../../../lib/utils/is-windows.js')) -}) - -t.test('is windows, shell', async t => { - mockGlobals(t, { - 'process.platform': 'win32', - 'process.env': { - MSYSTEM: 'notmingw', - TERM: 'notcygwin', - }, - }) - t.match({ - isWindows: true, - isWindowsShell: true, - }, t.mock('../../../lib/utils/is-windows.js')) -}) - -t.test('is windows, not shell', async t => { - mockGlobals(t, { - 'process.platform': 'win32', - 'process.env': { - MSYSTEM: 'MINGW32', - TERM: 'cygwin', - }, - }) - t.match({ - isWindows: true, - isWindowsShell: false, - }, t.mock('../../../lib/utils/is-windows.js')) -}) diff --git a/deps/npm/test/lib/utils/npm-usage.js b/deps/npm/test/lib/utils/npm-usage.js deleted file mode 100644 index 035d4bbb21..0000000000 --- a/deps/npm/test/lib/utils/npm-usage.js +++ /dev/null @@ -1,60 +0,0 @@ -const t = require('tap') -const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') - -t.test('usage', async t => { - const { npm } = await loadMockNpm(t) - t.afterEach(() => { - npm.config.set('viewer', null) - npm.config.set('long', false) - npm.config.set('userconfig', '/some/config/file/.npmrc') - }) - const { dirname } = require('path') - const basedir = dirname(dirname(dirname(__dirname))) - t.cleanSnapshot = str => str.split(basedir).join('{BASEDIR}') - .split(require('../../../package.json').version).join('{VERSION}') - - npm.config.set('viewer', null) - npm.config.set('long', false) - npm.config.set('userconfig', '/some/config/file/.npmrc') - - t.test('basic usage', async t => { - t.matchSnapshot(await npm.usage) - t.end() - }) - - t.test('with browser', async t => { - npm.config.set('viewer', 'browser') - t.matchSnapshot(await npm.usage) - t.end() - }) - - t.test('with long', async t => { - npm.config.set('long', true) - t.matchSnapshot(await npm.usage) - t.end() - }) - - t.test('set process.stdout.columns', async t => { - const { columns } = process.stdout - t.teardown(() => { - Object.defineProperty(process.stdout, 'columns', { - value: columns, - enumerable: true, - configurable: true, - writable: true, - }) - }) - const cases = [0, 90] - for (const cols of cases) { - t.test(`columns=${cols}`, async t => { - Object.defineProperty(process.stdout, 'columns', { - value: cols, - enumerable: true, - configurable: true, - writable: true, - }) - t.matchSnapshot(await npm.usage) - }) - } - }) -}) diff --git a/deps/npm/test/lib/utils/ping.js b/deps/npm/test/lib/utils/ping.js deleted file mode 100644 index 1bebfa69d2..0000000000 --- a/deps/npm/test/lib/utils/ping.js +++ /dev/null @@ -1,35 +0,0 @@ -const t = require('tap') - -t.test('pings', async (t) => { - t.plan(3) - - const options = { fake: 'options' } - const response = { some: 'details' } - const ping = t.mock('../../../lib/utils/ping.js', { - 'npm-registry-fetch': (url, opts) => { - t.equal(url, '/-/ping?write=true', 'calls the correct url') - t.equal(opts, options, 'passes through options') - return { json: () => Promise.resolve(response) } - }, - }) - - const res = await ping(options) - t.match(res, response, 'returns json response') -}) - -t.test('catches errors and returns empty json', async (t) => { - t.plan(3) - - const options = { fake: 'options' } - const response = { some: 'details' } - const ping = t.mock('../../../lib/utils/ping.js', { - 'npm-registry-fetch': (url, opts) => { - t.equal(url, '/-/ping?write=true', 'calls the correct url') - t.equal(opts, options, 'passes through options') - return { json: () => Promise.reject(response) } - }, - }) - - const res = await ping(options) - t.match(res, {}, 'returns empty json response') -}) |