@@ -22,44 +22,81 @@ public static class SeleniumExtensions
2222 private static readonly TimeSpan ExplicitTimespan = TimeSpan . FromSeconds ( 20 ) ;
2323 private static readonly TimeSpan ShortExplicitTimespan = TimeSpan . FromSeconds ( 5 ) ;
2424
25- public static IWebDriver CreateDefaultWebDriver ( )
25+ public static IWebDriver CreateDefaultWebDriver ( int maxRetries = 3 , int timeoutSeconds = 30 )
2626 {
27- // ---------- Chrome launch flags ----------
28- var options = new ChromeOptions ( ) ;
29- options . AddArguments (
30- "--headless=new" , // modern headless mode (remove this for debugging)
31- "--disable-gpu" ,
32- "--window-size=1920,1080" ,
33- "--remote-allow-origins=*" ,
34- "--disable-dev-shm-usage" ) ; // avoids crashes in low-memory containers
35-
36- // ---------- Pick a driver binary ----------
37- // 1) Prefer explicit env-var so devs can override locally
38- var driverDir = Environment . GetEnvironmentVariable ( "CHROMEWEBDRIVER" ) ;
39-
40- // 2) Otherwise use the folder where CI drops a matching chromedriver
41- if ( string . IsNullOrEmpty ( driverDir ) )
27+
28+ for ( int attempt = 1 ; attempt <= maxRetries ; attempt ++ )
4229 {
43- driverDir = Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "drivers" ) ;
44- }
30+ try
31+ {
32+ Trace . WriteLine ( $ "[Selenium] Creating Chrome WebDriver (attempt { attempt } /{ maxRetries } )") ;
33+
34+ // ---------- Chrome launch flags ----------
35+ var options = new ChromeOptions ( ) ;
36+ options . AddArguments (
37+ "--headless=new" , // modern headless mode (remove this for debugging)
38+ "--disable-gpu" ,
39+ "--window-size=1920,1080" ,
40+ "--remote-allow-origins=*" ,
41+ "--disable-dev-shm-usage" ) ; // avoids crashes in low-memory containers
42+
43+ // Additional options to improve stability
44+ options . PageLoadStrategy = PageLoadStrategy . Eager ;
45+
46+ // ---------- Pick a driver binary ----------
47+ // 1) Prefer explicit env-var so devs can override locally
48+ var driverDir = Environment . GetEnvironmentVariable ( "CHROMEWEBDRIVER" ) ;
49+
50+ // 2) Otherwise use the folder where CI drops a matching chromedriver
51+ if ( string . IsNullOrEmpty ( driverDir ) )
52+ {
53+ driverDir = Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "drivers" ) ;
54+ }
4555
46- // 3) Fallback: let Selenium look on PATH
47- ChromeDriverService service = string . IsNullOrEmpty ( driverDir )
48- ? ChromeDriverService . CreateDefaultService ( )
49- : ChromeDriverService . CreateDefaultService ( driverDir ) ;
56+ // 3) Fallback: let Selenium look on PATH
57+ ChromeDriverService service = string . IsNullOrEmpty ( driverDir )
58+ ? ChromeDriverService . CreateDefaultService ( )
59+ : ChromeDriverService . CreateDefaultService ( driverDir ) ;
5060
51- service . HideCommandPromptWindow = true ;
52- service . EnableVerboseLogging = true ;
61+ service . HideCommandPromptWindow = true ;
62+ service . EnableVerboseLogging = true ;
63+
64+ var driver = new ChromeDriver (
65+ service ,
66+ options ,
67+ TimeSpan . FromSeconds ( timeoutSeconds ) ) ;
68+
69+ driver . Manage ( ) . Timeouts ( ) . ImplicitWait = ImplicitTimespan ;
70+
71+ try
72+ {
73+ driver . Navigate ( ) . GoToUrl ( "about:blank" ) ;
74+ // If this succeeds, the browser is responding
75+ }
76+ catch ( Exception )
77+ {
78+ driver . Dispose ( ) ;
79+ throw ;
80+ }
5381
54- var driver = new ChromeDriver (
55- service ,
56- options ,
57- TimeSpan . FromSeconds ( 120 ) ) ; // generous startup timeout
82+ TryMaximize ( driver ) ;
83+ Trace . WriteLine ( $ "[Selenium] Chrome WebDriver created successfully") ;
84+ return driver ;
85+ }
86+ catch ( Exception ex )
87+ {
88+ if ( attempt == maxRetries )
89+ {
90+ Trace . WriteLine ( $ "[Selenium] Failed to create Chrome WebDriver after { maxRetries } attempts. Last error: { ex . Message } ") ;
91+ throw ;
92+ }
5893
59- driver . Manage ( ) . Timeouts ( ) . ImplicitWait = ImplicitTimespan ;
94+ Thread . Sleep ( 1000 ) ;
95+ }
96+ }
6097
61- TryMaximize ( driver ) ;
62- return driver ;
98+ // This should never be reached due to the throw in the catch block on the last attempt
99+ throw new InvalidOperationException ( "Failed to create Chrome WebDriver" ) ;
63100 }
64101
65102 private static void TryMaximize ( IWebDriver driver )
@@ -311,7 +348,7 @@ private static void EnterUsername(IWebDriver driver, LabUser user, bool withLogi
311348 {
312349 Trace . WriteLine ( "No, workaround failed" ) ;
313350 }
314- }
351+ }
315352 }
316353 }
317354
0 commit comments