Skip to content

Commit

Permalink
fix(reporters): rewrite dot renderer without log-update
Browse files Browse the repository at this point in the history
  • Loading branch information
AriPerkkio committed Nov 26, 2024
1 parent 80cde2a commit d7a87a0
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 167 deletions.
24 changes: 24 additions & 0 deletions packages/vitest/LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,30 @@ Repository: git://github.com/feross/run-parallel.git
---------------------------------------

## signal-exit
License: ISC
By: Ben Coe
Repository: https://github.com/tapjs/signal-exit.git

> The ISC License
>
> Copyright (c) 2015, Contributors
>
> Permission to use, copy, modify, and/or distribute this software
> for any purpose with or without fee is hereby granted, provided
> that the above copyright notice and this permission notice
> appear in all copies.
>
> THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
> OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
> OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
> WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
> ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---------------------------------------

## sisteransi
License: MIT
By: Terkel Gjervig
Expand Down
142 changes: 109 additions & 33 deletions packages/vitest/src/node/reporters/dot.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,129 @@
import type { UserConsoleLog } from '../../types/general'
import type { File, TaskResultPack, TaskState, Test } from '@vitest/runner'
import type { Vitest } from '../core'
import c from 'tinyrainbow'
import { BaseReporter } from './base'
import { createDotRenderer } from './renderers/dotRenderer'
import { WindowRenderer } from './renderers/windowedRenderer'
import { TaskParser } from './task-parser'

export class DotReporter extends BaseReporter {
renderer?: ReturnType<typeof createDotRenderer>
private summary?: DotSummary

onTaskUpdate() {}
onInit(ctx: Vitest) {
super.onInit(ctx)

onCollected() {
if (this.isTTY) {
const files = this.ctx.state.getFiles(this.watchFilters)
if (!this.renderer) {
this.renderer = createDotRenderer(files, {
logger: this.ctx.logger,
}).start()
}
else {
this.renderer.update(files)
}
this.summary = new DotSummary()
this.summary.onInit(ctx)
}
}

onTaskUpdate(packs: TaskResultPack[]) {
this.summary?.onTaskUpdate(packs)

if (!this.isTTY) {
super.onTaskUpdate(packs)
}
}

async onFinished(
files = this.ctx.state.getFiles(),
errors = this.ctx.state.getUnhandledErrors(),
) {
await this.stopListRender()
this.ctx.logger.log()
onWatcherRerun(files: string[], trigger?: string) {
this.summary?.onWatcherRerun()
super.onWatcherRerun(files, trigger)
}

onFinished(files?: File[], errors?: unknown[]) {
this.summary?.onFinished()
super.onFinished(files, errors)
}
}

async onWatcherStart() {
await this.stopListRender()
super.onWatcherStart()
class DotSummary extends TaskParser {
private renderer!: WindowRenderer
private tests = new Map<Test['id'], TaskState>()

onInit(ctx: Vitest): void {
this.ctx = ctx

this.renderer = new WindowRenderer({
logger: ctx.logger,
getWindow: () => this.createSummary(),
})

this.ctx.onClose(() => this.renderer.stop())
}

async stopListRender() {
this.renderer?.stop()
this.renderer = undefined
await new Promise(resolve => setTimeout(resolve, 10))
onWatcherRerun() {
this.tests.clear()
this.renderer.start()
}

async onWatcherRerun(files: string[], trigger?: string) {
await this.stopListRender()
super.onWatcherRerun(files, trigger)
onFinished() {
const finalLog = Array.from(this.tests.values()).map(getIcon).join('')
this.ctx.logger.log(finalLog)

this.tests.clear()
this.renderer.finish()
}

onTestStart(test: Test) {
if (!this.tests.has(test.id)) {
this.tests.set(test.id, 'run')
}
}

onTestFinished(test: Test) {
this.tests.set(test.id, test.result?.state || 'skip')
}

onUserConsoleLog(log: UserConsoleLog) {
this.renderer?.clear()
super.onUserConsoleLog(log)
onTestFileFinished() {
const columns = this.renderer.getColumns()

if (this.tests.size < columns) {
return
}

const finishedTests = Array.from(this.tests).filter(entry => entry[1] !== 'run')

if (finishedTests.length < columns) {
return
}

// Remove finished tests from state and render them in static output
let output = ''
let count = 0

for (const [id, state] of finishedTests) {
if (count++ >= columns) {
break
}

this.tests.delete(id)
output += getIcon(state)
}

this.ctx.logger.log(output)
}

private createSummary() {
const summary = []

const row = Array.from(this.tests.values()).map(getIcon).join('')
summary.push(row)

summary.push('')
return summary
}
}

function getIcon(state: TaskState) {
switch (state) {
case 'pass':
return c.green('·')
case 'fail':
return c.red('x')
case 'skip':
case 'todo':
return c.dim(c.gray('-'))
default:
return c.yellow('*')
}
}
130 changes: 0 additions & 130 deletions packages/vitest/src/node/reporters/renderers/dotRenderer.ts

This file was deleted.

11 changes: 7 additions & 4 deletions packages/vitest/src/node/reporters/renderers/windowedRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ export class WindowRenderer {
clearInterval(this.renderInterval)
}

getColumns() {
return 'columns' in this.options.logger.outputStream ? this.options.logger.outputStream.columns : 80
}

private flushBuffer() {
if (this.buffer.length === 0) {
return this.render()
Expand Down Expand Up @@ -112,11 +116,11 @@ export class WindowRenderer {
}

const windowContent = this.options.getWindow()
const rowCount = getRenderedRowCount(windowContent, this.options.logger.outputStream)
const rowCount = getRenderedRowCount(windowContent, this.getColumns())
let padding = this.windowHeight - rowCount

if (padding > 0 && message) {
padding -= getRenderedRowCount([message], this.options.logger.outputStream)
padding -= getRenderedRowCount([message], this.getColumns())
}

this.write(SYNC_START)
Expand Down Expand Up @@ -203,9 +207,8 @@ export class WindowRenderer {
}

/** Calculate the actual row count needed to render `rows` into `stream` */
function getRenderedRowCount(rows: string[], stream: Options['logger']['outputStream']) {
function getRenderedRowCount(rows: string[], columns: number) {
let count = 0
const columns = 'columns' in stream ? stream.columns : 80

for (const row of rows) {
const text = stripVTControlCharacters(row)
Expand Down
Loading

0 comments on commit d7a87a0

Please sign in to comment.