mirror of
https://github.com/vitest-dev/vitest.git
synced 2025-12-08 18:26:03 +00:00
156 lines
4.2 KiB
Vue
156 lines
4.2 KiB
Vue
<script setup lang="ts">
|
|
import type { RunnerTask, RunnerTestFile, RunnerTestSuite } from 'vitest'
|
|
import { computed } from 'vue'
|
|
import { browserState, config } from '~/composables/client'
|
|
import { isDark } from '~/composables/dark'
|
|
import { mapLeveledTaskStacks } from '~/composables/error'
|
|
import { openScreenshot, useScreenshot } from '~/composables/screenshot'
|
|
import IconButton from '../IconButton.vue'
|
|
import Modal from '../Modal.vue'
|
|
import ScreenshotError from './ScreenshotError.vue'
|
|
import ViewReportError from './ViewReportError.vue'
|
|
|
|
const props = defineProps<{
|
|
file: RunnerTestFile
|
|
}>()
|
|
|
|
type LeveledTask = RunnerTask & {
|
|
level: number
|
|
}
|
|
|
|
function collectFailed(task: RunnerTask, level: number): LeveledTask[] {
|
|
if (task.result?.state !== 'fail') {
|
|
return []
|
|
}
|
|
|
|
if (task.type === 'test') {
|
|
return [{ ...task, level }]
|
|
}
|
|
else {
|
|
return [
|
|
{ ...task, level },
|
|
...task.tasks.flatMap(t => collectFailed(t, level + 1)),
|
|
]
|
|
}
|
|
}
|
|
|
|
const failed = computed(() => {
|
|
const file = props.file
|
|
const failedFlatMap = file.tasks?.flatMap(t => collectFailed(t, 0)) ?? []
|
|
const result = file.result
|
|
const fileError = result?.errors?.[0]
|
|
// we must check also if the test cannot compile
|
|
if (fileError) {
|
|
// create a dummy one
|
|
const fileErrorTask: RunnerTestSuite & { level: number } = {
|
|
id: file!.id,
|
|
file: file!,
|
|
name: file!.name,
|
|
level: 0,
|
|
type: 'suite',
|
|
mode: 'run',
|
|
meta: {},
|
|
tasks: [],
|
|
result,
|
|
}
|
|
failedFlatMap.unshift(fileErrorTask)
|
|
}
|
|
return failedFlatMap.length > 0
|
|
? mapLeveledTaskStacks(isDark.value, failedFlatMap)
|
|
: failedFlatMap
|
|
})
|
|
|
|
const {
|
|
currentTask,
|
|
showScreenshot,
|
|
showScreenshotModal,
|
|
currentScreenshotUrl,
|
|
} = useScreenshot()
|
|
</script>
|
|
|
|
<template>
|
|
<div h-full class="scrolls">
|
|
<template v-if="failed.length">
|
|
<div v-for="task of failed" :id="task.id" :key="task.id">
|
|
<div
|
|
bg="red-500/10"
|
|
text="red-500 sm"
|
|
p="x3 y2"
|
|
m-2
|
|
rounded
|
|
:style="{
|
|
'margin-left': `${
|
|
task.result?.htmlError ? 0.5 : 2 * (task as LeveledTask).level + 0.5
|
|
}rem`,
|
|
}"
|
|
>
|
|
<div flex="~ gap-2 items-center">
|
|
<span>{{ task.name }}</span>
|
|
<template v-if="browserState && task.meta?.failScreenshotPath">
|
|
<IconButton
|
|
v-tooltip.bottom="'View screenshot error'"
|
|
class="!op-100"
|
|
icon="i-carbon:image"
|
|
title="View screenshot error"
|
|
@click="showScreenshotModal(task)"
|
|
/>
|
|
<IconButton
|
|
v-tooltip.bottom="'Open screenshot error in editor'"
|
|
class="!op-100"
|
|
icon="i-carbon:image-reference"
|
|
title="Open screenshot error in editor"
|
|
@click="openScreenshot(task)"
|
|
/>
|
|
</template>
|
|
</div>
|
|
<div
|
|
v-if="task.result?.htmlError"
|
|
class="scrolls scrolls-rounded task-error"
|
|
data-testid="task-error"
|
|
>
|
|
<pre v-html="task.result.htmlError" />
|
|
</div>
|
|
<template v-else-if="task.result?.errors">
|
|
<ViewReportError
|
|
v-for="(error, idx) of task.result.errors"
|
|
:key="idx"
|
|
:error="error"
|
|
:filename="file.name"
|
|
:root="config.root"
|
|
:file-id="file.id"
|
|
/>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<template v-else>
|
|
<div bg="green-500/10" text="green-500 sm" p="x4 y2" m-2 rounded>
|
|
All tests passed in this file
|
|
</div>
|
|
</template>
|
|
<template v-if="browserState">
|
|
<Modal v-model="showScreenshot" direction="right">
|
|
<template v-if="currentTask">
|
|
<Suspense>
|
|
<ScreenshotError
|
|
:file="currentTask.file.filepath"
|
|
:name="currentTask.name"
|
|
:url="currentScreenshotUrl"
|
|
@close="showScreenshot = false"
|
|
/>
|
|
</Suspense>
|
|
</template>
|
|
</Modal>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.task-error {
|
|
--cm-ttc-c-thumb: #ccc;
|
|
}
|
|
html.dark .task-error {
|
|
--cm-ttc-c-thumb: #444;
|
|
}
|
|
</style>
|