@@ -16,6 +16,7 @@ import {
1616 getTestEntries ,
1717 getForceRerunTriggerMessage ,
1818 getNoTestFilesMessage ,
19+ isDebug ,
1920 logger ,
2021 resolveShardedEntries ,
2122 type TraceEvent ,
@@ -143,6 +144,29 @@ const notifyReportersOnTestRunEnd = async ({
143144 }
144145} ;
145146
147+ const isLifecycleDebugEnabled = isDebug ( ) ;
148+
149+ const runLifecycleStep = async < T > (
150+ label : string ,
151+ fn : ( ) => Promise < T > ,
152+ ) : Promise < T > => {
153+ if ( ! isLifecycleDebugEnabled ) {
154+ return fn ( ) ;
155+ }
156+
157+ const startTime = Date . now ( ) ;
158+ logger . debug ( `lifecycle: start ${ label } ` ) ;
159+
160+ try {
161+ const result = await fn ( ) ;
162+ logger . debug ( `lifecycle: finish ${ label } (${ Date . now ( ) - startTime } ms)` ) ;
163+ return result ;
164+ } catch ( error ) {
165+ logger . debug ( `lifecycle: fail ${ label } (${ Date . now ( ) - startTime } ms)` ) ;
166+ throw error ;
167+ }
168+ } ;
169+
146170export async function runTests ( context : Rstest ) : Promise < void > {
147171 cleanCoverageReports ( context . normalizedConfig . coverage ) ;
148172
@@ -196,7 +220,9 @@ export async function runTests(context: Rstest): Promise<void> {
196220 } ) ;
197221 }
198222
199- await traceController . close ( ) ;
223+ await runLifecycleStep ( 'trace controller cleanup' , ( ) =>
224+ traceController . close ( ) ,
225+ ) ;
200226 return ;
201227 }
202228
@@ -245,7 +271,9 @@ export async function runTests(context: Rstest): Promise<void> {
245271 }
246272 }
247273
248- await traceController . shutdown ( traceRun ) ;
274+ await runLifecycleStep ( 'trace shutdown' , ( ) =>
275+ traceController . shutdown ( traceRun ) ,
276+ ) ;
249277 return ;
250278 }
251279
@@ -390,7 +418,9 @@ export async function runTests(context: Rstest): Promise<void> {
390418 // fires for the pre-allocated buffer. Flush any browser events the
391419 // host emitted into it before exiting so `--trace` still produces a
392420 // file for filtered mixed-mode runs.
393- await traceController . shutdown ( activeTraceRun ) ;
421+ await runLifecycleStep ( 'trace shutdown' , ( ) =>
422+ traceController . shutdown ( activeTraceRun ) ,
423+ ) ;
394424 return ;
395425 }
396426 // If no node projects at all, and no browser tests to run,
@@ -725,25 +755,29 @@ export async function runTests(context: Rstest): Promise<void> {
725755 process . exitCode = 1 ;
726756 }
727757
728- await notifyReportersOnTestRunEnd ( {
729- context,
730- coverage : mergedCoverageMap ,
731- duration,
732- getSourcemap,
733- unhandledErrors : errors ,
734- filterRerunTestPaths : currentEntries . length
735- ? currentEntries . map ( ( e ) => e . testPath )
736- : undefined ,
737- } ) ;
758+ await runLifecycleStep ( 'reporter onTestRunEnd' , ( ) =>
759+ notifyReportersOnTestRunEnd ( {
760+ context,
761+ coverage : mergedCoverageMap ,
762+ duration,
763+ getSourcemap,
764+ unhandledErrors : errors ,
765+ filterRerunTestPaths : currentEntries . length
766+ ? currentEntries . map ( ( e ) => e . testPath )
767+ : undefined ,
768+ } ) ,
769+ ) ;
738770
739771 // Generate coverage reports after all tests complete
740772 if ( coverageProvider && ( ! isFailure || coverage . reportOnFailure ) ) {
741773 const { generateCoverage } = await import ( '../coverage/generate' ) ;
742774
743- await generateCoverage ( context , mergedCoverageMap ! , coverageProvider ) ;
775+ await runLifecycleStep ( 'coverage report generation' , ( ) =>
776+ generateCoverage ( context , mergedCoverageMap ! , coverageProvider ) ,
777+ ) ;
744778 }
745779
746- await traceRun . finalize ( ) ;
780+ await runLifecycleStep ( 'trace run finalize' , ( ) => traceRun . finalize ( ) ) ;
747781 // Pre-allocate the next watch-rerun buffer so browser events emitted
748782 // between reruns (or before the next `run()` adopts a fresh buffer)
749783 // are not lost.
@@ -761,7 +795,9 @@ export async function runTests(context: Rstest): Promise<void> {
761795 }
762796 }
763797 } finally {
764- await browserClose ?.( ) ;
798+ if ( browserClose ) {
799+ await runLifecycleStep ( 'browser result cleanup' , ( ) => browserClose ( ) ) ;
800+ }
765801 }
766802 } ;
767803
@@ -777,16 +813,20 @@ export async function runTests(context: Rstest): Promise<void> {
777813 isCleaningUp = true ;
778814
779815 try {
780- await runGlobalTeardown ( ) ;
781- await pool . close ( ) ;
782- await closeServer ( ) ;
816+ await runLifecycleStep ( 'global teardown' , ( ) => runGlobalTeardown ( ) ) ;
817+ await runLifecycleStep ( 'worker pool cleanup' , ( ) => pool . close ( ) ) ;
818+ await runLifecycleStep ( 'rsbuild server cleanup' , ( ) => closeServer ( ) ) ;
783819 // Flush any browser events the host pushed into the pre-allocated
784820 // buffer since the last `run()` finalized — otherwise they get
785821 // dropped when the controller closes. Inline (not `shutdown`)
786822 // because cleanup may run from a SIGINT handler and `waitForExit`
787823 // would block waiting for another signal.
788- await activeTraceRun . finalize ( ) ;
789- await traceController . close ( ) ;
824+ await runLifecycleStep ( 'trace run finalize' , ( ) =>
825+ activeTraceRun . finalize ( ) ,
826+ ) ;
827+ await runLifecycleStep ( 'trace controller cleanup' , ( ) =>
828+ traceController . close ( ) ,
829+ ) ;
790830 } catch ( error ) {
791831 logger . log ( color . red ( `Error during cleanup: ${ error } ` ) ) ;
792832 }
@@ -823,11 +863,15 @@ export async function runTests(context: Rstest): Promise<void> {
823863 const { onBeforeRestart } = await import ( './restart' ) ;
824864
825865 onBeforeRestart ( async ( ) => {
826- await runGlobalTeardown ( ) ;
827- await pool . close ( ) ;
828- await closeServer ( ) ;
829- await activeTraceRun . finalize ( ) ;
830- await traceController . close ( ) ;
866+ await runLifecycleStep ( 'global teardown' , ( ) => runGlobalTeardown ( ) ) ;
867+ await runLifecycleStep ( 'worker pool cleanup' , ( ) => pool . close ( ) ) ;
868+ await runLifecycleStep ( 'rsbuild server cleanup' , ( ) => closeServer ( ) ) ;
869+ await runLifecycleStep ( 'trace run finalize' , ( ) =>
870+ activeTraceRun . finalize ( ) ,
871+ ) ;
872+ await runLifecycleStep ( 'trace controller cleanup' , ( ) =>
873+ traceController . close ( ) ,
874+ ) ;
831875 } ) ;
832876
833877 let buildStart : number | undefined ;
@@ -847,10 +891,16 @@ export async function runTests(context: Rstest): Promise<void> {
847891 if ( isFirstCompile && enableCliShortcuts ) {
848892 const closeCliShortcuts = await setupCliShortcuts ( {
849893 closeServer : async ( ) => {
850- await pool . close ( ) ;
851- await closeServer ( ) ;
852- await activeTraceRun . finalize ( ) ;
853- await traceController . close ( ) ;
894+ await runLifecycleStep ( 'worker pool cleanup' , ( ) => pool . close ( ) ) ;
895+ await runLifecycleStep ( 'rsbuild server cleanup' , ( ) =>
896+ closeServer ( ) ,
897+ ) ;
898+ await runLifecycleStep ( 'trace run finalize' , ( ) =>
899+ activeTraceRun . finalize ( ) ,
900+ ) ;
901+ await runLifecycleStep ( 'trace controller cleanup' , ( ) =>
902+ traceController . close ( ) ,
903+ ) ;
854904 } ,
855905 runAll : async ( ) => {
856906 clearScreen ( ) ;
@@ -975,11 +1025,15 @@ export async function runTests(context: Rstest): Promise<void> {
9751025 isCleaningUp = true ;
9761026
9771027 try {
978- await runGlobalTeardown ( ) ;
979- await pool . close ( ) ;
980- await closeServer ( ) ;
981- await activeTraceRun . finalize ( ) ;
982- await traceController . close ( ) ;
1028+ await runLifecycleStep ( 'global teardown' , ( ) => runGlobalTeardown ( ) ) ;
1029+ await runLifecycleStep ( 'worker pool cleanup' , ( ) => pool . close ( ) ) ;
1030+ await runLifecycleStep ( 'rsbuild server cleanup' , ( ) => closeServer ( ) ) ;
1031+ await runLifecycleStep ( 'trace run finalize' , ( ) =>
1032+ activeTraceRun . finalize ( ) ,
1033+ ) ;
1034+ await runLifecycleStep ( 'trace controller cleanup' , ( ) =>
1035+ traceController . close ( ) ,
1036+ ) ;
9831037 } catch ( error ) {
9841038 logger . log ( color . red ( `Error during cleanup: ${ error } ` ) ) ;
9851039 }
@@ -1023,18 +1077,20 @@ export async function runTests(context: Rstest): Promise<void> {
10231077 try {
10241078 await run ( ) ;
10251079 isTeardown = true ;
1026- await pool . close ( ) ;
1027- await closeServer ( ) ;
1080+ await runLifecycleStep ( 'worker pool cleanup' , ( ) => pool . close ( ) ) ;
1081+ await runLifecycleStep ( 'rsbuild server cleanup' , ( ) => closeServer ( ) ) ;
10281082
10291083 // Run global teardown after all tests are done
1030- await runGlobalTeardown ( ) ;
1084+ await runLifecycleStep ( 'global teardown' , ( ) => runGlobalTeardown ( ) ) ;
10311085 } finally {
10321086 process . off ( 'exit' , unExpectedExit ) ;
10331087 process . off ( 'SIGINT' , handleSignal ) ;
10341088 process . off ( 'SIGTERM' , handleSignal ) ;
10351089 process . off ( 'SIGTSTP' , handleSignal ) ;
10361090 }
10371091
1038- await traceController . waitForExit ( ) ;
1092+ await runLifecycleStep ( 'trace wait for exit' , ( ) =>
1093+ traceController . waitForExit ( ) ,
1094+ ) ;
10391095 }
10401096}
0 commit comments