Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add async support for Directory Sync #288

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading