1
+ import type { File , Test } from '@vitest/runner/types'
2
+ import { rmSync } from 'node:fs'
1
3
import { resolve } from 'node:path'
2
- import { expect , test } from 'vitest'
4
+ import { createFileTask } from '@vitest/runner/utils'
5
+ import { beforeEach , expect , test } from 'vitest'
6
+ import { version } from 'vitest/package.json'
7
+ import { writeBlob } from 'vitest/src/node/reporters/blob.js'
3
8
import { runVitest } from '../../test-utils'
4
9
10
+ // always relative to CWD because it's used only from the CLI,
11
+ // so we need to correctly resolve it here
12
+ const reportsDir = resolve ( './fixtures/merge-reports/.vitest-reports' )
13
+
14
+ beforeEach ( ( ) => {
15
+ rmSync ( reportsDir , { force : true , recursive : true } )
16
+ } )
17
+
5
18
test ( 'merge reports' , async ( ) => {
6
19
await runVitest ( {
7
20
root : './fixtures/merge-reports' ,
8
21
include : [ 'first.test.ts' ] ,
9
22
reporters : [ [ 'blob' , { outputFile : './.vitest-reports/first-run.json' } ] ] ,
10
23
} )
24
+
11
25
await runVitest ( {
12
26
root : './fixtures/merge-reports' ,
13
27
include : [ 'second.test.ts' ] ,
14
28
reporters : [ [ 'blob' , { outputFile : './.vitest-reports/second-run.json' } ] ] ,
15
29
} )
16
30
17
- // always relative to CWD because it's used only from the CLI,
18
- // so we need to correctly resolve it here
19
- const mergeReports = resolve ( './fixtures/merge-reports/.vitest-reports' )
20
-
21
31
const { stdout : reporterDefault , stderr : stderrDefault , exitCode } = await runVitest ( {
22
32
root : './fixtures/merge-reports' ,
23
- mergeReports,
33
+ mergeReports : reportsDir ,
24
34
reporters : [ [ 'default' , { isTTY : false } ] ] ,
25
35
} )
26
36
27
37
expect ( exitCode ) . toBe ( 1 )
28
38
29
- // remove "RUN v{} path" and "Duration" because it's not stable
30
- const stdoutCheck = reporterDefault
31
- . split ( '\n' )
32
- . slice ( 2 , - 3 )
33
- . join ( '\n' )
34
- . replace ( / S t a r t a t [ \w \s : ] + / , 'Start at <time>' )
39
+ const stdoutCheck = trimReporterOutput ( reporterDefault )
35
40
const stderrArr = stderrDefault . split ( '\n' )
36
41
const stderrCheck = [
37
42
...stderrArr . slice ( 4 , 19 ) ,
@@ -76,9 +81,8 @@ test('merge reports', async () => {
76
81
"
77
82
` )
78
83
79
- expect ( stdoutCheck . replace ( / \d + m s / g, '<time>' ) ) . toMatchInlineSnapshot ( `
80
- "
81
- stdout | first.test.ts
84
+ expect ( stdoutCheck ) . toMatchInlineSnapshot ( `
85
+ "stdout | first.test.ts
82
86
global scope
83
87
84
88
stdout | first.test.ts > test 1-1
@@ -105,12 +109,13 @@ test('merge reports', async () => {
105
109
106
110
Test Files 2 failed (2)
107
111
Tests 2 failed | 3 passed (5)
108
- Start at <time>"
112
+ Duration <time> (transform <time>, setup <time>, collect <time>, tests <time>, environment <time>, prepare <time>)
113
+ Per blob <time> <time>"
109
114
` )
110
115
111
116
const { stdout : reporterJson } = await runVitest ( {
112
117
root : './fixtures/merge-reports' ,
113
- mergeReports,
118
+ mergeReports : reportsDir ,
114
119
reporters : [ [ 'json' , { outputFile : /** so it outputs into stdout */ null } ] ] ,
115
120
} )
116
121
@@ -234,3 +239,62 @@ test('merge reports', async () => {
234
239
}
235
240
` )
236
241
} )
242
+
243
+ test ( 'total and merged execution times are shown' , async ( ) => {
244
+ for ( const [ _index , name ] of [ 'first.test.ts' , 'second.test.ts' ] . entries ( ) ) {
245
+ const index = 1 + _index
246
+ const file = createFileTask (
247
+ resolve ( './fixtures/merge-reports' , name ) ,
248
+ resolve ( './fixtures/merge-reports' ) ,
249
+ '' ,
250
+ )
251
+ file . tasks . push ( createTest ( 'some test' , file ) )
252
+
253
+ await writeBlob (
254
+ [ version , [ file ] , [ ] , [ ] , undefined , 1500 * index ] ,
255
+ resolve ( `./fixtures/merge-reports/.vitest-reports/blob-${ index } -2.json` ) ,
256
+ )
257
+ }
258
+
259
+ const { stdout } = await runVitest ( {
260
+ root : resolve ( './fixtures/merge-reports' ) ,
261
+ mergeReports : resolve ( './fixtures/merge-reports/.vitest-reports' ) ,
262
+ reporters : [ [ 'default' , { isTTY : false } ] ] ,
263
+ } )
264
+
265
+ expect ( stdout ) . toContain ( '✓ first.test.ts (1 test)' )
266
+ expect ( stdout ) . toContain ( '✓ second.test.ts (1 test)' )
267
+
268
+ expect ( stdout ) . toContain ( 'Duration 4.50s' )
269
+ expect ( stdout ) . toContain ( 'Per blob 1.50s 3.00s' )
270
+ } )
271
+
272
+ function trimReporterOutput ( report : string ) {
273
+ const rows = report
274
+ . replace ( / \d + m s / g, '<time>' )
275
+ . replace ( / \d + \. \d + s / g, '<time>' )
276
+ . split ( '\n' )
277
+
278
+ // Trim start and end, capture just rendered tree
279
+ rows . splice ( 0 , 1 + rows . findIndex ( row => row . includes ( 'RUN v' ) ) )
280
+ rows . splice ( rows . findIndex ( row => row . includes ( 'Start at' ) ) , 1 )
281
+
282
+ return rows . join ( '\n' ) . trim ( )
283
+ }
284
+
285
+ function createTest ( name : string , file : File ) : Test {
286
+ file . result = { state : 'pass' }
287
+
288
+ return {
289
+ type : 'test' ,
290
+ name,
291
+ id : `${ file . id } _0` ,
292
+ mode : 'run' ,
293
+ file,
294
+ suite : file ,
295
+ timeout : 0 ,
296
+ result : { state : 'pass' } ,
297
+ meta : { } ,
298
+ context : { } as any ,
299
+ }
300
+ }
0 commit comments