2525using System ;
2626using System . Collections . Generic ;
2727using System . Globalization ;
28+ using System . Linq ;
2829using System . Text . Json ;
2930using System . Text . Json . Serialization ;
3031using System . Threading . Tasks ;
@@ -34,50 +35,66 @@ namespace Microsoft.Playwright.MSTest;
3435
3536internal class BrowserService : IWorkerService
3637{
37- public IBrowser Browser { get ; internal set ; } = null ! ;
38-
39- public Task ResetAsync ( ) => Task . CompletedTask ;
40-
41- public Task DisposeAsync ( ) => Browser ? . CloseAsync ( ) ?? Task . CompletedTask ;
38+ public IBrowser Browser { get ; private set ; }
4239
4340 private BrowserService ( IBrowser browser )
4441 {
4542 Browser = browser ;
4643 }
4744
48- public static Task < BrowserService > Register ( WorkerAwareTest test , IBrowserType browserType )
45+ public static Task < BrowserService > Register ( WorkerAwareTest test , IBrowserType browserType , ( string , BrowserTypeConnectOptions ? ) ? connectOptions )
4946 {
50- return test . RegisterService ( "Browser" , async ( ) => new BrowserService ( await CreateBrowser ( browserType ) . ConfigureAwait ( false ) ) ) ;
47+ return test . RegisterService ( "Browser" , async ( ) => new BrowserService ( await CreateBrowser ( browserType , connectOptions ) . ConfigureAwait ( false ) ) ) ;
5148 }
5249
53- private static async Task < IBrowser > CreateBrowser ( IBrowserType browserType )
50+ private static async Task < IBrowser > CreateBrowser ( IBrowserType browserType , ( string WSEndpoint , BrowserTypeConnectOptions ? Options ) ? connectOptions )
51+ {
52+ if ( connectOptions . HasValue && connectOptions . Value . WSEndpoint != null )
53+ {
54+ var options = new BrowserTypeConnectOptions ( connectOptions ? . Options ?? new ( ) ) ;
55+ var headers = options . Headers ? . ToDictionary ( kvp => kvp . Key , kvp => kvp . Value ) ?? [ ] ;
56+ headers . Add ( "x-playwright-launch-options" , JsonSerializer . Serialize ( PlaywrightSettingsProvider . LaunchOptions , new JsonSerializerOptions ( ) { DefaultIgnoreCondition = JsonIgnoreCondition . WhenWritingNull } ) ) ;
57+ options . Headers = headers ;
58+ return await browserType . ConnectAsync ( connectOptions ! . Value . WSEndpoint , options ) . ConfigureAwait ( false ) ;
59+ }
60+
61+ var legacyBrowser = await ConnectBasedOnEnv ( browserType ) ;
62+ if ( legacyBrowser != null )
63+ {
64+ return legacyBrowser ;
65+ }
66+ return await browserType . LaunchAsync ( PlaywrightSettingsProvider . LaunchOptions ) . ConfigureAwait ( false ) ;
67+ }
68+
69+ // TODO: Remove at some point
70+ private static async Task < IBrowser ? > ConnectBasedOnEnv ( IBrowserType browserType )
5471 {
5572 var accessToken = Environment . GetEnvironmentVariable ( "PLAYWRIGHT_SERVICE_ACCESS_TOKEN" ) ;
5673 var serviceUrl = Environment . GetEnvironmentVariable ( "PLAYWRIGHT_SERVICE_URL" ) ;
5774
5875 if ( string . IsNullOrEmpty ( accessToken ) || string . IsNullOrEmpty ( serviceUrl ) )
5976 {
60- return await browserType . LaunchAsync ( PlaywrightSettingsProvider . LaunchOptions ) . ConfigureAwait ( false ) ;
77+ return null ;
6178 }
62- else
79+
80+ var exposeNetwork = Environment . GetEnvironmentVariable ( "PLAYWRIGHT_SERVICE_EXPOSE_NETWORK" ) ?? "<loopback>" ;
81+ var os = Uri . EscapeDataString ( Environment . GetEnvironmentVariable ( "PLAYWRIGHT_SERVICE_OS" ) ?? "linux" ) ;
82+ var runId = Uri . EscapeDataString ( Environment . GetEnvironmentVariable ( "PLAYWRIGHT_SERVICE_RUN_ID" ) ?? DateTime . Now . ToUniversalTime ( ) . ToString ( "yyyy-MM-ddTHH:mm:ss" , CultureInfo . InvariantCulture ) ) ;
83+ var apiVersion = "2023-10-01-preview" ;
84+ var wsEndpoint = $ "{ serviceUrl } ?os={ os } &runId={ runId } &api-version={ apiVersion } ";
85+
86+ return await browserType . ConnectAsync ( wsEndpoint , new BrowserTypeConnectOptions
6387 {
64- var exposeNetwork = Environment . GetEnvironmentVariable ( "PLAYWRIGHT_SERVICE_EXPOSE_NETWORK" ) ?? "<loopback>" ;
65- var os = Uri . EscapeDataString ( Environment . GetEnvironmentVariable ( "PLAYWRIGHT_SERVICE_OS" ) ?? "linux" ) ;
66- var runId = Uri . EscapeDataString ( Environment . GetEnvironmentVariable ( "PLAYWRIGHT_SERVICE_RUN_ID" ) ?? DateTime . Now . ToUniversalTime ( ) . ToString ( "yyyy-MM-ddTHH:mm:ss" , CultureInfo . InvariantCulture ) ) ;
67- var apiVersion = "2023-10-01-preview" ;
68- var wsEndpoint = $ "{ serviceUrl } ?os={ os } &runId={ runId } &api-version={ apiVersion } ";
69- var connectOptions = new BrowserTypeConnectOptions
88+ Timeout = 3 * 60 * 1000 ,
89+ ExposeNetwork = exposeNetwork ,
90+ Headers = new Dictionary < string , string >
7091 {
71- Timeout = 3 * 60 * 1000 ,
72- ExposeNetwork = exposeNetwork ,
73- Headers = new Dictionary < string , string >
74- {
75- [ "Authorization" ] = $ "Bearer { accessToken } ",
76- [ "x-playwright-launch-options" ] = JsonSerializer . Serialize ( PlaywrightSettingsProvider . LaunchOptions , new JsonSerializerOptions ( ) { DefaultIgnoreCondition = JsonIgnoreCondition . WhenWritingNull } )
77- }
78- } ;
79-
80- return await browserType . ConnectAsync ( wsEndpoint , connectOptions ) . ConfigureAwait ( false ) ;
81- }
92+ [ "Authorization" ] = $ "Bearer { accessToken } ",
93+ [ "x-playwright-launch-options" ] = JsonSerializer . Serialize ( PlaywrightSettingsProvider . LaunchOptions , new JsonSerializerOptions ( ) { DefaultIgnoreCondition = JsonIgnoreCondition . WhenWritingNull } )
94+ }
95+ } ) . ConfigureAwait ( false ) ;
8296 }
97+
98+ public Task ResetAsync ( ) => Task . CompletedTask ;
99+ public Task DisposeAsync ( ) => Browser . CloseAsync ( ) ;
83100}
0 commit comments