1818from urllib .parse import parse_qs , urljoin , urlparse
1919from uuid import uuid4
2020
21+ import httpx
2122import pytest
22- import requests
2323
2424if TYPE_CHECKING :
2525 from diracx .core .settings import DevelopmentSettings
@@ -616,7 +616,7 @@ async def test_login(monkeypatch, capfd, cli_env):
616616
617617 poll_attempts = 0
618618
619- def fake_sleep (* args , ** kwargs ):
619+ async def fake_sleep (* args , ** kwargs ):
620620 nonlocal poll_attempts
621621
622622 # Keep track of the number of times this is called
@@ -629,13 +629,13 @@ def fake_sleep(*args, **kwargs):
629629 match = re .search (rf"{ cli_env ['DIRACX_URL' ]} [^\n]+" , captured .out )
630630 assert match , captured
631631
632- do_device_flow_with_dex (match .group (), cli_env ["DIRACX_CA_PATH" ])
632+ await do_device_flow_with_dex (match .group (), cli_env ["DIRACX_CA_PATH" ])
633633
634634 # Ensure we don't poll forever
635635 assert poll_attempts <= 100
636636
637637 # Reduce the sleep duration to zero to speed up the test
638- return unpatched_sleep (0 )
638+ await unpatched_sleep (0. 0 )
639639
640640 # We monkeypatch asyncio.sleep to provide a hook to run the actions that
641641 # would normally be done by a user. This includes capturing the login URL
@@ -650,7 +650,7 @@ def fake_sleep(*args, **kwargs):
650650
651651 # Run the login command
652652 with monkeypatch .context () as m :
653- m .setattr ("asyncio .sleep" , fake_sleep )
653+ m .setattr ("diracx.cli.auth .sleep" , fake_sleep )
654654 await cli .auth .login (vo = "diracAdmin" , group = None , property = None )
655655 captured = capfd .readouterr ()
656656 assert "Login successful!" in captured .out
@@ -664,18 +664,22 @@ def fake_sleep(*args, **kwargs):
664664 return expected_credentials_path .read_text ()
665665
666666
667- def do_device_flow_with_dex (url : str , ca_path : str ) -> None :
667+ async def do_device_flow_with_dex (url : str , ca_path : str ) -> None :
668668 """Do the device flow with dex."""
669669
670670 class DexLoginFormParser (HTMLParser ):
671671 def handle_starttag (self , tag , attrs ):
672672 nonlocal action_url
673673 if "form" in str (tag ):
674674 assert action_url is None
675- action_url = urljoin (login_page_url , dict (attrs )["action" ])
675+ action_url = urljoin (str ( login_page_url ) , dict (attrs )["action" ])
676676
677+ ssl_context = ssl .create_default_context (cafile = ca_path )
678+ client_kwargs = dict (verify = ssl_context , follow_redirects = True )
677679 # Get the login page
678- r = requests .get (url , verify = ca_path )
680+ async with httpx .AsyncClient (** client_kwargs ) as client :
681+ r = await client .get (url )
682+
679683 r .raise_for_status ()
680684 login_page_url = r .url # This is not the same as URL as we redirect to dex
681685 login_page_body = r .text
@@ -686,19 +690,24 @@ def handle_starttag(self, tag, attrs):
686690 assert action_url is not None , login_page_body
687691
688692 # Do the actual login
689- r = requests .post (
690- action_url ,
691- data = {"login" : "admin@example.com" , "password" : "password" },
692- verify = ca_path ,
693- )
693+ async with httpx .AsyncClient (** client_kwargs ) as client :
694+ r = await client .post (
695+ action_url ,
696+ data = {"login" : "admin@example.com" , "password" : "password" },
697+ )
698+
694699 r .raise_for_status ()
695700 approval_url = r .url # This is not the same as URL as we redirect to dex
696701 # Do the actual approval
697- r = requests .post (
698- approval_url ,
699- {"approval" : "approve" , "req" : parse_qs (urlparse (r .url ).query )["req" ][0 ]},
700- verify = ca_path ,
701- )
702+
703+ async with httpx .AsyncClient (** client_kwargs ) as client :
704+ r = await client .post (
705+ approval_url ,
706+ data = {
707+ "approval" : "approve" ,
708+ "req" : parse_qs (urlparse (str (r .url )).query )["req" ][0 ],
709+ },
710+ )
702711
703712 # This should have redirected to the DiracX page that shows the login is complete
704713 assert "Please close the window" in r .text
0 commit comments