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

`}

`