@@ -8,6 +8,7 @@ namespace PrompterOne.Web.UITests;
88public sealed partial class StandaloneAppFixture : IAsyncInitializer , IAsyncDisposable
99{
1010 private const int MinimumPageCount = 1 ;
11+ private const int ContextBootstrapAttemptCount = 3 ;
1112 private const int ServerStartupTimeoutSeconds = 60 ;
1213 private const int ServerProbeDelayMilliseconds = 500 ;
1314 private readonly ConcurrentDictionary < IBrowserContext , byte > _contexts = [ ] ;
@@ -72,7 +73,7 @@ public async Task<IReadOnlyList<IPage>> NewSharedPagesAsync(
7273
7374 private async Task < IPage > CreateAdditionalPageAsync ( )
7475 {
75- while ( true )
76+ for ( var attempt = 1 ; ; attempt ++ )
7677 {
7778 var context = await CreateTrackedContextAsync ( ) ;
7879
@@ -84,7 +85,11 @@ private async Task<IPage> CreateAdditionalPageAsync()
8485 await WarmUpContextPageIfNeededAsync ( page , BaseAddress ) ;
8586 return page ;
8687 }
87- catch ( PlaywrightException exception ) when ( IsBrowserClosedException ( exception ) )
88+ catch ( PlaywrightException exception ) when ( attempt < ContextBootstrapAttemptCount && IsBrowserClosedException ( exception ) )
89+ {
90+ await DisposeContextAsync ( context ) ;
91+ }
92+ catch ( InvalidOperationException exception ) when ( attempt < ContextBootstrapAttemptCount && IsContextWarmupFailure ( exception ) )
8893 {
8994 await DisposeContextAsync ( context ) ;
9095 }
@@ -93,7 +98,7 @@ private async Task<IPage> CreateAdditionalPageAsync()
9398
9499 private async Task < IPage > CreateSharedPageAsync ( string contextKey )
95100 {
96- while ( true )
101+ for ( var attempt = 1 ; ; attempt ++ )
97102 {
98103 var ( context , isNewSharedContext ) = await GetOrCreateSharedContextAsync ( contextKey ) ;
99104
@@ -105,7 +110,7 @@ private async Task<IPage> CreateSharedPageAsync(string contextKey)
105110 if ( isNewSharedContext )
106111 {
107112 await PrimeIsolatedBrowserStorageAsync ( page ) ;
108- await WarmUpContextPageIfNeededAsync ( page , BaseAddress ) ;
113+ await WarmUpContextPageIfNeededAsync ( page , BaseAddress , warmAllRuntimeRoutes : true ) ;
109114 }
110115 else
111116 {
@@ -114,7 +119,11 @@ private async Task<IPage> CreateSharedPageAsync(string contextKey)
114119
115120 return page ;
116121 }
117- catch ( PlaywrightException exception ) when ( IsBrowserClosedException ( exception ) )
122+ catch ( PlaywrightException exception ) when ( attempt < ContextBootstrapAttemptCount && IsBrowserClosedException ( exception ) )
123+ {
124+ RemoveSharedContext ( context ) ;
125+ }
126+ catch ( InvalidOperationException exception ) when ( attempt < ContextBootstrapAttemptCount && IsContextWarmupFailure ( exception ) )
118127 {
119128 RemoveSharedContext ( context ) ;
120129 }
@@ -229,6 +238,9 @@ private static bool IsBrowserClosedException(PlaywrightException exception) =>
229238 exception . Message . Contains ( "Target page, context or browser has been closed" , StringComparison . Ordinal )
230239 || exception . Message . Contains ( "Process exited" , StringComparison . Ordinal ) ;
231240
241+ private static bool IsContextWarmupFailure ( InvalidOperationException exception ) =>
242+ exception . Message . StartsWith ( "Browser context warmup failed." , StringComparison . Ordinal ) ;
243+
232244 private Task PrimeIsolatedBrowserStorageAsync ( IPage page ) =>
233245 PrimeIsolatedBrowserStorageAsync ( page , BaseAddress ) ;
234246
0 commit comments