from collections.abc import Iterator import httpx import pytest import respx from dmp.adapters.google.client import GoogleClient from dmp.adapters.google.models import ( AccessToken, AdAccount, AdAccountApiResponse, AdAccountResourceResponse, AudienceApiResponse, CampaignApiResponse, GoogleGrantType, NestedAdAccount, NestedAdAccountApiResponse, RefreshToken, User, ) from tests.unit.faker import FakerTyped from tests.unit.types import BuildModel class TestGoogleClient: @pytest.fixture def client(self) -> Iterator[GoogleClient]: with GoogleClient( client_id="client", client_secret="secret", developer_token="developer_token", ) as client: yield client def test_get_user( self, client: GoogleClient, respx_mock: respx.MockRouter, build_model: BuildModel, fake: FakerTyped, ) -> None: user = build_model(User) user_access_token = fake.plain_token() respx_mock.get( "https://www.googleapis.com/oauth2/v1/userinfo", headers={ "Authorization": f"Bearer {user_access_token}", }, ).mock(return_value=httpx.Response(status_code=200, json=user.model_dump())) result = client.get_user( access_token=user_access_token, ) assert result == user def test_get_refresh_token( self, client: GoogleClient, respx_mock: respx.MockRouter, build_model: BuildModel, fake: FakerTyped, ) -> None: refresh_token = build_model(RefreshToken) redirect_uri = fake.url() code_verifier = fake.pystr() auth_code = fake.plain_token() respx_mock.post( "https://oauth2.googleapis.com/token", json={ "client_id": client.client_id, "client_secret": client.client_secret, "code": auth_code, "grant_type": GoogleGrantType.AUTHORIZATION_CODE, "redirect_uri": redirect_uri, "code_verifier": code_verifier, }, ).mock( return_value=httpx.Response( status_code=200, json=refresh_token.model_dump() ) ) result = client.get_refresh_token( auth_code=auth_code, redirect_uri=redirect_uri, code_verifier=code_verifier, ) assert result == refresh_token def test_get_access_token( self, client: GoogleClient, respx_mock: respx.MockRouter, build_model: BuildModel, fake: FakerTyped, ) -> None: access_token = build_model(AccessToken) response_data = { "access_token": access_token.access_token, "scope": access_token.scope, } refresh_token = fake.plain_token() respx_mock.post( "https://oauth2.googleapis.com/token", json={ "client_id": client.client_id, "client_secret": client.client_secret, "refresh_token": refresh_token, "grant_type": GoogleGrantType.REFRESH_TOKEN, }, ).mock(return_value=httpx.Response(status_code=200, json=response_data)) result = client.get_access_token( refresh_token=refresh_token, ) assert result == access_token def test_get_ad_account_resources( self, client: GoogleClient, respx_mock: respx.MockRouter, build_model: BuildModel, fake: FakerTyped, ) -> None: access_token = fake.plain_token() response = build_model(AdAccountResourceResponse) respx_mock.get( "https://googleads.googleapis.com/v22/customers:listAccessibleCustomers", headers={ "Authorization": f"Bearer {access_token}", }, ).mock( return_value=httpx.Response( status_code=200, json=response.model_dump(by_alias=True) ) ) result = client.get_ad_account_resources(access_token=access_token) assert result == response def test_get_ad_account_details( self, client: GoogleClient, respx_mock: respx.MockRouter, build_model: BuildModel, fake: FakerTyped, ) -> None: access_token = fake.plain_token() response = build_model(AdAccountApiResponse, results=[build_model(AdAccount)]) ad_account_id = fake.integer() respx_mock.post( f"https://googleads.googleapis.com/v22/customers/{ad_account_id}/googleAds:search", headers={ "Authorization": f"Bearer {access_token}", "developer-token": client.developer_token, }, ).mock( return_value=httpx.Response( status_code=200, json=response.model_dump(by_alias=True) ) ) result = client.get_ad_account_details( access_token=access_token, ad_account_id=ad_account_id, parent_ad_account_id=None, ) assert result == response def test_get_nested_ad_account_details( self, client: GoogleClient, respx_mock: respx.MockRouter, build_model: BuildModel, fake: FakerTyped, ) -> None: access_token = fake.plain_token() response = build_model( NestedAdAccountApiResponse, results=[build_model(NestedAdAccount)] ) ad_account_id = fake.integer() respx_mock.post( f"https://googleads.googleapis.com/v22/customers/{ad_account_id}/googleAds:search", headers={ "Authorization": f"Bearer {access_token}", "developer-token": client.developer_token, }, ).mock( return_value=httpx.Response( status_code=200, json=response.model_dump(by_alias=True) ) ) result = client.get_nested_ad_account_details( access_token=access_token, ad_account_id=ad_account_id ) assert result == response def test_get_campaign_ids( self, client: GoogleClient, respx_mock: respx.MockRouter, build_model: BuildModel, fake: FakerTyped, ) -> None: access_token = fake.plain_token() response = build_model(CampaignApiResponse) ad_account_id = fake.integer() respx_mock.post( f"https://googleads.googleapis.com/v22/customers/{ad_account_id}/googleAds:search", headers={ "Authorization": f"Bearer {access_token}", "developer-token": client.developer_token, }, ).mock( return_value=httpx.Response( status_code=200, json=response.model_dump(by_alias=True) ) ) result = client.get_campaign_ids( access_token=access_token, ad_account_id=ad_account_id, login_customer_id=None, ) assert result == response def test_create_user_list( self, client: GoogleClient, respx_mock: respx.MockRouter, build_model: BuildModel, fake: FakerTyped, ) -> None: access_token = fake.plain_token() response = build_model(AudienceApiResponse) ad_account_id = fake.pystr() audience_name = fake.pystr() audience_description = fake.pystr() respx_mock.post( f"https://googleads.googleapis.com/v22/customers/{ad_account_id}/userLists:mutate", headers={ "Authorization": f"Bearer {access_token}", "developer-token": client.developer_token, }, ).mock( return_value=httpx.Response( status_code=200, json=response.model_dump(by_alias=True) ) ) result = client.create_user_list( access_token=access_token, ad_account_id=ad_account_id, name=audience_name, description=audience_description, login_customer_id=None, ) assert result == response.results[0]