Skip to content

Commit ded1139

Browse files
committed
Add provider tests
1 parent 6114eb0 commit ded1139

1 file changed

Lines changed: 106 additions & 0 deletions

File tree

tests/sentry/identity/datadog/test_provider.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from urllib.parse import parse_qs, parse_qsl, urlparse
88

99
import orjson
10+
import pytest
1011
import responses
1112
from django.contrib.messages.storage.fallback import FallbackStorage
1213
from django.contrib.sessions.backends.base import SessionBase
@@ -15,7 +16,9 @@
1516
from requests.exceptions import SSLError
1617

1718
import sentry.identity
19+
from sentry.auth.exceptions import IdentityNotValid
1820
from sentry.identity.datadog.provider import (
21+
DatadogIdentityProvider,
1922
DatadogOAuth2CallbackView,
2023
DatadogOAuth2DCRView,
2124
DatadogOAuth2LoginView,
@@ -381,3 +384,106 @@ def test_pipeline_views(self, mock_record: MagicMock) -> None:
381384
f"Basic {base64.b64encode(b'dcr-client-id:dcr-client-secret').decode()}"
382385
)
383386
assert exchange_token_request.headers["Authorization"] == expected_auth_header
387+
388+
389+
@control_silo_test
390+
class DatadogIdentityProviderBuildIdentityTest(TestCase):
391+
def setUp(self) -> None:
392+
super().setUp()
393+
self.provider = DatadogIdentityProvider()
394+
self.provider.config = {"site": "datadoghq.com"}
395+
396+
@patch("sentry.identity.datadog.provider.get_user_info")
397+
def test_build_identity(self, mock_get_user_info: MagicMock) -> None:
398+
mock_get_user_info.return_value = {
399+
"id": "dd-user-123",
400+
"attributes": {"email": "user@example.com", "name": "Test User"},
401+
}
402+
403+
result = self.provider.build_identity(
404+
{
405+
"data": {
406+
"access_token": "token-abc",
407+
"refresh_token": "refresh-xyz",
408+
"expires_in": 3600,
409+
"token_type": "Bearer",
410+
"scope": "apm_read",
411+
},
412+
"dcr_client_id": "dcr-client-id",
413+
"dcr_client_secret": "dcr-client-secret",
414+
}
415+
)
416+
417+
assert result["id"] == "dd-user-123"
418+
assert result["email"] == "user@example.com"
419+
assert result["name"] == "Test User"
420+
assert result["type"] == "datadog"
421+
assert result["data"]["access_token"] == "token-abc"
422+
assert result["data"]["refresh_token"] == "refresh-xyz"
423+
assert "expires" in result["data"]
424+
assert result["data"]["token_type"] == "Bearer"
425+
assert result["data"]["scope"] == "apm_read"
426+
assert result["data"]["client_id"] == "dcr-client-id"
427+
assert result["data"]["client_secret"] == "dcr-client-secret"
428+
mock_get_user_info.assert_called_once_with("token-abc", "datadoghq.com")
429+
430+
@patch("sentry.identity.datadog.provider.get_user_info")
431+
def test_build_identity_missing_access_token(self, mock_get_user_info: MagicMock) -> None:
432+
with pytest.raises(ValueError, match="did not return an access_token"):
433+
self.provider.build_identity({"data": {}})
434+
mock_get_user_info.assert_not_called()
435+
436+
@patch("sentry.identity.datadog.provider.get_user_info")
437+
def test_build_identity_missing_user_attributes(self, mock_get_user_info: MagicMock) -> None:
438+
mock_get_user_info.return_value = {"id": "dd-user-456", "attributes": {}}
439+
440+
result = self.provider.build_identity({"data": {"access_token": "token"}})
441+
442+
assert result["id"] == "dd-user-456"
443+
assert result["email"] is None
444+
assert result["name"] is None
445+
446+
447+
@control_silo_test
448+
class DatadogIdentityProviderRefreshTest(TestCase):
449+
def setUp(self) -> None:
450+
super().setUp()
451+
self.provider = DatadogIdentityProvider()
452+
self.provider.config = {"site": "datadoghq.com"}
453+
454+
@responses.activate
455+
def test_get_refresh_token_success(self) -> None:
456+
responses.add(responses.POST, TOKEN_URL, json={"access_token": "new-token"})
457+
458+
identity = MagicMock()
459+
identity.data = {"client_id": "dcr-client", "client_secret": "dcr-secret"}
460+
461+
result = self.provider.get_refresh_token("refresh-token", TOKEN_URL, identity)
462+
463+
assert result.status_code == 200
464+
465+
auth_header = responses.calls[0].request.headers["Authorization"]
466+
assert auth_header == f"Basic {base64.b64encode(b'dcr-client:dcr-secret').decode()}"
467+
468+
data = dict(parse_qsl(responses.calls[0].request.body))
469+
assert data["grant_type"] == "refresh_token"
470+
assert data["refresh_token"] == "refresh-token"
471+
assert "client_id" not in data
472+
assert "client_secret" not in data
473+
474+
def test_get_refresh_token_missing_dcr_credentials(self) -> None:
475+
identity = MagicMock()
476+
identity.data = {}
477+
478+
with pytest.raises(IdentityNotValid, match="Missing DCR credentials"):
479+
self.provider.get_refresh_token("refresh-token", TOKEN_URL, identity)
480+
481+
@responses.activate
482+
def test_get_refresh_token_unauthorized(self) -> None:
483+
responses.add(responses.POST, TOKEN_URL, json={"error": "invalid_grant"}, status=401)
484+
485+
identity = MagicMock()
486+
identity.data = {"client_id": "dcr-client-id", "client_secret": "dcr-client-secret"}
487+
488+
with pytest.raises(IdentityNotValid):
489+
self.provider.get_refresh_token("refresh-token", TOKEN_URL, identity)

0 commit comments

Comments
 (0)