From eae9637cce7de995cf9dae9067fd80f9f73537d6 Mon Sep 17 00:00:00 2001 From: Gar Date: Tue, 3 May 2022 13:01:27 -0700 Subject: [PATCH] fix: remove test coverage map Turns out there were three files that still had no test coverage because of the combination of the mocks in tests and the coverage map. Removing the map altogether exposed them. This PR removes the coverage map and fixes test to cover all lines that were being missed. While adding coverage to the `npm search` codebase multiple unneeded guards and at least one bug was found (it was impossible to exclude searches based on username). These were fixed. The `npm view` tests were also refactored to use the real npm object. Finally, a small inlining of lib/utils/file-exists.js was done. --- lib/commands/completion.js | 18 +- lib/commands/search.js | 47 +- lib/commands/view.js | 3 - lib/search/package-filter.js | 43 -- lib/utils/config/definitions.js | 2 +- lib/utils/file-exists.js | 10 - lib/utils/format-bytes.js | 1 + .../format-search-stream.js} | 66 +-- 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, 729 insertions(+), 861 deletions(-) delete mode 100644 lib/search/package-filter.js delete mode 100644 lib/utils/file-exists.js rename lib/{search/format-package-stream.js => utils/format-search-stream.js} (70%) delete mode 100644 lib/utils/read-package-name.js delete mode 100644 test/coverage-map.js delete mode 100644 test/lib/utils/file-exists.js diff --git a/lib/commands/completion.js b/lib/commands/completion.js index 5b7e0d355c63c..c24fb050dcb34 100644 --- a/lib/commands/completion.js +++ b/lib/commands/completion.js @@ -29,18 +29,26 @@ // 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 = require('../utils/file-exists.js') +const fileExists = async (file) => { + try { + const stat = await fs.stat(file) + return stat.isFile() + } catch { + return false + } +} -const { promisify } = require('util') const BaseCommand = require('../base-command.js') class Completion extends BaseCommand { @@ -189,12 +197,10 @@ 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 readFile(p, 'utf8')).replace(/^#!.*?\n/, '') + const d = (await fs.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 a06ba4031443b..8751e9e7d22fd 100644 --- a/lib/commands/search.js +++ b/lib/commands/search.js @@ -3,26 +3,33 @@ const Pipeline = require('minipass-pipeline') const libSearch = require('libnpmsearch') const log = require('../utils/log-shim.js') -const formatPackageStream = require('../search/format-package-stream.js') -const packageFilter = require('../search/package-filter.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 + } -function prepareIncludes (args) { - return args - .map(s => s.toLowerCase()) - .filter(s => s) + return true } -function prepareExcludes (searchexclude) { - var exclude - if (typeof searchexclude === 'string') { - exclude = searchexclude.split(/\s+/) - } else { - exclude = [] +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) } - - return exclude - .map(s => s.toLowerCase()) - .filter(s => s) + return words.indexOf(pattern) !== -1 } const BaseCommand = require('../base-command.js') @@ -50,8 +57,8 @@ class Search extends BaseCommand { const opts = { ...this.npm.flatOptions, ...this.npm.flatOptions.search, - include: prepareIncludes(args), - exclude: prepareExcludes(this.npm.flatOptions.search.exclude), + include: args.map(s => s.toLowerCase()).filter(s => s), + exclude: this.npm.flatOptions.search.exclude.split(/\s+/), } if (opts.include.length === 0) { @@ -63,7 +70,7 @@ class Search extends BaseCommand { class FilterStream extends Minipass { write (pkg) { - if (packageFilter(pkg, opts.include, opts.exclude)) { + if (filter(pkg, opts.include, opts.exclude)) { super.write(pkg) } } @@ -73,7 +80,7 @@ class Search extends BaseCommand { // Grab a configured output stream that will spit out packages in the // desired format. - const outputStream = formatPackageStream({ + const outputStream = formatSearchStream({ args, // --searchinclude options are not highlighted ...opts, }) diff --git a/lib/commands/view.js b/lib/commands/view.js index 403d09d813dc7..d78ee77dc0a3d 100644 --- a/lib/commands/view.js +++ b/lib/commands/view.js @@ -57,9 +57,6 @@ 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/search/package-filter.js b/lib/search/package-filter.js deleted file mode 100644 index bb0ae679bdccd..0000000000000 --- a/lib/search/package-filter.js +++ /dev/null @@ -1,43 +0,0 @@ -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 6f1b1a7244a50..a5eac8c826c84 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] + flatOptions.search.exclude = obj[key].toLowerCase() }, }) diff --git a/lib/utils/file-exists.js b/lib/utils/file-exists.js deleted file mode 100644 index 605472536aab0..0000000000000 --- a/lib/utils/file-exists.js +++ /dev/null @@ -1,10 +0,0 @@ -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 d7cf6d144e339..d293001df5524 100644 --- a/lib/utils/format-bytes.js +++ b/lib/utils/format-bytes.js @@ -23,6 +23,7 @@ const formatBytes = (bytes, space = true) => { return `${(bytes / 1000000).toFixed(1)}${spacer}MB` } + // GB return `${(bytes / 1000000000).toFixed(1)}${spacer}GB` } diff --git a/lib/search/format-package-stream.js b/lib/utils/format-search-stream.js similarity index 70% rename from lib/search/format-package-stream.js rename to lib/utils/format-search-stream.js index acead79e1a770..2a2dadd5c3434 100644 --- a/lib/search/format-package-stream.js +++ b/lib/utils/format-search-stream.js @@ -1,6 +1,3 @@ -// 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') @@ -18,32 +15,26 @@ const columnify = require('columnify') // The returned stream will format this package data // into a byte stream of formatted, displayable output. -module.exports = (opts = {}) => - opts.json ? new JSONOutputStream() : new TextOutputStream(opts) +module.exports = (opts) => { + return opts.json ? new JSONOutputStream() : new TextOutputStream(opts) +} class JSONOutputStream extends Minipass { - constructor () { - super() - this._didFirst = false - } + #didFirst = false write (obj) { - if (!this._didFirst) { + if (!this.#didFirst) { super.write('[\n') - this._didFirst = true + this.#didFirst = true } else { super.write('\n,\n') } - try { - return super.write(JSON.stringify(obj)) - } catch (er) { - return this.emit('error', er) - } + return super.write(JSON.stringify(obj)) } end () { - super.write(this._didFirst ? ']\n' : '\n[]\n') + super.write(this.#didFirst ? ']\n' : '\n[]\n') super.end() } } @@ -61,14 +52,11 @@ class TextOutputStream extends Minipass { } function prettify (data, num, opts) { - opts = opts || {} var truncate = !opts.long var pkg = normalizePackage(data, opts) - var columns = opts.description - ? ['name', 'description', 'author', 'date', 'version', 'keywords'] - : ['name', 'author', 'date', 'version', 'keywords'] + var columns = ['name', 'description', 'author', 'date', 'version', 'keywords'] if (opts.parseable) { return columns.map(function (col) { @@ -76,7 +64,10 @@ function prettify (data, num, opts) { }).join('\t') } - var output = columnify( + // stdout in tap is never a tty + /* istanbul ignore next */ + const maxWidth = process.stdout.isTTY ? process.stdout.getWindowSize()[0] : Infinity + let output = columnify( [pkg], { include: columns, @@ -92,8 +83,8 @@ function prettify (data, num, opts) { keywords: { maxWidth: Infinity }, }, } - ) - output = trimToMaxWidth(output) + ).split('\n').map(line => line.slice(0, maxWidth)).join('\n') + if (opts.color) { output = highlightSearchTerms(output, opts.args) } @@ -140,26 +131,6 @@ 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) @@ -169,13 +140,10 @@ function highlightSearchTerms (str, terms) { } function normalizePackage (data, opts) { - opts = opts || {} return { name: data.name, - description: opts.description ? data.description : '', - author: (data.maintainers || []).map(function (m) { - return '=' + m.username - }).join(' '), + description: data.description, + author: data.maintainers.map((m) => `=${m.username}`).join(' '), keywords: Array.isArray(data.keywords) ? data.keywords.join(' ') : typeof data.keywords === 'string' diff --git a/lib/utils/read-package-name.js b/lib/utils/read-package-name.js deleted file mode 100644 index 7ed15987767bb..0000000000000 --- a/lib/utils/read-package-name.js +++ /dev/null @@ -1,9 +0,0 @@ -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 d3e55ad623a43..687e9025fe7ac 100644 --- a/package.json +++ b/package.json @@ -230,8 +230,13 @@ ], "color": 1, "files": "test/{lib,bin,index.js}", - "coverage-map": "test/coverage-map.js", - "timeout": 600 + "timeout": 600, + "nyc-arg": [ + "--exclude", + "workspaces/**", + "--exclude", + "tap-snapshots/**" + ] }, "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 139fca25981ce..152e6605676e7 100644 --- a/tap-snapshots/test/lib/commands/search.js.test.cjs +++ b/tap-snapshots/test/lib/commands/search.js.test.cjs @@ -9,12 +9,130 @@ 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 --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 > 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 | +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 | ` diff --git a/tap-snapshots/test/lib/commands/view.js.test.cjs b/tap-snapshots/test/lib/commands/view.js.test.cjs index 5868e7b04babe..d5b7a3b4a7906 100644 --- a/tap-snapshots/test/lib/commands/view.js.test.cjs +++ b/tap-snapshots/test/lib/commands/view.js.test.cjs @@ -5,96 +5,102 @@ * Make sure to inspect the output below. Do not ignore changes! */ 'use strict' -exports[`test/lib/commands/view.js TAP should log info by field name array field - 1 element > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP deprecated package with license, bugs, repository and other fields > must match snapshot 1`] = ` -claudia -` +green@1.0.0 | ACME | deps: 2 | versions: 2 +green is a very important color -exports[`test/lib/commands/view.js TAP should log info by field name array field - 2 elements > must match snapshot 1`] = ` +DEPRECATED!! - true -maintainers[0].name = 'claudia' -maintainers[1].name = 'isaacs' -` +keywords:,colors, green, crayola -exports[`test/lib/commands/view.js TAP should log info by field name maintainers with email > must match snapshot 1`] = ` +bin:,green -{ - "maintainers": [ - { - "name": "claudia", - "email": "c@yellow.com", - "twitter": "cyellow" - }, - { - "name": "isaacs", - "email": "i@yellow.com", - "twitter": "iyellow" - } - ], - "name": "yellow" -} -` +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 -exports[`test/lib/commands/view.js TAP should log info by field name maintainers with url > must match snapshot 1`] = ` +maintainers: +-,claudia <c@yellow.com> +-,isaacs <i@yellow.com> -[ - "claudia (http://c.pink.com)", - "isaacs (http://i.pink.com)" -] +dist-tags: +latest: 1.0.0 ` -exports[`test/lib/commands/view.js TAP should log info by field name nested field with brackets > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP deprecated package with unicode > must match snapshot 1`] = ` -"123" -` +green@1.0.0 | ACME | deps: 2 | versions: 2 +green is a very important color -exports[`test/lib/commands/view.js TAP should log info by field name readme > must match snapshot 1`] = ` +DEPRECATED ⚠️ - true -a very useful readme -` +keywords:,colors, green, crayola -exports[`test/lib/commands/view.js TAP should log info by field name several fields > must match snapshot 1`] = ` +bin:,green -{ - "name": "yellow", - "version": "1.0.0" -} -` +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 -exports[`test/lib/commands/view.js TAP should log info by field name several fields with several versions > must match snapshot 1`] = ` +maintainers: +-,claudia <c@yellow.com> +-,isaacs <i@yellow.com> -yellow@1.0.0 'claudia' -yellow@1.0.1 'claudia' -yellow@1.0.2 'claudia' +dist-tags: +latest: 1.0.0 ` -exports[`test/lib/commands/view.js TAP should log info of package in current working dir directory > must match snapshot 1`] = ` +exports[`test/lib/commands/view.js TAP package from git > 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 -blue@1.0.0 | Proprietary | deps: none | versions: 2 +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.0 GB + +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 should log info of package in current working dir non-specific version > must match snapshot 1`] = ` - +exports[`test/lib/commands/view.js TAP package in cwd directory > 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 @@ -102,16 +108,15 @@ dist-tags: published {TIME} ago ` -exports[`test/lib/commands/view.js TAP should log info of package in current working dir specific version > must match snapshot 1`] = ` - +exports[`test/lib/commands/view.js TAP package in cwd 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 @@ -119,38 +124,23 @@ dist-tags: published {TIME} ago ` -exports[`test/lib/commands/view.js TAP should log package info package from git > 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 +exports[`test/lib/commands/view.js TAP package in cwd specific version > must match snapshot 1`] = ` -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 B - -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 -` -exports[`test/lib/commands/view.js TAP should log package info package with --json and semver range > must match snapshot 1`] = ` +published {TIME} ago +` +exports[`test/lib/commands/view.js TAP package with --json and semver range > must match snapshot 1`] = ` [ { "_npmUser": "claudia ", @@ -168,7 +158,7 @@ exports[`test/lib/commands/view.js TAP should log package info package with --js "tarball": "http://hm.cyan.com/1.0.0.tgz", "integrity": "---", "fileCount": 1, - "unpackedSize": 1 + "unpackedSize": 1000000 } }, { @@ -185,77 +175,44 @@ exports[`test/lib/commands/view.js TAP should log package info package with --js ] ` -exports[`test/lib/commands/view.js TAP should log package info package with homepage > must match snapshot 1`] = ` - +exports[`test/lib/commands/view.js TAP 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 - -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> +.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 maintainers info as object > must match snapshot 1`] = ` - +exports[`test/lib/commands/view.js TAP 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 should log package info package with more than 25 deps > must match snapshot 1`] = ` - +exports[`test/lib/commands/view.js TAP 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 @@ -288,16 +245,15 @@ dist-tags: latest: 1.0.0 ` -exports[`test/lib/commands/view.js TAP should log package info package with no modified time > must match snapshot 1`] = ` - +exports[`test/lib/commands/view.js TAP 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 B +.tarball:,http://hm.cyan.com/1.0.0.tgz +.shasum:,123 +.integrity:,--- +.unpackedSize:,1.0 MB dist-tags: latest: 1.0.0 @@ -305,16 +261,15 @@ dist-tags: published by claudia <claudia@cyan.com> ` -exports[`test/lib/commands/view.js TAP should log package info package with no repo or homepage > must match snapshot 1`] = ` - +exports[`test/lib/commands/view.js TAP 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 @@ -322,16 +277,15 @@ dist-tags: published {TIME} ago ` -exports[`test/lib/commands/view.js TAP should log package info package with semver range > must match snapshot 1`] = ` - +exports[`test/lib/commands/view.js TAP 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 @@ -341,10 +295,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 B +.tarball:,http://hm.blue.com/1.0.1.tgz +.shasum:,124 +.integrity:,--- +.unpackedSize:,1.0 kB dist-tags: latest: 1.0.0 @@ -352,8 +306,47 @@ dist-tags: published over a year from now ` -exports[`test/lib/commands/view.js TAP workspaces all workspaces --json > must match snapshot 1`] = ` +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", @@ -406,7 +399,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": 1 + "unpackedSize": 1000000000 } }, "orange": { @@ -434,29 +427,28 @@ 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 B +.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> +-,claudia <c@yellow.com> +-,isaacs <i@yellow.com> dist-tags: latest: 1.0.0 @@ -465,10 +457,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 @@ -479,13 +471,11 @@ 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" @@ -493,7 +483,6 @@ 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: @@ -502,55 +491,56 @@ 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 B +.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> +-,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 single workspace --json > must match snapshot 1`] = ` +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", @@ -603,7 +593,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": 1 + "unpackedSize": 1000000000 } } } diff --git a/test/coverage-map.js b/test/coverage-map.js deleted file mode 100644 index 9a289b6489e3e..0000000000000 --- a/test/coverage-map.js +++ /dev/null @@ -1,26 +0,0 @@ -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 4d3aca396fbca..b2ec20f59efeb 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: new Date('2019-07-16T17:50:00.572Z'), + date: '2019-07-16T17:50:00.572Z', links: { npm: 'https://www.npmjs.com/package/libnpm', homepage: 'https://github.com/npm/libnpm#readme', @@ -26,7 +26,8 @@ module.exports = [ scope: 'unscoped', version: '4.0.1', description: 'programmatic library for `npm access` commands', - date: new Date('2020-11-03T19:19:00.526Z'), + keywords: 'libnpmaccess', + date: '2020-11-03T19:19:00.526Z', links: { npm: 'https://www.npmjs.com/package/libnpmaccess', homepage: 'https://npmjs.com/package/libnpmaccess', @@ -47,7 +48,7 @@ module.exports = [ scope: 'evocateur', version: '3.1.2', description: 'programmatic library for `npm access` commands', - date: new Date('2019-07-16T19:43:33.959Z'), + date: '2019-07-16T19:43:33.959Z', links: { npm: 'https://www.npmjs.com/package/%40evocateur%2Flibnpmaccess', homepage: 'https://npmjs.com/package/@evocateur/libnpmaccess', @@ -63,7 +64,7 @@ module.exports = [ scope: 'evocateur', version: '1.2.2', description: 'Programmatic API for the bits behind npm publish and unpublish', - date: new Date('2019-07-16T19:40:40.850Z'), + date: '2019-07-16T19:40:40.850Z', links: { npm: 'https://www.npmjs.com/package/%40evocateur%2Flibnpmpublish', homepage: 'https://npmjs.com/package/@evocateur/libnpmpublish', @@ -80,7 +81,7 @@ module.exports = [ version: '2.0.1', description: 'Programmatic api for `npm org` commands', keywords: ['libnpm', 'npm', 'package manager', 'api', 'orgs', 'teams'], - date: new Date('2020-11-03T19:21:57.757Z'), + date: '2020-11-03T19:21:57.757Z', links: { npm: 'https://www.npmjs.com/package/libnpmorg', homepage: 'https://npmjs.com/package/libnpmorg', @@ -102,7 +103,7 @@ module.exports = [ version: '3.1.0', description: 'Programmatic API for searching in npm and compatible registries.', keywords: ['npm', 'search', 'api', 'libnpm'], - date: new Date('2020-12-08T23:54:18.374Z'), + date: '2020-12-08T23:54:18.374Z', links: { npm: 'https://www.npmjs.com/package/libnpmsearch', homepage: 'https://npmjs.com/package/libnpmsearch', @@ -123,7 +124,7 @@ module.exports = [ scope: 'unscoped', version: '2.0.2', description: 'npm Team management APIs', - date: new Date('2020-11-03T19:24:42.380Z'), + date: '2020-11-03T19:24:42.380Z', links: { npm: 'https://www.npmjs.com/package/libnpmteam', homepage: 'https://npmjs.com/package/libnpmteam', @@ -145,7 +146,7 @@ module.exports = [ version: '6.0.1', description: 'programmatic API for managing npm registry hooks', keywords: ['npm', 'hooks', 'registry', 'npm api'], - date: new Date('2020-11-03T19:20:45.818Z'), + date: '2020-11-03T19:20:45.818Z', links: { npm: 'https://www.npmjs.com/package/libnpmhook', homepage: 'https://github.com/npm/libnpmhook#readme', @@ -166,7 +167,7 @@ module.exports = [ scope: 'unscoped', version: '4.0.0', description: 'Programmatic API for the bits behind npm publish and unpublish', - date: new Date('2020-11-03T19:13:43.780Z'), + date: '2020-11-03T19:13:43.780Z', links: { npm: 'https://www.npmjs.com/package/libnpmpublish', homepage: 'https://npmjs.com/package/libnpmpublish', @@ -193,7 +194,7 @@ module.exports = [ 'git', 'fund', 'gitfund', ], - date: new Date('2020-12-08T23:22:00.213Z'), + date: '2020-12-08T23:22:00.213Z', links: { npm: 'https://www.npmjs.com/package/libnpmfund', homepage: 'https://github.com/npm/libnpmfund#readme', @@ -222,7 +223,7 @@ module.exports = [ 'workspaces', 'map-workspaces', ], - date: new Date('2020-09-30T15:16:29.017Z'), + 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', @@ -243,7 +244,7 @@ module.exports = [ scope: 'unscoped', version: '1.0.7', description: "library to do the things that 'npm version' does", - date: new Date('2020-11-04T00:21:41.069Z'), + date: '2020-11-04T00:21:41.069Z', links: { npm: 'https://www.npmjs.com/package/libnpmversion', homepage: 'https://github.com/npm/libnpmversion#readme', @@ -269,7 +270,7 @@ module.exports = [ scope: 'types', version: '2.0.1', description: 'TypeScript definitions for libnpmsearch', - date: new Date('2019-09-26T22:24:28.713Z'), + 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 5890fa7ee9366..01d43ba3d980b 100644 --- a/test/fixtures/mock-registry.js +++ b/test/fixtures/mock-registry.js @@ -46,6 +46,19 @@ 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 d2462b1aed4cc..f18fcc475a99c 100644 --- a/test/lib/commands/search.js +++ b/test/lib/commands/search.js @@ -1,169 +1,92 @@ const t = require('tap') -const Minipass = require('minipass') -const { fake: mockNpm } = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') +const MockRegistry = require('../../fixtures/mock-registry.js') 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( - search.exec([]), + npm.exec('search', []), /search must be called with arguments/, 'should throw usage instructions' ) }) -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, +t.test('search text', async t => { + const { npm, joinedOutput } = await loadMockNpm(t) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), }) - const search = new Search(npm) - for (const i of libnpmsearchResultFixture) { - src.write(i) - } - - src.end() - - await search.exec(['libnpm']) - t.matchSnapshot(result, 'should have expected search results') + registry.search({ results: libnpmsearchResultFixture }) + await npm.exec('search', ['libnpm']) + t.matchSnapshot(joinedOutput(), 'should have expected search results') }) 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 { npm, joinedOutput } = await loadMockNpm(t, { config: { json: true } }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), }) - const search = new Search(npm) - for (const i of libnpmsearchResultFixture) { - src.write(i) - } + registry.search({ results: libnpmsearchResultFixture }) - src.end() - await search.exec(['libnpm']) - - const parsedResult = JSON.parse(result) - parsedResult.forEach((entry) => { - entry.date = new Date(entry.date) - }) + await npm.exec('search', ['libnpm']) t.same( - parsedResult, + JSON.parse(joinedOutput()), libnpmsearchResultFixture, 'should have expected search results as json' ) +}) - config.json = false +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') }) -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, +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'), }) - const search = new Search(npm) - src.end() - await search.exec(['foo']) + registry.search({ results: libnpmsearchResultFixture }) + await npm.exec('search', ['libnpm']) + t.matchSnapshot(joinedOutput(), 'should have expected search results with color') +}) - t.equal(result, '\n[]\n', 'should have expected empty square brackets') +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'), + }) - config.json = false + registry.search({ results: libnpmsearchResultFixture }) + await npm.exec('search', ['/libnpm/']) + t.matchSnapshot(joinedOutput(), 'should have expected search results with color') }) -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, +t.test('search ', async t => { + const { npm, joinedOutput } = await loadMockNpm(t) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), }) - const search = new Search(npm) - src.write({ + registry.search({ results: [{ name: 'foo', scope: 'unscoped', version: '1.0.0', @@ -175,8 +98,7 @@ t.test('search --searchexclude --searchopts', async t => { maintainers: [ { username: 'foo', email: 'foo@npmjs.com' }, ], - }) - src.write({ + }, { name: 'libnpmversion', scope: 'unscoped', version: '1.0.0', @@ -188,58 +110,100 @@ t.test('search --searchexclude --searchopts', async t => { maintainers: [ { username: 'foo', email: 'foo@npmjs.com' }, ], - }) + }] }) - src.end() - await search.exec(['foo']) + await npm.exec('search', ['foo']) - t.matchSnapshot(result, 'should have filtered expected search results') + t.matchSnapshot(joinedOutput(), 'should have filtered expected search results') }) 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 { npm, joinedOutput } = await loadMockNpm(t) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), }) - const search = new Search(npm) - src.end() - await search.exec(['foo']) + registry.search({ results: [] }) + await npm.exec('search', ['foo']) - t.matchSnapshot(result, 'should have expected search results') + t.matchSnapshot(joinedOutput(), 'should have expected search results') }) -t.test('search api response error', async t => { - const src = new Minipass() - src.objectMode = true - const libnpmsearch = { - stream () { - return src - }, - } - - const Search = t.mock('../../../lib/commands/search.js', { - ...mocks, - libnpmsearch, +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'), }) - const search = new Search(npm) - setImmediate(() => { - src.emit('error', new Error('ERR')) - src.end() + registry.search({ results: [] }) + + await npm.exec('search', ['foo']) + t.equal(joinedOutput(), '\n[]\n', 'should have expected empty square brackets') +}) + +t.test('search api response error', async t => { + const { npm } = await loadMockNpm(t) + + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), }) + registry.search({ error: 'ERR' }) + await t.rejects( - search.exec(['foo']), + npm.exec('search', ['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 82be1201ee169..da823db5d7507 100644 --- a/test/lib/commands/view.js +++ b/test/lib/commands/view.js @@ -1,4 +1,5 @@ const t = require('tap') +const { load: _loadMockNpm } = require('../../fixtures/mock-npm.js') t.cleanSnapshot = str => str .replace(/(published ).*?( ago)/g, '$1{TIME}$2') @@ -6,18 +7,6 @@ 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) @@ -71,7 +60,7 @@ const packument = (nv, opts) => { tarball: 'http://hm.blue.com/1.0.1.tgz', integrity: '---', fileCount: 1, - unpackedSize: 1, + unpackedSize: 1000, }, }, }, @@ -94,7 +83,7 @@ const packument = (nv, opts) => { tarball: 'http://hm.cyan.com/1.0.0.tgz', integrity: '---', fileCount: 1, - unpackedSize: 1, + unpackedSize: 1000000, }, }, '1.0.1': {}, @@ -180,7 +169,7 @@ const packument = (nv, opts) => { tarball: 'http://hm.green.com/1.0.0.tgz', integrity: '---', fileCount: 1, - unpackedSize: 1, + unpackedSize: 1000000000, }, }, '1.0.1': {}, @@ -271,289 +260,212 @@ const packument = (nv, opts) => { return mocks[nv.name] } -t.beforeEach(cleanLogs) - -t.test('should log package info', async t => { - const View = t.mock('../../../lib/commands/view.js', { - pacote: { - packument, - }, - }) - const npm = mockNpm({ - config: { unicode: false }, - }) - const view = new View(npm) - - const ViewJson = t.mock('../../../lib/commands/view.js', { - pacote: { - packument, +const loadMockNpm = async function (t, opts = {}) { + const consoleLogs = [] + const mockNpm = await _loadMockNpm(t, { + mocks: { + pacote: { + packument, + }, }, - }) - const jsonNpm = mockNpm({ - config: { - json: true, - tag: 'latest', + globals: { + 'console.log': (...args) => { + consoleLogs.push(args) + }, }, + ...opts, }) - const viewJson = new ViewJson(jsonNpm) + return { ...mockNpm, consoleLogs } +} - const ViewUnicode = t.mock('../../../lib/commands/view.js', { - pacote: { - packument, - }, - }) - const unicodeNpm = mockNpm({ - config: { unicode: true }, - }) - const viewUnicode = new ViewUnicode(unicodeNpm) +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')) +}) - t.test('package from git', async t => { - await view.exec(['https://github.com/npm/green']) - t.matchSnapshot(logs) - }) +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 with license, bugs, repository and other fields', async t => { - await view.exec(['green@1.0.0']) - 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 more than 25 deps', async t => { - await view.exec(['black@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 maintainers info as object', async t => { - await view.exec(['pink@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 homepage', async t => { - await view.exec(['orange@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 no versions', async t => { - await view.exec(['brown']) - t.equal(logs, '', 'no info to display') - }) +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 repo or homepage', async t => { - await view.exec(['blue@1.0.0']) - t.matchSnapshot(logs) - }) +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 semver range', 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 no modified time', async t => { - await viewUnicode.exec(['cyan@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 --json and semver range', async t => { - await viewJson.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 no versions', async t => { - await viewJson.exec(['brown']) - t.equal(logs, '', 'no info to display') - }) +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('should log info of package in current working dir', async t => { - const testDir = t.testdir({ +t.test('package in cwd', async t => { + const prefixDir = { '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 => { - await view.exec(['.@1.0.0']) - t.matchSnapshot(logs) + const { npm, consoleLogs } = await loadMockNpm(t, { prefixDir }) + await npm.exec('view', ['.@1.0.0']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('non-specific version', async t => { - await view.exec(['.']) - t.matchSnapshot(logs) + const { npm, consoleLogs } = await loadMockNpm(t, { prefixDir }) + await npm.exec('view', ['.']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('directory', async t => { - await view.exec(['./blue']) - t.matchSnapshot(logs) + const { npm, consoleLogs } = await loadMockNpm(t, { prefixDir }) + await npm.exec('view', ['./blue']) + t.matchSnapshot(consoleLogs.join('\n')) }) }) -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, - }, +t.test('specific field names', async t => { + const { npm, consoleLogs } = await loadMockNpm(t) + t.afterEach(() => { + consoleLogs.length = 0 }) - const npm = mockNpm() - const view = new View(npm) - t.test('readme', async t => { - await view.exec(['yellow@1.0.0', 'readme']) - t.matchSnapshot(logs) + await npm.exec('view', ['yellow@1.0.0', 'readme']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('several fields', async t => { - await viewJson.exec(['yellow@1.0.0', 'name', 'version', 'foo[bar]']) - t.matchSnapshot(logs) + await npm.exec('view', ['yellow@1.0.0', 'name', 'version', 'foo[bar]']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('several fields with several versions', async t => { - await view.exec(['yellow@1.x.x', 'author']) - t.matchSnapshot(logs) + await npm.exec('view', ['yellow@1.x.x', 'author']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('nested field with brackets', async t => { - await viewJson.exec(['orange@1.0.0', 'dist[shasum]']) - t.matchSnapshot(logs) + await npm.exec('view', ['orange@1.0.0', 'dist[shasum]']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('maintainers with email', async t => { - await viewJson.exec(['yellow@1.0.0', 'maintainers', 'name']) - t.matchSnapshot(logs) + await npm.exec('view', ['yellow@1.0.0', 'maintainers', 'name']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('maintainers with url', async t => { - await viewJson.exec(['pink@1.0.0', 'maintainers']) - t.matchSnapshot(logs) + await npm.exec('view', ['pink@1.0.0', 'maintainers']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('unknown nested field ', async t => { - await view.exec(['yellow@1.0.0', 'dist.foobar']) - t.equal(logs, '', 'no info to display') + await npm.exec('view', ['yellow@1.0.0', 'dist.foobar']) + t.equal(consoleLogs.join('\n'), '', 'no info to display') }) t.test('array field - 1 element', async t => { - await view.exec(['purple@1.0.0', 'maintainers.name']) - t.matchSnapshot(logs) + await npm.exec('view', ['purple@1.0.0', 'maintainers.name']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('array field - 2 elements', async t => { - await view.exec(['yellow@1.x.x', 'maintainers.name']) - t.matchSnapshot(logs) + await npm.exec('view', ['yellow@1.x.x', 'maintainers.name']) + t.matchSnapshot(consoleLogs.join('\n')) }) }) t.test('throw error if global mode', async t => { - const View = t.mock('../../../lib/commands/view.js') - const npm = mockNpm({ - config: { - global: true, - tag: 'latest', - }, - }) - const view = new View(npm) + const { npm } = await loadMockNpm(t, { config: { global: true } }) await t.rejects( - view.exec([]), + npm.exec('view', []), /Cannot use view command in global mode./ ) }) t.test('throw ENOENT error if package.json missing', async t => { - const testDir = t.testdir({}) - - const View = t.mock('../../../lib/commands/view.js') - const npm = mockNpm({ - prefix: testDir, - }) - const view = new View(npm) + const { npm } = await loadMockNpm(t) await t.rejects( - view.exec([]), + npm.exec('view', []), { 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 testDir = t.testdir({ - 'package.json': '{}', - }) - - const View = t.mock('../../../lib/commands/view.js') - const npm = mockNpm({ - prefix: testDir, + const { npm } = await loadMockNpm(t, { + prefixDir: { + 'package.json': '{}', + }, }) - const view = new View(npm) await t.rejects( - view.exec([]), + npm.exec('view', []), /Invalid package.json, no "name" field/ ) }) t.test('throws when unpublished', async t => { - const View = t.mock('../../../lib/commands/view.js', { - pacote: { - packument, - }, - }) - const npm = mockNpm({ - config: { - tag: '1.0.1', - }, - }) - const view = new View(npm) + const { npm } = await loadMockNpm(t) await t.rejects( - view.exec(['red']), + npm.exec('view', ['red']), { code: 'E404', pkgid: 'red@1.0.1', message: 'Unpublished on 2012-12-20T00:00:00.000Z' } ) }) t.test('workspaces', async t => { - t.beforeEach(() => { - warnMsg = undefined - config.json = false - }) - const testDir = t.testdir({ + const prefixDir = { 'package.json': JSON.stringify({ name: 'workspaces-test-package', version: '1.2.3', @@ -571,106 +483,103 @@ 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 => { - await view.execWorkspaces([], []) - t.matchSnapshot(logs) + const { npm, consoleLogs } = await loadMockNpm(t, { + prefixDir, + config: { unicode: false, workspaces: true }, + }) + await npm.exec('view', []) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('one specific workspace', async t => { - await view.execWorkspaces([], ['green']) - t.matchSnapshot(logs) + const { npm, consoleLogs } = await loadMockNpm(t, { + prefixDir, + config: { unicode: false, workspace: ['green'] }, + }) + await npm.exec('view', []) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('all workspaces --json', async t => { - config.json = true - await view.execWorkspaces([], []) - t.matchSnapshot(logs) + const { npm, consoleLogs } = await loadMockNpm(t, { + prefixDir, + config: { unicode: false, workspaces: true, json: true }, + }) + await npm.exec('view', []) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('all workspaces single field', async t => { - await view.execWorkspaces(['.', 'name'], []) - t.matchSnapshot(logs) + const { npm, consoleLogs } = await loadMockNpm(t, { + prefixDir, + config: { unicode: false, workspaces: true }, + }) + await npm.exec('view', ['.', 'name']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('all workspaces nonexistent field', async t => { - await view.execWorkspaces(['.', 'foo'], []) - t.matchSnapshot(logs) + const { npm, consoleLogs } = await loadMockNpm(t, { + prefixDir, + config: { unicode: false, workspaces: true }, + }) + await npm.exec('view', ['.', 'foo']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('all workspaces nonexistent field --json', async t => { - config.json = true - await view.execWorkspaces(['.', 'foo'], []) - t.matchSnapshot(logs) + const { npm, consoleLogs } = await loadMockNpm(t, { + prefixDir, + config: { unicode: false, workspaces: true, json: true }, + }) + await npm.exec('view', ['.', 'foo']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('all workspaces single field --json', async t => { - config.json = true - await view.execWorkspaces(['.', 'name'], []) - t.matchSnapshot(logs) + const { npm, consoleLogs } = await loadMockNpm(t, { + prefixDir, + config: { unicode: false, workspaces: true, json: true }, + }) + await npm.exec('view', ['.', 'name']) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('single workspace --json', async t => { - config.json = true - await view.execWorkspaces([], ['green']) - t.matchSnapshot(logs) + const { npm, consoleLogs } = await loadMockNpm(t, { + prefixDir, + config: { unicode: false, workspace: ['green'], json: true }, + }) + await npm.exec('view', []) + t.matchSnapshot(consoleLogs.join('\n')) }) t.test('remote package name', async t => { - await view.execWorkspaces(['pink'], []) - t.matchSnapshot(warnMsg) - t.matchSnapshot(logs) + 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') }) }) t.test('completion', async t => { - const View = t.mock('../../../lib/commands/view.js', { - pacote: { - packument, - }, - }) - const npm = mockNpm({ - config: { - tag: '1.0.1', - }, - }) - const view = new View(npm) + const { npm } = await loadMockNpm(t) + const view = await npm.cmd('view') const res = await view.completion({ conf: { argv: { remain: ['npm', 'view', 'green@1.0.0'] } }, }) t.ok(res, 'returns back fields') }) -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) +t.test('no package completion', async t => { + const { npm } = await loadMockNpm(t) + const view = await npm.cmd('view') 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 088d0cdb6e128..200ee9e5536d1 100644 --- a/test/lib/utils/config/definitions.js +++ b/test/lib/utils/config/definitions.js @@ -457,6 +457,13 @@ 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[