/
state.ts
116 lines (96 loc) · 2.85 KB
/
state.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import type { ErrorWithDiff, File, Task, TaskResultPack, UserConsoleLog } from '../types'
// can't import actual functions from utils, because it's incompatible with @vitest/browsers
import type { AggregateError as AggregateErrorPonyfill } from '../utils'
interface CollectingPromise {
promise: Promise<void>
resolve: () => void
}
export const isAggregateError = (err: unknown): err is AggregateErrorPonyfill => {
if (typeof AggregateError !== 'undefined' && err instanceof AggregateError)
return true
return err instanceof Error && 'errors' in err
}
// Note this file is shared for both node and browser, be aware to avoid node specific logic
export class StateManager {
filesMap = new Map<string, File>()
pathsSet: Set<string> = new Set()
collectingPromise: CollectingPromise | undefined = undefined
idMap = new Map<string, Task>()
taskFileMap = new WeakMap<Task, File>()
errorsSet = new Set<unknown>()
processTimeoutCauses = new Set<string>()
catchError(err: unknown, type: string): void {
if (isAggregateError(err))
return err.errors.forEach(error => this.catchError(error, type));
(err as ErrorWithDiff).type = type
this.errorsSet.add(err)
}
clearErrors() {
this.errorsSet.clear()
}
getUnhandledErrors() {
return Array.from(this.errorsSet.values())
}
addProcessTimeoutCause(cause: string) {
this.processTimeoutCauses.add(cause)
}
getProcessTimeoutCauses() {
return Array.from(this.processTimeoutCauses.values())
}
getPaths() {
return Array.from(this.pathsSet)
}
getFiles(keys?: string[]): File[] {
if (keys)
return keys.map(key => this.filesMap.get(key)!).filter(Boolean)
return Array.from(this.filesMap.values())
}
getFilepaths(): string[] {
return Array.from(this.filesMap.keys())
}
getFailedFilepaths() {
return this.getFiles()
.filter(i => i.result?.state === 'fail')
.map(i => i.filepath)
}
collectPaths(paths: string[] = []) {
paths.forEach((path) => {
this.pathsSet.add(path)
})
}
collectFiles(files: File[] = []) {
files.forEach((file) => {
this.filesMap.set(file.filepath, file)
this.updateId(file)
})
}
clearFiles(paths: string[] = []) {
paths.forEach((path) => {
this.filesMap.delete(path)
})
}
updateId(task: Task) {
if (this.idMap.get(task.id) === task)
return
this.idMap.set(task.id, task)
if (task.type === 'suite') {
task.tasks.forEach((task) => {
this.updateId(task)
})
}
}
updateTasks(packs: TaskResultPack[]) {
for (const [id, result] of packs) {
if (this.idMap.has(id))
this.idMap.get(id)!.result = result
}
}
updateUserLog(log: UserConsoleLog) {
const task = log.taskId && this.idMap.get(log.taskId)
if (task) {
if (!task.logs)
task.logs = []
task.logs.push(log)
}
}
}