Skip to content

Commit

Permalink
feat: make this method synchronous
Browse files Browse the repository at this point in the history
BREAKING CHANGE: this removes the promise return value, replacing it
with a regular value.
  • Loading branch information
isaacs committed Apr 24, 2020
1 parent 1390024 commit 620842a
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 245 deletions.
9 changes: 4 additions & 5 deletions README.md
Expand Up @@ -24,10 +24,9 @@ const options = {
reporter: 'json'
}
Report(response, options, (result) => {
console.log(result.report)
process.exitCode = result.exitCode
})
const result = Report(response, options)
console.log(result.report)
process.exitCode = result.exitCode
```


Expand All @@ -37,4 +36,4 @@ Report(response, options, (result) => {
| :--- | :--- | :--- |:--- |
| reporter     | `install`, `detail`, `json`, `quiet` | `install` | specify which output format you want to use |
| withColor     | `true`, `false`   | `true`   | indicates if some report elements should use colors |
| withUnicode   | `true`, `false`                  | `true` | indicates if unicode characters should be used|
| withUnicode   | `true`, `false`                  | `true` | indicates if unicode characters should be used|
5 changes: 1 addition & 4 deletions index.js
Expand Up @@ -16,10 +16,7 @@ const report = function (data, options) {
}

const config = Object.assign({}, defaults, options)
return new Promise((resolve) => {
const result = reporters[config.reporter](data, config)
return resolve(result)
})
return reporters[config.reporter](data, config)
}

module.exports = report
134 changes: 61 additions & 73 deletions test/detail-report-test.js
Expand Up @@ -4,99 +4,87 @@ const tap = require('tap')
const Report = require('../')
const fixtures = require('./lib/test-fixtures')

tap.test('it generates a detail report with no vulns', function (t) {
return Report(fixtures['no-vulns'], {reporter: 'detail', withColor: false}).then((report) => {
t.match(report.exitCode, 0, 'successful exit code')
t.match(report.report, /found 0 vulnerabilities/, 'no vulns reported')
t.match(report.report, /918 scanned packages/, 'reports scanned count')
})
tap.test('it generates a detail report with no vulns', async t => {
const report = Report(fixtures['no-vulns'], {reporter: 'detail', withColor: false})
t.match(report.exitCode, 0, 'successful exit code')
t.match(report.report, /found 0 vulnerabilities/, 'no vulns reported')
t.match(report.report, /918 scanned packages/, 'reports scanned count')
})

tap.test('it generates a detail report with one vuln (update action)', function (t) {
return Report(fixtures['one-vuln-one-pkg'], {reporter: 'detail'}).then((report) => {
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /npm update tough-cookie --depth 6/, 'recommends update command with --depth')
t.match(report.report, /1 scanned package/, 'reports a single scanned pkg')
})
tap.test('it generates a detail report with one vuln (update action)', async t => {
const report = Report(fixtures['one-vuln-one-pkg'], {reporter: 'detail'})
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /npm update tough-cookie --depth 6/, 'recommends update command with --depth')
t.match(report.report, /1 scanned package/, 'reports a single scanned pkg')
})

tap.test('it generates a detail report with one vuln (install action)', function (t) {
return Report(fixtures['one-vuln-install'], {reporter: 'detail'}).then((report) => {
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /npm install knex@3\.0\.0/, 'recommends install command')
})
tap.test('it generates a detail report with one vuln (install action)', async t => {
const report = Report(fixtures['one-vuln-install'], {reporter: 'detail'})
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /npm install knex@3\.0\.0/, 'recommends install command')
})

tap.test('it adds a message if a dep isMajor (one vuln)', function (t) {
return Report(fixtures['one-vuln-install-ismajor'], {reporter: 'detail', withColor: false}).then((report) => {
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /1 vulnerability requires semver-major dependency updates/, 'reports one semver-major bump')
})
tap.test('it adds a message if a dep isMajor (one vuln)', async t => {
const report = Report(fixtures['one-vuln-install-ismajor'], {reporter: 'detail', withColor: false})
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /1 vulnerability requires semver-major dependency updates/, 'reports one semver-major bump')
})

tap.test('it adds a message if a dep isMajor (multiple vulns)', function (t) {
return Report(fixtures['some-vulns-ismajor'], {reporter: 'detail', withColor: false}).then((report) => {
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /6 vulnerabilities require semver-major dependency updates/, 'reports multiple semver-major bumps')
})
tap.test('it adds a message if a dep isMajor (multiple vulns)', async t => {
const report = Report(fixtures['some-vulns-ismajor'], {reporter: 'detail', withColor: false})
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /6 vulnerabilities require semver-major dependency updates/, 'reports multiple semver-major bumps')
})

tap.test('it generates a detail report with one vuln (install dev dep)', function (t) {
return Report(fixtures['one-vuln-dev'], {reporter: 'detail'}).then((report) => {
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /npm install --save-dev knex@3\.0\.0/, 'adds --save-dev to recommendation')
})
tap.test('it generates a detail report with one vuln (install dev dep)', async t => {
const report = Report(fixtures['one-vuln-dev'], {reporter: 'detail'})
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /npm install --save-dev knex@3\.0\.0/, 'adds --save-dev to recommendation')
})

tap.test('it generates a detail report with one vuln (review dev dep)', function (t) {
return Report(fixtures['one-vuln-dev-review'], {reporter: 'detail'}).then((report) => {
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /knex \[dev\]/, 'mentions the dep and tags it as dev')
t.match(report.report, /Manual Review/, 'reports a manual review requirement')
})
tap.test('it generates a detail report with one vuln (review dev dep)', async t => {
const report = Report(fixtures['one-vuln-dev-review'], {reporter: 'detail'})
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /knex \[dev\]/, 'mentions the dep and tags it as dev')
t.match(report.report, /Manual Review/, 'reports a manual review requirement')
})

tap.test('it generates a detail report with one vuln, no color', function (t) {
return Report(fixtures['one-vuln'], {reporter: 'detail', withColor: false}).then((report) => {
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /# Run {2}npm update tough-cookie --depth 6 {2}to resolve 1 vulnerability/, 'individual update command printed')
})
tap.test('it generates a detail report with one vuln, no color', async t => {
const report = Report(fixtures['one-vuln'], {reporter: 'detail', withColor: false})
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /# Run {2}npm update tough-cookie --depth 6 {2}to resolve 1 vulnerability/, 'individual update command printed')
})

tap.test('it generates a detail report with one vuln, no unicode', function (t) {
return Report(fixtures['one-vuln'], {reporter: 'detail', withUnicode: false}).then((report) => {
t.equal(report.exitCode, 1, 'non-zero exit code')
t.notMatch(report.report, //, 'prints a fancy table')
})
tap.test('it generates a detail report with one vuln, no unicode', async t => {
const report = Report(fixtures['one-vuln'], {reporter: 'detail', withUnicode: false})
t.equal(report.exitCode, 1, 'non-zero exit code')
t.notMatch(report.report, //, 'prints a fancy table')
})

tap.test('it generates a detail report with some vulns', function (t) {
return Report(fixtures['some-vulns'], {reporter: 'detail', withColor: false}).then((report) => {
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /Manual Review/, 'expects manual review')
t.match(report.report, /found 12 vulnerabilities/, 'reports vuln count')
t.match(report.report, /9 low, 3 high/, 'severity breakdown reported')
t.match(report.report, /Denial of Service/, 'mentions one vuln title')
t.match(report.report, /Cryptographically Weak PRNG/, 'mentions the other vuln title')
})
tap.test('it generates a detail report with some vulns', async t => {
const report = Report(fixtures['some-vulns'], {reporter: 'detail', withColor: false})
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /Manual Review/, 'expects manual review')
t.match(report.report, /found 12 vulnerabilities/, 'reports vuln count')
t.match(report.report, /9 low, 3 high/, 'severity breakdown reported')
t.match(report.report, /Denial of Service/, 'mentions one vuln title')
t.match(report.report, /Cryptographically Weak PRNG/, 'mentions the other vuln title')
})

tap.test('it generates a detail report with vulns of all severities', function (t) {
return Report(fixtures['all-severity-vulns'], {reporter: 'detail', withColor: false}).then((report) => {
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /Manual Review/, 'expects manual review')
t.match(report.report, /found 31 vulnerabilities/, 'reports vuln count')
t.match(report.report, /16 info, 8 low, 4 moderate, 2 high, 1 critical/, 'severity breakdown reported')
t.match(report.report, /Denial of Service/, 'mentions one vuln title')
t.match(report.report, /Cryptographically Weak PRNG/, 'mentions the other vuln title')
})
tap.test('it generates a detail report with vulns of all severities', async t => {
const report = Report(fixtures['all-severity-vulns'], {reporter: 'detail', withColor: false})
t.equal(report.exitCode, 1, 'non-zero exit code')
t.match(report.report, /Manual Review/, 'expects manual review')
t.match(report.report, /found 31 vulnerabilities/, 'reports vuln count')
t.match(report.report, /16 info, 8 low, 4 moderate, 2 high, 1 critical/, 'severity breakdown reported')
t.match(report.report, /Denial of Service/, 'mentions one vuln title')
t.match(report.report, /Cryptographically Weak PRNG/, 'mentions the other vuln title')
})

tap.test('it generates a detail report with review vulns, no unicode', function (t) {
return Report(fixtures['update-review'], {reporter: 'detail', withUnicode: false, withColor: false}).then((report) => {
t.equal(report.exitCode, 1, 'non-zero exit code')
t.notMatch(report.report, //, 'unicode table not printed')
t.match(report.report, /Manual Review/, 'manual review reported')
t.match(report.report, /1 low, 1 moderate, 1 critical/, 'severity breakdown reported')
})
tap.test('it generates a detail report with review vulns, no unicode', async t => {
const report = Report(fixtures['update-review'], {reporter: 'detail', withUnicode: false, withColor: false})
t.equal(report.exitCode, 1, 'non-zero exit code')
t.notMatch(report.report, //, 'unicode table not printed')
t.match(report.report, /Manual Review/, 'manual review reported')
t.match(report.report, /1 low, 1 moderate, 1 critical/, 'severity breakdown reported')
})
67 changes: 30 additions & 37 deletions test/install-report-test.js
Expand Up @@ -4,53 +4,46 @@ const tap = require('tap')
const Report = require('../')
const fixtures = require('./lib/test-fixtures')

tap.test('it generates an install report with no vulns', function (t) {
return Report(fixtures['no-vulns']).then((report) => {
t.match(report.report, /found .*0.* vulnerabilities/)
t.match(report.exitCode, 0)
})
tap.test('it generates an install report with no vulns', async t => {
const report = Report(fixtures['no-vulns'])
t.match(report.report, /found .*0.* vulnerabilities/)
t.match(report.exitCode, 0)
})

tap.test('it generates an install report with no vulns, no colors', function (t) {
return Report(fixtures['no-vulns'], {withColor: false}).then((report) => {
t.match(report.report, /found 0 vulnerabilities/)
t.match(report.exitCode, 0)
})
tap.test('it generates an install report with no vulns, no colors', async t => {
const report = Report(fixtures['no-vulns'], {withColor: false})
t.match(report.report, /found 0 vulnerabilities/)
t.match(report.exitCode, 0)
})

tap.test('it generates an install report with one vuln', function (t) {
return Report(fixtures['one-vuln'], {withColor: false}).then((report) => {
t.match(report.report, /found 1 high severity vulnerability/)
t.match(report.exitCode, 1)
})
tap.test('it generates an install report with one vuln', async t => {
const report = Report(fixtures['one-vuln'], {withColor: false})
t.match(report.report, /found 1 high severity vulnerability/)
t.match(report.exitCode, 1)
})

tap.test('recommend `npm audit fix` when install actions present', t => {
return Report(fixtures['one-vuln'], {withColor: false}).then((report) => {
t.match(report.report, /run `npm audit fix`/)
t.match(report.exitCode, 1)
})
tap.test('recommend `npm audit fix` when install actions present', async t => {
const report = Report(fixtures['one-vuln'], {withColor: false})
t.match(report.report, /run `npm audit fix`/)
t.match(report.exitCode, 1)
})

tap.test('it generates an install report with multiple vulns of one type', function (t) {
return Report(fixtures['some-same-type'], {withColor: false}).then((report) => {
t.match(report.report, /found 12 high severity vulnerabilities/)
t.match(report.exitCode, 1)
})
tap.test('it generates an install report with multiple vulns of one type', async t => {
const report = Report(fixtures['some-same-type'], {withColor: false})
t.match(report.report, /found 12 high severity vulnerabilities/)
t.match(report.exitCode, 1)
})

tap.test('it generates an install report with more than one vuln', function (t) {
return Report(fixtures['some-vulns']).then((report) => {
t.match(report.report, /^found .*12.* vulnerabilities/)
t.match(report.report, /9 .*low.*, 3 .*high.*/)
t.match(report.exitCode, 1)
})
tap.test('it generates an install report with more than one vuln', async t => {
const report = Report(fixtures['some-vulns'])
t.match(report.report, /^found .*12.* vulnerabilities/)
t.match(report.report, /9 .*low.*, 3 .*high.*/)
t.match(report.exitCode, 1)
})

tap.test('it generates an install report with vulns of all severities', function (t) {
return Report(fixtures['all-severity-vulns']).then((report) => {
t.match(report.report, /^found .*31.* vulnerabilities/)
t.match(report.report, /16 .*info, 8 .*low.*, 4 .*moderate.*, 2 .*high.*, 1 .*critical.*/)
t.match(report.exitCode, 1)
})
tap.test('it generates an install report with vulns of all severities', async t => {
const report = Report(fixtures['all-severity-vulns'])
t.match(report.report, /^found .*31.* vulnerabilities/)
t.match(report.report, /16 .*info, 8 .*low.*, 4 .*moderate.*, 2 .*high.*, 1 .*critical.*/)
t.match(report.exitCode, 1)
})
21 changes: 10 additions & 11 deletions test/json-report-test.js
Expand Up @@ -4,17 +4,16 @@ const tap = require('tap')
const Report = require('../')
const fixtures = require('./lib/test-fixtures')

tap.test('it generates a json report with zero for every severity', function (t) {
return Report(fixtures['no-vulns'], {reporter: 'json'}).then((reportRaw) => {
const exitCode = reportRaw.exitCode
const vulnerabilities = JSON.parse(reportRaw.report).metadata.vulnerabilities
tap.test('it generates a json report with zero for every severity', async t => {
const reportRaw = Report(fixtures['no-vulns'], {reporter: 'json'})
const exitCode = reportRaw.exitCode
const vulnerabilities = JSON.parse(reportRaw.report).metadata.vulnerabilities

t.equal(exitCode, 0)
t.equal(exitCode, 0)

t.equal(vulnerabilities.info, 0)
t.equal(vulnerabilities.low, 0)
t.equal(vulnerabilities.moderate, 0)
t.equal(vulnerabilities.high, 0)
t.equal(vulnerabilities.critical, 0)
})
t.equal(vulnerabilities.info, 0)
t.equal(vulnerabilities.low, 0)
t.equal(vulnerabilities.moderate, 0)
t.equal(vulnerabilities.high, 0)
t.equal(vulnerabilities.critical, 0)
})

0 comments on commit 620842a

Please sign in to comment.