163 lines
3.8 KiB
TypeScript

import type { RunnerTask, RunnerTestSuite } from 'vitest'
export function isSuite(task: RunnerTask): task is RunnerTestSuite {
return Object.hasOwn(task, 'tasks')
}
export function isTaskDone(task: RunnerTask) {
const state = task.result?.state
const mode = task.mode
return state === 'pass' || state === 'fail' || state === 'skip' || mode === 'skip' || mode === 'todo'
}
export function caseInsensitiveMatch(target: string, str2: string) {
if (typeof target !== 'string' || typeof str2 !== 'string') {
return false
}
return target.toLowerCase().includes(str2.toLowerCase())
}
export function formatTime(time: number): string {
if (time > 1000) {
return `${(time / 1000).toFixed(2)}s`
}
return `${Math.round(time)}ms`
}
export function formatPreciseTime(time: number): string {
if (time > 1000) {
return `${(time / 1000).toFixed(2)}s`
}
return `${time.toFixed(2)}ms`
}
export interface ModuleLabelItem {
id: string
raw: string
splits: string[]
candidate: string
finished: boolean
}
export function calcExternalLabels(
labels: ModuleLabelItem[],
): Map<string, string> {
const result: Map<string, string> = new Map()
const splitMap: Map<string, number[]> = new Map()
const firsts: number[] = []
while (true) {
let finishedCount = 0
labels.forEach((label, i) => {
const { splits, finished } = label
// record the candidate as final label text when label is marked finished
if (finished) {
finishedCount++
const { raw, candidate } = label
result.set(raw, candidate)
return
}
if (splits.length === 0) {
label.finished = true
return
}
const head = splits[0]
if (splitMap.has(head)) {
label.candidate += label.candidate === '' ? head : `/${head}`
splitMap.get(head)?.push(i)
splits.shift()
}
else {
splitMap.set(head, [i])
// record the index of the label where the head first appears
firsts.push(i)
}
})
// update candidate of label which index appears in first array
firsts.forEach((i) => {
const label = labels[i]
const head = label.splits.shift()
label.candidate += label.candidate === '' ? head : `/${head}`
})
splitMap.forEach((value) => {
if (value.length === 1) {
const index = value[0]
labels[index].finished = true
}
})
splitMap.clear()
firsts.length = 0
if (finishedCount === labels.length) {
break
}
}
return result
}
export function createModuleLabelItem(module: string): ModuleLabelItem {
let raw = module
if (raw.includes('/node_modules/')) {
raw = module.split(/\/node_modules\//g).pop()!
}
const splits = raw.split(/\//g)
return {
raw,
splits,
candidate: '',
finished: false,
id: module,
}
}
export function getExternalModuleName(module: string) {
const label = createModuleLabelItem(module)
return label.raw
}
export function getImportDurationType(duration: number) {
if (duration >= 500) {
return 'danger'
}
if (duration >= 100) {
return 'warning'
}
}
export function getDurationClass(duration: number) {
const type = getImportDurationType(duration)
if (type === 'danger') {
return 'text-red'
}
if (type === 'warning') {
return 'text-orange'
}
}
export function getProjectNameColor(name: string | undefined) {
if (!name) {
return ''
}
const index = name
.split('')
.reduce((acc, v, idx) => acc + v.charCodeAt(0) + idx, 0)
const colors = ['yellow', 'cyan', 'green', 'magenta']
return colors[index % colors.length]
}
export function getProjectTextColor(color: string) {
switch (color) {
case 'blue':
case 'green':
case 'magenta':
case 'black':
case 'red':
return 'white'
case 'yellow':
case 'cyan':
case 'white':
default:
return 'black'
}
}