@@ -349,8 +349,71 @@ def test_create_session_register_uridirect_ignores_empty_values(self):
349349
350350 assert driver .command_executor ._client_config .remote_server_addr == SERVER_URL_BASE
351351
352+ @pytest .mark .parametrize ('prefix' , ['' , 'appium:' ])
353+ @pytest .mark .parametrize ('path' , ['' , '/' , None ])
352354 @httpretty .activate
353- def test_create_session_register_uridirect_with_custom_connection (self ):
355+ def test_direct_connect_root_path (self , prefix , path ):
356+ caps = {
357+ f'{ prefix } directConnectProtocol' : 'http' ,
358+ f'{ prefix } directConnectHost' : 'localhost2' ,
359+ f'{ prefix } directConnectPort' : 4800 ,
360+ f'{ prefix } directConnectPath' : path ,
361+ }
362+ # An explicit empty prefixed path must win over a legacy path.
363+ if prefix :
364+ caps ['directConnectPath' ] = '/legacy' if path is not None else None
365+ httpretty .register_uri (
366+ httpretty .POST ,
367+ f'{ SERVER_URL_BASE } /session' ,
368+ body = json .dumps ({'sessionId' : 'session-id' , 'capabilities' : caps }),
369+ )
370+ endpoint = SERVER_URL_BASE if path is None else f'http://localhost2:4800{ path } '
371+ httpretty .register_uri (
372+ httpretty .GET ,
373+ f'{ endpoint } /session/session-id/contexts' ,
374+ body = json .dumps ({'value' : ['NATIVE_APP' ]}),
375+ )
376+ driver = webdriver .Remote (
377+ options = UiAutomator2Options (),
378+ client_config = AppiumClientConfig (remote_server_addr = SERVER_URL_BASE , direct_connection = True ),
379+ )
380+ assert driver .command_executor .client_config .remote_server_addr == endpoint
381+ assert driver .contexts == ['NATIVE_APP' ]
382+
383+ @pytest .mark .parametrize ('keep_alive' , [True , False ])
384+ def test_direct_connect_rebuilds_proxy_pool (self , monkeypatch , keep_alive ):
385+ monkeypatch .setenv ('http_proxy' , 'http://proxy:8080' )
386+ monkeypatch .setenv ('no_proxy' , 'grid' )
387+ config = AppiumClientConfig (remote_server_addr = 'http://grid:4444' , keep_alive = keep_alive )
388+ connection = AppiumConnection (client_config = config )
389+ assert connection ._proxy_url is None
390+ driver = WebDriver .__new__ (WebDriver )
391+ driver .command_executor = connection
392+ driver .caps = {
393+ 'directConnectProtocol' : 'http' ,
394+ 'directConnectHost' : 'node' ,
395+ 'directConnectPort' : 4723 ,
396+ 'directConnectPath' : '' ,
397+ }
398+ with patch .object (connection , '_get_connection_manager' , wraps = connection ._get_connection_manager ) as manager :
399+ if keep_alive :
400+ old_pool = connection ._conn
401+ with patch .object (old_pool , 'clear' , wraps = old_pool .clear ) as clear :
402+ driver ._update_command_executor (keep_alive )
403+ clear .assert_called_once ()
404+ assert connection ._conn is not old_pool
405+ assert isinstance (connection ._conn , urllib3 .ProxyManager )
406+ manager .assert_called_once ()
407+ else :
408+ driver ._update_command_executor (keep_alive )
409+ manager .assert_not_called ()
410+ assert connection ._proxy_url == 'http://proxy:8080'
411+ assert config .remote_server_addr == 'http://grid:4444'
412+ connection .close ()
413+
414+ @pytest .mark .parametrize ('keep_alive' , [True , False ])
415+ @httpretty .activate
416+ def test_create_session_register_uridirect_with_custom_connection (self , keep_alive ):
354417 httpretty .register_uri (
355418 httpretty .POST ,
356419 f'{ SERVER_URL_BASE } /session' ,
@@ -369,22 +432,38 @@ def test_create_session_register_uridirect_with_custom_connection(self):
369432 )
370433
371434 class CustomAppiumConnection (AppiumConnection ):
372- pass
435+ def __init__ (self , token , client_config ):
436+ super ().__init__ (client_config = client_config )
437+ self .token = token
373438
374439 desired_caps = {
375440 'platformName' : 'Android' ,
376441 'deviceName' : 'Android Emulator' ,
377442 'app' : 'path/to/app' ,
378443 'automationName' : 'UIAutomator2' ,
379444 }
380- client_config = AppiumClientConfig (remote_server_addr = SERVER_URL_BASE , direct_connection = True )
381- custom_connection = CustomAppiumConnection (client_config = client_config )
445+ client_config = AppiumClientConfig (remote_server_addr = SERVER_URL_BASE , direct_connection = True , keep_alive = keep_alive )
446+ custom_connection = CustomAppiumConnection ('custom-token' , client_config = client_config )
447+ state = object ()
448+ custom_connection .state = state
449+ custom_connection ._commands = custom_connection ._commands .copy ()
450+ custom_connection .add_command ('custom_command' , 'GET' , '/session/$sessionId/custom' )
451+ httpretty .register_uri (
452+ httpretty .GET ,
453+ 'http://localhost2:4800/special/path/wd/hub/session/session-id/custom' ,
454+ body = json .dumps ({'value' : 'custom-result' }),
455+ )
382456 driver = webdriver .Remote (
383457 custom_connection ,
384458 options = UiAutomator2Options ().load_capabilities (desired_caps ),
385459 )
386460
387- assert isinstance (driver .command_executor , CustomAppiumConnection )
461+ assert driver .command_executor is custom_connection
462+ assert custom_connection .token == 'custom-token'
463+ assert custom_connection .state is state
464+ assert client_config .remote_server_addr == SERVER_URL_BASE
465+ assert driver .command_executor .client_config .keep_alive is keep_alive
466+ assert driver .execute ('custom_command' )['value' ] == 'custom-result'
388467 assert driver .command_executor ._client_config .remote_server_addr == 'http://localhost2:4800/special/path/wd/hub'
389468
390469 @httpretty .activate
0 commit comments