@@ -634,6 +634,175 @@ def test_patch(self):
634634 timeout = DEFAULT_TIMEOUT_SECONDS ,
635635 )
636636
637+ def test_patch_with_status (self ):
638+ # Test invalid status value
639+ with self .assertRaises (AuthException ) as context :
640+ self .client .mgmt .user .patch ("valid-id" , status = "invalid_status" )
641+
642+ self .assertEqual (context .exception .status_code , 400 )
643+ self .assertIn ("Invalid status value: invalid_status" , str (context .exception ))
644+
645+ # Test valid status values
646+ valid_statuses = ["enabled" , "disabled" , "invited" ]
647+
648+ for status in valid_statuses :
649+ with patch ("requests.patch" ) as mock_patch :
650+ network_resp = mock .Mock ()
651+ network_resp .ok = True
652+ network_resp .json .return_value = json .loads (
653+ """{"user": {"id": "u1"}}"""
654+ )
655+ mock_patch .return_value = network_resp
656+
657+ resp = self .client .mgmt .user .patch ("id" , status = status )
658+ user = resp ["user" ]
659+ self .assertEqual (user ["id" ], "u1" )
660+
661+ mock_patch .assert_called_with (
662+ f"{ common .DEFAULT_BASE_URL } { MgmtV1 .user_patch_path } " ,
663+ headers = {
664+ ** common .default_headers ,
665+ "Authorization" : f"Bearer { self .dummy_project_id } :{ self .dummy_management_key } " ,
666+ "x-descope-project-id" : self .dummy_project_id ,
667+ },
668+ params = None ,
669+ json = {
670+ "loginId" : "id" ,
671+ "status" : status ,
672+ },
673+ allow_redirects = False ,
674+ verify = True ,
675+ timeout = DEFAULT_TIMEOUT_SECONDS ,
676+ )
677+
678+ # Test that status is not included when None
679+ with patch ("requests.patch" ) as mock_patch :
680+ network_resp = mock .Mock ()
681+ network_resp .ok = True
682+ network_resp .json .return_value = json .loads ("""{"user": {"id": "u1"}}""" )
683+ mock_patch .return_value = network_resp
684+
685+ resp = self .client .mgmt .user .patch ("id" , display_name = "test" , status = None )
686+ user = resp ["user" ]
687+ self .assertEqual (user ["id" ], "u1" )
688+
689+ # Verify that status is not in the JSON payload
690+ call_args = mock_patch .call_args
691+ json_payload = call_args [1 ]["json" ]
692+ self .assertNotIn ("status" , json_payload )
693+ self .assertEqual (json_payload ["displayName" ], "test" )
694+
695+ def test_patch_batch (self ):
696+ # Test invalid status value in batch
697+ users_with_invalid_status = [
698+ UserObj (login_id = "user1" , status = "invalid_status" ),
699+ UserObj (login_id = "user2" , status = "enabled" ),
700+ ]
701+
702+ with self .assertRaises (AuthException ) as context :
703+ self .client .mgmt .user .patch_batch (users_with_invalid_status )
704+
705+ self .assertEqual (context .exception .status_code , 400 )
706+ self .assertIn (
707+ "Invalid status value: invalid_status for user user1" ,
708+ str (context .exception ),
709+ )
710+
711+ # Test successful batch patch
712+ users = [
713+ UserObj (
login_id = "user1" ,
email = "[email protected] " ,
status = "enabled" ),
714+ UserObj (login_id = "user2" , display_name = "User Two" , status = "disabled" ),
715+ UserObj (login_id = "user3" , phone = "+123456789" , status = "invited" ),
716+ ]
717+
718+ with patch ("requests.patch" ) as mock_patch :
719+ network_resp = mock .Mock ()
720+ network_resp .ok = True
721+ network_resp .json .return_value = json .loads (
722+ """{"patchedUsers": [{"id": "u1"}, {"id": "u2"}, {"id": "u3"}], "failedUsers": []}"""
723+ )
724+ mock_patch .return_value = network_resp
725+
726+ resp = self .client .mgmt .user .patch_batch (users )
727+
728+ self .assertEqual (len (resp ["patchedUsers" ]), 3 )
729+ self .assertEqual (len (resp ["failedUsers" ]), 0 )
730+
731+ mock_patch .assert_called_with (
732+ f"{ common .DEFAULT_BASE_URL } { MgmtV1 .user_patch_batch_path } " ,
733+ headers = {
734+ ** common .default_headers ,
735+ "Authorization" : f"Bearer { self .dummy_project_id } :{ self .dummy_management_key } " ,
736+ "x-descope-project-id" : self .dummy_project_id ,
737+ },
738+ params = None ,
739+ json = {
740+ "users" : [
741+ {
742+ "loginId" : "user1" ,
743+ 744+ "status" : "enabled" ,
745+ },
746+ {
747+ "loginId" : "user2" ,
748+ "displayName" : "User Two" ,
749+ "status" : "disabled" ,
750+ },
751+ {
752+ "loginId" : "user3" ,
753+ "phone" : "+123456789" ,
754+ "status" : "invited" ,
755+ },
756+ ]
757+ },
758+ allow_redirects = False ,
759+ verify = True ,
760+ timeout = DEFAULT_TIMEOUT_SECONDS ,
761+ )
762+
763+ # Test batch with mixed success/failure response
764+ with patch ("requests.patch" ) as mock_patch :
765+ network_resp = mock .Mock ()
766+ network_resp .ok = True
767+ network_resp .json .return_value = json .loads (
768+ """{"patchedUsers": [{"id": "u1"}], "failedUsers": [{"failure": "User not found", "user": {"loginId": "user2"}}]}"""
769+ )
770+ mock_patch .return_value = network_resp
771+
772+ resp = self .client .mgmt .user .patch_batch (
773+ [UserObj (login_id = "user1" ), UserObj (login_id = "user2" )]
774+ )
775+
776+ self .assertEqual (len (resp ["patchedUsers" ]), 1 )
777+ self .assertEqual (len (resp ["failedUsers" ]), 1 )
778+ self .assertEqual (resp ["failedUsers" ][0 ]["failure" ], "User not found" )
779+
780+ # Test failed batch operation
781+ with patch ("requests.patch" ) as mock_patch :
782+ mock_patch .return_value .ok = False
783+ self .assertRaises (
784+ AuthException ,
785+ self .client .mgmt .user .patch_batch ,
786+ [UserObj (login_id = "user1" )],
787+ )
788+
789+ # Test with test users flag
790+ with patch ("requests.patch" ) as mock_patch :
791+ network_resp = mock .Mock ()
792+ network_resp .ok = True
793+ network_resp .json .return_value = json .loads (
794+ """{"patchedUsers": [{"id": "u1"}], "failedUsers": []}"""
795+ )
796+ mock_patch .return_value = network_resp
797+
798+ resp = self .client .mgmt .user .patch_batch (
799+ [UserObj (login_id = "test_user1" )], test = True
800+ )
801+
802+ call_args = mock_patch .call_args
803+ json_payload = call_args [1 ]["json" ]
804+ self .assertTrue (json_payload ["users" ][0 ]["test" ])
805+
637806 def test_delete (self ):
638807 # Test failed flows
639808 with patch ("requests.post" ) as mock_post :
@@ -1056,8 +1225,12 @@ def test_search_all(self):
10561225 )
10571226 mock_post .return_value = network_resp
10581227 resp = self .client .mgmt .user .search_all (
1059- tenant_role_ids = {"tenant1" : {"values" : ["roleA" , "roleB" ], "and" : True }},
1060- tenant_role_names = {"tenant2" : {"values" : ["admin" , "user" ], "and" : False }},
1228+ tenant_role_ids = {
1229+ "tenant1" : {"values" : ["roleA" , "roleB" ], "and" : True }
1230+ },
1231+ tenant_role_names = {
1232+ "tenant2" : {"values" : ["admin" , "user" ], "and" : False }
1233+ },
10611234 )
10621235 users = resp ["users" ]
10631236 self .assertEqual (len (users ), 2 )
@@ -1078,8 +1251,12 @@ def test_search_all(self):
10781251 "page" : 0 ,
10791252 "testUsersOnly" : False ,
10801253 "withTestUser" : False ,
1081- "tenantRoleIds" : {"tenant1" : {"values" : ["roleA" , "roleB" ], "and" : True }},
1082- "tenantRoleNames" : {"tenant2" : {"values" : ["admin" , "user" ], "and" : False }},
1254+ "tenantRoleIds" : {
1255+ "tenant1" : {"values" : ["roleA" , "roleB" ], "and" : True }
1256+ },
1257+ "tenantRoleNames" : {
1258+ "tenant2" : {"values" : ["admin" , "user" ], "and" : False }
1259+ },
10831260 },
10841261 allow_redirects = False ,
10851262 verify = True ,
@@ -1302,8 +1479,12 @@ def test_search_all_test_users(self):
13021479 )
13031480 mock_post .return_value = network_resp
13041481 resp = self .client .mgmt .user .search_all_test_users (
1305- tenant_role_ids = {"tenant1" : {"values" : ["roleA" , "roleB" ], "and" : True }},
1306- tenant_role_names = {"tenant2" : {"values" : ["admin" , "user" ], "and" : False }},
1482+ tenant_role_ids = {
1483+ "tenant1" : {"values" : ["roleA" , "roleB" ], "and" : True }
1484+ },
1485+ tenant_role_names = {
1486+ "tenant2" : {"values" : ["admin" , "user" ], "and" : False }
1487+ },
13071488 )
13081489 users = resp ["users" ]
13091490 self .assertEqual (len (users ), 2 )
@@ -1324,8 +1505,12 @@ def test_search_all_test_users(self):
13241505 "page" : 0 ,
13251506 "testUsersOnly" : True ,
13261507 "withTestUser" : True ,
1327- "tenantRoleIds" : {"tenant1" : {"values" : ["roleA" , "roleB" ], "and" : True }},
1328- "tenantRoleNames" : {"tenant2" : {"values" : ["admin" , "user" ], "and" : False }},
1508+ "tenantRoleIds" : {
1509+ "tenant1" : {"values" : ["roleA" , "roleB" ], "and" : True }
1510+ },
1511+ "tenantRoleNames" : {
1512+ "tenant2" : {"values" : ["admin" , "user" ], "and" : False }
1513+ },
13291514 },
13301515 allow_redirects = False ,
13311516 verify = True ,
0 commit comments