@@ -393,3 +393,170 @@ def test_file_uploads_complete(client, part_uploaded_file_upload_id):
393393 assert response ["content_type" ] == "text/plain"
394394 assert response ["number_of_parts" ]["total" ] == 3
395395 assert response ["number_of_parts" ]["sent" ] == 3
396+
397+
398+ def test_oauth_introspect (client , mocker ):
399+ """Test OAuth token introspection with mock - tests Basic auth encoding"""
400+ mock_response = {"active" : False , "request_id" : "test-request-id" }
401+
402+ mock_send = mocker .patch .object (
403+ client .client ,
404+ "send" ,
405+ return_value = mocker .Mock (
406+ json = lambda : mock_response , raise_for_status = lambda : None
407+ ),
408+ )
409+
410+ response = client .oauth .introspect (
411+ client_id = "test_client_id" ,
412+ client_secret = "test_client_secret" ,
413+ token = "test_token" ,
414+ )
415+
416+ assert "active" in response
417+ assert isinstance (response ["active" ], bool )
418+
419+ mock_send .assert_called_once ()
420+ request = mock_send .call_args [0 ][0 ]
421+ assert "Authorization" in request .headers
422+ assert request .headers ["Authorization" ].startswith ("Basic " )
423+ assert (
424+ request .headers ["Authorization" ]
425+ == "Basic dGVzdF9jbGllbnRfaWQ6dGVzdF9jbGllbnRfc2VjcmV0"
426+ )
427+
428+
429+ def test_oauth_token_with_basic_auth (client , mocker ):
430+ """Test OAuth token exchange with Basic auth - exercises auth encoding path"""
431+ mock_response = {
432+ "access_token" : "secret_test_token" ,
433+ "token_type" : "bearer" ,
434+ "bot_id" : "bot_123" ,
435+ }
436+
437+ mock_send = mocker .patch .object (
438+ client .client ,
439+ "send" ,
440+ return_value = mocker .Mock (
441+ json = lambda : mock_response , raise_for_status = lambda : None
442+ ),
443+ )
444+
445+ response = client .oauth .token (
446+ client_id = "test_client_id" ,
447+ client_secret = "test_client_secret" ,
448+ grant_type = "authorization_code" ,
449+ code = "test_code" ,
450+ redirect_uri = "http://localhost:3000/callback" ,
451+ )
452+
453+ assert response ["access_token" ] == "secret_test_token"
454+
455+ mock_send .assert_called_once ()
456+ request = mock_send .call_args [0 ][0 ]
457+ assert "Authorization" in request .headers
458+ assert request .headers ["Authorization" ].startswith ("Basic " )
459+ import base64
460+
461+ expected = base64 .b64encode (b"test_client_id:test_client_secret" ).decode ()
462+ assert request .headers ["Authorization" ] == f"Basic { expected } "
463+
464+
465+ def test_oauth_revoke_with_basic_auth (client , mocker ):
466+ """Test OAuth revoke with Basic auth - exercises auth encoding path"""
467+ mock_response = {}
468+
469+ mock_send = mocker .patch .object (
470+ client .client ,
471+ "send" ,
472+ return_value = mocker .Mock (
473+ json = lambda : mock_response , raise_for_status = lambda : None
474+ ),
475+ )
476+
477+ response = client .oauth .revoke (
478+ client_id = "test_client_id" ,
479+ client_secret = "test_client_secret" ,
480+ token = "test_token" ,
481+ )
482+
483+ assert response == {}
484+
485+ mock_send .assert_called_once ()
486+ request = mock_send .call_args [0 ][0 ]
487+ assert "Authorization" in request .headers
488+ assert request .headers ["Authorization" ].startswith ("Basic " )
489+
490+
491+ def test_oauth_revoke (client , mocker ):
492+ """Test OAuth token revocation with mock (can't use cassette - token becomes invalid)"""
493+ mock_response = {}
494+ mock_request = mocker .patch .object (client , "request" , return_value = mock_response )
495+
496+ response = client .oauth .revoke (
497+ client_id = "test_client_id" ,
498+ client_secret = "test_client_secret" ,
499+ token = "test_token" ,
500+ )
501+
502+ assert response == {}
503+ mock_request .assert_called_once_with (
504+ path = "oauth/revoke" ,
505+ method = "POST" ,
506+ body = {"token" : "test_token" },
507+ auth = {"client_id" : "test_client_id" , "client_secret" : "test_client_secret" },
508+ )
509+
510+
511+ def test_oauth_token_authorization_code (client , mocker ):
512+ mock_response = {
513+ "access_token" : "secret_test_token" ,
514+ "token_type" : "bearer" ,
515+ "bot_id" : "bot_123" ,
516+ "workspace_id" : "ws_456" ,
517+ "workspace_name" : "Test Workspace" ,
518+ "owner" : {"type" : "user" , "user" : {"object" : "user" , "id" : "user_789" }},
519+ }
520+
521+ mock_request = mocker .patch .object (client , "request" , return_value = mock_response )
522+
523+ response = client .oauth .token (
524+ client_id = "test_client_id" ,
525+ client_secret = "test_client_secret" ,
526+ grant_type = "authorization_code" ,
527+ code = "test_code" ,
528+ redirect_uri = "http://localhost:3000/callback" ,
529+ )
530+
531+ assert response ["access_token" ] == "secret_test_token"
532+ assert response ["bot_id" ] == "bot_123"
533+ mock_request .assert_called_once ()
534+ call_kwargs = mock_request .call_args [1 ]
535+ assert call_kwargs ["path" ] == "oauth/token"
536+ assert call_kwargs ["method" ] == "POST"
537+ assert call_kwargs ["auth" ] == {
538+ "client_id" : "test_client_id" ,
539+ "client_secret" : "test_client_secret" ,
540+ }
541+
542+
543+ def test_oauth_token_refresh_token (client , mocker ):
544+ mock_response = {
545+ "access_token" : "secret_refreshed_token" ,
546+ "token_type" : "bearer" ,
547+ "bot_id" : "bot_123" ,
548+ }
549+
550+ mock_request = mocker .patch .object (client , "request" , return_value = mock_response )
551+
552+ response = client .oauth .token (
553+ client_id = "test_client_id" ,
554+ client_secret = "test_client_secret" ,
555+ grant_type = "refresh_token" ,
556+ refresh_token = "test_refresh_token" ,
557+ )
558+
559+ assert response ["access_token" ] == "secret_refreshed_token"
560+ mock_request .assert_called_once ()
561+ call_kwargs = mock_request .call_args [1 ]
562+ assert call_kwargs ["path" ] == "oauth/token"
0 commit comments