Skip to content

Commit

Permalink
fix: remove test coverage map
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
wraithgar committed May 5, 2022
1 parent 8e7ea9b commit f11fd1b
Show file tree
Hide file tree
Showing 14 changed files with 708 additions and 804 deletions.
47 changes: 27 additions & 20 deletions lib/commands/search.js
Expand Up @@ -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')
Expand Down Expand Up @@ -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) {
Expand All @@ -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)
}
}
Expand All @@ -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,
})
Expand Down
3 changes: 0 additions & 3 deletions lib/commands/view.js
Expand Up @@ -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) {
Expand Down
43 changes: 0 additions & 43 deletions lib/search/package-filter.js

This file was deleted.

2 changes: 1 addition & 1 deletion lib/utils/config/definitions.js
Expand Up @@ -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()
},
})

Expand Down
1 change: 1 addition & 0 deletions lib/utils/format-bytes.js
Expand Up @@ -23,6 +23,7 @@ const formatBytes = (bytes, space = true) => {
return `${(bytes / 1000000).toFixed(1)}${spacer}MB`
}

// GB
return `${(bytes / 1000000000).toFixed(1)}${spacer}GB`
}

Expand Down
@@ -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')

Expand All @@ -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()
}
}
Expand All @@ -61,22 +52,22 @@ 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) {
return pkg[col] && ('' + pkg[col]).replace(/\t/g, ' ')
}).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,
Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
Expand All @@ -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'
Expand Down
9 changes: 7 additions & 2 deletions package.json
Expand Up @@ -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,
Expand Down

0 comments on commit f11fd1b

Please sign in to comment.