Skip to content

Commit

Permalink
Add async support for Directory Sync (#288)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattgd authored Jul 24, 2024
1 parent 3138264 commit 79a5de3
Show file tree
Hide file tree
Showing 13 changed files with 859 additions and 194 deletions.
68 changes: 59 additions & 9 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Mapping, Union
from unittest.mock import AsyncMock, MagicMock

import httpx
Expand All @@ -6,7 +7,7 @@

from tests.utils.list_resource import list_response_of
import workos
from workos.utils.http_client import SyncHTTPClient
from workos.utils.http_client import AsyncHTTPClient, SyncHTTPClient


class MockResponse(object):
Expand Down Expand Up @@ -124,20 +125,69 @@ def mock(*args, **kwargs):


@pytest.fixture
def mock_sync_http_client_with_response():
def inner(http_client: SyncHTTPClient, response_dict: dict, status_code: int):
http_client._client.request = MagicMock(
return_value=httpx.Response(status_code, json=response_dict),
def mock_http_client_with_response(monkeypatch):
def inner(
http_client: Union[SyncHTTPClient, AsyncHTTPClient],
response_dict: dict,
status_code: int = 200,
headers: Mapping[str, str] = None,
):
mock_class = (
AsyncMock if isinstance(http_client, AsyncHTTPClient) else MagicMock
)
mock = mock_class(
return_value=httpx.Response(
status_code=status_code, headers=headers, json=response_dict
),
)
monkeypatch.setattr(http_client._client, "request", mock)

return inner


@pytest.fixture
def mock_async_http_client_with_response():
def inner(http_client: SyncHTTPClient, response_dict: dict, status_code: int):
http_client._client.request = AsyncMock(
return_value=httpx.Response(status_code, json=response_dict),
def mock_pagination_request_for_http_client(monkeypatch):
# Mocking pagination correctly requires us to index into a list of data
# and correctly set the before and after metadata in the response.
def inner(
http_client: Union[SyncHTTPClient, AsyncHTTPClient],
data_list: list,
status_code: int = 200,
headers: Mapping[str, str] = None,
):
# For convenient index lookup, store the list of object IDs.
data_ids = list(map(lambda x: x["id"], data_list))

def mock_function(*args, **kwargs):
params = kwargs.get("params") or {}
request_after = params.get("after", None)
limit = params.get("limit", 10)

if request_after is None:
# First page
start = 0
else:
# A subsequent page, return the first item _after_ the index we locate
start = data_ids.index(request_after) + 1
data = data_list[start : start + limit]
if len(data) < limit or len(data) == 0:
# No more data, set after to None
after = None
else:
# Set after to the last item in this page of results
after = data[-1]["id"]

return httpx.Response(
status_code=status_code,
headers=headers,
json=list_response_of(data=data, before=request_after, after=after),
)

mock_class = (
AsyncMock if isinstance(http_client, AsyncHTTPClient) else MagicMock
)
mock = mock_class(side_effect=mock_function)

monkeypatch.setattr(http_client._client, "request", mock)

return inner
83 changes: 0 additions & 83 deletions tests/test_async_events.py

This file was deleted.

49 changes: 48 additions & 1 deletion tests/test_client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from workos import client
from workos import async_client, client
from workos.exceptions import ConfigurationException


Expand All @@ -9,6 +9,7 @@ class TestClient(object):
def setup(self):
client._audit_logs = None
client._directory_sync = None
client._events = None
client._organizations = None
client._passwordless = None
client._portal = None
Expand All @@ -24,6 +25,9 @@ def test_initialize_audit_logs(self, set_api_key):
def test_initialize_directory_sync(self, set_api_key):
assert bool(client.directory_sync)

def test_initialize_events(self, set_api_key):
assert bool(client.events)

def test_initialize_organizations(self, set_api_key):
assert bool(client.organizations)

Expand Down Expand Up @@ -76,6 +80,14 @@ def test_initialize_directory_sync_missing_api_key(self):

assert "api_key" in message

def test_initialize_events_missing_api_key(self):
with pytest.raises(ConfigurationException) as ex:
client.events

message = str(ex)

assert "api_key" in message

def test_initialize_organizations_missing_api_key(self):
with pytest.raises(ConfigurationException) as ex:
client.organizations
Expand Down Expand Up @@ -124,3 +136,38 @@ def test_initialize_user_management_missing_api_key_and_client_id(self):

assert "api_key" in message
assert "client_id" in message


class TestAsyncClient(object):
@pytest.fixture(autouse=True)
def setup(self):
async_client._audit_logs = None
async_client._directory_sync = None
async_client._events = None
async_client._organizations = None
async_client._passwordless = None
async_client._portal = None
async_client._sso = None
async_client._user_management = None

def test_initialize_directory_sync(self, set_api_key):
assert bool(async_client.directory_sync)

def test_initialize_directory_sync_missing_api_key(self):
with pytest.raises(ConfigurationException) as ex:
async_client.directory_sync

message = str(ex)

assert "api_key" in message

def test_initialize_events(self, set_api_key):
assert bool(async_client.events)

def test_initialize_events_missing_api_key(self):
with pytest.raises(ConfigurationException) as ex:
async_client.events

message = str(ex)

assert "api_key" in message
Loading

0 comments on commit 79a5de3

Please sign in to comment.