mirror of
https://github.com/pnpm/pnpm.git
synced 2026-05-04 22:16:33 -04:00
515 lines
13 KiB
TypeScript
515 lines
13 KiB
TypeScript
import logger, {
|
|
createStreamParser,
|
|
} from '@pnpm/logger'
|
|
import test = require('tape')
|
|
import normalizeNewline = require('normalize-newline')
|
|
import {toOutput$} from 'pnpm-default-reporter'
|
|
import {stripIndents} from 'common-tags'
|
|
import chalk from 'chalk'
|
|
import xs, {Stream} from 'xstream'
|
|
import StackTracey = require('stacktracey')
|
|
|
|
const WARN = chalk.bgYellow.black('\u2009WARN\u2009')
|
|
const ERROR = chalk.bgRed.black('\u2009ERROR\u2009')
|
|
const DEPRECATED = chalk.red('deprecated')
|
|
const versionColor = chalk.grey
|
|
const ADD = chalk.green('+')
|
|
const SUB = chalk.red('-')
|
|
const LINKED = chalk.magentaBright('#')
|
|
const h1 = chalk.blue
|
|
const hlValue = chalk.blue
|
|
const hlPkgId = chalk['whiteBright']
|
|
const POSTINSTALL = hlValue('postinstall')
|
|
const PREINSTALL = hlValue('preinstall')
|
|
const INSTALL = hlValue('install')
|
|
|
|
const progressLogger = logger<object>('progress')
|
|
const stageLogger = logger<string>('stage')
|
|
const rootLogger = logger<object>('root')
|
|
const deprecationLogger = logger<object>('deprecation')
|
|
const summaryLogger = logger<object>('summary')
|
|
const lifecycleLogger = logger<object>('lifecycle')
|
|
const packageJsonLogger = logger<object>('package-json')
|
|
|
|
test('prints progress beginning', t => {
|
|
const output$ = toOutput$(createStreamParser())
|
|
|
|
const pkgId = 'registry.npmjs.org/foo/1.0.0'
|
|
|
|
progressLogger.debug({
|
|
status: 'resolving_content',
|
|
pkgId,
|
|
})
|
|
|
|
t.plan(1)
|
|
|
|
output$.take(1).subscribe({
|
|
next: output => {
|
|
t.equal(output, `Resolving: total ${hlValue('1')}, reused ${hlValue('0')}, downloaded ${hlValue('0')}`)
|
|
},
|
|
error: t.end,
|
|
complete: t.end,
|
|
})
|
|
})
|
|
|
|
test('prints progress on first download', t => {
|
|
const output$ = toOutput$(createStreamParser())
|
|
|
|
const pkgId = 'registry.npmjs.org/foo/1.0.0'
|
|
|
|
progressLogger.debug({
|
|
status: 'resolving_content',
|
|
pkgId,
|
|
})
|
|
progressLogger.debug({
|
|
status: 'fetched',
|
|
pkgId,
|
|
})
|
|
|
|
t.plan(1)
|
|
|
|
output$.drop(1).take(1).subscribe({
|
|
next: output => {
|
|
t.equal(output, `Resolving: total ${hlValue('1')}, reused ${hlValue('0')}, downloaded ${hlValue('1')}`)
|
|
},
|
|
complete: t.end,
|
|
error: t.end,
|
|
})
|
|
})
|
|
|
|
test('moves fixed line to the end', t => {
|
|
const output$ = toOutput$(createStreamParser())
|
|
|
|
const pkgId = 'registry.npmjs.org/foo/1.0.0'
|
|
|
|
progressLogger.debug({
|
|
status: 'resolving_content',
|
|
pkgId,
|
|
})
|
|
progressLogger.debug({
|
|
status: 'fetched',
|
|
pkgId,
|
|
})
|
|
logger.warn('foo')
|
|
stageLogger.debug('resolution_done')
|
|
|
|
t.plan(1)
|
|
|
|
output$.drop(3).take(1).map(normalizeNewline).subscribe({
|
|
next: output => {
|
|
t.equal(output, stripIndents`
|
|
${WARN} foo
|
|
Resolving: total ${hlValue('1')}, reused ${hlValue('0')}, downloaded ${hlValue('1')}, done
|
|
`)
|
|
},
|
|
complete: t.end,
|
|
error: t.end,
|
|
})
|
|
})
|
|
|
|
test('prints "Already up-to-date"', t => {
|
|
const output$ = toOutput$(createStreamParser())
|
|
|
|
stageLogger.debug('resolution_done')
|
|
|
|
t.plan(1)
|
|
|
|
output$.take(1).map(normalizeNewline).subscribe({
|
|
next: output => {
|
|
t.equal(output, stripIndents`
|
|
Already up-to-date
|
|
`)
|
|
},
|
|
complete: t.end,
|
|
error: t.end,
|
|
})
|
|
})
|
|
|
|
test('prints summary', t => {
|
|
const output$ = toOutput$(createStreamParser())
|
|
|
|
packageJsonLogger.debug({
|
|
initial: {
|
|
dependencies: {
|
|
'is-13': '^1.0.0',
|
|
},
|
|
devDependencies: {
|
|
'is-negative': '^1.0.0',
|
|
},
|
|
},
|
|
})
|
|
deprecationLogger.warn({
|
|
pkgName: 'bar',
|
|
pkgVersion: '2.0.0',
|
|
pkgId: 'registry.npmjs.org/bar/2.0.0',
|
|
deprecated: 'This package was deprecated because bla bla bla',
|
|
depth: 0,
|
|
})
|
|
rootLogger.info({
|
|
added: {
|
|
dependencyType: 'prod',
|
|
name: 'foo',
|
|
version: '1.0.0',
|
|
id: 'registry.npmjs.org/foo/1.0.0',
|
|
},
|
|
})
|
|
rootLogger.info({
|
|
added: {
|
|
dependencyType: 'prod',
|
|
name: 'bar',
|
|
version: '2.0.0',
|
|
id: 'registry.npmjs.org/bar/2.0.0',
|
|
},
|
|
})
|
|
rootLogger.info({
|
|
removed: {
|
|
dependencyType: 'prod',
|
|
name: 'foo',
|
|
version: '0.1.0',
|
|
},
|
|
})
|
|
rootLogger.info({
|
|
added: {
|
|
dependencyType: 'dev',
|
|
name: 'qar',
|
|
version: '2.0.0',
|
|
id: 'registry.npmjs.org/qar/2.0.0',
|
|
},
|
|
})
|
|
rootLogger.info({
|
|
added: {
|
|
dependencyType: 'optional',
|
|
name: 'lala',
|
|
version: '1.1.0',
|
|
id: 'registry.npmjs.org/lala/1.1.0',
|
|
},
|
|
})
|
|
rootLogger.info({
|
|
removed: {
|
|
dependencyType: 'optional',
|
|
name: 'is-positive',
|
|
},
|
|
})
|
|
rootLogger.debug({
|
|
linked: {
|
|
dependencyType: 'optional',
|
|
from: '/src/is-linked',
|
|
name: 'is-linked',
|
|
to: '/src/project/node_modules'
|
|
},
|
|
})
|
|
packageJsonLogger.debug({
|
|
updated: {
|
|
dependencies: {
|
|
'is-negative': '^1.0.0',
|
|
},
|
|
devDependencies: {
|
|
'is-13': '^1.0.0',
|
|
},
|
|
}
|
|
})
|
|
summaryLogger.info()
|
|
|
|
t.plan(1)
|
|
|
|
output$.drop(1).take(1).map(normalizeNewline).subscribe({
|
|
next: output => {
|
|
t.equal(output, stripIndents`
|
|
${WARN} ${DEPRECATED} bar@2.0.0: This package was deprecated because bla bla bla
|
|
|
|
${h1('dependencies:')}
|
|
${ADD} bar ${versionColor('2.0.0')} ${DEPRECATED}
|
|
${SUB} foo ${versionColor('0.1.0')}
|
|
${ADD} foo ${versionColor('1.0.0')}
|
|
${SUB} is-13 ${versionColor('^1.0.0')}
|
|
${ADD} is-negative ${versionColor('^1.0.0')}
|
|
|
|
${h1('optionalDependencies:')}
|
|
${LINKED} is-linked ${chalk.magentaBright('linked from')} ${chalk.grey('/src/is-linked')}
|
|
${SUB} is-positive
|
|
${ADD} lala ${versionColor('1.1.0')}
|
|
|
|
${h1('devDependencies:')}
|
|
${ADD} is-13 ${versionColor('^1.0.0')}
|
|
${SUB} is-negative ${versionColor('^1.0.0')}
|
|
${ADD} qar ${versionColor('2.0.0')}
|
|
` + '\n')
|
|
},
|
|
complete: t.end,
|
|
error: t.end,
|
|
})
|
|
})
|
|
|
|
test('groups lifecycle output', t => {
|
|
const output$ = toOutput$(createStreamParser())
|
|
|
|
const pkgId = 'registry.npmjs.org/foo/1.0.0'
|
|
|
|
lifecycleLogger.debug({
|
|
pkgId: 'registry.npmjs.org/foo/1.0.0',
|
|
line: 'foo',
|
|
script: 'preinstall',
|
|
})
|
|
lifecycleLogger.debug({
|
|
pkgId: 'registry.npmjs.org/foo/1.0.0',
|
|
line: 'foo I',
|
|
script: 'postinstall',
|
|
})
|
|
lifecycleLogger.debug({
|
|
pkgId: 'registry.npmjs.org/bar/1.0.0',
|
|
line: 'bar I',
|
|
script: 'postinstall',
|
|
})
|
|
lifecycleLogger.debug({
|
|
pkgId: 'registry.npmjs.org/foo/1.0.0',
|
|
line: 'foo II',
|
|
script: 'postinstall',
|
|
})
|
|
lifecycleLogger.debug({
|
|
pkgId: 'registry.npmjs.org/foo/1.0.0',
|
|
line: 'foo III',
|
|
script: 'postinstall',
|
|
})
|
|
lifecycleLogger.debug({
|
|
pkgId: 'registry.npmjs.org/qar/1.0.0',
|
|
line: '...',
|
|
script: 'install',
|
|
})
|
|
lifecycleLogger.debug({
|
|
pkgId: 'registry.npmjs.org/qar/1.0.0',
|
|
exitCode: 0,
|
|
script: 'install',
|
|
})
|
|
|
|
t.plan(1)
|
|
|
|
const childOutputColor = chalk.grey
|
|
|
|
output$.drop(6).take(1).map(normalizeNewline).subscribe({
|
|
next: output => {
|
|
t.equal(output, stripIndents`
|
|
Running ${PREINSTALL} for ${hlPkgId('registry.npmjs.org/foo/1.0.0')}: ${childOutputColor('foo')}
|
|
Running ${POSTINSTALL} for ${hlPkgId('registry.npmjs.org/foo/1.0.0')}: ${childOutputColor('foo III')}
|
|
Running ${POSTINSTALL} for ${hlPkgId('registry.npmjs.org/bar/1.0.0')}: ${childOutputColor('bar I')}
|
|
Running ${INSTALL} for ${hlPkgId('registry.npmjs.org/qar/1.0.0')}, done
|
|
`)
|
|
},
|
|
complete: t.end,
|
|
error: t.end,
|
|
})
|
|
})
|
|
|
|
test('prints lifecycle progress', t => {
|
|
const output$ = toOutput$(createStreamParser())
|
|
|
|
const pkgId = 'registry.npmjs.org/foo/1.0.0'
|
|
|
|
lifecycleLogger.debug({
|
|
pkgId: 'registry.npmjs.org/foo/1.0.0',
|
|
line: 'foo I',
|
|
script: 'postinstall',
|
|
})
|
|
lifecycleLogger.debug({
|
|
pkgId: 'registry.npmjs.org/bar/1.0.0',
|
|
line: 'bar I',
|
|
script: 'postinstall',
|
|
})
|
|
lifecycleLogger.error({
|
|
pkgId: 'registry.npmjs.org/foo/1.0.0',
|
|
line: 'foo II',
|
|
script: 'postinstall',
|
|
})
|
|
lifecycleLogger.debug({
|
|
pkgId: 'registry.npmjs.org/foo/1.0.0',
|
|
line: 'foo III',
|
|
script: 'postinstall',
|
|
})
|
|
|
|
t.plan(1)
|
|
|
|
const childOutputColor = chalk.grey
|
|
const childOutputError = chalk.red
|
|
|
|
output$.drop(3).take(1).map(normalizeNewline).subscribe({
|
|
next: output => {
|
|
t.equal(output, stripIndents`
|
|
Running ${POSTINSTALL} for ${hlPkgId('registry.npmjs.org/foo/1.0.0')}: ${childOutputColor('foo I')}
|
|
Running ${POSTINSTALL} for ${hlPkgId('registry.npmjs.org/foo/1.0.0')}! ${childOutputError('foo II')}
|
|
Running ${POSTINSTALL} for ${hlPkgId('registry.npmjs.org/foo/1.0.0')}: ${childOutputColor('foo III')}
|
|
Running ${POSTINSTALL} for ${hlPkgId('registry.npmjs.org/bar/1.0.0')}: ${childOutputColor('bar I')}
|
|
`)
|
|
},
|
|
complete: t.end,
|
|
error: t.end,
|
|
})
|
|
})
|
|
|
|
test('prints generic error', t => {
|
|
const output$ = toOutput$(createStreamParser())
|
|
|
|
const err = new Error('some error')
|
|
logger.error(err)
|
|
|
|
t.plan(1)
|
|
|
|
output$.take(1).subscribe({
|
|
next: output => {
|
|
t.equal(output, stripIndents`
|
|
${ERROR} ${chalk.red('some error')}
|
|
${new StackTracey(err.stack).pretty}
|
|
`)
|
|
},
|
|
complete: t.end,
|
|
error: t.end,
|
|
})
|
|
})
|
|
|
|
test('prints info', t => {
|
|
const output$ = toOutput$(createStreamParser())
|
|
|
|
logger.info('info message')
|
|
|
|
t.plan(1)
|
|
|
|
output$.take(1).subscribe({
|
|
next: output => {
|
|
t.equal(output, 'info message')
|
|
},
|
|
complete: t.end,
|
|
error: t.end,
|
|
})
|
|
})
|
|
|
|
test('prints progress of big files download', t => {
|
|
let output$ = toOutput$(createStreamParser()).map(normalizeNewline) as Stream<string>
|
|
const stream$: Stream<string>[] = []
|
|
|
|
const pkgId1 = 'registry.npmjs.org/foo/1.0.0'
|
|
const pkgId2 = 'registry.npmjs.org/bar/2.0.0'
|
|
const pkgId3 = 'registry.npmjs.org/qar/3.0.0'
|
|
|
|
progressLogger.debug({
|
|
status: 'resolving_content',
|
|
pkgId: pkgId1,
|
|
})
|
|
|
|
stream$.push(
|
|
output$.take(1)
|
|
.debug(output => t.equal(output, `Resolving: total ${hlValue('1')}, reused ${hlValue('0')}, downloaded ${hlValue('0')}`))
|
|
)
|
|
|
|
output$ = output$.drop(1)
|
|
|
|
progressLogger.debug({
|
|
status: 'fetching_started',
|
|
pkgId: pkgId1,
|
|
size: 1024 * 1024 * 10, // 10 MB
|
|
attempt: 1,
|
|
})
|
|
|
|
stream$.push(
|
|
output$.take(1)
|
|
.debug(output => t.equal(output, stripIndents`
|
|
Resolving: total ${hlValue('1')}, reused ${hlValue('0')}, downloaded ${hlValue('0')}
|
|
Downloading ${hlPkgId(pkgId1)}: ${hlValue('0 B')}/${hlValue('10.5 MB')}
|
|
`))
|
|
)
|
|
|
|
output$ = output$.drop(1)
|
|
|
|
progressLogger.debug({
|
|
status: 'fetching_progress',
|
|
pkgId: pkgId1,
|
|
downloaded: 1024 * 1024 * 5.5, // 5.5 MB
|
|
})
|
|
|
|
stream$.push(
|
|
output$.take(1)
|
|
.debug(output => t.equal(output, stripIndents`
|
|
Resolving: total ${hlValue('1')}, reused ${hlValue('0')}, downloaded ${hlValue('0')}
|
|
Downloading ${hlPkgId(pkgId1)}: ${hlValue('5.77 MB')}/${hlValue('10.5 MB')}
|
|
`))
|
|
)
|
|
|
|
output$ = output$.drop(1)
|
|
|
|
progressLogger.debug({
|
|
status: 'resolving_content',
|
|
pkgId: pkgId2,
|
|
})
|
|
|
|
progressLogger.debug({
|
|
status: 'fetching_started',
|
|
pkgId: pkgId1,
|
|
size: 10, // 10 B
|
|
attempt: 1,
|
|
})
|
|
|
|
progressLogger.debug({
|
|
status: 'fetching_progress',
|
|
pkgId: pkgId1,
|
|
downloaded: 1024 * 1024 * 7,
|
|
})
|
|
|
|
stream$.push(
|
|
output$.drop(1).take(1)
|
|
.debug(output => t.equal(output, stripIndents`
|
|
Resolving: total ${hlValue('2')}, reused ${hlValue('0')}, downloaded ${hlValue('0')}
|
|
Downloading ${hlPkgId(pkgId1)}: ${hlValue('7.34 MB')}/${hlValue('10.5 MB')}
|
|
`, 'downloading of small package not reported'))
|
|
)
|
|
|
|
output$ = output$.drop(2)
|
|
|
|
progressLogger.debug({
|
|
status: 'resolving_content',
|
|
pkgId: pkgId3,
|
|
})
|
|
|
|
progressLogger.debug({
|
|
status: 'fetching_started',
|
|
pkgId: pkgId3,
|
|
size: 1024 * 1024 * 20, // 20 MB
|
|
attempt: 1,
|
|
})
|
|
|
|
progressLogger.debug({
|
|
status: 'fetching_progress',
|
|
pkgId: pkgId3,
|
|
downloaded: 1024 * 1024 * 19, // 19 MB
|
|
})
|
|
|
|
stream$.push(
|
|
output$.drop(2).take(1)
|
|
.debug(output => t.equal(output, stripIndents`
|
|
Resolving: total ${hlValue('3')}, reused ${hlValue('0')}, downloaded ${hlValue('0')}
|
|
Downloading ${hlPkgId(pkgId1)}: ${hlValue('7.34 MB')}/${hlValue('10.5 MB')}
|
|
Downloading ${hlPkgId(pkgId3)}: ${hlValue('19.9 MB')}/${hlValue('21 MB')}
|
|
`))
|
|
)
|
|
|
|
output$ = output$.drop(3)
|
|
|
|
progressLogger.debug({
|
|
status: 'fetching_progress',
|
|
pkgId: pkgId1,
|
|
downloaded: 1024 * 1024 * 10, // 10 MB
|
|
})
|
|
|
|
stream$.push(
|
|
output$.take(1)
|
|
.debug(output => t.equal(output, stripIndents`
|
|
${chalk.dim(`Downloading ${hlPkgId(pkgId1)}: ${hlValue('10.5 MB')}/${hlValue('10.5 MB')}, done`)}
|
|
Resolving: total ${hlValue('3')}, reused ${hlValue('0')}, downloaded ${hlValue('0')}
|
|
Downloading ${hlPkgId(pkgId3)}: ${hlValue('19.9 MB')}/${hlValue('21 MB')}
|
|
`))
|
|
)
|
|
|
|
xs.combine
|
|
.apply(xs, stream$)
|
|
.subscribe({
|
|
complete: t.end,
|
|
error: t.end,
|
|
})
|
|
})
|