Skip to content

Commit 21ea819

Browse files
committed
fix: tests
1 parent 18d1769 commit 21ea819

1 file changed

Lines changed: 113 additions & 129 deletions

File tree

test/oauth2_test.py

Lines changed: 113 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,7 @@
1212

1313
from datetime import datetime, timedelta
1414
from unittest import IsolatedAsyncioTestCase
15-
16-
import unittest
17-
import pytest
18-
from unittest.mock import patch, MagicMock
19-
from openfga_sdk.credentials import CredentialConfiguration
20-
from openfga_sdk.oauth2 import OAuth2Client
21-
15+
from unittest.mock import patch
2216

2317
import urllib3
2418

@@ -501,126 +495,116 @@ async def test_get_authentication_add_scheme_and_path(self, mock_request):
501495
)
502496
await rest_client.close()
503497

504-
class TestOAuth2ClientScopeHandling(unittest.TestCase):
505-
"""Test OAuth2Client scope serialization in synchronous context"""
498+
@patch.object(rest.RESTClientObject, "request")
499+
async def test_get_authentication_obtain_client_credentials_with_scopes_list(self, mock_request):
500+
"""
501+
Test getting authentication header when method is client credentials with scopes as list
502+
"""
503+
response_body = """
504+
{
505+
"expires_in": 120,
506+
"access_token": "AABBCCDD"
507+
}
508+
"""
509+
mock_request.return_value = mock_response(response_body, 200)
506510

