Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions src/command/scan/output-scan-report.mts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ export type OutputScanReportConfig = {
short: boolean
}

function isFullScanReport(
report: ScanReport | { healthy: boolean },
): report is ScanReport {
return 'alerts' in report
}

export type ReportAlertRow = {
alertType: string
introducedBy: string
Expand Down Expand Up @@ -86,9 +92,12 @@ export function formatAlertTable(rows: ReportAlertRow[]): string[] {
row.introducedBy,
row.manifest,
])
const widths = headers.map((header, i) =>
Math.max(header.length, ...cells.map(cell => (cell[i] ?? '').length)),
)
const widths = headers.map(header => header.length)
for (const cell of cells) {
for (let i = 0, { length } = cell; i < length; i += 1) {
widths[i] = Math.max(widths[i] ?? 0, cell[i]?.length ?? 0)
}
}
const toRow = (values: string[]) =>
` ${values
.map((value, i) => value.padEnd(widths[i] ?? 0))
Expand Down Expand Up @@ -159,10 +168,10 @@ export async function outputGeneratedScanReport(

if (short) {
logger.log(scanReport.data.healthy ? 'OK' : 'ERR')
} else if (isFullScanReport(scanReport.data)) {
logger.log(toPlainTextReport(scanReport.data, includeLicensePolicy))
} else {
logger.log(
toPlainTextReport(scanReport.data as ScanReport, includeLicensePolicy),
)
logger.log(scanReport.data.healthy ? 'OK' : 'ERR')
}
}

Expand Down Expand Up @@ -401,8 +410,10 @@ export function toPlainTextReport(
lines.push(
` ${rows.length} ${pluralize('alert', { count: rows.length })} with a policy set to at least "${reportLevel}".`,
'',
...formatAlertTable(rows),
'',
)
for (const line of formatAlertTable(rows)) {
lines.push(line)
}
lines.push('')
return lines.join('\n')
}
28 changes: 27 additions & 1 deletion test/unit/command/scan/output-scan-report-text.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import {
toPlainTextReport,
} from '../../../../src/command/scan/output-scan-report.mts'

import type { ScanReport } from '../../../../src/command/scan/generate-report.mts'
import type {
ReportLeafNode,
ScanReport,
} from '../../../../src/command/scan/generate-report.mts'

// Matches any ANSI escape sequence, the codes that show up as literal noise
// like "[32m" in a log viewer that does not interpret them.
Expand Down Expand Up @@ -204,6 +207,29 @@ describe('toPlainTextReport', () => {
expect(overlong).toEqual([])
})

it('renders a large alert report without argument-count failures', () => {
const alertRow: ReportLeafNode = {
manifest: ['package.json'],
policy: 'error',
type: 'envVars',
url: '',
}
const packages = new Map<string, Map<string, ReportLeafNode>>()
const alertCount = 200_000
for (let i = 0; i < alertCount; i += 1) {
packages.set(
`package-${String(i).padStart(6, '0')}`,
new Map([['1.0.0', alertRow]]),
)
}
const alerts: ScanReport['alerts'] = new Map([['npm', packages]])
const text = toPlainTextReport(buildReport({ alerts, healthy: false }))

expect(text).toContain('200000 alerts with a policy')
expect(text).toContain('package-000000')
expect(text).toContain('package-199999')
})

it('says so plainly when there are no alerts', () => {
const text = toPlainTextReport(
buildReport({ alerts: new Map(), healthy: true }),
Expand Down
Loading