11import { format , isObject , objDisplay , objectAttr } from '@vitest/utils'
2+ import { parseSingleStack } from '@vitest/utils/source-map'
23import type { Custom , CustomAPI , File , Fixtures , RunMode , Suite , SuiteAPI , SuiteCollector , SuiteFactory , SuiteHooks , Task , TaskCustomOptions , Test , TestAPI , TestFunction , TestOptions } from './types'
34import type { VitestRunner } from './types/runner'
45import { createChainable } from './utils/chain'
@@ -25,19 +26,25 @@ export const it = test
2526
2627let runner : VitestRunner
2728let defaultSuite : SuiteCollector
29+ let currentTestFilepath : string
2830
2931export function getDefaultSuite ( ) {
3032 return defaultSuite
3133}
3234
35+ export function getTestFilepath ( ) {
36+ return currentTestFilepath
37+ }
38+
3339export function getRunner ( ) {
3440 return runner
3541}
3642
37- export function clearCollectorContext ( currentRunner : VitestRunner ) {
43+ export function clearCollectorContext ( filepath : string , currentRunner : VitestRunner ) {
3844 if ( ! defaultSuite )
3945 defaultSuite = currentRunner . config . sequence . shuffle ? suite . shuffle ( '' ) : currentRunner . config . sequence . concurrent ? suite . concurrent ( '' ) : suite ( '' )
4046 runner = currentRunner
47+ currentTestFilepath = filepath
4148 collectorContext . tasks . length = 0
4249 defaultSuite . clear ( )
4350 collectorContext . currentSuite = defaultSuite
@@ -103,7 +110,7 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m
103110
104111 let suite : Suite
105112
106- initSuite ( )
113+ initSuite ( true )
107114
108115 const task = function ( name = '' , options : TaskCustomOptions = { } ) {
109116 const task : Custom = {
@@ -140,6 +147,17 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m
140147 ) )
141148 }
142149
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+
143161 tasks . push ( task )
144162 return task
145163 }
@@ -183,7 +201,7 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m
183201 getHooks ( suite ) [ name ] . push ( ...fn as any )
184202 }
185203
186- function initSuite ( ) {
204+ function initSuite ( includeLocation : boolean ) {
187205 if ( typeof suiteOptions === 'number' )
188206 suiteOptions = { timeout : suiteOptions }
189207
@@ -199,13 +217,27 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m
199217 projectName : '' ,
200218 }
201219
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+
202234 setHooks ( suite , createSuiteHooks ( ) )
203235 }
204236
205237 function clear ( ) {
206238 tasks . length = 0
207239 factoryQueue . length = 0
208- initSuite ( )
240+ initSuite ( false )
209241 }
210242
211243 async function collect ( file ?: File ) {
@@ -397,3 +429,18 @@ function formatTemplateString(cases: any[], args: any[]): any[] {
397429 }
398430 return res
399431}
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