From ff2ad744cd96dc064102559d1c64348054cf968e Mon Sep 17 00:00:00 2001 From: Zixuan Chen Date: Sun, 19 Jun 2022 17:08:22 +0800 Subject: [PATCH] feat: show enqueue status, show test result faster --- samples/basic/test/add.test.ts | 8 +++++ samples/basic/test/snapshot.test.ts | 4 +++ src/pure/ApiProcess.ts | 48 +++++++++++++++++++++-------- src/pure/runner.ts | 5 +++ src/pure/watch/client.ts | 8 +++-- src/runHandler.ts | 10 +++++- 6 files changed, 68 insertions(+), 15 deletions(-) diff --git a/samples/basic/test/add.test.ts b/samples/basic/test/add.test.ts index 853b9fc7..2d011b72 100644 --- a/samples/basic/test/add.test.ts +++ b/samples/basic/test/add.test.ts @@ -19,6 +19,14 @@ describe('addition', () => { await new Promise(resolve => setTimeout(resolve, 100)) }) + it('async task 0.5s', async () => { + await new Promise(resolve => setTimeout(resolve, 500)) + }) + + it('async task 1s', async () => { + await new Promise(resolve => setTimeout(resolve, 1000)) + }) + it('long task', () => { let sum = 0 for (let i = 0; i < 2e8; i++) diff --git a/samples/basic/test/snapshot.test.ts b/samples/basic/test/snapshot.test.ts index 2834e2d2..2944c559 100644 --- a/samples/basic/test/snapshot.test.ts +++ b/samples/basic/test/snapshot.test.ts @@ -4,4 +4,8 @@ describe('snapshots', () => { it('string', () => { expect('bc').toMatchSnapshot() }) + it('async', async () => { + await new Promise(resolve => setTimeout(resolve, 200)) + expect('bc').toMatchSnapshot() + }) }) diff --git a/src/pure/ApiProcess.ts b/src/pure/ApiProcess.ts index a50af330..3795f585 100644 --- a/src/pure/ApiProcess.ts +++ b/src/pure/ApiProcess.ts @@ -1,12 +1,12 @@ import type { ChildProcess } from 'child_process' import getPort from 'get-port' -import type { WebSocketEvents } from 'vitest' +import type { File, WebSocketEvents } from 'vitest' import { getConfig } from '../config' import { log } from '../log' import { execWithLog, filterColorFormatOutput, sanitizeFilePath } from './utils' import { buildWatchClient } from './watch/client' -type Handlers = Partial & { log?: (msg: string) => void } +type Handlers = Partial & { log?: (msg: string) => void; onUpdate?: (files: File[]) => void } export class ApiProcess { private process?: ChildProcess @@ -26,6 +26,26 @@ export class ApiProcess { this.handlers.log?.(content) } } + if (this.handlers.onUpdate) { + const taskUpdateHandler = this.handlers.onTaskUpdate + this.handlers.onTaskUpdate = (packs) => { + taskUpdateHandler && taskUpdateHandler(packs) + if (!this.vitestState) + return + + const idMap = this.vitestState.client.state.idMap + const fileSet = new Set() + for (const [id] of packs) { + const task = idMap.get(id) + if (!task) + continue + + task.file && fileSet.add(task.file) + } + + this.handlers.onUpdate && this.handlers.onUpdate(Array.from(fileSet)) + } + } } async start() { @@ -75,17 +95,21 @@ export class ApiProcess { this.dispose() }) - this.vitestState = buildWatchClient({ - port, - handlers: this.handlers, - }) + setTimeout(() => { + this.vitestState = buildWatchClient({ + port, + handlers: this.handlers, + reconnectInterval: 100, + reconnectTries: 100, + }) - this.vitestState.loadingPromise.then((isRunning) => { - if (!isRunning) { - const files = this.vitestState!.files.value - files && this.handlers?.onFinished?.(files) - } - }) + this.vitestState.loadingPromise.then((isRunning) => { + if (!isRunning) { + const files = this.vitestState!.files.value + files && this.handlers?.onFinished?.(files) + } + }) + }, 50) } get client() { diff --git a/src/pure/runner.ts b/src/pure/runner.ts index 72111810..0f01ebb4 100644 --- a/src/pure/runner.ts +++ b/src/pure/runner.ts @@ -78,6 +78,7 @@ export class TestRunner { ? this.defaultVitestCommand : { cmd: 'npx', args: ['vitest'] }, updateSnapshot = false, + onUpdate?: (files: File[]) => void, ): Promise<{ testResultFiles: File[]; output: string }> { const command = vitestCommand.cmd const args = [ @@ -111,6 +112,10 @@ export class TestRunner { testResultFiles = files }, + onCollected: (files) => { + files && onUpdate && onUpdate(files) + }, + onUpdate, }) return { testResultFiles, output } diff --git a/src/pure/watch/client.ts b/src/pure/watch/client.ts index a03eddd3..9dd96f10 100644 --- a/src/pure/watch/client.ts +++ b/src/pure/watch/client.ts @@ -9,16 +9,20 @@ type WebSocketStatus = 'OPEN' | 'CONNECTING' | 'CLOSED'; export type RunState = 'idle' | 'running' export function buildWatchClient( - { port, url = `ws://localhost:${port}/__vitest_api__`, handlers }: { + { port, url = `ws://localhost:${port}/__vitest_api__`, handlers, reconnectInterval, reconnectTries }: { url?: string handlers?: Partial port: number + reconnectInterval?: number + reconnectTries?: number }, ) { const client = createClient(url, { handlers, WebSocketConstructor: WebSocket as any, reactive: reactive as any, + reconnectInterval, + reconnectTries, }) const config = shallowRef({} as any) @@ -54,7 +58,7 @@ export function buildWatchClient( const loadingPromise = client.waitForConnection().then(async () => { const files = await client.rpc.getFiles() const idResultPairs: [string, TaskResult][] = [] - let isRunning = false + let isRunning = files.length === 0 files && travel(files) function travel(tasks: Task[]) { for (const task of tasks) { diff --git a/src/runHandler.ts b/src/runHandler.ts index 2fcfb8e9..27eef692 100644 --- a/src/runHandler.ts +++ b/src/runHandler.ts @@ -1,6 +1,7 @@ import { isAbsolute, relative } from 'path' import { existsSync } from 'fs' import * as vscode from 'vscode' +import type { File } from 'vitest' import { readFile } from 'fs-extra' import type { FormattedTestResults } from './pure/runner' import { @@ -237,7 +238,7 @@ async function runTest( } testCaseSet.forEach((testCase) => { - run.started(testCase) + run.enqueued(testCase) }) if (mode === 'run' || mode === 'update') { @@ -267,6 +268,9 @@ async function runTest( config.env || undefined, command, mode === 'update', + (files: File[]) => { + syncFilesTestStatus(files, discover, ctrl, run, false, false) + }, ) const finishedTests = syncFilesTestStatus(testResultFiles, discover, ctrl, run, true, false) @@ -279,6 +283,10 @@ async function runTest( return } + testCaseSet.forEach((testCase) => { + run.started(testCase) + }) + const pathToFile = new Map() for (const file of fileItems) pathToFile.set(sanitizeFilePath(file.uri!.fsPath), file)