1
1
import { format , isObject , objDisplay , objectAttr } from '@vitest/utils'
2
+ import { parseSingleStack } from '@vitest/utils/source-map'
2
3
import type { Custom , CustomAPI , File , Fixtures , RunMode , Suite , SuiteAPI , SuiteCollector , SuiteFactory , SuiteHooks , Task , TaskCustomOptions , Test , TestAPI , TestFunction , TestOptions } from './types'
3
4
import type { VitestRunner } from './types/runner'
4
5
import { createChainable } from './utils/chain'
@@ -25,19 +26,25 @@ export const it = test
25
26
26
27
let runner : VitestRunner
27
28
let defaultSuite : SuiteCollector
29
+ let currentTestFilepath : string
28
30
29
31
export function getDefaultSuite ( ) {
30
32
return defaultSuite
31
33
}
32
34
35
+ export function getTestFilepath ( ) {
36
+ return currentTestFilepath
37
+ }
38
+
33
39
export function getRunner ( ) {
34
40
return runner
35
41
}
36
42
37
- export function clearCollectorContext ( currentRunner : VitestRunner ) {
43
+ export function clearCollectorContext ( filepath : string , currentRunner : VitestRunner ) {
38
44
if ( ! defaultSuite )
39
45
defaultSuite = currentRunner . config . sequence . shuffle ? suite . shuffle ( '' ) : currentRunner . config . sequence . concurrent ? suite . concurrent ( '' ) : suite ( '' )
40
46
runner = currentRunner
47
+ currentTestFilepath = filepath
41
48
collectorContext . tasks . length = 0
42
49
defaultSuite . clear ( )
43
50
collectorContext . currentSuite = defaultSuite
@@ -103,7 +110,7 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m
103
110
104
111
let suite : Suite
105
112
106
- initSuite ( )
113
+ initSuite ( true )
107
114
108
115
const task = function ( name = '' , options : TaskCustomOptions = { } ) {
109
116
const task : Custom = {
@@ -140,6 +147,17 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m
140
147
) )
141
148
}
142
149
150
+ if ( runner . config . includeTaskLocation ) {
151
+ const limit = Error . stackTraceLimit
152
+ // custom can be called from any place, let's assume the limit is 10 stacks
153
+ Error . stackTraceLimit = 10
154
+ const error = new Error ( 'stacktrace' ) . stack !
155
+ Error . stackTraceLimit = limit
156
+ const stack = findStackTrace ( error )
157
+ if ( stack )
158
+ task . location = stack
159
+ }
160
+
143
161
tasks . push ( task )
144
162
return task
145
163
}
@@ -183,7 +201,7 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m
183
201
getHooks ( suite ) [ name ] . push ( ...fn as any )
184
202
}
185
203
186
- function initSuite ( ) {
204
+ function initSuite ( includeLocation : boolean ) {
187
205
if ( typeof suiteOptions === 'number' )
188
206
suiteOptions = { timeout : suiteOptions }
189
207
@@ -199,13 +217,27 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m
199
217
projectName : '' ,
200
218
}
201
219
220
+ if ( runner && includeLocation && runner . config . includeTaskLocation ) {
221
+ const limit = Error . stackTraceLimit
222
+ Error . stackTraceLimit = 5
223
+ const error = new Error ( 'stacktrace' ) . stack !
224
+ Error . stackTraceLimit = limit
225
+ const stack = parseSingleStack ( error . split ( '\n' ) [ 5 ] )
226
+ if ( stack ) {
227
+ suite . location = {
228
+ line : stack . line ,
229
+ column : stack . column ,
230
+ }
231
+ }
232
+ }
233
+
202
234
setHooks ( suite , createSuiteHooks ( ) )
203
235
}
204
236
205
237
function clear ( ) {
206
238
tasks . length = 0
207
239
factoryQueue . length = 0
208
- initSuite ( )
240
+ initSuite ( false )
209
241
}
210
242
211
243
async function collect ( file ?: File ) {
@@ -397,3 +429,18 @@ function formatTemplateString(cases: any[], args: any[]): any[] {
397
429
}
398
430
return res
399
431
}
432
+
433
+ function findStackTrace ( error : string ) {
434
+ // first line is the error message
435
+ // and the first 3 stacks are always from the collector
436
+ const lines = error . split ( '\n' ) . slice ( 4 )
437
+ for ( const line of lines ) {
438
+ const stack = parseSingleStack ( line )
439
+ if ( stack && stack . file === getTestFilepath ( ) ) {
440
+ return {
441
+ line : stack . line ,
442
+ column : stack . column ,
443
+ }
444
+ }
445
+ }
446
+ }
0 commit comments