@@ -22,44 +22,81 @@ public static class SeleniumExtensions
22
22
private static readonly TimeSpan ExplicitTimespan = TimeSpan . FromSeconds ( 20 ) ;
23
23
private static readonly TimeSpan ShortExplicitTimespan = TimeSpan . FromSeconds ( 5 ) ;
24
24
25
- public static IWebDriver CreateDefaultWebDriver ( )
25
+ public static IWebDriver CreateDefaultWebDriver ( int maxRetries = 3 , int timeoutSeconds = 30 )
26
26
{
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 ++ )
42
29
{
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
+ }
45
55
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 ) ;
50
60
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
+ }
53
81
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
+ }
58
93
59
- driver . Manage ( ) . Timeouts ( ) . ImplicitWait = ImplicitTimespan ;
94
+ Thread . Sleep ( 1000 ) ;
95
+ }
96
+ }
60
97
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" ) ;
63
100
}
64
101
65
102
private static void TryMaximize ( IWebDriver driver )
@@ -311,7 +348,7 @@ private static void EnterUsername(IWebDriver driver, LabUser user, bool withLogi
311
348
{
312
349
Trace . WriteLine ( "No, workaround failed" ) ;
313
350
}
314
- }
351
+ }
315
352
}
316
353
}
317
354
0 commit comments