507-
def setUp(self):
508-
self.config = CredentialConfiguration(
509-
client_id="test_client_id",
510-
client_secret="test_client_secret",
511-
api_issuer="https://example.com",
512-
api_audience="test_audience"
513-
)
514-
self.oauth_client = OAuth2Client(self.config)
515-
516-
@patch('requests.post')
517-
def test_list_scopes_serialization(self, mock_post):
518-
"""Test that list scopes are serialized as space-delimited string"""
519-
# Setup mock response
520-
mock_response = MagicMock()
521-
mock_response.json.return_value = {"access_token": "test_token", "expires_in": 3600}
522-
mock_response.status_code = 200
523-
mock_post.return_value = mock_response
524-
525-
# Set list scopes
526-
self.config.scopes = ["read", "write", "admin"]
527-
528-
# Make token request
529-
self.oauth_client.request_token()
530-
531-
# Verify scope parameter was correctly formatted
532-
args, kwargs = mock_post.call_args
533-
self.assertIn('data', kwargs)
534-
self.assertIn('scope', kwargs['data'])
535-
self.assertEqual(kwargs['data']['scope'], "read write admin")
536-
537-
@patch('requests.post')
538-
def test_string_scope_serialization(self, mock_post):
539-
"""Test that string scope is used unchanged"""
540-
# Setup mock response
541-
mock_response = MagicMock()
542-
mock_response.json.return_value = {"access_token": "test_token", "expires_in": 3600}
543-
mock_response.status_code = 200
544-
mock_post.return_value = mock_response
545-
546-
# Set string scope
547-
self.config.scopes = "read write admin"
548-
549-
# Make token request
550-
self.oauth_client.request_token()
551-
552-
# Verify scope parameter was passed unchanged
553-
args, kwargs = mock_post.call_args
554-
self.assertIn('data', kwargs)
555-
self.assertIn('scope', kwargs['data'])
556-
self.assertEqual(kwargs['data']['scope'], "read write admin")
557-
558-
559-
class TestOAuth2ClientScopeHandlingAsync:
560-
"""Test OAuth2Client scope serialization in asynchronous context"""
561-
562-
@pytest.fixture
563-
def oauth_client(self):
564-
config = CredentialConfiguration(
565-
client_id="test_client_id",
566-
client_secret="test_client_secret",
567-
api_issuer="https://example.com",
568-
api_audience="test_audience"
569-
)
570-
return OAuth2Client(config)
571-
572-
@pytest.mark.asyncio
573-
async def test_list_scopes_serialization_async(self, oauth_client, monkeypatch):
574-
"""Test that list scopes are serialized as space-delimited string in async context"""
575-
# Mock the async HTTP response
576-
mock_response = MagicMock()
577-
mock_response.json = MagicMock(return_value={"access_token": "test_token", "expires_in": 3600})
578-
mock_response.status_code = 200
579-
580-
# Set up mock for the async HTTP client
581-
mock_client_session = MagicMock()
582-
mock_client_session.post = MagicMock(return_value=mock_response)
583-
mock_client_session.__aenter__ = MagicMock(return_value=mock_client_session)
584-
mock_client_session.__aexit__ = MagicMock(return_value=None)
585-
586-
monkeypatch.setattr('aiohttp.ClientSession', MagicMock(return_value=mock_client_session))
587-
588-
# Set list scopes
589-
oauth_client.configuration.scopes = ["read", "write", "admin"]
590-
591-
# Make async token request
592-
await oauth_client.request_token_async()
593-
594-
# Verify scope parameter was correctly formatted
595-
args, kwargs = mock_client_session.post.call_args
596-
self.assertIn('data', kwargs)
597-
self.assertIn('scope', kwargs['data'])
598-
self.assertEqual(kwargs['data']['scope'], "read write admin")
599-
600-
@pytest.mark.asyncio
601-
async def test_string_scope_serialization_async(self, oauth_client, monkeypatch):
602-
"""Test that string scope is used unchanged in async context"""
603-
# Mock the async HTTP response
604-
mock_response = MagicMock()
605-
mock_response.json = MagicMock(return_value={"access_token": "test_token", "expires_in": 3600})
606-
mock_response.status_code = 200
607-
608-
# Set up mock for the async HTTP client
609-
mock_client_session = MagicMock()
610-
mock_client_session.post = MagicMock(return_value=mock_response)
611-
mock_client_session.__aenter__ = MagicMock(return_value=mock_client_session)
612-
mock_client_session.__aexit__ = MagicMock(return_value=None)
613-
614-
monkeypatch.setattr('aiohttp.ClientSession', MagicMock(return_value=mock_client_session))
615-
616-
# Set string scope
617-
oauth_client.configuration.scopes = "read write admin"
618-
619-
# Make async token request
620-
await oauth_client.request_token_async()
621-
622-
# Verify scope parameter was passed unchanged
623-
args, kwargs = mock_client_session.post.call_args
624-
self.assertIn('data', kwargs)
625-
self.assertIn('scope', kwargs['data'])
626-
self.assertEqual(kwargs['data']['scope'], "read write admin")
511+
credentials = Credentials(
512+
method="client_credentials",
513+
configuration=CredentialConfiguration(
514+
client_id="myclientid",
515+
client_secret="mysecret",
516+
api_issuer="issuer.fga.example",
517+
api_audience="myaudience",
518+
scopes=["read", "write", "admin"],
519+
),
520+
)
521+
rest_client = rest.RESTClientObject(Configuration())
522+
current_time = datetime.now()
523+
client = OAuth2Client(credentials)
524+
auth_header = await client.get_authentication_header(rest_client)
525+
self.assertEqual(auth_header, {"Authorization": "Bearer AABBCCDD"})
526+
self.assertEqual(client._access_token, "AABBCCDD")
527+
self.assertGreaterEqual(
528+
client._access_expiry_time, current_time + timedelta(seconds=120)
529+
)
530+
expected_header = urllib3.response.HTTPHeaderDict(
531+
{
532+
"Accept": "application/json",
533+
"Content-Type": "application/x-www-form-urlencoded",
534+
"User-Agent": "openfga-sdk (python) 0.9.5",
535+
}
536+
)
537+
mock_request.assert_called_once_with(
538+
method="POST",
539+
url="https://issuer.fga.example/oauth/token",
540+
headers=expected_header,
541+
query_params=None,
542+
body=None,
543+
_preload_content=True,
544+
_request_timeout=None,
545+
post_params={
546+
"client_id": "myclientid",
547+
"client_secret": "mysecret",
548+
"audience": "myaudience",
549+
"grant_type": "client_credentials",
550+
"scope": "read write admin",
551+
},
552+
)
553+
await rest_client.close()
554+
555+
@patch.object(rest.RESTClientObject, "request")
556+
async def test_get_authentication_obtain_client_credentials_with_scopes_string(self, mock_request):
557+
"""
558+
Test getting authentication header when method is client credentials with scopes as string
559+
"""
560+
response_body = """
561+
{
562+
"expires_in": 120,
563+
"access_token": "AABBCCDD"
564+
}
565+
"""
566+
mock_request.return_value = mock_response(response_body, 200)
567+
568+
credentials = Credentials(
569+
method="client_credentials",
570+
configuration=CredentialConfiguration(
571+
client_id="myclientid",
572+
client_secret="mysecret",
573+
api_issuer="issuer.fga.example",
574+
api_audience="myaudience",
575+
scopes="read write admin",
576+
),
577+
)
578+
rest_client = rest.RESTClientObject(Configuration())
579+
current_time = datetime.now()
580+
client = OAuth2Client(credentials)
581+
auth_header = await client.get_authentication_header(rest_client)
582+
self.assertEqual(auth_header, {"Authorization": "Bearer AABBCCDD"})
583+
self.assertEqual(client._access_token, "AABBCCDD")
584+
self.assertGreaterEqual(
585+
client._access_expiry_time, current_time + timedelta(seconds=120)
586+
)
587+
expected_header = urllib3.response.HTTPHeaderDict(
588+
{
589+
"Accept": "application/json",
590+
"Content-Type": "application/x-www-form-urlencoded",
591+
"User-Agent": "openfga-sdk (python) 0.9.5",
592+
}
593+
)
594+
mock_request.assert_called_once_with(
595+
method="POST",
596+
url="https://issuer.fga.example/oauth/token",
597+
headers=expected_header,
598+
query_params=None,
599+
body=None,
600+
_preload_content=True,
601+
_request_timeout=None,
602+
post_params={
603+
"client_id": "myclientid",
604+
"client_secret": "mysecret",
605+
"audience": "myaudience",
606+
"grant_type": "client_credentials",
607+
"scope": "read write admin",
608+
},
609+
)
610+
await rest_client.close()

0 commit comments

Comments
 (0)