fix(ui): fix missing source code in html reporter metadata when mergi… · vitest-dev/vitest@4f7c267 (original) (raw)
1
``
`-
import type { BirpcReturn } from 'birpc'
`
2
1
`import type {
`
3
2
`ModuleGraphData,
`
4
3
`RunnerTestFile,
`
5
4
`SerializedRootConfig,
`
6
``
`-
WebSocketEvents,
`
7
``
`-
WebSocketHandlers,
`
8
5
`} from 'vitest'
`
9
``
`-
import type { VitestClient } from './ws'
`
``
6
`+
import type { VitestClient, VitestClientRpc } from './ws'
`
10
7
`import { decompressSync, strFromU8 } from 'fflate'
`
11
8
`import { parse } from 'flatted'
`
12
9
`import { reactive } from 'vue'
`
13
10
`import { StateManager } from './state'
`
14
11
``
15
``
`-
interface HTMLReportMetadata {
`
16
``
`-
paths: string[]
`
``
12
`+
export interface HTMLReportMetadata {
`
17
13
`files: RunnerTestFile[]
`
18
14
`config: SerializedRootConfig
`
19
15
`moduleGraph: Record<string, Record<string, ModuleGraphData>>
`
20
16
`unhandledErrors: unknown[]
`
21
``
`-
// filename -> source
`
22
``
`-
sources: Record<string, string>
`
``
17
`+
testModules: {
`
``
18
`+
projectName: string
`
``
19
`+
moduleId: string
`
``
20
`+
relativeModuleId: string
`
``
21
`+
}[]
`
``
22
`+
sourceCode: {
`
``
23
`+
codeTable: string[]
`
``
24
`+
testModules: { [projectName: string]: { [relativeModuleId: string]: number } }
`
``
25
`+
}
`
23
26
`}
`
24
27
``
25
``
`-
const noop: any = () => {}
`
26
``
`-
const asyncNoop: any = () => Promise.resolve()
`
27
``
-
28
``
`-
export function createStaticClient(): VitestClient {
`
29
``
`-
const ctx = reactive({
`
30
``
`-
state: new StateManager(),
`
31
``
`-
waitForConnection,
`
32
``
`-
reconnect,
`
33
``
`-
ws: new EventTarget(),
`
34
``
`-
}) as VitestClient
`
35
``
-
36
``
`-
ctx.state.filesMap = reactive(ctx.state.filesMap)
`
37
``
`-
ctx.state.idMap = reactive(ctx.state.idMap)
`
38
``
-
39
``
`-
let metadata!: HTMLReportMetadata
`
``
28
`+
function deserializeReportMetadata(metadata: HTMLReportMetadata) {
`
``
29
`+
const sourceCodes: { [moduleId: string]: string } = {}
`
``
30
`+
for (const testModule of metadata.testModules) {
`
``
31
`+
const codeIndex = metadata.sourceCode.testModules[testModule.projectName]?.[testModule.relativeModuleId]
`
``
32
`+
if (codeIndex != null) {
`
``
33
`+
sourceCodes[testModule.moduleId] = metadata.sourceCode.codeTable[codeIndex]
`
``
34
`+
}
`
``
35
`+
}
`
40
36
``
41
``
`-
const rpc = {
`
42
``
`-
getFiles: () => {
`
``
37
`+
const rpc: VitestClientRpc = {
`
``
38
`+
getFiles: async () => {
`
43
39
`return metadata.files
`
44
40
`},
`
45
``
`-
getPaths: () => {
`
46
``
`-
return metadata.paths
`
47
``
`-
},
`
48
``
`-
getConfig: () => {
`
``
41
`+
getConfig: async () => {
`
49
42
`return metadata.config
`
50
43
`},
`
51
44
`getModuleGraph: async (projectName, id) => {
`
52
45
`return metadata.moduleGraph[projectName]?.[id]
`
53
46
`},
`
54
``
`-
getUnhandledErrors: () => {
`
``
47
`+
getUnhandledErrors: async () => {
`
55
48
`return metadata.unhandledErrors
`
56
49
`},
`
57
``
`-
getExternalResult: asyncNoop,
`
58
``
`-
getTransformResult: asyncNoop,
`
59
``
`-
onDone: noop,
`
60
``
`-
writeFile: asyncNoop,
`
61
``
`-
rerun: asyncNoop,
`
62
``
`-
rerunTask: asyncNoop,
`
63
``
`-
updateSnapshot: asyncNoop,
`
64
``
`-
resolveSnapshotPath: asyncNoop,
`
65
``
`-
snapshotSaved: asyncNoop,
`
66
``
`-
onAfterSuiteRun: asyncNoop,
`
67
``
`-
onCancel: asyncNoop,
`
68
``
`-
getCountOfFailedTests: () => 0,
`
69
``
`-
sendLog: asyncNoop,
`
70
``
`-
resolveSnapshotRawPath: asyncNoop,
`
71
``
`-
readSnapshotFile: asyncNoop,
`
72
``
`-
saveSnapshotFile: asyncNoop,
`
73
``
`-
readTestFile: async (id: string) => {
`
74
``
`-
return metadata.sources[id]
`
``
50
`+
readTestFile: async (id) => {
`
``
51
`+
return sourceCodes[id]
`
75
52
`},
`
76
``
`-
removeSnapshotFile: asyncNoop,
`
77
``
`-
onUnhandledError: noop,
`
78
``
`-
saveTestFile: asyncNoop,
`
79
``
`-
getProvidedContext: () => ({}),
`
80
``
`-
getTestFiles: asyncNoop,
`
81
``
`-
} as Omit<WebSocketHandlers, 'getResolvedProjectLabels'>
`
82
``
-
83
``
`-
ctx.rpc = rpc as any as BirpcReturn<WebSocketHandlers, WebSocketEvents>
`
``
53
`+
getPaths: async () => [],
`
``
54
`+
getResolvedProjectLabels: async () => [],
`
``
55
`+
getExternalResult: async () => undefined,
`
``
56
`+
getTransformResult: async () => undefined,
`
``
57
`+
rerun: async () => {},
`
``
58
`+
rerunTask: async () => {},
`
``
59
`+
updateSnapshot: async () => {},
`
``
60
`+
saveTestFile: async () => {},
`
``
61
`+
getTestFiles: async () => [],
`
``
62
`+
}
`
``
63
`+
return rpc
`
``
64
`+
}
`
84
65
``
85
``
`-
const openPromise = Promise.resolve()
`
``
66
`+
export function createStaticClient(): VitestClient {
`
``
67
`+
const ctx = reactive({
`
``
68
`+
ws: new EventTarget() as WebSocket,
`
``
69
`+
state: new StateManager(),
`
``
70
`+
rpc: undefined!,
`
``
71
`+
reconnect: () => registerMetadata(),
`
``
72
`+
waitForConnection: async () => {},
`
``
73
`+
})
`
86
74
``
87
``
`-
function reconnect() {
`
88
``
`-
registerMetadata()
`
89
``
`-
}
`
``
75
`+
ctx.state.filesMap = reactive(ctx.state.filesMap)
`
``
76
`+
ctx.state.idMap = reactive(ctx.state.idMap)
`
90
77
``
91
78
`async function registerMetadata() {
`
92
79
`const res = await fetch(window.METADATA_PATH!)
`
93
80
`const content = new Uint8Array(await res.arrayBuffer())
`
94
``
-
``
81
`+
let metadata: HTMLReportMetadata
`
95
82
`// Check for gzip magic numbers (0x1f 0x8b) to determine if content is compressed.
`
96
83
`// This handles cases where a static server incorrectly sets Content-Encoding: gzip
`
97
84
`// for .gz files, causing the browser to auto-decompress before we process the raw gzip data.
`
98
85
`if (content.length >= 2 && content[0] === 0x1F && content[1] === 0x8B) {
`
99
86
`const decompressed = strFromU8(decompressSync(content))
`
100
``
`-
metadata = parse(decompressed) as HTMLReportMetadata
`
``
87
`+
metadata = parse(decompressed)
`
101
88
`}
`
102
89
`else {
`
103
``
`-
metadata = parse(strFromU8(content)) as HTMLReportMetadata
`
``
90
`+
metadata = parse(strFromU8(content))
`
104
91
`}
`
105
``
`-
const event = new Event('open')
`
106
``
`-
ctx.ws.dispatchEvent(event)
`
``
92
`+
ctx.rpc = deserializeReportMetadata(metadata)
`
``
93
`+
ctx.ws.dispatchEvent(new Event('open'))
`
107
94
`}
`
108
95
``
109
96
`registerMetadata()
`
110
97
``
111
``
`-
function waitForConnection() {
`
112
``
`-
return openPromise
`
113
``
`-
}
`
114
``
-
115
98
`return ctx
`
116
99
`}
`