Skip to content

Commit

Permalink
feat: introduce experimental reported tasks (#6149)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed Jul 30, 2024
1 parent e7acd0c commit 13d85bd
Show file tree
Hide file tree
Showing 34 changed files with 1,258 additions and 112 deletions.
2 changes: 1 addition & 1 deletion packages/browser/src/node/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export function setupBrowserRpc(
ctx.state.catchError(error, type)
},
async onCollected(files) {
ctx.state.collectFiles(files)
ctx.state.collectFiles(project, files)
await ctx.report('onCollected', files)
},
async onTaskUpdate(packs) {
Expand Down
14 changes: 11 additions & 3 deletions packages/runner/src/collect.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { processError } from '@vitest/utils/error'
import { toArray } from '@vitest/utils'
import type { File, SuiteHooks } from './types/tasks'
import type { VitestRunner } from './types/runner'
import {
Expand Down Expand Up @@ -34,11 +35,18 @@ export async function collectTests(
clearCollectorContext(filepath, runner)

try {
const setupStart = now()
await runSetupFiles(config, runner)
const setupFiles = toArray(config.setupFiles)
if (setupFiles.length) {
const setupStart = now()
await runSetupFiles(config, setupFiles, runner)
const setupEnd = now()
file.setupDuration = setupEnd - setupStart
}
else {
file.setupDuration = 0
}

const collectStart = now()
file.setupDuration = collectStart - setupStart

await runner.importFile(filepath, 'collect')

Expand Down
3 changes: 1 addition & 2 deletions packages/runner/src/setup.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { toArray } from '@vitest/utils'
import type { VitestRunner, VitestRunnerConfig } from './types/runner'

export async function runSetupFiles(
config: VitestRunnerConfig,
files: string[],
runner: VitestRunner,
): Promise<void> {
const files = toArray(config.setupFiles)
if (config.sequence.setupFiles === 'parallel') {
await Promise.all(
files.map(async (fsPath) => {
Expand Down
3 changes: 1 addition & 2 deletions packages/ui/client/composables/client/static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {
} from 'vitest'
import { parse } from 'flatted'
import { decompressSync, strFromU8 } from 'fflate'
import { StateManager } from '../../../../vitest/src/node/state'
import { StateManager } from '../../../../ws-client/src/state'

interface HTMLReportMetadata {
paths: string[]
Expand Down Expand Up @@ -55,7 +55,6 @@ export function createStaticClient(): VitestClient {
},
getTransformResult: asyncNoop,
onDone: noop,
onCollected: asyncNoop,
onTaskUpdate: noop,
writeFile: asyncNoop,
rerun: asyncNoop,
Expand Down
10 changes: 5 additions & 5 deletions packages/utils/src/diff/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const FALLBACK_FORMAT_OPTIONS = {
* @param options Diff options
* @returns {string | null} a string diff
*/
export function diff(a: any, b: any, options?: DiffOptions): string | null {
export function diff(a: any, b: any, options?: DiffOptions): string | undefined {
if (Object.is(a, b)) {
return ''
}
Expand All @@ -80,11 +80,11 @@ export function diff(a: any, b: any, options?: DiffOptions): string | null {
if (aType === 'object' && typeof a.asymmetricMatch === 'function') {
if (a.$$typeof !== Symbol.for('jest.asymmetricMatcher')) {
// Do not know expected type of user-defined asymmetric matcher.
return null
return undefined
}
if (typeof a.getExpectedType !== 'function') {
// For example, expect.anything() matches either null or undefined
return null
return undefined
}
expectedType = a.getExpectedType()
// Primitive types boolean and number omit difference below.
Expand All @@ -104,7 +104,7 @@ export function diff(a: any, b: any, options?: DiffOptions): string | null {
}

if (omitDifference) {
return null
return undefined
}

switch (aType) {
Expand Down Expand Up @@ -234,7 +234,7 @@ export function printDiffOrStringify(
expected: unknown,
received: unknown,
options?: DiffOptions,
): string | null {
): string | undefined {
const { aAnnotation, bAnnotation } = normalizeDiffOptions(options)

if (
Expand Down
27 changes: 16 additions & 11 deletions packages/utils/src/error.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type DiffOptions, printDiffOrStringify } from './diff'
import { format, stringify } from './display'
import type { TestError } from './types'

// utils is bundled for any environment and might not support `Element`
declare class Element {
Expand All @@ -26,7 +27,7 @@ function getUnserializableMessage(err: unknown) {
}

// https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
export function serializeError(val: any, seen: WeakMap<WeakKey, any> = new WeakMap()): any {
export function serializeValue(val: any, seen: WeakMap<WeakKey, any> = new WeakMap()): any {
if (!val || typeof val === 'string') {
return val
}
Expand All @@ -41,7 +42,7 @@ export function serializeError(val: any, seen: WeakMap<WeakKey, any> = new WeakM
}
// cannot serialize immutables as immutables
if (isImmutable(val)) {
return serializeError(val.toJSON(), seen)
return serializeValue(val.toJSON(), seen)
}
if (
val instanceof Promise
Expand All @@ -56,7 +57,7 @@ export function serializeError(val: any, seen: WeakMap<WeakKey, any> = new WeakM
return `${val.toString()} ${format(val.sample)}`
}
if (typeof val.toJSON === 'function') {
return serializeError(val.toJSON(), seen)
return serializeValue(val.toJSON(), seen)
}

if (seen.has(val)) {
Expand All @@ -69,7 +70,7 @@ export function serializeError(val: any, seen: WeakMap<WeakKey, any> = new WeakM
seen.set(val, clone)
val.forEach((e, i) => {
try {
clone[i] = serializeError(e, seen)
clone[i] = serializeValue(e, seen)
}
catch (err) {
clone[i] = getUnserializableMessage(err)
Expand All @@ -90,7 +91,7 @@ export function serializeError(val: any, seen: WeakMap<WeakKey, any> = new WeakM
return
}
try {
clone[key] = serializeError(val[key], seen)
clone[key] = serializeValue(val[key], seen)
}
catch (err) {
// delete in case it has a setter from prototype that might throw
Expand All @@ -104,18 +105,22 @@ export function serializeError(val: any, seen: WeakMap<WeakKey, any> = new WeakM
}
}

export { serializeValue as serializeError }

function normalizeErrorMessage(message: string) {
return message.replace(/__(vite_ssr_import|vi_import)_\d+__\./g, '')
}

export function processError(
err: any,
_err: any,
diffOptions?: DiffOptions,
seen: WeakSet<WeakKey> = new WeakSet(),
): any {
if (!err || typeof err !== 'object') {
return { message: err }
if (!_err || typeof _err !== 'object') {
return { message: String(_err) }
}
const err = _err as TestError

// stack is not serialized in worker communication
// we stringify it first
if (err.stack) {
Expand All @@ -133,7 +138,7 @@ export function processError(
) {
err.diff = printDiffOrStringify(err.actual, err.expected, {
...diffOptions,
...err.diffOptions,
...err.diffOptions as DiffOptions,
})
}

Expand Down Expand Up @@ -163,10 +168,10 @@ export function processError(
catch {}

try {
return serializeError(err)
return serializeValue(err)
}
catch (e: any) {
return serializeError(
return serializeValue(
new Error(
`Failed to fully serialize error: ${e?.message}\nInner error message: ${err?.message}`,
),
Expand Down
2 changes: 2 additions & 0 deletions packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,6 @@ export type {
Constructable,
ParsedStack,
ErrorWithDiff,
SerializedError,
TestError,
} from './types'
2 changes: 1 addition & 1 deletion packages/utils/src/source-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface StackTraceParserOptions {
ignoreStackEntries?: (RegExp | string)[]
getSourceMap?: (file: string) => unknown
getFileName?: (id: string) => string
frameFilter?: (error: Error, frame: ParsedStack) => boolean | void
frameFilter?: (error: ErrorWithDiff, frame: ParsedStack) => boolean | void
}

const CHROME_IE_STACK_REGEXP = /^\s*at .*(?:\S:\d+|\(native\))/m
Expand Down
25 changes: 23 additions & 2 deletions packages/utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,29 @@ export interface ParsedStack {
column: number
}

export interface ErrorWithDiff extends Error {
name: string
export interface SerializedError {
message: string
stack?: string
name?: string
stacks?: ParsedStack[]
cause?: SerializedError
[key: string]: unknown
}

export interface TestError extends SerializedError {
cause?: TestError
diff?: string
actual?: string
expected?: string
}

/**
* @deprecated Use `TestError` instead
*/
export interface ErrorWithDiff {
message: string
name?: string
cause?: unknown
nameStr?: string
stack?: string
stackStr?: string
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const plugins = [
json(),
commonjs(),
esbuild({
target: 'node14',
target: 'node18',
}),
]

Expand Down
4 changes: 0 additions & 4 deletions packages/vitest/src/api/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ export function setup(ctx: Vitest, _server?: ViteDevServer) {
function setupClient(ws: WebSocket) {
const rpc = createBirpc<WebSocketEvents, WebSocketHandlers>(
{
async onCollected(files) {
ctx.state.collectFiles(files)
await ctx.report('onCollected', files)
},
async onTaskUpdate(packs) {
ctx.state.updateTasks(packs)
await ctx.report('onTaskUpdate', packs)
Expand Down
1 change: 0 additions & 1 deletion packages/vitest/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export interface TransformResultWithSource {
}

export interface WebSocketHandlers {
onCollected: (files?: File[]) => Promise<void>
onTaskUpdate: (packs: TaskResultPack[]) => void
getFiles: () => File[]
getTestFiles: () => Promise<SerializedSpec[]>
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ export class Vitest {
files.forEach((file) => {
file.logs?.forEach(log => this.state.updateUserLog(log))
})
this.state.collectFiles(files)
this.state.collectFiles(project, files)
}

await this.report('onCollected', files).catch(noop)
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ function printModuleWarningForSourceCode(logger: Logger, path: string) {
)
}

export function displayDiff(diff: string | null, console: Console) {
export function displayDiff(diff: string | undefined, console: Console) {
if (diff) {
console.error(`\n${diff}\n`)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/pools/forks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export function createForksPool(
&& error instanceof Error
&& /The task has been cancelled/.test(error.message)
) {
ctx.state.cancelFiles(files, ctx.config.root, project.config.name)
ctx.state.cancelFiles(files, project)
}
else {
throw error
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/pools/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export function createMethodsRPC(project: WorkspaceProject, options: MethodsOpti
return ctx.report('onPathsCollected', paths)
},
onCollected(files) {
ctx.state.collectFiles(files)
ctx.state.collectFiles(project, files)
return ctx.report('onCollected', files)
},
onAfterSuiteRun(meta) {
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/pools/threads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export function createThreadsPool(
&& error instanceof Error
&& /The task has been cancelled/.test(error.message)
) {
ctx.state.cancelFiles(files, ctx.config.root, project.config.name)
ctx.state.cancelFiles(files, project)
}
else {
throw error
Expand Down
8 changes: 4 additions & 4 deletions packages/vitest/src/node/pools/typecheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function createTypecheckPool(ctx: Vitest): ProcessPool {
checker.setFiles(files)

checker.onParseStart(async () => {
ctx.state.collectFiles(checker.getTestFiles())
ctx.state.collectFiles(project, checker.getTestFiles())
await ctx.report('onCollected')
})

Expand All @@ -80,7 +80,7 @@ export function createTypecheckPool(ctx: Vitest): ProcessPool {
}

await checker.collectTests()
ctx.state.collectFiles(checker.getTestFiles())
ctx.state.collectFiles(project, checker.getTestFiles())

await ctx.report('onTaskUpdate', checker.getTestPacks())
await ctx.report('onCollected')
Expand All @@ -107,7 +107,7 @@ export function createTypecheckPool(ctx: Vitest): ProcessPool {
const checker = await createWorkspaceTypechecker(project, files)
checker.setFiles(files)
await checker.collectTests()
ctx.state.collectFiles(checker.getTestFiles())
ctx.state.collectFiles(project, checker.getTestFiles())
await ctx.report('onCollected')
}
}
Expand Down Expand Up @@ -135,7 +135,7 @@ export function createTypecheckPool(ctx: Vitest): ProcessPool {
})
const triggered = await _p
if (project.typechecker && !triggered) {
ctx.state.collectFiles(project.typechecker.getTestFiles())
ctx.state.collectFiles(project, project.typechecker.getTestFiles())
await ctx.report('onCollected')
await onParseEnd(project, project.typechecker.getResult())
continue
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/pools/vmForks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export function createVmForksPool(
&& error instanceof Error
&& /The task has been cancelled/.test(error.message)
) {
ctx.state.cancelFiles(files, ctx.config.root, project.config.name)
ctx.state.cancelFiles(files, project)
}
else {
throw error
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/pools/vmThreads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export function createVmThreadsPool(
&& error instanceof Error
&& /The task has been cancelled/.test(error.message)
) {
ctx.state.cancelFiles(files, ctx.config.root, project.config.name)
ctx.state.cancelFiles(files, project)
}
else {
throw error
Expand Down
Loading

0 comments on commit 13d85bd

Please sign in to comment.