@@ -5,6 +5,7 @@ import assertThrown from '../assert/throws.js'
55import { ucfirst , isAsyncFunction } from '../utils.js'
66import { getInjectedArguments } from './inject.js'
77import { fireHook } from './hooks.js'
8+ import Config from '../config.js'
89
910const injectHook = function ( inject , suite ) {
1011 // Run the hook body inside recorder queue to ensure async parts complete before returning
@@ -59,6 +60,7 @@ function test(test) {
5960 const doneFn = makeDoneCallableOnce ( done )
6061 let testPassed = false
6162 let testFailed = false
63+ let testAfterEmitted = false
6264
6365 // Ensure recorder is running so any steps added inside test function are executed
6466 recorder . startUnlessRunning ( )
@@ -82,7 +84,10 @@ function test(test) {
8284 // Add test.after emission after event listeners have added their operations
8385 process . nextTick ( ( ) => {
8486 recorder . add ( 'fire test.after' , ( ) => {
85- event . emit ( event . test . after , test )
87+ if ( ! testAfterEmitted ) {
88+ testAfterEmitted = true
89+ event . emit ( event . test . after , test )
90+ }
8691 } )
8792 } )
8893 recorder . add ( doneFn )
@@ -95,11 +100,12 @@ function test(test) {
95100 test . err = err
96101 event . emit ( event . test . failed , test , err )
97102 event . emit ( event . test . finished , test )
98- // Add test.after emission after event listeners have added their operations
99- setImmediate ( ( ) => {
100- recorder . add ( 'fire test.after for failed test' , ( ) => {
103+ // Add test.after emission immediately after helper events
104+ recorder . add ( 'fire test.after for failed test' , ( ) => {
105+ if ( ! testAfterEmitted ) {
106+ testAfterEmitted = true
101107 event . emit ( event . test . after , test )
102- } )
108+ }
103109 } )
104110 recorder . add ( ( ) => doneFn ( err ) )
105111 } )
@@ -127,7 +133,10 @@ function test(test) {
127133 // Add test.after to the queue after event listeners have added their operations
128134 process . nextTick ( ( ) => {
129135 recorder . add ( 'fire test.after' , ( ) => {
130- event . emit ( event . test . after , test )
136+ if ( ! testAfterEmitted ) {
137+ testAfterEmitted = true
138+ event . emit ( event . test . after , test )
139+ }
131140 } )
132141 } )
133142 } )
@@ -152,7 +161,10 @@ function test(test) {
152161 // Add test.after to the queue after event listeners have added their operations
153162 process . nextTick ( ( ) => {
154163 recorder . add ( 'fire test.after' , ( ) => {
155- event . emit ( event . test . after , test )
164+ if ( ! testAfterEmitted ) {
165+ testAfterEmitted = true
166+ event . emit ( event . test . after , test )
167+ }
156168 } )
157169 } )
158170 } )
@@ -206,7 +218,18 @@ function injected(fn, suite, hookName) {
206218 }
207219
208220 const opts = suite . opts || { }
209- const retries = opts [ `retry${ ucfirst ( hookName ) } ` ] || 0
221+ let retries = opts [ `retry${ ucfirst ( hookName ) } ` ] || 0
222+
223+ // If no retries set and this is a hook, check the global retry config directly
224+ if ( retries === 0 && ( hookName === 'beforeSuite' || hookName === 'afterSuite' || hookName === 'before' || hookName === 'after' ) ) {
225+ const retryConfig = Config . get ( 'retry' )
226+ if ( retryConfig && typeof retryConfig === 'object' && ! Array . isArray ( retryConfig ) ) {
227+ const hookRetryKey = ucfirst ( hookName )
228+ if ( retryConfig [ hookRetryKey ] ) {
229+ retries = retryConfig [ hookRetryKey ]
230+ }
231+ }
232+ }
210233
211234 const currentTest = hookName === 'before' || hookName === 'after' ? suite ?. ctx ?. currentTest : null
212235
@@ -275,19 +298,10 @@ function teardown(suite) {
275298}
276299
277300function suiteSetup ( suite ) {
278- // Execute immediately to ensure config is applied before tests run
279- ; ( async ( ) => {
301+ return ( ) => {
280302 recorder . startUnlessRunning ( )
281- const suiteModule = await import ( './suite.js' )
282- const { enhanceMochaSuite } = suiteModule . default || suiteModule
283- const enhancedSuite = enhanceMochaSuite ( suite )
284- event . emit ( event . suite . before , enhancedSuite )
285- } ) ( ) . catch ( err => {
286- console . error ( 'Suite setup error:' , err )
287- } )
288-
289- // Return empty function for Mocha hook compatibility
290- return ( ) => { }
303+ event . emit ( event . suite . before , suite )
304+ }
291305}
292306
293307function suiteTeardown ( suite ) {
0 commit comments