From f25e68742ce93f3d12b9a02e818fcecdc38359b6 Mon Sep 17 00:00:00 2001 From: maricarlagumbay1 <105158769+maricarlagumbay1@users.noreply.github.com> Date: Sun, 8 May 2022 21:20:37 +0800 Subject: [PATCH] Revert "fix: remove test coverage map (#4862)" This reverts commit 48d2db6037487fd782f67bbcd2cf12e009ece17b. --- lib/commands/completion.js | 18 +- lib/commands/search.js | 47 +- lib/commands/view.js | 3 + .../format-package-stream.js} | 66 ++- lib/search/package-filter.js | 43 ++ lib/utils/config/definitions.js | 2 +- lib/utils/file-exists.js | 10 + lib/utils/format-bytes.js | 1 - lib/utils/read-package-name.js | 9 + package.json | 9 +- .../test/lib/commands/search.js.test.cjs | 130 +---- .../test/lib/commands/view.js.test.cjs | 386 ++++++++------- test/coverage-map.js | 26 + test/fixtures/libnpmsearch-stream-result.js | 27 +- test/fixtures/mock-registry.js | 13 - test/lib/commands/search.js | 302 +++++++----- test/lib/commands/view.js | 457 +++++++++++------- test/lib/utils/config/definitions.js | 11 +- test/lib/utils/file-exists.js | 30 ++ 19 files changed, 861 insertions(+), 729 deletions(-) rename lib/{utils/format-search-stream.js => search/format-package-stream.js} (70%) create mode 100644 lib/search/package-filter.js create mode 100644 lib/utils/file-exists.js create mode 100644 lib/utils/read-package-name.js create mode 100644 test/coverage-map.js create mode 100644 test/lib/utils/file-exists.js diff --git a/lib/commands/completion.js b/lib/commands/completion.js index c24fb050dcb34..5b7e0d355c63c 100644 --- a/lib/commands/completion.js +++ b/lib/commands/completion.js @@ -29,26 +29,18 @@ // as an array. // -const fs = require('@npmcli/fs') -const nopt = require('nopt') - const { definitions, shorthands } = require('../utils/config/index.js') const { aliases, cmdList, plumbing } = require('../utils/cmd-list.js') const aliasNames = Object.keys(aliases) const fullList = cmdList.concat(aliasNames).filter(c => !plumbing.includes(c)) +const nopt = require('nopt') const configNames = Object.keys(definitions) const shorthandNames = Object.keys(shorthands) const allConfs = configNames.concat(shorthandNames) const { isWindowsShell } = require('../utils/is-windows.js') -const fileExists = async (file) => { - try { - const stat = await fs.stat(file) - return stat.isFile() - } catch { - return false - } -} +const fileExists = require('../utils/file-exists.js') +const { promisify } = require('util') const BaseCommand = require('../base-command.js') class Completion extends BaseCommand { @@ -197,10 +189,12 @@ class Completion extends BaseCommand { } const dumpScript = async () => { + const fs = require('fs') + const readFile = promisify(fs.readFile) const { resolve } = require('path') const p = resolve(__dirname, '..', 'utils', 'completion.sh') - const d = (await fs.readFile(p, 'utf8')).replace(/^#!.*?\n/, '') + const d = (await readFile(p, 'utf8')).replace(/^#!.*?\n/, '') await new Promise((res, rej) => { let done = false process.stdout.on('error', er => { diff --git a/lib/commands/search.js b/lib/commands/search.js index 8751e9e7d22fd..a06ba4031443b 100644 --- a/lib/commands/search.js +++ b/lib/commands/search.js @@ -3,33 +3,26 @@ const Pipeline = require('minipass-pipeline') const libSearch = require('libnpmsearch') const log = require('../utils/log-shim.js') -const formatSearchStream = require('../utils/format-search-stream.js') - -function filter (data, include, exclude) { - const words = [data.name] - .concat(data.maintainers.map(m => `=${m.username}`)) - .concat(data.keywords || []) - .map(f => f && f.trim && f.trim()) - .filter(f => f) - .join(' ') - .toLowerCase() - - if (exclude.find(e => match(words, e))) { - return false - } +const formatPackageStream = require('../search/format-package-stream.js') +const packageFilter = require('../search/package-filter.js') - return true +function prepareIncludes (args) { + return args + .map(s => s.toLowerCase()) + .filter(s => s) } -function match (words, pattern) { - if (pattern.startsWith('/')) { - if (pattern.endsWith('/')) { - pattern = pattern.slice(0, -1) - } - pattern = new RegExp(pattern.slice(1)) - return words.match(pattern) +function prepareExcludes (searchexclude) { + var exclude + if (typeof searchexclude === 'string') { + exclude = searchexclude.split(/\s+/) + } else { + exclude = [] } - return words.indexOf(pattern) !== -1 + + return exclude + .map(s => s.toLowerCase()) + .filter(s => s) } const BaseCommand = require('../base-command.js') @@ -57,8 +50,8 @@ class Search extends BaseCommand { const opts = { ...this.npm.flatOptions, ...this.npm.flatOptions.search, - include: args.map(s => s.toLowerCase()).filter(s => s), - exclude: this.npm.flatOptions.search.exclude.split(/\s+/), + include: prepareIncludes(args), + exclude: prepareExcludes(this.npm.flatOptions.search.exclude), } if (opts.include.length === 0) { @@ -70,7 +63,7 @@ class Search extends BaseCommand { class FilterStream extends Minipass { write (pkg) { - if (filter(pkg, opts.include, opts.exclude)) { + if (packageFilter(pkg, opts.include, opts.exclude)) { super.write(pkg) } } @@ -80,7 +73,7 @@ class Search extends BaseCommand { // Grab a configured output stream that will spit out packages in the // desired format. - const outputStream = formatSearchStream({ + const outputStream = formatPackageStream({ args, // --searchinclude options are not highlighted ...opts, }) diff --git a/lib/commands/view.js b/lib/commands/view.js index d78ee77dc0a3d..403d09d813dc7 100644 --- a/lib/commands/view.js +++ b/lib/commands/view.js @@ -57,6 +57,9 @@ class View extends BaseCommand { function getFields (d, f, pref) { f = f || [] + if (!d) { + return f + } pref = pref || [] Object.keys(d).forEach((k) => { if (k.charAt(0) === '_' || k.indexOf('.') !== -1) { diff --git a/lib/utils/format-search-stream.js b/lib/search/format-package-stream.js similarity index 70% rename from lib/utils/format-search-stream.js rename to lib/search/format-package-stream.js index 2a2dadd5c3434..acead79e1a770 100644 --- a/lib/utils/format-search-stream.js +++ b/lib/search/format-package-stream.js @@ -1,3 +1,6 @@ +// XXX these output classes should not live in here forever. it'd be good to +// split them out, perhaps to libnpmsearch + const Minipass = require('minipass') const columnify = require('columnify') @@ -15,26 +18,32 @@ const columnify = require('columnify') // The returned stream will format this package data // into a byte stream of formatted, displayable output. -module.exports = (opts) => { - return opts.json ? new JSONOutputStream() : new TextOutputStream(opts) -} +module.exports = (opts = {}) => + opts.json ? new JSONOutputStream() : new TextOutputStream(opts) class JSONOutputStream extends Minipass { - #didFirst = false + constructor () { + super() + this._didFirst = false + } write (obj) { - if (!this.#didFirst) { + if (!this._didFirst) { super.write('[\n') - this.#didFirst = true + this._didFirst = true } else { super.write('\n,\n') } - return super.write(JSON.stringify(obj)) + try { + return super.write(JSON.stringify(obj)) + } catch (er) { + return this.emit('error', er) + } } end () { - super.write(this.#didFirst ? ']\n' : '\n[]\n') + super.write(this._didFirst ? ']\n' : '\n[]\n') super.end() } } @@ -52,11 +61,14 @@ class TextOutputStream extends Minipass { } function prettify (data, num, opts) { + opts = opts || {} var truncate = !opts.long var pkg = normalizePackage(data, opts) - var columns = ['name', 'description', 'author', 'date', 'version', 'keywords'] + var columns = opts.description + ? ['name', 'description', 'author', 'date', 'version', 'keywords'] + : ['name', 'author', 'date', 'version', 'keywords'] if (opts.parseable) { return columns.map(function (col) { @@ -64,10 +76,7 @@ function prettify (data, num, opts) { }).join('\t') } - // stdout in tap is never a tty - /* istanbul ignore next */ - const maxWidth = process.stdout.isTTY ? process.stdout.getWindowSize()[0] : Infinity - let output = columnify( + var output = columnify( [pkg], { include: columns, @@ -83,8 +92,8 @@ function prettify (data, num, opts) { keywords: { maxWidth: Infinity }, }, } - ).split('\n').map(line => line.slice(0, maxWidth)).join('\n') - + ) + output = trimToMaxWidth(output) if (opts.color) { output = highlightSearchTerms(output, opts.args) } @@ -131,6 +140,26 @@ function colorize (line) { return line.split('\u0000').join(uncolor) } +function getMaxWidth () { + var cols + try { + var tty = require('tty') + var stdout = process.stdout + cols = !tty.isatty(stdout.fd) ? Infinity : process.stdout.getWindowSize()[0] + cols = (cols === 0) ? Infinity : cols + } catch (ex) { + cols = Infinity + } + return cols +} + +function trimToMaxWidth (str) { + var maxWidth = getMaxWidth() + return str.split('\n').map(function (line) { + return line.slice(0, maxWidth) + }).join('\n') +} + function highlightSearchTerms (str, terms) { terms.forEach(function (arg, i) { str = addColorMarker(str, arg, i) @@ -140,10 +169,13 @@ function highlightSearchTerms (str, terms) { } function normalizePackage (data, opts) { + opts = opts || {} return { name: data.name, - description: data.description, - author: data.maintainers.map((m) => `=${m.username}`).join(' '), + description: opts.description ? data.description : '', + author: (data.maintainers || []).map(function (m) { + return '=' + m.username + }).join(' '), keywords: Array.isArray(data.keywords) ? data.keywords.join(' ') : typeof data.keywords === 'string' diff --git a/lib/search/package-filter.js b/lib/search/package-filter.js new file mode 100644 index 0000000000000..bb0ae679bdccd --- /dev/null +++ b/lib/search/package-filter.js @@ -0,0 +1,43 @@ +module.exports = filter +function filter (data, include, exclude, opts) { + return typeof data === 'object' && + filterWords(data, include, exclude, opts) +} + +function getWords (data, opts) { + return [data.name] + .concat((opts && opts.description) ? data.description : []) + .concat((data.maintainers || []).map(m => `=${m.name}`)) + .concat(data.versions && data.versions.length && data.url && ('<' + data.url + '>')) + .concat(data.keywords || []) + .map(f => f && f.trim && f.trim()) + .filter(f => f) + .join(' ') + .toLowerCase() +} + +function filterWords (data, include, exclude, opts) { + var words = getWords(data, opts) + for (var i = 0, l = include.length; i < l; i++) { + if (!match(words, include[i])) { + return false + } + } + + for (i = 0, l = exclude.length; i < l; i++) { + if (match(words, exclude[i])) { + return false + } + } + + return true +} + +function match (words, pattern) { + if (pattern.charAt(0) === '/') { + pattern = pattern.replace(/\/$/, '') + pattern = new RegExp(pattern.slice(1)) + return words.match(pattern) + } + return words.indexOf(pattern) !== -1 +} diff --git a/lib/utils/config/definitions.js b/lib/utils/config/definitions.js index a5eac8c826c84..6f1b1a7244a50 100644 --- a/lib/utils/config/definitions.js +++ b/lib/utils/config/definitions.js @@ -1856,7 +1856,7 @@ define('searchexclude', { `, flatten (key, obj, flatOptions) { flatOptions.search = flatOptions.search || { limit: 20 } - flatOptions.search.exclude = obj[key].toLowerCase() + flatOptions.search.exclude = obj[key] }, }) diff --git a/lib/utils/file-exists.js b/lib/utils/file-exists.js new file mode 100644 index 0000000000000..605472536aab0 --- /dev/null +++ b/lib/utils/file-exists.js @@ -0,0 +1,10 @@ +const fs = require('fs') +const util = require('util') + +const stat = util.promisify(fs.stat) + +const fileExists = (file) => stat(file) + .then((stat) => stat.isFile()) + .catch(() => false) + +module.exports = fileExists diff --git a/lib/utils/format-bytes.js b/lib/utils/format-bytes.js index d293001df5524..d7cf6d144e339 100644 --- a/lib/utils/format-bytes.js +++ b/lib/utils/format-bytes.js @@ -23,7 +23,6 @@ const formatBytes = (bytes, space = true) => { return `${(bytes / 1000000).toFixed(1)}${spacer}MB` } - // GB return `${(bytes / 1000000000).toFixed(1)}${spacer}GB` } diff --git a/lib/utils/read-package-name.js b/lib/utils/read-package-name.js new file mode 100644 index 0000000000000..7ed15987767bb --- /dev/null +++ b/lib/utils/read-package-name.js @@ -0,0 +1,9 @@ +const { resolve } = require('path') +const readJson = require('read-package-json-fast') +async function readLocalPackageName (prefix) { + const filepath = resolve(prefix, 'package.json') + const json = await readJson(filepath) + return json.name +} + +module.exports = readLocalPackageName diff --git a/package.json b/package.json index 687e9025fe7ac..d3e55ad623a43 100644 --- a/package.json +++ b/package.json @@ -230,13 +230,8 @@ ], "color": 1, "files": "test/{lib,bin,index.js}", - "timeout": 600, - "nyc-arg": [ - "--exclude", - "workspaces/**", - "--exclude", - "tap-snapshots/**" - ] + "coverage-map": "test/coverage-map.js", + "timeout": 600 }, "templateOSS": { "rootRepo": false, diff --git a/tap-snapshots/test/lib/commands/search.js.test.cjs b/tap-snapshots/test/lib/commands/search.js.test.cjs index 152e6605676e7..139fca25981ce 100644 --- a/tap-snapshots/test/lib/commands/search.js.test.cjs +++ b/tap-snapshots/test/lib/commands/search.js.test.cjs @@ -9,130 +9,12 @@ exports[`test/lib/commands/search.js TAP empty search results > should have expe No matches found for "foo" ` -exports[`test/lib/commands/search.js TAP search //--color > should have expected search results with color 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 | -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 | -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm npmcli libnpm cli workspaces map-workspaces -libnpmversion | library to do the… | =nlf… | 2020-11-04 | 1.0.7 | -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | +exports[`test/lib/commands/search.js TAP search --searchexclude --searchopts > should have filtered expected search results 1`] = ` +NAME | AUTHOR | DATE | VERSION | KEYWORDS +foo | =foo | prehistoric | 1.0.0 | ` -exports[`test/lib/commands/search.js TAP search --color > should have expected search results with color 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 |  -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 |  -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 |  -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 |  -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm npmcli libnpm cli workspaces map-workspaces -libnpmversion | library to do the… | =nlf… | 2020-11-04 | 1.0.7 |  -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 |  -` - -exports[`test/lib/commands/search.js TAP search --parseable > should have expected search results as parseable 1`] = ` -libnpm Collection of programmatic APIs for the npm CLI =nlf =ruyadorno =darcyclarke =isaacs 2019-07-16 3.0.1 npm api package manager lib -libnpmaccess programmatic library for \`npm access\` commands =nlf =ruyadorno =darcyclarke =isaacs 2020-11-03 4.0.1 libnpmaccess -@evocateur/libnpmaccess programmatic library for \`npm access\` commands =evocateur 2019-07-16 3.1.2 -@evocateur/libnpmpublish Programmatic API for the bits behind npm publish and unpublish =evocateur 2019-07-16 1.2.2 -libnpmorg Programmatic api for \`npm org\` commands =nlf =ruyadorno =darcyclarke =isaacs 2020-11-03 2.0.1 libnpm npm package manager api orgs teams -libnpmsearch Programmatic API for searching in npm and compatible registries. =nlf =ruyadorno =darcyclarke =isaacs 2020-12-08 3.1.0 npm search api libnpm -libnpmteam npm Team management APIs =nlf =ruyadorno =darcyclarke =isaacs 2020-11-03 2.0.2 -libnpmhook programmatic API for managing npm registry hooks =nlf =ruyadorno =darcyclarke =isaacs 2020-11-03 6.0.1 npm hooks registry npm api -libnpmpublish Programmatic API for the bits behind npm publish and unpublish =nlf =ruyadorno =darcyclarke =isaacs 2020-11-03 4.0.0 -libnpmfund Programmatic API for npm fund =nlf =ruyadorno =darcyclarke =isaacs 2020-12-08 1.0.2 npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces Retrieves a name:pathname Map for a given workspaces config =nlf =ruyadorno =darcyclarke =isaacs 2020-09-30 1.0.1 npm npmcli libnpm cli workspaces map-workspaces -libnpmversion library to do the things that 'npm version' does =nlf =ruyadorno =darcyclarke =isaacs 2020-11-04 1.0.7 -@types/libnpmsearch TypeScript definitions for libnpmsearch =types 2019-09-26 2.0.1 -` - -exports[`test/lib/commands/search.js TAP search > should have filtered expected search results 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -foo | | =foo | prehistoric | 1.0.0 | -libnpmversion | | =foo | prehistoric | 1.0.0 | -` - -exports[`test/lib/commands/search.js TAP search text > should have expected search results 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 | -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 | -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm npmcli libnpm cli workspaces map-workspaces -libnpmversion | library to do the… | =nlf… | 2020-11-04 | 1.0.7 | -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | -` - -exports[`test/lib/commands/search.js TAP search exclude forward slash > results should not have libnpmversion 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 | -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 | -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm npmcli libnpm cli workspaces map-workspaces -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | -` - -exports[`test/lib/commands/search.js TAP search exclude regex > results should not have libnpmversion 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 | -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 | -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm npmcli libnpm cli workspaces map-workspaces -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | -` - -exports[`test/lib/commands/search.js TAP search exclude string > results should not have libnpmversion 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 | -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 | -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm npmcli libnpm cli workspaces map-workspaces -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | -` - -exports[`test/lib/commands/search.js TAP search exclude username with upper case letters > results should not have nlf 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | +exports[`test/lib/commands/search.js TAP search > should have expected search results 1`] = ` +NAME | AUTHOR | DATE | VERSION | KEYWORDS +libnpm | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager liblibnpmaccess | =nlf… | 2020-11-03 | 4.0.1 | @evocateur/libnpmaccess | =evocateur | 2019-07-16 | 3.1.2 | @evocateur/libnpmpublish | =evocateur | 2019-07-16 | 1.2.2 | libnpmorg | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teamslibnpmsearch | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpmlibnpmteam | =nlf… | 2020-11-03 | 2.0.2 | libnpmhook | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm apilibnpmpublish | =nlf… | 2020-11-03 | 4.0.0 | libnpmfund | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund@npmcli/map-workspaces | =nlf… | 2020-09-30 | 1.0.1 | npm npmcli libnpm cli workspaces map-workspaceslibnpmversion | =nlf… | 2020-11-04 | 1.0.7 | @types/libnpmsearch | =types | 2019-09-26 | 2.0.1 | ` diff --git a/tap-snapshots/test/lib/commands/view.js.test.cjs b/tap-snapshots/test/lib/commands/view.js.test.cjs index d5b7a3b4a7906..5868e7b04babe 100644 --- a/tap-snapshots/test/lib/commands/view.js.test.cjs +++ b/tap-snapshots/test/lib/commands/view.js.test.cjs @@ -5,102 +5,96 @@ * Make sure to inspect the output below. Do not ignore changes! */ 'use strict' -exports[`test/lib/commands/view.js TAP deprecated package with license, bugs, repository and other fields > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log info by field name array field - 1 element > must match snapshot 1`] = ` -green@1.0.0 | ACME | deps: 2 | versions: 2 -green is a very important color - -DEPRECATED!! - true - -keywords:,colors, green, crayola - -bin:,green +claudia +` -dist -.tarball:,http://hm.green.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1.0 GB +exports[`test/lib/commands/view.js TAP should log info by field name array field - 2 elements > must match snapshot 1`] = ` -dependencies: -red: 1.0.0 -yellow: 1.0.0 +maintainers[0].name = 'claudia' +maintainers[1].name = 'isaacs' +` -maintainers: --,claudia <c@yellow.com> --,isaacs <i@yellow.com> +exports[`test/lib/commands/view.js TAP should log info by field name maintainers with email > must match snapshot 1`] = ` -dist-tags: -latest: 1.0.0 +{ + "maintainers": [ + { + "name": "claudia", + "email": "c@yellow.com", + "twitter": "cyellow" + }, + { + "name": "isaacs", + "email": "i@yellow.com", + "twitter": "iyellow" + } + ], + "name": "yellow" +} ` -exports[`test/lib/commands/view.js TAP deprecated package with unicode > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log info by field name maintainers with url > must match snapshot 1`] = ` -green@1.0.0 | ACME | deps: 2 | versions: 2 -green is a very important color - -DEPRECATED ⚠️ - true +[ + "claudia (http://c.pink.com)", + "isaacs (http://i.pink.com)" +] +` -keywords:,colors, green, crayola +exports[`test/lib/commands/view.js TAP should log info by field name nested field with brackets > must match snapshot 1`] = ` -bin:,green +"123" +` -dist -.tarball:,http://hm.green.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1.0 GB +exports[`test/lib/commands/view.js TAP should log info by field name readme > must match snapshot 1`] = ` -dependencies: -red: 1.0.0 -yellow: 1.0.0 +a very useful readme +` -maintainers: --,claudia <c@yellow.com> --,isaacs <i@yellow.com> +exports[`test/lib/commands/view.js TAP should log info by field name several fields > must match snapshot 1`] = ` -dist-tags: -latest: 1.0.0 +{ + "name": "yellow", + "version": "1.0.0" +} ` -exports[`test/lib/commands/view.js TAP package from git > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log info by field name several fields with several versions > must match snapshot 1`] = ` -green@1.0.0 | ACME | deps: 2 | versions: 2 -green is a very important color +yellow@1.0.0 'claudia' +yellow@1.0.1 'claudia' +yellow@1.0.2 'claudia' +` -DEPRECATED!! - true +exports[`test/lib/commands/view.js TAP should log info of package in current working dir directory > must match snapshot 1`] = ` -keywords:,colors, green, crayola -bin:,green +blue@1.0.0 | Proprietary | deps: none | versions: 2 dist -.tarball:,http://hm.green.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1.0 GB - -dependencies: -red: 1.0.0 -yellow: 1.0.0 - -maintainers: --,claudia <c@yellow.com> --,isaacs <i@yellow.com> +.tarball:http://hm.blue.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dist-tags: latest: 1.0.0 + +published {TIME} ago ` -exports[`test/lib/commands/view.js TAP package in cwd directory > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log info of package in current working dir non-specific version > must match snapshot 1`] = ` + blue@1.0.0 | Proprietary | deps: none | versions: 2 dist -.tarball:,http://hm.blue.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1 B +.tarball:http://hm.blue.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -108,15 +102,16 @@ dist-tags: published {TIME} ago ` -exports[`test/lib/commands/view.js TAP package in cwd non-specific version > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log info of package in current working dir specific version > must match snapshot 1`] = ` + blue@1.0.0 | Proprietary | deps: none | versions: 2 dist -.tarball:,http://hm.blue.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1 B +.tarball:http://hm.blue.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -124,23 +119,38 @@ dist-tags: published {TIME} ago ` -exports[`test/lib/commands/view.js TAP package in cwd specific version > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log package info package from git > must match snapshot 1`] = ` -blue@1.0.0 | Proprietary | deps: none | versions: 2 + +green@1.0.0 | ACME | deps: 2 | versions: 2 +green is a very important color + +DEPRECATED!! - true + +keywords:colors, green, crayola + +bin:green dist -.tarball:,http://hm.blue.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1 B +.tarball:http://hm.green.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B + +dependencies: +red: 1.0.0 +yellow: 1.0.0 + +maintainers: +-claudia <c@yellow.com> +-isaacs <i@yellow.com> dist-tags: latest: 1.0.0 - -published {TIME} ago ` -exports[`test/lib/commands/view.js TAP package with --json and semver range > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log package info package with --json and semver range > must match snapshot 1`] = ` + [ { "_npmUser": "claudia ", @@ -158,7 +168,7 @@ exports[`test/lib/commands/view.js TAP package with --json and semver range > mu "tarball": "http://hm.cyan.com/1.0.0.tgz", "integrity": "---", "fileCount": 1, - "unpackedSize": 1000000 + "unpackedSize": 1 } }, { @@ -175,44 +185,77 @@ exports[`test/lib/commands/view.js TAP package with --json and semver range > mu ] ` -exports[`test/lib/commands/view.js TAP package with homepage > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log package info package with homepage > must match snapshot 1`] = ` + orange@1.0.0 | Proprietary | deps: none | versions: 2 http://hm.orange.com dist -.tarball:,http://hm.orange.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1 B +.tarball:http://hm.orange.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B + +dist-tags: +latest: 1.0.0 +` + +exports[`test/lib/commands/view.js TAP should log package info package with license, bugs, repository and other fields > must match snapshot 1`] = ` + + +green@1.0.0 | ACME | deps: 2 | versions: 2 +green is a very important color + +DEPRECATED!! - true + +keywords:colors, green, crayola + +bin:green + +dist +.tarball:http://hm.green.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B + +dependencies: +red: 1.0.0 +yellow: 1.0.0 + +maintainers: +-claudia <c@yellow.com> +-isaacs <i@yellow.com> dist-tags: latest: 1.0.0 ` -exports[`test/lib/commands/view.js TAP package with maintainers info as object > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log package info package with maintainers info as object > must match snapshot 1`] = ` + pink@1.0.0 | Proprietary | deps: none | versions: 2 dist -.tarball:,http://hm.pink.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1 B +.tarball:http://hm.pink.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dist-tags: latest: 1.0.0 ` -exports[`test/lib/commands/view.js TAP package with more than 25 deps > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log package info package with more than 25 deps > must match snapshot 1`] = ` + black@1.0.0 | Proprietary | deps: 25 | versions: 2 dist -.tarball:,http://hm.black.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1 B +.tarball:http://hm.black.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dependencies: 0: 1.0.0 @@ -245,15 +288,16 @@ dist-tags: latest: 1.0.0 ` -exports[`test/lib/commands/view.js TAP package with no modified time > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log package info package with no modified time > must match snapshot 1`] = ` + cyan@1.0.0 | Proprietary | deps: none | versions: 2 dist -.tarball:,http://hm.cyan.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1.0 MB +.tarball:http://hm.cyan.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -261,15 +305,16 @@ dist-tags: published by claudia <claudia@cyan.com> ` -exports[`test/lib/commands/view.js TAP package with no repo or homepage > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log package info package with no repo or homepage > must match snapshot 1`] = ` + blue@1.0.0 | Proprietary | deps: none | versions: 2 dist -.tarball:,http://hm.blue.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1 B +.tarball:http://hm.blue.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -277,15 +322,16 @@ dist-tags: published {TIME} ago ` -exports[`test/lib/commands/view.js TAP package with semver range > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP should log package info package with semver range > must match snapshot 1`] = ` + blue@1.0.0 | Proprietary | deps: none | versions: 2 dist -.tarball:,http://hm.blue.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1 B +.tarball:http://hm.blue.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -295,10 +341,10 @@ published {TIME} ago blue@1.0.1 | Proprietary | deps: none | versions: 2 dist -.tarball:,http://hm.blue.com/1.0.1.tgz -.shasum:,124 -.integrity:,--- -.unpackedSize:,1.0 kB +.tarball:http://hm.blue.com/1.0.1.tgz +.shasum:124 +.integrity:--- +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -306,47 +352,8 @@ dist-tags: published over a year from now ` -exports[`test/lib/commands/view.js TAP specific field names array field - 1 element > must match snapshot 1`] = ` -claudia -` - -exports[`test/lib/commands/view.js TAP specific field names array field - 2 elements > must match snapshot 1`] = ` -maintainers[0].name = 'claudia' -maintainers[1].name = 'isaacs' -` - -exports[`test/lib/commands/view.js TAP specific field names maintainers with email > must match snapshot 1`] = ` -maintainers = [ - { name: 'claudia', email: 'c@yellow.com', twitter: 'cyellow' }, - { name: 'isaacs', email: 'i@yellow.com', twitter: 'iyellow' } -] -name = 'yellow' -` - -exports[`test/lib/commands/view.js TAP specific field names maintainers with url > must match snapshot 1`] = ` -[ 'claudia (http://c.pink.com)', 'isaacs (http://i.pink.com)' ] -` - -exports[`test/lib/commands/view.js TAP specific field names nested field with brackets > must match snapshot 1`] = ` -123 -` - -exports[`test/lib/commands/view.js TAP specific field names readme > must match snapshot 1`] = ` -a very useful readme -` - -exports[`test/lib/commands/view.js TAP specific field names several fields > must match snapshot 1`] = ` -name = 'yellow' -version = '1.0.0' -` - -exports[`test/lib/commands/view.js TAP specific field names several fields with several versions > must match snapshot 1`] = ` -yellow@1.0.0 'claudia' -yellow@1.0.1 'claudia' -yellow@1.0.2 'claudia' -` - exports[`test/lib/commands/view.js TAP workspaces all workspaces --json > must match snapshot 1`] = ` + { "green": { "_id": "green", @@ -399,7 +406,7 @@ exports[`test/lib/commands/view.js TAP workspaces all workspaces --json > must m "tarball": "http://hm.green.com/1.0.0.tgz", "integrity": "---", "fileCount": 1, - "unpackedSize": 1000000000 + "unpackedSize": 1 } }, "orange": { @@ -427,28 +434,29 @@ exports[`test/lib/commands/view.js TAP workspaces all workspaces --json > must m exports[`test/lib/commands/view.js TAP workspaces all workspaces > must match snapshot 1`] = ` + green@1.0.0 | ACME | deps: 2 | versions: 2 green is a very important color DEPRECATED!! - true -keywords:,colors, green, crayola +keywords:colors, green, crayola -bin:,green +bin:green dist -.tarball:,http://hm.green.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1.0 GB +.tarball:http://hm.green.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dependencies: red: 1.0.0 yellow: 1.0.0 maintainers: --,claudia <c@yellow.com> --,isaacs <i@yellow.com> +-claudia <c@yellow.com> +-isaacs <i@yellow.com> dist-tags: latest: 1.0.0 @@ -457,10 +465,10 @@ dist-tags: http://hm.orange.com dist -.tarball:,http://hm.orange.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1 B +.tarball:http://hm.orange.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -471,11 +479,13 @@ exports[`test/lib/commands/view.js TAP workspaces all workspaces nonexistent fie ` exports[`test/lib/commands/view.js TAP workspaces all workspaces nonexistent field > must match snapshot 1`] = ` + green: orange: ` exports[`test/lib/commands/view.js TAP workspaces all workspaces single field --json > must match snapshot 1`] = ` + { "green": "green", "orange": "orange" @@ -483,6 +493,7 @@ exports[`test/lib/commands/view.js TAP workspaces all workspaces single field -- ` exports[`test/lib/commands/view.js TAP workspaces all workspaces single field > must match snapshot 1`] = ` + green: green orange: @@ -491,56 +502,55 @@ orange exports[`test/lib/commands/view.js TAP workspaces one specific workspace > must match snapshot 1`] = ` + green@1.0.0 | ACME | deps: 2 | versions: 2 green is a very important color DEPRECATED!! - true -keywords:,colors, green, crayola +keywords:colors, green, crayola -bin:,green +bin:green dist -.tarball:,http://hm.green.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1.0 GB +.tarball:http://hm.green.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dependencies: red: 1.0.0 yellow: 1.0.0 maintainers: --,claudia <c@yellow.com> --,isaacs <i@yellow.com> +-claudia <c@yellow.com> +-isaacs <i@yellow.com> dist-tags: latest: 1.0.0 ` exports[`test/lib/commands/view.js TAP workspaces remote package name > must match snapshot 1`] = ` +Ignoring workspaces for specified package(s) +` + +exports[`test/lib/commands/view.js TAP workspaces remote package name > must match snapshot 2`] = ` + pink@1.0.0 | Proprietary | deps: none | versions: 2 dist -.tarball:,http://hm.pink.com/1.0.0.tgz -.shasum:,123 -.integrity:,--- -.unpackedSize:,1 B +.tarball:http://hm.pink.com/1.0.0.tgz +.shasum:123 +.integrity:--- +.unpackedSize:1 B dist-tags: latest: 1.0.0 ` -exports[`test/lib/commands/view.js TAP workspaces remote package name > should have warning of ignoring workspaces 1`] = ` -Array [ - Array [ - "Ignoring workspaces for specified package(s)", - ], -] -` - exports[`test/lib/commands/view.js TAP workspaces single workspace --json > must match snapshot 1`] = ` + { "green": { "_id": "green", @@ -593,7 +603,7 @@ exports[`test/lib/commands/view.js TAP workspaces single workspace --json > must "tarball": "http://hm.green.com/1.0.0.tgz", "integrity": "---", "fileCount": 1, - "unpackedSize": 1000000000 + "unpackedSize": 1 } } } diff --git a/test/coverage-map.js b/test/coverage-map.js new file mode 100644 index 0000000000000..9a289b6489e3e --- /dev/null +++ b/test/coverage-map.js @@ -0,0 +1,26 @@ +const coverageMap = (filename) => { + const { basename } = require('path') + const testbase = basename(filename) + if (filename === 'test/index.js') { + return ['index.js'] + } + if (testbase === 'load-all-commands.js') { + const { cmdList } = require('../lib/utils/cmd-list.js') + return cmdList.map(cmd => `lib/${cmd}.js`) + .concat('lib/base-command.js') + } + if (/^test\/lib\/commands/.test(filename) || filename === 'test/lib/npm.js') { + return [ + filename.replace(/^test\//, ''), + 'lib/npm.js', + 'lib/base-command.js', + 'lib/exec/get-workspace-location-msg.js', + ] + } + if (/^test\/(lib|bin)\//.test(filename)) { + return filename.replace(/^test\//, '') + } + return [] +} + +module.exports = coverageMap diff --git a/test/fixtures/libnpmsearch-stream-result.js b/test/fixtures/libnpmsearch-stream-result.js index b2ec20f59efeb..4d3aca396fbca 100644 --- a/test/fixtures/libnpmsearch-stream-result.js +++ b/test/fixtures/libnpmsearch-stream-result.js @@ -5,7 +5,7 @@ module.exports = [ version: '3.0.1', description: 'Collection of programmatic APIs for the npm CLI', keywords: ['npm', 'api', 'package manager', 'lib'], - date: '2019-07-16T17:50:00.572Z', + date: new Date('2019-07-16T17:50:00.572Z'), links: { npm: 'https://www.npmjs.com/package/libnpm', homepage: 'https://github.com/npm/libnpm#readme', @@ -26,8 +26,7 @@ module.exports = [ scope: 'unscoped', version: '4.0.1', description: 'programmatic library for `npm access` commands', - keywords: 'libnpmaccess', - date: '2020-11-03T19:19:00.526Z', + date: new Date('2020-11-03T19:19:00.526Z'), links: { npm: 'https://www.npmjs.com/package/libnpmaccess', homepage: 'https://npmjs.com/package/libnpmaccess', @@ -48,7 +47,7 @@ module.exports = [ scope: 'evocateur', version: '3.1.2', description: 'programmatic library for `npm access` commands', - date: '2019-07-16T19:43:33.959Z', + date: new Date('2019-07-16T19:43:33.959Z'), links: { npm: 'https://www.npmjs.com/package/%40evocateur%2Flibnpmaccess', homepage: 'https://npmjs.com/package/@evocateur/libnpmaccess', @@ -64,7 +63,7 @@ module.exports = [ scope: 'evocateur', version: '1.2.2', description: 'Programmatic API for the bits behind npm publish and unpublish', - date: '2019-07-16T19:40:40.850Z', + date: new Date('2019-07-16T19:40:40.850Z'), links: { npm: 'https://www.npmjs.com/package/%40evocateur%2Flibnpmpublish', homepage: 'https://npmjs.com/package/@evocateur/libnpmpublish', @@ -81,7 +80,7 @@ module.exports = [ version: '2.0.1', description: 'Programmatic api for `npm org` commands', keywords: ['libnpm', 'npm', 'package manager', 'api', 'orgs', 'teams'], - date: '2020-11-03T19:21:57.757Z', + date: new Date('2020-11-03T19:21:57.757Z'), links: { npm: 'https://www.npmjs.com/package/libnpmorg', homepage: 'https://npmjs.com/package/libnpmorg', @@ -103,7 +102,7 @@ module.exports = [ version: '3.1.0', description: 'Programmatic API for searching in npm and compatible registries.', keywords: ['npm', 'search', 'api', 'libnpm'], - date: '2020-12-08T23:54:18.374Z', + date: new Date('2020-12-08T23:54:18.374Z'), links: { npm: 'https://www.npmjs.com/package/libnpmsearch', homepage: 'https://npmjs.com/package/libnpmsearch', @@ -124,7 +123,7 @@ module.exports = [ scope: 'unscoped', version: '2.0.2', description: 'npm Team management APIs', - date: '2020-11-03T19:24:42.380Z', + date: new Date('2020-11-03T19:24:42.380Z'), links: { npm: 'https://www.npmjs.com/package/libnpmteam', homepage: 'https://npmjs.com/package/libnpmteam', @@ -146,7 +145,7 @@ module.exports = [ version: '6.0.1', description: 'programmatic API for managing npm registry hooks', keywords: ['npm', 'hooks', 'registry', 'npm api'], - date: '2020-11-03T19:20:45.818Z', + date: new Date('2020-11-03T19:20:45.818Z'), links: { npm: 'https://www.npmjs.com/package/libnpmhook', homepage: 'https://github.com/npm/libnpmhook#readme', @@ -167,7 +166,7 @@ module.exports = [ scope: 'unscoped', version: '4.0.0', description: 'Programmatic API for the bits behind npm publish and unpublish', - date: '2020-11-03T19:13:43.780Z', + date: new Date('2020-11-03T19:13:43.780Z'), links: { npm: 'https://www.npmjs.com/package/libnpmpublish', homepage: 'https://npmjs.com/package/libnpmpublish', @@ -194,7 +193,7 @@ module.exports = [ 'git', 'fund', 'gitfund', ], - date: '2020-12-08T23:22:00.213Z', + date: new Date('2020-12-08T23:22:00.213Z'), links: { npm: 'https://www.npmjs.com/package/libnpmfund', homepage: 'https://github.com/npm/libnpmfund#readme', @@ -223,7 +222,7 @@ module.exports = [ 'workspaces', 'map-workspaces', ], - date: '2020-09-30T15:16:29.017Z', + date: new Date('2020-09-30T15:16:29.017Z'), links: { npm: 'https://www.npmjs.com/package/%40npmcli%2Fmap-workspaces', homepage: 'https://github.com/npm/map-workspaces#readme', @@ -244,7 +243,7 @@ module.exports = [ scope: 'unscoped', version: '1.0.7', description: "library to do the things that 'npm version' does", - date: '2020-11-04T00:21:41.069Z', + date: new Date('2020-11-04T00:21:41.069Z'), links: { npm: 'https://www.npmjs.com/package/libnpmversion', homepage: 'https://github.com/npm/libnpmversion#readme', @@ -270,7 +269,7 @@ module.exports = [ scope: 'types', version: '2.0.1', description: 'TypeScript definitions for libnpmsearch', - date: '2019-09-26T22:24:28.713Z', + date: new Date('2019-09-26T22:24:28.713Z'), links: { npm: 'https://www.npmjs.com/package/%40types%2Flibnpmsearch' }, publisher: { username: 'types', email: 'ts-npm-types@microsoft.com' }, maintainers: [{ username: 'types', email: 'ts-npm-types@microsoft.com' }], diff --git a/test/fixtures/mock-registry.js b/test/fixtures/mock-registry.js index 01d43ba3d980b..5890fa7ee9366 100644 --- a/test/fixtures/mock-registry.js +++ b/test/fixtures/mock-registry.js @@ -46,19 +46,6 @@ class MockRegistry { this.#nock = nock } - search ({ responseCode = 200, results = [], error }) { - // the flags, score, and searchScore parts of the response are never used - // by npm, only package is used - const response = results.map(p => ({ package: p })) - this.nock = this.nock.get('/-/v1/search').query(true) - if (error) { - this.nock = this.nock.replyWithError(error) - } else { - this.nock = this.nock.reply(responseCode, { objects: response }) - } - return this.nock - } - whoami ({ username, body, responseCode = 200, times = 1 }) { if (username) { this.nock = this.nock.get('/-/whoami').times(times).reply(responseCode, { username }) diff --git a/test/lib/commands/search.js b/test/lib/commands/search.js index f18fcc475a99c..d2462b1aed4cc 100644 --- a/test/lib/commands/search.js +++ b/test/lib/commands/search.js @@ -1,92 +1,169 @@ const t = require('tap') -const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') -const MockRegistry = require('../../fixtures/mock-registry.js') +const Minipass = require('minipass') +const { fake: mockNpm } = require('../../fixtures/mock-npm') const libnpmsearchResultFixture = require('../../fixtures/libnpmsearch-stream-result.js') +let result = '' +const flatOptions = { + search: { + exclude: null, + limit: 20, + opts: '', + }, +} +const config = { + json: false, + parseable: false, +} +const npm = mockNpm({ + config, + flatOptions: { ...flatOptions }, + output: (...msg) => { + result += msg.join('\n') + }, +}) +const npmlog = { + silly () {}, + clearProgress () {}, +} +const libnpmsearch = { + stream () {}, +} +const mocks = { + npmlog, + libnpmsearch, +} + +t.afterEach(() => { + result = '' + config.json = false + config.parseable = false + npm.flatOptions = { ...flatOptions } +}) + +const Search = t.mock('../../../lib/commands/search.js', mocks) +const search = new Search(npm) + t.test('no args', async t => { - const { npm } = await loadMockNpm(t) await t.rejects( - npm.exec('search', []), + search.exec([]), /search must be called with arguments/, 'should throw usage instructions' ) }) -t.test('search text', async t => { - const { npm, joinedOutput } = await loadMockNpm(t) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), +t.test('search ', async t => { + const src = new Minipass() + src.objectMode = true + const libnpmsearch = { + stream () { + return src + }, + } + + const Search = t.mock('../../../lib/commands/search.js', { + ...mocks, + libnpmsearch, }) + const search = new Search(npm) - registry.search({ results: libnpmsearchResultFixture }) - await npm.exec('search', ['libnpm']) - t.matchSnapshot(joinedOutput(), 'should have expected search results') + for (const i of libnpmsearchResultFixture) { + src.write(i) + } + + src.end() + + await search.exec(['libnpm']) + t.matchSnapshot(result, 'should have expected search results') }) t.test('search --json', async t => { - const { npm, joinedOutput } = await loadMockNpm(t, { config: { json: true } }) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), + const src = new Minipass() + src.objectMode = true + + npm.flatOptions.json = true + config.json = true + const libnpmsearch = { + stream () { + return src + }, + } + + const Search = t.mock('../../../lib/commands/search.js', { + ...mocks, + libnpmsearch, }) + const search = new Search(npm) - registry.search({ results: libnpmsearchResultFixture }) + for (const i of libnpmsearchResultFixture) { + src.write(i) + } - await npm.exec('search', ['libnpm']) + src.end() + await search.exec(['libnpm']) + + const parsedResult = JSON.parse(result) + parsedResult.forEach((entry) => { + entry.date = new Date(entry.date) + }) t.same( - JSON.parse(joinedOutput()), + parsedResult, libnpmsearchResultFixture, 'should have expected search results as json' ) -}) -t.test('search --parseable', async t => { - const { npm, joinedOutput } = await loadMockNpm(t, { config: { parseable: true } }) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), - }) - - registry.search({ results: libnpmsearchResultFixture }) - await npm.exec('search', ['libnpm']) - t.matchSnapshot(joinedOutput(), 'should have expected search results as parseable') + config.json = false }) -t.test('search --color', async t => { - const { npm, joinedOutput } = await loadMockNpm(t, { config: { color: 'always' } }) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), +t.test('search --json', async t => { + const src = new Minipass() + src.objectMode = true + + npm.flatOptions.json = true + config.json = true + const libnpmsearch = { + stream () { + return src + }, + } + + const Search = t.mock('../../../lib/commands/search.js', { + ...mocks, + libnpmsearch, }) + const search = new Search(npm) - registry.search({ results: libnpmsearchResultFixture }) - await npm.exec('search', ['libnpm']) - t.matchSnapshot(joinedOutput(), 'should have expected search results with color') -}) + src.end() + await search.exec(['foo']) -t.test('search //--color', async t => { - const { npm, joinedOutput } = await loadMockNpm(t, { config: { color: 'always' } }) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), - }) + t.equal(result, '\n[]\n', 'should have expected empty square brackets') - registry.search({ results: libnpmsearchResultFixture }) - await npm.exec('search', ['/libnpm/']) - t.matchSnapshot(joinedOutput(), 'should have expected search results with color') + config.json = false }) -t.test('search ', async t => { - const { npm, joinedOutput } = await loadMockNpm(t) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), +t.test('search --searchexclude --searchopts', async t => { + npm.flatOptions.search = { + ...flatOptions.search, + exclude: '', + } + + const src = new Minipass() + src.objectMode = true + const libnpmsearch = { + stream () { + return src + }, + } + + const Search = t.mock('../../../lib/commands/search.js', { + ...mocks, + libnpmsearch, }) + const search = new Search(npm) - registry.search({ results: [{ + src.write({ name: 'foo', scope: 'unscoped', version: '1.0.0', @@ -98,7 +175,8 @@ t.test('search ', async t => { maintainers: [ { username: 'foo', email: 'foo@npmjs.com' }, ], - }, { + }) + src.write({ name: 'libnpmversion', scope: 'unscoped', version: '1.0.0', @@ -110,100 +188,58 @@ t.test('search ', async t => { maintainers: [ { username: 'foo', email: 'foo@npmjs.com' }, ], - }] }) - - await npm.exec('search', ['foo']) - - t.matchSnapshot(joinedOutput(), 'should have filtered expected search results') -}) - -t.test('empty search results', async t => { - const { npm, joinedOutput } = await loadMockNpm(t) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), }) - registry.search({ results: [] }) - await npm.exec('search', ['foo']) + src.end() + await search.exec(['foo']) - t.matchSnapshot(joinedOutput(), 'should have expected search results') + t.matchSnapshot(result, 'should have filtered expected search results') }) -t.test('empty search results --json', async t => { - const { npm, joinedOutput } = await loadMockNpm(t, { config: { json: true } }) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), +t.test('empty search results', async t => { + const src = new Minipass() + src.objectMode = true + const libnpmsearch = { + stream () { + return src + }, + } + + const Search = t.mock('../../../lib/commands/search.js', { + ...mocks, + libnpmsearch, }) + const search = new Search(npm) - registry.search({ results: [] }) + src.end() + await search.exec(['foo']) - await npm.exec('search', ['foo']) - t.equal(joinedOutput(), '\n[]\n', 'should have expected empty square brackets') + t.matchSnapshot(result, 'should have expected search results') }) t.test('search api response error', async t => { - const { npm } = await loadMockNpm(t) - - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), + const src = new Minipass() + src.objectMode = true + const libnpmsearch = { + stream () { + return src + }, + } + + const Search = t.mock('../../../lib/commands/search.js', { + ...mocks, + libnpmsearch, }) + const search = new Search(npm) - registry.search({ error: 'ERR' }) + setImmediate(() => { + src.emit('error', new Error('ERR')) + src.end() + }) await t.rejects( - npm.exec('search', ['foo']), + search.exec(['foo']), /ERR/, 'should throw response error' ) }) - -t.test('search exclude string', async t => { - const { npm, joinedOutput } = await loadMockNpm(t, { config: { searchexclude: 'libnpmversion' } }) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), - }) - - registry.search({ results: libnpmsearchResultFixture }) - await npm.exec('search', ['libnpm']) - t.matchSnapshot(joinedOutput(), 'results should not have libnpmversion') -}) - -t.test('search exclude username with upper case letters', async t => { - const { npm, joinedOutput } = await loadMockNpm(t, { config: { searchexclude: 'NLF' } }) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), - }) - - registry.search({ results: libnpmsearchResultFixture }) - await npm.exec('search', ['libnpm']) - t.matchSnapshot(joinedOutput(), 'results should not have nlf') -}) - -t.test('search exclude regex', async t => { - const { npm, joinedOutput } = await loadMockNpm(t, { config: { searchexclude: '/version/' } }) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), - }) - - registry.search({ results: libnpmsearchResultFixture }) - await npm.exec('search', ['libnpm']) - t.matchSnapshot(joinedOutput(), 'results should not have libnpmversion') -}) - -t.test('search exclude forward slash', async t => { - const { npm, joinedOutput } = await loadMockNpm(t, { config: { searchexclude: '/version' } }) - const registry = new MockRegistry({ - tap: t, - registry: npm.config.get('registry'), - }) - - registry.search({ results: libnpmsearchResultFixture }) - await npm.exec('search', ['libnpm']) - t.matchSnapshot(joinedOutput(), 'results should not have libnpmversion') -}) diff --git a/test/lib/commands/view.js b/test/lib/commands/view.js index da823db5d7507..82be1201ee169 100644 --- a/test/lib/commands/view.js +++ b/test/lib/commands/view.js @@ -1,5 +1,4 @@ const t = require('tap') -const { load: _loadMockNpm } = require('../../fixtures/mock-npm.js') t.cleanSnapshot = str => str .replace(/(published ).*?( ago)/g, '$1{TIME}$2') @@ -7,6 +6,18 @@ t.cleanSnapshot = str => str // run the same as tap does when running directly with node process.stdout.columns = undefined +const { fake: mockNpm } = require('../../fixtures/mock-npm') + +let logs +const cleanLogs = () => { + logs = '' + const fn = (...args) => { + logs += '\n' + args.map(el => logs += el) + } + console.log = fn +} + // 3 days. its never yesterday and never a week ago const yesterday = new Date(Date.now() - 1000 * 60 * 60 * 24 * 3) @@ -60,7 +71,7 @@ const packument = (nv, opts) => { tarball: 'http://hm.blue.com/1.0.1.tgz', integrity: '---', fileCount: 1, - unpackedSize: 1000, + unpackedSize: 1, }, }, }, @@ -83,7 +94,7 @@ const packument = (nv, opts) => { tarball: 'http://hm.cyan.com/1.0.0.tgz', integrity: '---', fileCount: 1, - unpackedSize: 1000000, + unpackedSize: 1, }, }, '1.0.1': {}, @@ -169,7 +180,7 @@ const packument = (nv, opts) => { tarball: 'http://hm.green.com/1.0.0.tgz', integrity: '---', fileCount: 1, - unpackedSize: 1000000000, + unpackedSize: 1, }, }, '1.0.1': {}, @@ -260,212 +271,289 @@ const packument = (nv, opts) => { return mocks[nv.name] } -const loadMockNpm = async function (t, opts = {}) { - const consoleLogs = [] - const mockNpm = await _loadMockNpm(t, { - mocks: { - pacote: { - packument, - }, +t.beforeEach(cleanLogs) + +t.test('should log package info', async t => { + const View = t.mock('../../../lib/commands/view.js', { + pacote: { + packument, }, - globals: { - 'console.log': (...args) => { - consoleLogs.push(args) - }, + }) + const npm = mockNpm({ + config: { unicode: false }, + }) + const view = new View(npm) + + const ViewJson = t.mock('../../../lib/commands/view.js', { + pacote: { + packument, }, - ...opts, }) - return { ...mockNpm, consoleLogs } -} + const jsonNpm = mockNpm({ + config: { + json: true, + tag: 'latest', + }, + }) + const viewJson = new ViewJson(jsonNpm) -t.test('package from git', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { unicode: false } }) - await npm.exec('view', ['https://github.com/npm/green']) - t.matchSnapshot(consoleLogs.join('\n')) -}) + const ViewUnicode = t.mock('../../../lib/commands/view.js', { + pacote: { + packument, + }, + }) + const unicodeNpm = mockNpm({ + config: { unicode: true }, + }) + const viewUnicode = new ViewUnicode(unicodeNpm) -t.test('deprecated package with license, bugs, repository and other fields', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { unicode: false } }) - await npm.exec('view', ['green@1.0.0']) - t.matchSnapshot(consoleLogs.join('\n')) -}) + t.test('package from git', async t => { + await view.exec(['https://github.com/npm/green']) + t.matchSnapshot(logs) + }) -t.test('deprecated package with unicode', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { unicode: true } }) - await npm.exec('view', ['green@1.0.0']) - t.matchSnapshot(consoleLogs.join('\n')) -}) + t.test('package with license, bugs, repository and other fields', async t => { + await view.exec(['green@1.0.0']) + t.matchSnapshot(logs) + }) -t.test('package with more than 25 deps', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { unicode: false } }) - await npm.exec('view', ['black@1.0.0']) - t.matchSnapshot(consoleLogs.join('\n')) -}) + t.test('package with more than 25 deps', async t => { + await view.exec(['black@1.0.0']) + t.matchSnapshot(logs) + }) -t.test('package with maintainers info as object', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { unicode: false } }) - await npm.exec('view', ['pink@1.0.0']) - t.matchSnapshot(consoleLogs.join('\n')) -}) + t.test('package with maintainers info as object', async t => { + await view.exec(['pink@1.0.0']) + t.matchSnapshot(logs) + }) -t.test('package with homepage', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { unicode: false } }) - await npm.exec('view', ['orange@1.0.0']) - t.matchSnapshot(consoleLogs.join('\n')) -}) + t.test('package with homepage', async t => { + await view.exec(['orange@1.0.0']) + t.matchSnapshot(logs) + }) -t.test('package with no versions', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { unicode: false } }) - await npm.exec('view', ['brown']) - t.equal(consoleLogs.join('\n'), '', 'no info to display') -}) + t.test('package with no versions', async t => { + await view.exec(['brown']) + t.equal(logs, '', 'no info to display') + }) -t.test('package with no repo or homepage', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { unicode: false } }) - await npm.exec('view', ['blue@1.0.0']) - t.matchSnapshot(consoleLogs.join('\n')) -}) + t.test('package with no repo or homepage', async t => { + await view.exec(['blue@1.0.0']) + t.matchSnapshot(logs) + }) -t.test('package with semver range', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { unicode: false } }) - await npm.exec('view', ['blue@^1.0.0']) - t.matchSnapshot(consoleLogs.join('\n')) -}) + t.test('package with semver range', async t => { + await view.exec(['blue@^1.0.0']) + t.matchSnapshot(logs) + }) -t.test('package with no modified time', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { unicode: false } }) - await npm.exec('view', ['cyan@1.0.0']) - t.matchSnapshot(consoleLogs.join('\n')) -}) + t.test('package with no modified time', async t => { + await viewUnicode.exec(['cyan@1.0.0']) + t.matchSnapshot(logs) + }) -t.test('package with --json and semver range', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { json: true } }) - await npm.exec('view', ['cyan@^1.0.0']) - t.matchSnapshot(consoleLogs.join('\n')) -}) + t.test('package with --json and semver range', async t => { + await viewJson.exec(['cyan@^1.0.0']) + t.matchSnapshot(logs) + }) -t.test('package with --json and no versions', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { config: { json: true } }) - await npm.exec('view', ['brown']) - t.equal(consoleLogs.join('\n'), '', 'no info to display') + t.test('package with --json and no versions', async t => { + await viewJson.exec(['brown']) + t.equal(logs, '', 'no info to display') + }) }) -t.test('package in cwd', async t => { - const prefixDir = { +t.test('should log info of package in current working dir', async t => { + const testDir = t.testdir({ 'package.json': JSON.stringify({ name: 'blue', version: '1.0.0', }, null, 2), - } + }) + + const View = t.mock('../../../lib/commands/view.js', { + pacote: { + packument, + }, + }) + const npm = mockNpm({ + prefix: testDir, + config: { + tag: '1.0.0', + }, + }) + const view = new View(npm) t.test('specific version', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { prefixDir }) - await npm.exec('view', ['.@1.0.0']) - t.matchSnapshot(consoleLogs.join('\n')) + await view.exec(['.@1.0.0']) + t.matchSnapshot(logs) }) t.test('non-specific version', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { prefixDir }) - await npm.exec('view', ['.']) - t.matchSnapshot(consoleLogs.join('\n')) + await view.exec(['.']) + t.matchSnapshot(logs) }) t.test('directory', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { prefixDir }) - await npm.exec('view', ['./blue']) - t.matchSnapshot(consoleLogs.join('\n')) + await view.exec(['./blue']) + t.matchSnapshot(logs) }) }) -t.test('specific field names', async t => { - const { npm, consoleLogs } = await loadMockNpm(t) - t.afterEach(() => { - consoleLogs.length = 0 +t.test('should log info by field name', async t => { + const ViewJson = t.mock('../../../lib/commands/view.js', { + pacote: { + packument, + }, + }) + const jsonNpm = mockNpm({ + config: { + tag: 'latest', + json: true, + }, + }) + + const viewJson = new ViewJson(jsonNpm) + + const View = t.mock('../../../lib/commands/view.js', { + pacote: { + packument, + }, }) + const npm = mockNpm() + const view = new View(npm) + t.test('readme', async t => { - await npm.exec('view', ['yellow@1.0.0', 'readme']) - t.matchSnapshot(consoleLogs.join('\n')) + await view.exec(['yellow@1.0.0', 'readme']) + t.matchSnapshot(logs) }) t.test('several fields', async t => { - await npm.exec('view', ['yellow@1.0.0', 'name', 'version', 'foo[bar]']) - t.matchSnapshot(consoleLogs.join('\n')) + await viewJson.exec(['yellow@1.0.0', 'name', 'version', 'foo[bar]']) + t.matchSnapshot(logs) }) t.test('several fields with several versions', async t => { - await npm.exec('view', ['yellow@1.x.x', 'author']) - t.matchSnapshot(consoleLogs.join('\n')) + await view.exec(['yellow@1.x.x', 'author']) + t.matchSnapshot(logs) }) t.test('nested field with brackets', async t => { - await npm.exec('view', ['orange@1.0.0', 'dist[shasum]']) - t.matchSnapshot(consoleLogs.join('\n')) + await viewJson.exec(['orange@1.0.0', 'dist[shasum]']) + t.matchSnapshot(logs) }) t.test('maintainers with email', async t => { - await npm.exec('view', ['yellow@1.0.0', 'maintainers', 'name']) - t.matchSnapshot(consoleLogs.join('\n')) + await viewJson.exec(['yellow@1.0.0', 'maintainers', 'name']) + t.matchSnapshot(logs) }) t.test('maintainers with url', async t => { - await npm.exec('view', ['pink@1.0.0', 'maintainers']) - t.matchSnapshot(consoleLogs.join('\n')) + await viewJson.exec(['pink@1.0.0', 'maintainers']) + t.matchSnapshot(logs) }) t.test('unknown nested field ', async t => { - await npm.exec('view', ['yellow@1.0.0', 'dist.foobar']) - t.equal(consoleLogs.join('\n'), '', 'no info to display') + await view.exec(['yellow@1.0.0', 'dist.foobar']) + t.equal(logs, '', 'no info to display') }) t.test('array field - 1 element', async t => { - await npm.exec('view', ['purple@1.0.0', 'maintainers.name']) - t.matchSnapshot(consoleLogs.join('\n')) + await view.exec(['purple@1.0.0', 'maintainers.name']) + t.matchSnapshot(logs) }) t.test('array field - 2 elements', async t => { - await npm.exec('view', ['yellow@1.x.x', 'maintainers.name']) - t.matchSnapshot(consoleLogs.join('\n')) + await view.exec(['yellow@1.x.x', 'maintainers.name']) + t.matchSnapshot(logs) }) }) t.test('throw error if global mode', async t => { - const { npm } = await loadMockNpm(t, { config: { global: true } }) + const View = t.mock('../../../lib/commands/view.js') + const npm = mockNpm({ + config: { + global: true, + tag: 'latest', + }, + }) + const view = new View(npm) await t.rejects( - npm.exec('view', []), + view.exec([]), /Cannot use view command in global mode./ ) }) t.test('throw ENOENT error if package.json missing', async t => { - const { npm } = await loadMockNpm(t) + const testDir = t.testdir({}) + + const View = t.mock('../../../lib/commands/view.js') + const npm = mockNpm({ + prefix: testDir, + }) + const view = new View(npm) await t.rejects( - npm.exec('view', []), + view.exec([]), { code: 'ENOENT' } ) }) +t.test('throw EJSONPARSE error if package.json not json', async t => { + const testDir = t.testdir({ + 'package.json': 'not json, nope, not even a little bit!', + }) + + const View = t.mock('../../../lib/commands/view.js') + const npm = mockNpm({ + prefix: testDir, + }) + const view = new View(npm) + await t.rejects( + view.exec([]), + { code: 'EJSONPARSE' } + ) +}) + t.test('throw error if package.json has no name', async t => { - const { npm } = await loadMockNpm(t, { - prefixDir: { - 'package.json': '{}', - }, + const testDir = t.testdir({ + 'package.json': '{}', + }) + + const View = t.mock('../../../lib/commands/view.js') + const npm = mockNpm({ + prefix: testDir, }) + const view = new View(npm) await t.rejects( - npm.exec('view', []), + view.exec([]), /Invalid package.json, no "name" field/ ) }) t.test('throws when unpublished', async t => { - const { npm } = await loadMockNpm(t) + const View = t.mock('../../../lib/commands/view.js', { + pacote: { + packument, + }, + }) + const npm = mockNpm({ + config: { + tag: '1.0.1', + }, + }) + const view = new View(npm) await t.rejects( - npm.exec('view', ['red']), + view.exec(['red']), { code: 'E404', pkgid: 'red@1.0.1', message: 'Unpublished on 2012-12-20T00:00:00.000Z' } ) }) t.test('workspaces', async t => { - const prefixDir = { + t.beforeEach(() => { + warnMsg = undefined + config.json = false + }) + const testDir = t.testdir({ 'package.json': JSON.stringify({ name: 'workspaces-test-package', version: '1.2.3', @@ -483,103 +571,106 @@ t.test('workspaces', async t => { version: '1.2.3', }), }, + }) + const View = t.mock('../../../lib/commands/view.js', { + pacote: { + packument, + }, + 'proc-log': { + warn: (msg) => { + warnMsg = msg + }, + silly: () => {}, + }, + }) + const config = { + unicode: false, + tag: 'latest', } + let warnMsg + const npm = mockNpm({ + config, + localPrefix: testDir, + }) + const view = new View(npm) t.test('all workspaces', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { - prefixDir, - config: { unicode: false, workspaces: true }, - }) - await npm.exec('view', []) - t.matchSnapshot(consoleLogs.join('\n')) + await view.execWorkspaces([], []) + t.matchSnapshot(logs) }) t.test('one specific workspace', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { - prefixDir, - config: { unicode: false, workspace: ['green'] }, - }) - await npm.exec('view', []) - t.matchSnapshot(consoleLogs.join('\n')) + await view.execWorkspaces([], ['green']) + t.matchSnapshot(logs) }) t.test('all workspaces --json', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { - prefixDir, - config: { unicode: false, workspaces: true, json: true }, - }) - await npm.exec('view', []) - t.matchSnapshot(consoleLogs.join('\n')) + config.json = true + await view.execWorkspaces([], []) + t.matchSnapshot(logs) }) t.test('all workspaces single field', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { - prefixDir, - config: { unicode: false, workspaces: true }, - }) - await npm.exec('view', ['.', 'name']) - t.matchSnapshot(consoleLogs.join('\n')) + await view.execWorkspaces(['.', 'name'], []) + t.matchSnapshot(logs) }) t.test('all workspaces nonexistent field', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { - prefixDir, - config: { unicode: false, workspaces: true }, - }) - await npm.exec('view', ['.', 'foo']) - t.matchSnapshot(consoleLogs.join('\n')) + await view.execWorkspaces(['.', 'foo'], []) + t.matchSnapshot(logs) }) t.test('all workspaces nonexistent field --json', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { - prefixDir, - config: { unicode: false, workspaces: true, json: true }, - }) - await npm.exec('view', ['.', 'foo']) - t.matchSnapshot(consoleLogs.join('\n')) + config.json = true + await view.execWorkspaces(['.', 'foo'], []) + t.matchSnapshot(logs) }) t.test('all workspaces single field --json', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { - prefixDir, - config: { unicode: false, workspaces: true, json: true }, - }) - await npm.exec('view', ['.', 'name']) - t.matchSnapshot(consoleLogs.join('\n')) + config.json = true + await view.execWorkspaces(['.', 'name'], []) + t.matchSnapshot(logs) }) t.test('single workspace --json', async t => { - const { npm, consoleLogs } = await loadMockNpm(t, { - prefixDir, - config: { unicode: false, workspace: ['green'], json: true }, - }) - await npm.exec('view', []) - t.matchSnapshot(consoleLogs.join('\n')) + config.json = true + await view.execWorkspaces([], ['green']) + t.matchSnapshot(logs) }) t.test('remote package name', async t => { - const { npm, logs, consoleLogs } = await loadMockNpm(t, { - prefixDir, - config: { unicode: false, workspaces: true }, - }) - await npm.exec('view', ['pink']) - t.matchSnapshot(consoleLogs.join('\n')) - t.matchSnapshot(logs.warn, 'should have warning of ignoring workspaces') + await view.execWorkspaces(['pink'], []) + t.matchSnapshot(warnMsg) + t.matchSnapshot(logs) }) }) t.test('completion', async t => { - const { npm } = await loadMockNpm(t) - const view = await npm.cmd('view') + const View = t.mock('../../../lib/commands/view.js', { + pacote: { + packument, + }, + }) + const npm = mockNpm({ + config: { + tag: '1.0.1', + }, + }) + const view = new View(npm) const res = await view.completion({ conf: { argv: { remain: ['npm', 'view', 'green@1.0.0'] } }, }) t.ok(res, 'returns back fields') }) -t.test('no package completion', async t => { - const { npm } = await loadMockNpm(t) - const view = await npm.cmd('view') +t.test('no registry completion', async t => { + const View = t.mock('../../../lib/commands/view.js') + const npm = mockNpm({ + config: { + tag: '1.0.1', + }, + }) + const view = new View(npm) const res = await view.completion({ conf: { argv: { remain: ['npm', 'view'] } } }) t.notOk(res, 'there is no package completion') t.end() diff --git a/test/lib/utils/config/definitions.js b/test/lib/utils/config/definitions.js index 200ee9e5536d1..088d0cdb6e128 100644 --- a/test/lib/utils/config/definitions.js +++ b/test/lib/utils/config/definitions.js @@ -457,13 +457,6 @@ t.test('retry options', t => { }) t.test('search options', t => { - const vals = { - description: 'test description', - exclude: 'test search exclude', - limit: 99, - staleneess: 99, - - } const obj = {} // : flat.search[