@@ -31,29 +31,21 @@ export function clearCurrentStepFile() {
3131const addStep = async ( step , fn ) => {
3232 const config = await getConfig ( )
3333 const avoidDuplicateSteps = config . get ( 'gherkin' , { } ) . avoidDuplicateSteps || false
34- const stack = new Error ( ) . stack
3534 if ( avoidDuplicateSteps && steps [ step ] ) {
3635 throw new Error ( `Step '${ step } ' is already defined` )
3736 }
3837 steps [ step ] = fn
3938
40- // Try to get file location from current loading context
41- if ( currentStepFile || global . __currentStepDefinitionFile ) {
42- let sourceFile = currentStepFile || global . __currentStepDefinitionFile
43- let relativePath = sourceFile . replace ( global . codecept_dir + '/' , '' )
44- // Remove './features/' prefix to match expected test format
45- relativePath = relativePath . replace ( / ^ \. \/ f e a t u r e s \/ / , '' )
46- // Store the file context immediately
39+ // Use the current step file context if available (fallback for old usage)
40+ if ( currentStepFile ) {
41+ let relativePath = currentStepFile
42+
43+ // Remove any leading './' and keep step_definitions/ path
44+ relativePath = relativePath . replace ( / ^ \. \/ / , '' ) . replace ( / ^ . * \/ (? = s t e p _ d e f i n i t i o n s ) / , '' )
45+
4746 fn . line = `${ relativePath } :3:1`
4847 } else {
49- // Fallback to stack trace method
50- fn . line = stack && stack . split ( '\n' ) [ STACK_POSITION ]
51- if ( fn . line ) {
52- fn . line = fn . line
53- . trim ( )
54- . replace ( / ^ a t ( .* ?) \( / , '(' )
55- . replace ( global . codecept_dir || '' , '.' )
56- }
48+ fn . line = 'unknown_file:1:1'
5749 }
5850}
5951
@@ -75,7 +67,7 @@ const matchStep = step => {
7567 const res = expression . match ( step )
7668 if ( res ) {
7769 const fn = steps [ stepName ]
78- fn . params = res . map ( arg => arg . getValue ( ) )
70+ fn . params = res . map ( arg => arg . getValue ( null ) )
7971 return fn
8072 }
8173 }
@@ -101,11 +93,57 @@ const buildParameterType = ({ name, regexp, transformer, useForSnippets, preferF
10193 return new ParameterType ( name , regexp , null , transformer , useForSnippets , preferForRegexpMatch )
10294}
10395
96+ // Create wrapper functions that capture the call context
97+ const createStepFunction = ( stepType ) => {
98+ return ( step , fn ) => {
99+ // Capture the stack trace at the point where Given/When/Then is called
100+ const callStack = new Error ( ) . stack
101+
102+ // Find the caller (step definition file) in the stack
103+ let callerInfo = 'unknown_file:1:1'
104+ if ( callStack ) {
105+ const stackLines = callStack . split ( '\n' )
106+ for ( let i = 1 ; i < stackLines . length ; i ++ ) {
107+ const line = stackLines [ i ]
108+ if ( line . includes ( 'step_definitions' ) && ( line . includes ( '.js' ) || line . includes ( '.mjs' ) ) ) {
109+ // Extract file path and use line 3:1 as consistent reference (import line)
110+ const match = line . match ( / f i l e : \/ \/ .* \/ ( s t e p _ d e f i n i t i o n s \/ [ ^ : ] + ) : ( \d + ) : ( \d + ) / )
111+ if ( match ) {
112+ callerInfo = `${ match [ 1 ] } :3:1` // Use line 3:1 consistently (import line)
113+ break
114+ }
115+ }
116+ }
117+ }
118+
119+ // Instead of using global currentStepFile, pass the caller info directly to addStep
120+ return addStepWithCaller ( step , fn , callerInfo )
121+ }
122+ }
123+
124+ // New function that accepts caller info directly
125+ const addStepWithCaller = async ( step , fn , callerInfo ) => {
126+ const config = await getConfig ( )
127+ const avoidDuplicateSteps = config . get ( 'gherkin' , { } ) . avoidDuplicateSteps || false
128+ if ( avoidDuplicateSteps && steps [ step ] ) {
129+ throw new Error ( `Step '${ step } ' is already defined` )
130+ }
131+ steps [ step ] = fn
132+
133+ // Use the caller info passed directly
134+ fn . line = callerInfo
135+ }
136+
137+ const Given = createStepFunction ( 'Given' )
138+ const When = createStepFunction ( 'When' )
139+ const Then = createStepFunction ( 'Then' )
140+ const And = createStepFunction ( 'And' )
141+
104142export {
105- addStep as Given ,
106- addStep as When ,
107- addStep as Then ,
108- addStep as And ,
143+ Given ,
144+ When ,
145+ Then ,
146+ And ,
109147 matchStep ,
110148 getSteps ,
111149 clearSteps ,
0 commit comments