@@ -31,29 +31,21 @@ export function clearCurrentStepFile() {
31
31
const addStep = async ( step , fn ) => {
32
32
const config = await getConfig ( )
33
33
const avoidDuplicateSteps = config . get ( 'gherkin' , { } ) . avoidDuplicateSteps || false
34
- const stack = new Error ( ) . stack
35
34
if ( avoidDuplicateSteps && steps [ step ] ) {
36
35
throw new Error ( `Step '${ step } ' is already defined` )
37
36
}
38
37
steps [ step ] = fn
39
38
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
+
47
46
fn . line = `${ relativePath } :3:1`
48
47
} 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'
57
49
}
58
50
}
59
51
@@ -75,7 +67,7 @@ const matchStep = step => {
75
67
const res = expression . match ( step )
76
68
if ( res ) {
77
69
const fn = steps [ stepName ]
78
- fn . params = res . map ( arg => arg . getValue ( ) )
70
+ fn . params = res . map ( arg => arg . getValue ( null ) )
79
71
return fn
80
72
}
81
73
}
@@ -101,11 +93,57 @@ const buildParameterType = ({ name, regexp, transformer, useForSnippets, preferF
101
93
return new ParameterType ( name , regexp , null , transformer , useForSnippets , preferForRegexpMatch )
102
94
}
103
95
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
+
104
142
export {
105
- addStep as Given ,
106
- addStep as When ,
107
- addStep as Then ,
108
- addStep as And ,
143
+ Given ,
144
+ When ,
145
+ Then ,
146
+ And ,
109
147
matchStep ,
110
148
getSteps ,
111
149
clearSteps ,
0 commit comments