1
1
<script setup lang="ts">
2
- import type { Task , TestAttachment } from ' @vitest/runner'
2
+ import type { Task } from ' @vitest/runner'
3
3
import type CodeMirror from ' codemirror'
4
4
import type { ErrorWithDiff , File , TestAnnotation , TestError } from ' vitest'
5
5
import { createTooltip , destroyTooltip } from ' floating-vue'
6
+ import { getAttachmentUrl , sanitizeFilePath } from ' ~/composables/attachments'
6
7
import { client , isReport } from ' ~/composables/client'
7
8
import { finished } from ' ~/composables/client/state'
8
9
import { codemirrorRef } from ' ~/composables/codemirror'
9
10
import { openInEditor } from ' ~/composables/error'
10
- import { lineNumber } from ' ~/composables/params'
11
+ import { columnNumber , lineNumber } from ' ~/composables/params'
11
12
12
13
const props = defineProps <{
13
14
file? : File
@@ -56,12 +57,12 @@ watch(
56
57
{ immediate: true },
57
58
)
58
59
59
- watch (() => [loading .value , saving .value , props .file , lineNumber .value ] as const , ([loadingFile , s , _ , l ]) => {
60
+ watch (() => [loading .value , saving .value , props .file , lineNumber .value , columnNumber . value ] as const , ([loadingFile , s , _ , l , c ]) => {
60
61
if (! loadingFile && ! s ) {
61
62
if (l != null ) {
62
63
nextTick (() => {
63
64
const cp = currentPosition .value
64
- const line = cp ?? { line: l ?? 0 , ch: 0 }
65
+ const line = cp ?? { line: ( l ?? 1 ) - 1 , ch: c ?? 0 }
65
66
// restore caret position: the watchDebounced below will use old value
66
67
if (cp ) {
67
68
currentPosition .value = undefined
@@ -155,7 +156,7 @@ function createErrorElement(e: ErrorWithDiff) {
155
156
div .className = ' op80 flex gap-x-2 items-center'
156
157
const pre = document .createElement (' pre' )
157
158
pre .className = ' c-red-600 dark:c-red-400'
158
- pre .textContent = ` ${' ' .repeat (stack .column )}^ ${e ?. nameStr || e .name }: ${
159
+ pre .textContent = ` ${' ' .repeat (stack .column )}^ ${e .name }: ${
159
160
e ?.message || ' '
160
161
} `
161
162
div .appendChild (pre )
@@ -184,7 +185,6 @@ function createErrorElement(e: ErrorWithDiff) {
184
185
185
186
function createAnnotationElement(annotation : TestAnnotation ) {
186
187
if (! annotation .location ) {
187
- // TODO(v4): print unknown annotations somewhere
188
188
return
189
189
}
190
190
@@ -222,9 +222,8 @@ function createAnnotationElement(annotation: TestAnnotation) {
222
222
if (attachment .contentType ?.startsWith (' image/' )) {
223
223
const link = document .createElement (' a' )
224
224
const img = document .createElement (' img' )
225
- img .classList .add (' mt-3' , ' inline-block' )
226
- img .width = 600
227
- img .width = 400
225
+ link .classList .add (' inline-block' , ' mt-3' )
226
+ link .style .maxWidth = ' 50vw'
228
227
const potentialUrl = attachment .path || attachment .body
229
228
if (typeof potentialUrl === ' string' && (potentialUrl .startsWith (' http://' ) || potentialUrl .startsWith (' https://' ))) {
230
229
img .setAttribute (' src' , potentialUrl )
@@ -241,7 +240,7 @@ function createAnnotationElement(annotation: TestAnnotation) {
241
240
else {
242
241
const download = document .createElement (' a' )
243
242
download .href = getAttachmentUrl (attachment )
244
- download .download = sanitizeFilePath (annotation .message )
243
+ download .download = sanitizeFilePath (annotation .message , attachment . contentType )
245
244
download .classList .add (' flex' , ' w-min' , ' gap-2' , ' items-center' , ' font-sans' , ' underline' , ' cursor-pointer' )
246
245
const icon = document .createElement (' div' )
247
246
icon .classList .add (' i-carbon:download' , ' block' )
@@ -254,19 +253,6 @@ function createAnnotationElement(annotation: TestAnnotation) {
254
253
widgets .push (codemirrorRef .value ! .addLineWidget (line - 1 , notice ))
255
254
}
256
255
257
- function getAttachmentUrl(attachment : TestAttachment ) {
258
- // html reporter always saves files into /data/ folder
259
- if (isReport ) {
260
- return ` /data/${attachment .path } `
261
- }
262
- const contentType = attachment .contentType ?? ' application/octet-stream'
263
- if (attachment .path ) {
264
- return ` /__vitest_attachment__?path=${encodeURIComponent (attachment .path )}&contentType=${contentType }&token=${(window as any ).VITEST_API_TOKEN } `
265
- }
266
- // attachment.body is always a string outside of the test frame
267
- return ` data:${contentType };base64,${attachment .body } `
268
- }
269
-
270
256
const { pause, resume } = watch (
271
257
[codemirrorRef , errors , annotations , finished ] as const ,
272
258
([cmValue , errors , annotations , end ]) => {
@@ -389,11 +375,6 @@ async function onSave(content: string) {
389
375
390
376
// we need to remove listeners before unmounting the component: the watcher will not be called
391
377
onBeforeUnmount (clearListeners )
392
-
393
- function sanitizeFilePath(s : string ): string {
394
- // eslint-disable-next-line no-control-regex
395
- return s .replace (/ [\x00 -\x2C \x2E\x2F \x3A -\x40\x5B -\x60\x7B -\x7F ] + / g , ' -' )
396
- }
397
378
</script >
398
379
399
380
<template >
0 commit comments