@@ -24,13 +24,57 @@ public class WebDriverFixture : IDisposable
2424 private static readonly object _lock = new object ( ) ;
2525 private bool _disposed = false ;
2626 private static System . Net . Http . HttpClient _httpClient ;
27+ private static int _instanceCount = 0 ;
28+ private static readonly object _httpClientLock = new object ( ) ;
2729
2830 public WebDriverFixture ( )
2931 {
30- // Initialize shared HttpClient if needed
31- if ( _httpClient == null )
32+ lock ( _httpClientLock )
3233 {
33- _httpClient = new System . Net . Http . HttpClient ( ) ;
34+ _instanceCount ++ ;
35+ Console . WriteLine ( $ "WebDriverFixture instance created. Count: { _instanceCount } ") ;
36+
37+ // Initialize HttpClient with proper configuration for CI/CD environments
38+ if ( _httpClient == null || IsHttpClientDisposed ( _httpClient ) )
39+ {
40+ if ( _httpClient != null )
41+ {
42+ Console . WriteLine ( "HttpClient was disposed, creating a new instance" ) ;
43+ }
44+
45+ _httpClient = CreateHttpClient ( ) ;
46+ }
47+ }
48+ }
49+
50+ private static System . Net . Http . HttpClient CreateHttpClient ( )
51+ {
52+ var httpClient = new System . Net . Http . HttpClient ( ) ;
53+ httpClient . Timeout = TimeSpan . FromSeconds ( 30 ) ; // Set reasonable timeout
54+
55+ // Add headers that might be needed for Azure Container Apps
56+ httpClient . DefaultRequestHeaders . Add ( "User-Agent" , "RazorPagesMovie-UITests/1.0" ) ;
57+
58+ Console . WriteLine ( "Created new HttpClient instance" ) ;
59+ return httpClient ;
60+ }
61+
62+ private static bool IsHttpClientDisposed ( System . Net . Http . HttpClient client )
63+ {
64+ try
65+ {
66+ // Try to access a property that would throw if disposed
67+ var timeout = client . Timeout ;
68+ return false ;
69+ }
70+ catch ( ObjectDisposedException )
71+ {
72+ return true ;
73+ }
74+ catch ( Exception )
75+ {
76+ // Other exceptions mean it's not disposed
77+ return false ;
3478 }
3579 }
3680
@@ -60,25 +104,14 @@ public IWebDriver GetDriver()
60104
61105 public System . Net . Http . HttpClient GetHttpClient ( )
62106 {
63- if ( _httpClient == null )
64- {
65- _httpClient = new System . Net . Http . HttpClient ( ) ;
66- }
67- else
107+ lock ( _httpClientLock )
68108 {
69- // Check if HttpClient is disposed
70- try
71- {
72- // Try to access a property that would throw if disposed
73- var baseAddress = _httpClient . BaseAddress ;
74- }
75- catch ( ObjectDisposedException )
109+ if ( _httpClient == null || IsHttpClientDisposed ( _httpClient ) )
76110 {
77- Console . WriteLine ( "HttpClient was disposed, creating a new instance" ) ;
78- _httpClient = new System . Net . Http . HttpClient ( ) ;
111+ _httpClient = CreateHttpClient ( ) ;
79112 }
113+ return _httpClient ;
80114 }
81- return _httpClient ;
82115 }
83116
84117 private void DisposeDriverOnly ( )
@@ -141,18 +174,32 @@ public IWebDriver CreateDriver()
141174
142175 private DriverOptions GetOptions ( string browser )
143176 {
177+ bool isCI = ! string . IsNullOrEmpty ( Environment . GetEnvironmentVariable ( "GITHUB_ACTIONS" ) ) ;
178+ Console . WriteLine ( $ "Running in CI environment: { isCI } ") ;
179+
144180 switch ( browser . ToLower ( ) )
145181 {
146182 case "firefox" :
147183 var firefoxOptions = new FirefoxOptions ( ) ;
148184 firefoxOptions . AcceptInsecureCertificates = true ;
149185 firefoxOptions . AddArgument ( "--headless" ) ;
186+ if ( isCI )
187+ {
188+ firefoxOptions . AddArgument ( "--no-sandbox" ) ;
189+ firefoxOptions . AddArgument ( "--disable-gpu" ) ;
190+ }
150191 return firefoxOptions ;
151192
152193 case "edge" :
153194 var edgeOptions = new EdgeOptions ( ) ;
154195 edgeOptions . AcceptInsecureCertificates = true ;
155196 edgeOptions . AddArgument ( "--headless" ) ;
197+ if ( isCI )
198+ {
199+ edgeOptions . AddArgument ( "--no-sandbox" ) ;
200+ edgeOptions . AddArgument ( "--disable-gpu" ) ;
201+ edgeOptions . AddArgument ( "--disable-dev-shm-usage" ) ;
202+ }
156203 return edgeOptions ;
157204
158205 case "chromium" :
@@ -168,6 +215,21 @@ private DriverOptions GetOptions(string browser)
168215 chromeOptions . AddArgument ( "--disable-sync" ) ;
169216 chromeOptions . AddArgument ( "--disable-background-networking" ) ;
170217 chromeOptions . AddArgument ( "--window-size=1280,1024" ) ;
218+
219+ if ( isCI )
220+ {
221+ // Additional options for CI environments
222+ chromeOptions . AddArgument ( "--disable-gpu" ) ;
223+ chromeOptions . AddArgument ( "--disable-background-timer-throttling" ) ;
224+ chromeOptions . AddArgument ( "--disable-backgrounding-occluded-windows" ) ;
225+ chromeOptions . AddArgument ( "--disable-renderer-backgrounding" ) ;
226+ chromeOptions . AddArgument ( "--disable-features=TranslateUI" ) ;
227+ chromeOptions . AddArgument ( "--disable-ipc-flooding-protection" ) ;
228+ chromeOptions . AddArgument ( "--no-first-run" ) ;
229+ chromeOptions . AddArgument ( "--disable-default-apps" ) ;
230+ chromeOptions . AddArgument ( "--disable-component-extensions-with-background-pages" ) ;
231+ }
232+
171233 return chromeOptions ;
172234 }
173235 }
@@ -176,33 +238,49 @@ public void Dispose()
176238 {
177239 if ( ! _disposed )
178240 {
179- // Only dispose the driver when the fixture itself is being disposed
180- // which should happen at the end of the collection
181- if ( _driver != null )
241+ lock ( _httpClientLock )
182242 {
183- try
184- {
185- _driver . Quit ( ) ;
186- _driver . Dispose ( ) ;
187- _driver = null ;
188- }
189- catch ( Exception ex )
243+ _instanceCount -- ;
244+ Console . WriteLine ( $ "WebDriverFixture disposing. Remaining instances: { _instanceCount } ") ;
245+
246+ // Only dispose resources when this is the last instance
247+ if ( _instanceCount <= 0 )
190248 {
191- Console . WriteLine ( $ "Error disposing WebDriver: { ex . Message } ") ;
192- }
193- }
194-
195- // Dispose HttpClient too
196- if ( _httpClient != null )
197- {
198- try
199- {
200- _httpClient . Dispose ( ) ;
201- _httpClient = null ;
202- }
203- catch ( Exception ex )
204- {
205- Console . WriteLine ( $ "Error disposing HttpClient: { ex . Message } ") ;
249+ Console . WriteLine ( "Last WebDriverFixture instance - disposing shared resources" ) ;
250+
251+ // Dispose WebDriver
252+ if ( _driver != null )
253+ {
254+ try
255+ {
256+ _driver . Quit ( ) ;
257+ _driver . Dispose ( ) ;
258+ _driver = null ;
259+ Console . WriteLine ( "WebDriver disposed" ) ;
260+ }
261+ catch ( Exception ex )
262+ {
263+ Console . WriteLine ( $ "Error disposing WebDriver: { ex . Message } ") ;
264+ }
265+ }
266+
267+ // Dispose HttpClient
268+ if ( _httpClient != null )
269+ {
270+ try
271+ {
272+ _httpClient . Dispose ( ) ;
273+ _httpClient = null ;
274+ Console . WriteLine ( "HttpClient disposed" ) ;
275+ }
276+ catch ( Exception ex )
277+ {
278+ Console . WriteLine ( $ "Error disposing HttpClient: { ex . Message } ") ;
279+ }
280+ }
281+
282+ // Reset instance count to prevent negative values
283+ _instanceCount = 0 ;
206284 }
207285 }
208286
0 commit comments