Skip to content

Commit

Permalink
wip: get new way to mock logs working in tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lukekarrys committed Apr 10, 2024
1 parent f97b196 commit d162325
Show file tree
Hide file tree
Showing 55 changed files with 1,761 additions and 2,732 deletions.
16 changes: 10 additions & 6 deletions lib/cli-entry.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
/* eslint-disable max-len */

// Separated out for easier unit testing
module.exports = async (process, validateEngines) => {
// set it here so that regardless of what happens later, we don't
// leak any private CLI configs to other programs
Expand All @@ -17,18 +14,25 @@ module.exports = async (process, validateEngines) => {
const npm = new Npm()
exitHandler.setNpm(npm)

// only log node and npm paths in argv initially since argv can contain sensitive info. a cleaned version will be logged later
// only log node and npm paths in argv initially since argv can contain
// sensitive info. a cleaned version will be logged later
const log = require('proc-log')
log.verbose('cli', process.argv.slice(0, 2).join(' '))
log.info('using', 'npm@%s', npm.version)
log.info('using', 'node@%s', process.version)

// At this point we've required a few files and can be pretty sure we dont contain invalid syntax for this version of node. It's possible a lazy require would, but that's unlikely enough that it's not worth catching anymore and we attach the more important exit handlers.
// At this point we've required a few files and can be pretty sure we dont
// contain invalid syntax for this version of node. It's possible a lazy
// require would, but that's unlikely enough that it's not worth catching
// anymore and we attach the more important exit handlers.
validateEngines.off()
process.on('uncaughtException', exitHandler)
process.on('unhandledRejection', exitHandler)

// It is now safe to log a warning if they are using a version of node that is not going to fail on syntax errors but is still unsupported and untested and might not work reliably. This is safe to use the logger now which we want since this will show up in the error log too.
// It is now safe to log a warning if they are using a version of node that is
// not going to fail on syntax errors but is still unsupported and untested
// and might not work reliably. This is safe to use the logger now which we
// want since this will show up in the error log too.
if (!satisfies(validateEngines.node, validateEngines.engines)) {
log.warn('cli', validateEngines.unsupportedMessage)
}
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Init extends BaseCommand {
// to create a workspace package.json file or its folders
const { content: pkg } = await PackageJson.normalize(this.npm.localPrefix).catch(err => {
if (err.code === 'ENOENT') {
log.warn('Missing package.json. Try with `--include-workspace-root`.')
log.warn('', 'Missing package.json. Try with `--include-workspace-root`.')
}
throw err
})
Expand Down
5 changes: 3 additions & 2 deletions lib/commands/ping.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class Ping extends BaseCommand {
const cleanRegistry = cleanUrl(this.npm.config.get('registry'))
log.notice('PING', cleanRegistry)
const start = Date.now()
const details = await pingUtil({ ...this.npm.flatOptions })
let details = await pingUtil({ ...this.npm.flatOptions })
details = { a: 1, b: 2 }
const time = Date.now() - start
log.notice('PONG', `${time}ms`)
if (this.npm.config.get('json')) {
Expand All @@ -22,7 +23,7 @@ class Ping extends BaseCommand {
details,
}, null, 2))
} else if (Object.keys(details).length) {
log.notice('PONG', `${JSON.stringify(details, null, 2)}`)
log.notice('PONG', JSON.stringify(details, null, 2))
}
}
}
Expand Down
13 changes: 10 additions & 3 deletions lib/npm.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ class Npm {
#logChalk = null
#noColorChalk = null

#display = null
#logFile = new LogFile()
#display = new Display()
#timers = new Timers({
start: 'npm',
listener: (name, ms) => {
Expand All @@ -71,7 +71,14 @@ class Npm {
// allows tests created by tap inside this repo to not set the local
// prefix to `npmRoot` since that is the first dir it would encounter when
// doing implicit detection
constructor ({ npmRoot = dirname(__dirname), argv = [], excludeNpmCwd = false } = {}) {
constructor ({
stdout = process.stdout,
stderr = process.stderr,
npmRoot = dirname(__dirname),
argv = [],
excludeNpmCwd = false,
} = {}) {
this.#display = new Display({ stdout, stderr })
this.#npmRoot = npmRoot
this.config = new Config({
npmPath: this.#npmRoot,
Expand Down Expand Up @@ -446,7 +453,7 @@ class Npm {
}

outputBuffer (arg) {
this.#display.outputBuffer.push(arg)
this.#display.outputBuffer(arg)
}

flushOutput (jsonError) {
Expand Down
17 changes: 11 additions & 6 deletions lib/utils/display.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const LEVEL_OPTIONS = {
const LEVEL_METHODS = {
...LEVEL_OPTIONS,
[LEVELS.timing]: {
show: ({ index, timing }) => timing && index !== 0,
show: ({ timing, index }) => !!timing && index !== 0,
},
}

Expand All @@ -68,7 +68,7 @@ const safeJsonParse = (maybeJsonStr) => {
try {
return JSON.parse(maybeJsonStr)
} catch {
return maybeJsonStr
return {}
}
}

Expand All @@ -93,7 +93,12 @@ class Display {
#json = false
#heading = 'npm'

constructor () {
#stdout = null
#stderr = null

constructor ({ stdout, stderr }) {
this.#stdout = stdout
this.#stderr = stderr
process.on('log', this.#logHandler)
}

Expand Down Expand Up @@ -135,11 +140,11 @@ class Display {

output (...args) {
// TODO: make this respect silent option
process.stdout.write(format(...args))
this.#stdout.write(format(...args))
}

outputError (...args) {
process.stderr.write(format(...args))
this.#stderr.write(format(...args))
}

outputBuffer (item) {
Expand Down Expand Up @@ -193,7 +198,7 @@ class Display {
this.#colors[levelName](level.label ?? levelName),
title ? this.#colors.title(title) : null,
]
process.stderr.write(formatWithOptions({ prefix }, ...args))
this.#stderr.write(formatWithOptions({ prefix }, ...args))
} else if (this.#progress) {
// TODO: make this display a single log line of filtered messages
}
Expand Down
4 changes: 2 additions & 2 deletions lib/utils/exit-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ process.on('exit', code => {

// Determine whether to show log file message and why it is
// being shown since in timing mode we always show the log file message
const logMethod = showLogFileError ? 'error' : timing ? 'info' : null
const logMethod = showLogFileError ? 'error' : timing ? 'notice' : null

if (logMethod) {
if (!npm.silent) {
Expand Down Expand Up @@ -121,7 +121,7 @@ const exitHandler = err => {

// only show the notification if it finished.
if (typeof npm.updateNotification === 'string') {
npm.forcceLog('notice', '', npm.updateNotification)
npm.forceLog('notice', '', npm.updateNotification)
}

let exitCode = process.exitCode || 0
Expand Down
8 changes: 2 additions & 6 deletions lib/utils/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,11 @@ const cleanControl = createCleaner((output) => {
})

const formatWithOptions = ({ prefix = [], eol = '\n', ...options }, ...args) => {
const prefixStr = prefix.filter(p => p != null).join(' ')
const pre = prefix.filter(p => p != null).join(' ')
return baseFormatWithOptions(options, ...args)
.trim()
.split(/\r?\n/)
.map(cleanControl)
.reduce((lines, line) =>
lines += prefixStr + (prefixStr && line ? ' ' : '') + line + eol,
''
)
.reduce((acc, l) => `${acc}${pre}${pre && l ? ' ' : ''}${l}${eol}`, '')
}

const format = (...args) => formatWithOptions({}, ...args)
Expand Down
10 changes: 3 additions & 7 deletions lib/utils/log-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ class LogFiles {
this.on()
}

static format (count, level, title, ...args) {
const prefix = [count, level, title || null]
return formatWithOptions({ prefix, eol: os.EOL, colors: false }, ...args)
}

on () {
this.#logStream = new Minipass()
process.on('log', this.#logHandler)
Expand Down Expand Up @@ -141,9 +136,10 @@ class LogFiles {
}
}

#formatLogItem (...args) {
#formatLogItem (level, title, ...args) {
this.#fileLogCount += 1
return LogFiles.format(this.#totalLogCount++, ...args)
const prefix = [this.#totalLogCount++, level, title || null]
return formatWithOptions({ prefix, eol: os.EOL, colors: false }, ...args)
}

#getLogFilePath (count = '') {
Expand Down
21 changes: 0 additions & 21 deletions tap-snapshots/test/lib/commands/audit.js.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ exports[`test/lib/commands/audit.js TAP audit signatures ignores optional depend
audited 1 package in xxx
1 package has a verified registry signature
`

exports[`test/lib/commands/audit.js TAP audit signatures json output with invalid and missing signatures > must match snapshot 1`] = `
Expand Down Expand Up @@ -131,14 +130,12 @@ exports[`test/lib/commands/audit.js TAP audit signatures multiple registries wit
audited 2 packages in xxx
2 packages have verified registry signatures
`

exports[`test/lib/commands/audit.js TAP audit signatures omit dev dependencies with missing signature > must match snapshot 1`] = `
audited 1 package in xxx
1 package has a verified registry signature
`

exports[`test/lib/commands/audit.js TAP audit signatures output details about missing signatures > must match snapshot 1`] = `
Expand All @@ -157,7 +154,6 @@ audited 1 package in xxx
@npmcli/arborist@1.0.14 (https://verdaccio-clone.org/)
Someone might have tampered with this package since it was published on the registry!
`

exports[`test/lib/commands/audit.js TAP audit signatures third-party registry with keys and missing signatures errors > must match snapshot 1`] = `
Expand All @@ -172,21 +168,18 @@ exports[`test/lib/commands/audit.js TAP audit signatures third-party registry wi
audited 1 package in xxx
1 package has a verified registry signature
`

exports[`test/lib/commands/audit.js TAP audit signatures third-party registry with sub-path (trailing slash) > must match snapshot 1`] = `
audited 1 package in xxx
1 package has a verified registry signature
`

exports[`test/lib/commands/audit.js TAP audit signatures third-party registry with sub-path > must match snapshot 1`] = `
audited 1 package in xxx
1 package has a verified registry signature
`

exports[`test/lib/commands/audit.js TAP audit signatures with both invalid and missing signatures > must match snapshot 1`] = `
Expand All @@ -201,14 +194,12 @@ async@1.1.1 (https://registry.npmjs.org/)
kms-demo@1.0.0 (https://registry.npmjs.org/)
Someone might have tampered with this package since it was published on the registry!
`

exports[`test/lib/commands/audit.js TAP audit signatures with bundled and peer deps and no signatures > must match snapshot 1`] = `
audited 1 package in xxx
1 package has a verified registry signature
`

exports[`test/lib/commands/audit.js TAP audit signatures with invalid attestations > must match snapshot 1`] = `
Expand All @@ -219,7 +210,6 @@ audited 1 package in xxx
sigstore@1.0.0 (https://registry.npmjs.org/)
Someone might have tampered with this package since it was published on the registry!
`

exports[`test/lib/commands/audit.js TAP audit signatures with invalid signatures > must match snapshot 1`] = `
Expand All @@ -230,7 +220,6 @@ audited 1 package in xxx
kms-demo@1.0.0 (https://registry.npmjs.org/)
Someone might have tampered with this package since it was published on the registry!
`

exports[`test/lib/commands/audit.js TAP audit signatures with invalid signtaures and color output enabled > must match snapshot 1`] = `
Expand All @@ -241,14 +230,12 @@ audited 1 package in xxx
kms-demo@1.0.0 (https://registry.npmjs.org/)
Someone might have tampered with this package since it was published on the registry!
`

exports[`test/lib/commands/audit.js TAP audit signatures with key fallback to legacy API > must match snapshot 1`] = `
audited 1 package in xxx
1 package has a verified registry signature
`

exports[`test/lib/commands/audit.js TAP audit signatures with keys but missing signature > must match snapshot 1`] = `
Expand All @@ -268,7 +255,6 @@ sigstore@1.0.0 (https://registry.npmjs.org/)
tuf-js@1.0.0 (https://registry.npmjs.org/)
Someone might have tampered with these packages since they were published on the registry!
`

exports[`test/lib/commands/audit.js TAP audit signatures with multiple invalid signatures > must match snapshot 1`] = `
Expand All @@ -280,7 +266,6 @@ async@1.1.1 (https://registry.npmjs.org/)
kms-demo@1.0.0 (https://registry.npmjs.org/)
Someone might have tampered with these packages since they were published on the registry!
`

exports[`test/lib/commands/audit.js TAP audit signatures with multiple missing signatures > must match snapshot 1`] = `
Expand All @@ -302,7 +287,6 @@ audited 3 packages in xxx
node-fetch@1.6.0 (https://registry.npmjs.org/)
Someone might have tampered with this package since it was published on the registry!
`

exports[`test/lib/commands/audit.js TAP audit signatures with valid and missing signatures > must match snapshot 1`] = `
Expand All @@ -321,35 +305,30 @@ audited 1 package in xxx
1 package has a verified registry signature
1 package has a verified attestation
`

exports[`test/lib/commands/audit.js TAP audit signatures with valid signatures > must match snapshot 1`] = `
audited 1 package in xxx
1 package has a verified registry signature
`

exports[`test/lib/commands/audit.js TAP audit signatures with valid signatures using alias > must match snapshot 1`] = `
audited 1 package in xxx
1 package has a verified registry signature
`

exports[`test/lib/commands/audit.js TAP audit signatures workspaces verifies registry deps and ignores local workspace deps > must match snapshot 1`] = `
audited 3 packages in xxx
3 packages have verified registry signatures
`

exports[`test/lib/commands/audit.js TAP audit signatures workspaces verifies registry deps when filtering by workspace name > must match snapshot 1`] = `
audited 2 packages in xxx
2 packages have verified registry signatures
`

exports[`test/lib/commands/audit.js TAP fallback audit > must match snapshot 1`] = `
Expand Down
Loading

0 comments on commit d162325

Please sign in to comment.