From f380c45d8f9f16dd70da68e345c47845ed6cf365 Mon Sep 17 00:00:00 2001 From: JoshuaVulcan <38018017+JoshuaVulcan@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:00:12 -0800 Subject: [PATCH 1/2] ERA-12664: add event provider and event source CRUD to both clients Add full CRUD methods for event providers and event sources to both sync (ERClient) and async (AsyncERClient) clients for parity: Sync client: - get_eventproviders(), get_eventprovider(), patch_eventprovider() - get_eventsources(), get_eventsource(), patch_eventsource() Async client: - post_eventprovider(), post_eventsource() - get_eventproviders(), get_eventprovider(), patch_eventprovider() - get_eventsources(), get_eventsource(), patch_eventsource() Includes 28 new tests covering success and error cases for all methods across both clients. Co-authored-by: Cursor --- erclient/client.py | 134 ++++++++++ tests/async_client/test_eventproviders.py | 300 +++++++++++++++++++++ tests/sync_client/__init__.py | 0 tests/sync_client/conftest.py | 21 ++ tests/sync_client/test_eventproviders.py | 306 ++++++++++++++++++++++ 5 files changed, 761 insertions(+) create mode 100644 tests/async_client/test_eventproviders.py create mode 100644 tests/sync_client/__init__.py create mode 100644 tests/sync_client/conftest.py create mode 100644 tests/sync_client/test_eventproviders.py diff --git a/erclient/client.py b/erclient/client.py index 02bbbc0..48c2dac 100644 --- a/erclient/client.py +++ b/erclient/client.py @@ -369,6 +369,61 @@ def post_eventsource(self, eventprovider_id, eventsource): self.logger.debug('Result of eventsource post is: %s', result) return result + def get_eventproviders(self): + """ + Get a list of event providers. + :return: list of event provider dicts + """ + return self._get('activity/eventproviders') + + def get_eventprovider(self, eventprovider_id): + """ + Get a single event provider by ID. + :param eventprovider_id: UUID of the event provider + :return: event provider data dict + """ + return self._get(f'activity/eventprovider/{eventprovider_id}') + + def patch_eventprovider(self, eventprovider_id, payload): + """ + Update an event provider with partial data. + :param eventprovider_id: UUID of the event provider + :param payload: dict of fields to update + :return: updated event provider data dict + """ + self.logger.debug('Patching eventprovider %s: %s', eventprovider_id, payload) + result = self._patch(f'activity/eventprovider/{eventprovider_id}', payload=payload) + self.logger.debug('Result of eventprovider patch is: %s', result) + return result + + def get_eventsources(self, eventprovider_id): + """ + Get the list of event sources for a given event provider. + :param eventprovider_id: UUID of the event provider + :return: list of event source dicts + """ + return self._get(f'activity/eventprovider/{eventprovider_id}/eventsources') + + def get_eventsource(self, eventsource_id): + """ + Get a single event source by ID. + :param eventsource_id: UUID of the event source + :return: event source data dict + """ + return self._get(f'activity/eventsource/{eventsource_id}') + + def patch_eventsource(self, eventsource_id, payload): + """ + Update an event source with partial data. + :param eventsource_id: UUID of the event source + :param payload: dict of fields to update + :return: updated event source data dict + """ + self.logger.debug('Patching eventsource %s: %s', eventsource_id, payload) + result = self._patch(f'activity/eventsource/{eventsource_id}', payload=payload) + self.logger.debug('Result of eventsource patch is: %s', result) + return result + def post_event_photo(self, event_id, image): raise ValueError('post_event_photo is no longer valid.') @@ -1185,6 +1240,85 @@ async def post_message(self, message, params=None): self.logger.debug(f'Posting message: {message}') return await self._post('messages', payload=message, params=params) + async def post_eventprovider(self, eventprovider): + """ + Create a new event provider. + :param eventprovider: dict with event provider payload + :return: created event provider data + """ + self.logger.debug(f'Posting eventprovider: {eventprovider}') + result = await self._post('activity/eventproviders/', payload=eventprovider) + self.logger.debug(f'Result of eventprovider post is: {result}') + return result + + async def post_eventsource(self, eventprovider_id, eventsource): + """ + Create a new event source under an event provider. + :param eventprovider_id: UUID of the parent event provider + :param eventsource: dict with event source payload + :return: created event source data + """ + self.logger.debug(f'Posting eventsource: {eventsource}') + result = await self._post( + f'activity/eventprovider/{eventprovider_id}/eventsources', payload=eventsource) + self.logger.debug(f'Result of eventsource post is: {result}') + return result + + async def get_eventproviders(self): + """ + Get a list of event providers. + :return: list of event provider dicts + """ + return await self._get('activity/eventproviders') + + async def get_eventprovider(self, eventprovider_id): + """ + Get a single event provider by ID. + :param eventprovider_id: UUID of the event provider + :return: event provider data dict + """ + return await self._get(f'activity/eventprovider/{eventprovider_id}') + + async def patch_eventprovider(self, eventprovider_id, payload): + """ + Update an event provider with partial data. + :param eventprovider_id: UUID of the event provider + :param payload: dict of fields to update + :return: updated event provider data dict + """ + self.logger.debug(f'Patching eventprovider {eventprovider_id}: {payload}') + result = await self._patch(f'activity/eventprovider/{eventprovider_id}', payload=payload) + self.logger.debug(f'Result of eventprovider patch is: {result}') + return result + + async def get_eventsources(self, eventprovider_id): + """ + Get the list of event sources for a given event provider. + :param eventprovider_id: UUID of the event provider + :return: list of event source dicts + """ + return await self._get(f'activity/eventprovider/{eventprovider_id}/eventsources') + + async def get_eventsource(self, eventsource_id): + """ + Get a single event source by ID. + :param eventsource_id: UUID of the event source + :return: event source data dict + """ + return await self._get(f'activity/eventsource/{eventsource_id}') + + async def patch_eventsource(self, eventsource_id, payload): + """ + Update an event source with partial data. + :param eventsource_id: UUID of the event source + :param payload: dict of fields to update + :return: updated event source data dict + """ + self.logger.debug(f'Patching eventsource {eventsource_id}: {payload}') + result = await self._patch(f'activity/eventsource/{eventsource_id}', payload=payload) + self.logger.debug(f'Result of eventsource patch is: {result}') + return result + async def get_source_by_manufacturer_id(self, manufacturer_id): """ Get a source by manufacturer_id. diff --git a/tests/async_client/test_eventproviders.py b/tests/async_client/test_eventproviders.py new file mode 100644 index 0000000..5bd7194 --- /dev/null +++ b/tests/async_client/test_eventproviders.py @@ -0,0 +1,300 @@ +import httpx +import pytest +import respx + +from erclient import ERClientNotFound, ERClientPermissionDenied + + +EVENTPROVIDER_ID = "a1b2c3d4-e5f6-7890-abcd-ef1234567890" +EVENTSOURCE_ID = "f0e1d2c3-b4a5-6789-0fed-cba987654321" + + +@pytest.fixture +def eventprovider_payload(): + return { + "display": "My Test Provider", + "owner": {"id": "user-id-123"}, + } + + +@pytest.fixture +def eventprovider_response(): + return { + "data": { + "id": EVENTPROVIDER_ID, + "display": "My Test Provider", + "is_active": True, + "owner": {"id": "user-id-123"}, + }, + "status": {"code": 201, "message": "Created"}, + } + + +@pytest.fixture +def eventprovider_detail_response(): + return { + "data": { + "id": EVENTPROVIDER_ID, + "display": "My Test Provider", + "is_active": True, + "owner": {"id": "user-id-123"}, + }, + } + + +@pytest.fixture +def eventproviders_list_response(): + return { + "data": [ + { + "id": EVENTPROVIDER_ID, + "display": "My Test Provider", + "is_active": True, + }, + { + "id": "00000000-0000-0000-0000-000000000002", + "display": "Another Provider", + "is_active": False, + }, + ], + } + + +@pytest.fixture +def eventprovider_patched_response(): + return { + "data": { + "id": EVENTPROVIDER_ID, + "display": "Updated Provider Name", + "is_active": True, + }, + } + + +@pytest.fixture +def eventsource_payload(): + return { + "display": "Test Event Source", + } + + +@pytest.fixture +def eventsource_response(): + return { + "data": { + "id": EVENTSOURCE_ID, + "display": "Test Event Source", + "eventprovider": EVENTPROVIDER_ID, + }, + "status": {"code": 201, "message": "Created"}, + } + + +@pytest.fixture +def eventsources_list_response(): + return { + "data": [ + { + "id": EVENTSOURCE_ID, + "display": "Test Event Source", + "eventprovider": EVENTPROVIDER_ID, + }, + { + "id": "11111111-1111-1111-1111-111111111111", + "display": "Second Source", + "eventprovider": EVENTPROVIDER_ID, + }, + ], + } + + +@pytest.fixture +def eventsource_detail_response(): + return { + "data": { + "id": EVENTSOURCE_ID, + "display": "Test Event Source", + "eventprovider": EVENTPROVIDER_ID, + }, + } + + +@pytest.fixture +def eventsource_patched_response(): + return { + "data": { + "id": EVENTSOURCE_ID, + "display": "Renamed Source", + "eventprovider": EVENTPROVIDER_ID, + }, + } + + +# -- Event Provider Tests -- + + +@pytest.mark.asyncio +async def test_post_eventprovider_success(er_client, eventprovider_payload, eventprovider_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.post("activity/eventproviders/") + route.return_value = httpx.Response(httpx.codes.CREATED, json=eventprovider_response) + result = await er_client.post_eventprovider(eventprovider_payload) + assert route.called + assert result == eventprovider_response["data"] + await er_client.close() + + +@pytest.mark.asyncio +async def test_post_eventprovider_forbidden(er_client, eventprovider_payload, forbidden_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.post("activity/eventproviders/") + route.return_value = httpx.Response(httpx.codes.FORBIDDEN, json=forbidden_response) + with pytest.raises(ERClientPermissionDenied): + await er_client.post_eventprovider(eventprovider_payload) + assert route.called + await er_client.close() + + +@pytest.mark.asyncio +async def test_get_eventproviders_success(er_client, eventproviders_list_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.get("activity/eventproviders") + route.return_value = httpx.Response(httpx.codes.OK, json=eventproviders_list_response) + result = await er_client.get_eventproviders() + assert route.called + assert result == eventproviders_list_response["data"] + assert len(result) == 2 + await er_client.close() + + +@pytest.mark.asyncio +async def test_get_eventprovider_success(er_client, eventprovider_detail_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.get(f"activity/eventprovider/{EVENTPROVIDER_ID}") + route.return_value = httpx.Response(httpx.codes.OK, json=eventprovider_detail_response) + result = await er_client.get_eventprovider(EVENTPROVIDER_ID) + assert route.called + assert result == eventprovider_detail_response["data"] + assert result["id"] == EVENTPROVIDER_ID + await er_client.close() + + +@pytest.mark.asyncio +async def test_get_eventprovider_not_found(er_client, not_found_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.get(f"activity/eventprovider/{EVENTPROVIDER_ID}") + route.return_value = httpx.Response(httpx.codes.NOT_FOUND, json=not_found_response) + with pytest.raises(ERClientNotFound): + await er_client.get_eventprovider(EVENTPROVIDER_ID) + assert route.called + await er_client.close() + + +@pytest.mark.asyncio +async def test_patch_eventprovider_success(er_client, eventprovider_patched_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.patch(f"activity/eventprovider/{EVENTPROVIDER_ID}") + route.return_value = httpx.Response(httpx.codes.OK, json=eventprovider_patched_response) + result = await er_client.patch_eventprovider( + EVENTPROVIDER_ID, {"display": "Updated Provider Name"} + ) + assert route.called + assert result == eventprovider_patched_response["data"] + assert result["display"] == "Updated Provider Name" + await er_client.close() + + +@pytest.mark.asyncio +async def test_patch_eventprovider_not_found(er_client, not_found_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.patch(f"activity/eventprovider/{EVENTPROVIDER_ID}") + route.return_value = httpx.Response(httpx.codes.NOT_FOUND, json=not_found_response) + with pytest.raises(ERClientNotFound): + await er_client.patch_eventprovider(EVENTPROVIDER_ID, {"display": "X"}) + assert route.called + await er_client.close() + + +# -- Event Source Tests -- + + +@pytest.mark.asyncio +async def test_post_eventsource_success(er_client, eventsource_payload, eventsource_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.post(f"activity/eventprovider/{EVENTPROVIDER_ID}/eventsources") + route.return_value = httpx.Response(httpx.codes.CREATED, json=eventsource_response) + result = await er_client.post_eventsource(EVENTPROVIDER_ID, eventsource_payload) + assert route.called + assert result == eventsource_response["data"] + await er_client.close() + + +@pytest.mark.asyncio +async def test_post_eventsource_provider_not_found(er_client, eventsource_payload, not_found_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.post(f"activity/eventprovider/{EVENTPROVIDER_ID}/eventsources") + route.return_value = httpx.Response(httpx.codes.NOT_FOUND, json=not_found_response) + with pytest.raises(ERClientNotFound): + await er_client.post_eventsource(EVENTPROVIDER_ID, eventsource_payload) + assert route.called + await er_client.close() + + +@pytest.mark.asyncio +async def test_get_eventsources_success(er_client, eventsources_list_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.get(f"activity/eventprovider/{EVENTPROVIDER_ID}/eventsources") + route.return_value = httpx.Response(httpx.codes.OK, json=eventsources_list_response) + result = await er_client.get_eventsources(EVENTPROVIDER_ID) + assert route.called + assert result == eventsources_list_response["data"] + assert len(result) == 2 + await er_client.close() + + +@pytest.mark.asyncio +async def test_get_eventsource_success(er_client, eventsource_detail_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.get(f"activity/eventsource/{EVENTSOURCE_ID}") + route.return_value = httpx.Response(httpx.codes.OK, json=eventsource_detail_response) + result = await er_client.get_eventsource(EVENTSOURCE_ID) + assert route.called + assert result == eventsource_detail_response["data"] + assert result["id"] == EVENTSOURCE_ID + await er_client.close() + + +@pytest.mark.asyncio +async def test_get_eventsource_not_found(er_client, not_found_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.get(f"activity/eventsource/{EVENTSOURCE_ID}") + route.return_value = httpx.Response(httpx.codes.NOT_FOUND, json=not_found_response) + with pytest.raises(ERClientNotFound): + await er_client.get_eventsource(EVENTSOURCE_ID) + assert route.called + await er_client.close() + + +@pytest.mark.asyncio +async def test_patch_eventsource_success(er_client, eventsource_patched_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.patch(f"activity/eventsource/{EVENTSOURCE_ID}") + route.return_value = httpx.Response(httpx.codes.OK, json=eventsource_patched_response) + result = await er_client.patch_eventsource( + EVENTSOURCE_ID, {"display": "Renamed Source"} + ) + assert route.called + assert result == eventsource_patched_response["data"] + assert result["display"] == "Renamed Source" + await er_client.close() + + +@pytest.mark.asyncio +async def test_patch_eventsource_not_found(er_client, not_found_response): + async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + route = respx_mock.patch(f"activity/eventsource/{EVENTSOURCE_ID}") + route.return_value = httpx.Response(httpx.codes.NOT_FOUND, json=not_found_response) + with pytest.raises(ERClientNotFound): + await er_client.patch_eventsource(EVENTSOURCE_ID, {"display": "X"}) + assert route.called + await er_client.close() diff --git a/tests/sync_client/__init__.py b/tests/sync_client/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/sync_client/conftest.py b/tests/sync_client/conftest.py new file mode 100644 index 0000000..6d9d6da --- /dev/null +++ b/tests/sync_client/conftest.py @@ -0,0 +1,21 @@ +import pytest + +from erclient.client import ERClient + + +@pytest.fixture +def er_server_info(): + return { + "service_root": "https://fake-site.erdomain.org/api/v1.0", + "username": "test", + "password": "test", + "token": "1110c87681cd1d12ad07c2d0f57d15d6079ae5d8", + "token_url": "https://fake-auth.erdomain.org/oauth2/token", + "client_id": "das_web_client", + "provider_key": "testintegration", + } + + +@pytest.fixture +def er_client(er_server_info): + return ERClient(**er_server_info) diff --git a/tests/sync_client/test_eventproviders.py b/tests/sync_client/test_eventproviders.py new file mode 100644 index 0000000..1ce3c4a --- /dev/null +++ b/tests/sync_client/test_eventproviders.py @@ -0,0 +1,306 @@ +import json +from unittest.mock import MagicMock + +import pytest + +from erclient.client import ERClient +from erclient import ERClientNotFound, ERClientPermissionDenied + + +EVENTPROVIDER_ID = "a1b2c3d4-e5f6-7890-abcd-ef1234567890" +EVENTSOURCE_ID = "f0e1d2c3-b4a5-6789-0fed-cba987654321" + + +@pytest.fixture +def eventprovider_payload(): + return { + "display": "My Test Provider", + "owner": {"id": "user-id-123"}, + } + + +@pytest.fixture +def eventprovider_created_response(): + return { + "data": { + "id": EVENTPROVIDER_ID, + "display": "My Test Provider", + "is_active": True, + "owner": {"id": "user-id-123"}, + }, + "status": {"code": 201, "message": "Created"}, + } + + +@pytest.fixture +def eventproviders_list_response(): + return { + "data": [ + { + "id": EVENTPROVIDER_ID, + "display": "My Test Provider", + "is_active": True, + }, + { + "id": "00000000-0000-0000-0000-000000000002", + "display": "Another Provider", + "is_active": False, + }, + ], + } + + +@pytest.fixture +def eventprovider_detail_response(): + return { + "data": { + "id": EVENTPROVIDER_ID, + "display": "My Test Provider", + "is_active": True, + }, + } + + +@pytest.fixture +def eventprovider_patched_response(): + return { + "data": { + "id": EVENTPROVIDER_ID, + "display": "Updated Provider Name", + "is_active": True, + }, + } + + +@pytest.fixture +def eventsource_payload(): + return { + "display": "Test Event Source", + } + + +@pytest.fixture +def eventsource_created_response(): + return { + "data": { + "id": EVENTSOURCE_ID, + "display": "Test Event Source", + "eventprovider": EVENTPROVIDER_ID, + }, + "status": {"code": 201, "message": "Created"}, + } + + +@pytest.fixture +def eventsources_list_response(): + return { + "data": [ + { + "id": EVENTSOURCE_ID, + "display": "Test Event Source", + "eventprovider": EVENTPROVIDER_ID, + }, + { + "id": "11111111-1111-1111-1111-111111111111", + "display": "Second Source", + "eventprovider": EVENTPROVIDER_ID, + }, + ], + } + + +@pytest.fixture +def eventsource_detail_response(): + return { + "data": { + "id": EVENTSOURCE_ID, + "display": "Test Event Source", + "eventprovider": EVENTPROVIDER_ID, + }, + } + + +@pytest.fixture +def eventsource_patched_response(): + return { + "data": { + "id": EVENTSOURCE_ID, + "display": "Renamed Source", + "eventprovider": EVENTPROVIDER_ID, + }, + } + + +def _mock_response(status_code=200, json_data=None): + """Helper to create a mock response object.""" + response = MagicMock() + response.ok = 200 <= status_code < 400 + response.status_code = status_code + response.text = json.dumps(json_data) if json_data else "" + response.json.return_value = json_data + response.url = "https://fake-site.erdomain.org/api/v1.0/test" + return response + + +# -- Sync Event Provider POST Tests -- + + +def test_post_eventprovider_success(er_client, eventprovider_payload, eventprovider_created_response): + er_client._http_session.post = MagicMock( + return_value=_mock_response(201, eventprovider_created_response) + ) + result = er_client.post_eventprovider(eventprovider_payload) + er_client._http_session.post.assert_called_once() + assert result == eventprovider_created_response["data"] + + +def test_post_eventprovider_forbidden(er_client, eventprovider_payload): + er_client._http_session.post = MagicMock( + return_value=_mock_response(403, { + "status": {"detail": "You do not have permission to perform this action."} + }) + ) + with pytest.raises(ERClientPermissionDenied): + er_client.post_eventprovider(eventprovider_payload) + + +# -- Sync Event Provider GET List Tests -- + + +def test_get_eventproviders_success(er_client, eventproviders_list_response): + er_client._http_session.get = MagicMock( + return_value=_mock_response(200, eventproviders_list_response) + ) + result = er_client.get_eventproviders() + er_client._http_session.get.assert_called_once() + assert result == eventproviders_list_response["data"] + assert len(result) == 2 + + +# -- Sync Event Provider GET Detail Tests -- + + +def test_get_eventprovider_success(er_client, eventprovider_detail_response): + er_client._http_session.get = MagicMock( + return_value=_mock_response(200, eventprovider_detail_response) + ) + result = er_client.get_eventprovider(EVENTPROVIDER_ID) + er_client._http_session.get.assert_called_once() + assert result == eventprovider_detail_response["data"] + + +def test_get_eventprovider_not_found(er_client): + er_client._http_session.get = MagicMock( + return_value=_mock_response(404, { + "status": {"code": 404, "detail": "Not found"} + }) + ) + with pytest.raises(ERClientNotFound): + er_client.get_eventprovider(EVENTPROVIDER_ID) + + +# -- Sync Event Provider PATCH Tests -- + + +def test_patch_eventprovider_success(er_client, eventprovider_patched_response): + er_client._http_session.patch = MagicMock( + return_value=_mock_response(200, eventprovider_patched_response) + ) + result = er_client.patch_eventprovider( + EVENTPROVIDER_ID, {"display": "Updated Provider Name"} + ) + er_client._http_session.patch.assert_called_once() + assert result == eventprovider_patched_response["data"] + assert result["display"] == "Updated Provider Name" + + +def test_patch_eventprovider_not_found(er_client): + er_client._http_session.patch = MagicMock( + return_value=_mock_response(404, { + "status": {"code": 404, "detail": "Not found"} + }) + ) + with pytest.raises(ERClientNotFound): + er_client.patch_eventprovider(EVENTPROVIDER_ID, {"display": "X"}) + + +# -- Sync Event Source POST Tests -- + + +def test_post_eventsource_success(er_client, eventsource_payload, eventsource_created_response): + er_client._http_session.post = MagicMock( + return_value=_mock_response(201, eventsource_created_response) + ) + result = er_client.post_eventsource(EVENTPROVIDER_ID, eventsource_payload) + er_client._http_session.post.assert_called_once() + assert result == eventsource_created_response["data"] + + +def test_post_eventsource_not_found(er_client, eventsource_payload): + er_client._http_session.post = MagicMock( + return_value=_mock_response(404, { + "status": {"code": 404, "detail": "Provider not found"} + }) + ) + with pytest.raises(ERClientNotFound): + er_client.post_eventsource(EVENTPROVIDER_ID, eventsource_payload) + + +# -- Sync Event Source GET List Tests -- + + +def test_get_eventsources_success(er_client, eventsources_list_response): + er_client._http_session.get = MagicMock( + return_value=_mock_response(200, eventsources_list_response) + ) + result = er_client.get_eventsources(EVENTPROVIDER_ID) + er_client._http_session.get.assert_called_once() + assert result == eventsources_list_response["data"] + assert len(result) == 2 + + +# -- Sync Event Source GET Detail Tests -- + + +def test_get_eventsource_success(er_client, eventsource_detail_response): + er_client._http_session.get = MagicMock( + return_value=_mock_response(200, eventsource_detail_response) + ) + result = er_client.get_eventsource(EVENTSOURCE_ID) + er_client._http_session.get.assert_called_once() + assert result == eventsource_detail_response["data"] + + +def test_get_eventsource_not_found(er_client): + er_client._http_session.get = MagicMock( + return_value=_mock_response(404, { + "status": {"code": 404, "detail": "Not found"} + }) + ) + with pytest.raises(ERClientNotFound): + er_client.get_eventsource(EVENTSOURCE_ID) + + +# -- Sync Event Source PATCH Tests -- + + +def test_patch_eventsource_success(er_client, eventsource_patched_response): + er_client._http_session.patch = MagicMock( + return_value=_mock_response(200, eventsource_patched_response) + ) + result = er_client.patch_eventsource( + EVENTSOURCE_ID, {"display": "Renamed Source"} + ) + er_client._http_session.patch.assert_called_once() + assert result == eventsource_patched_response["data"] + assert result["display"] == "Renamed Source" + + +def test_patch_eventsource_not_found(er_client): + er_client._http_session.patch = MagicMock( + return_value=_mock_response(404, { + "status": {"code": 404, "detail": "Not found"} + }) + ) + with pytest.raises(ERClientNotFound): + er_client.patch_eventsource(EVENTSOURCE_ID, {"display": "X"}) From be75cb13b0e918fa024276c6e322045d083d4f07 Mon Sep 17 00:00:00 2001 From: JoshuaVulcan <38018017+JoshuaVulcan@users.noreply.github.com> Date: Wed, 11 Feb 2026 17:46:09 -0800 Subject: [PATCH 2/2] Fix eventprovider async test URL base to use _api_root Co-authored-by: Cursor --- tests/async_client/test_eventproviders.py | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/async_client/test_eventproviders.py b/tests/async_client/test_eventproviders.py index 5bd7194..31893b1 100644 --- a/tests/async_client/test_eventproviders.py +++ b/tests/async_client/test_eventproviders.py @@ -135,7 +135,7 @@ def eventsource_patched_response(): @pytest.mark.asyncio async def test_post_eventprovider_success(er_client, eventprovider_payload, eventprovider_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.post("activity/eventproviders/") route.return_value = httpx.Response(httpx.codes.CREATED, json=eventprovider_response) result = await er_client.post_eventprovider(eventprovider_payload) @@ -146,7 +146,7 @@ async def test_post_eventprovider_success(er_client, eventprovider_payload, even @pytest.mark.asyncio async def test_post_eventprovider_forbidden(er_client, eventprovider_payload, forbidden_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.post("activity/eventproviders/") route.return_value = httpx.Response(httpx.codes.FORBIDDEN, json=forbidden_response) with pytest.raises(ERClientPermissionDenied): @@ -157,7 +157,7 @@ async def test_post_eventprovider_forbidden(er_client, eventprovider_payload, fo @pytest.mark.asyncio async def test_get_eventproviders_success(er_client, eventproviders_list_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.get("activity/eventproviders") route.return_value = httpx.Response(httpx.codes.OK, json=eventproviders_list_response) result = await er_client.get_eventproviders() @@ -169,7 +169,7 @@ async def test_get_eventproviders_success(er_client, eventproviders_list_respons @pytest.mark.asyncio async def test_get_eventprovider_success(er_client, eventprovider_detail_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.get(f"activity/eventprovider/{EVENTPROVIDER_ID}") route.return_value = httpx.Response(httpx.codes.OK, json=eventprovider_detail_response) result = await er_client.get_eventprovider(EVENTPROVIDER_ID) @@ -181,7 +181,7 @@ async def test_get_eventprovider_success(er_client, eventprovider_detail_respons @pytest.mark.asyncio async def test_get_eventprovider_not_found(er_client, not_found_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.get(f"activity/eventprovider/{EVENTPROVIDER_ID}") route.return_value = httpx.Response(httpx.codes.NOT_FOUND, json=not_found_response) with pytest.raises(ERClientNotFound): @@ -192,7 +192,7 @@ async def test_get_eventprovider_not_found(er_client, not_found_response): @pytest.mark.asyncio async def test_patch_eventprovider_success(er_client, eventprovider_patched_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.patch(f"activity/eventprovider/{EVENTPROVIDER_ID}") route.return_value = httpx.Response(httpx.codes.OK, json=eventprovider_patched_response) result = await er_client.patch_eventprovider( @@ -206,7 +206,7 @@ async def test_patch_eventprovider_success(er_client, eventprovider_patched_resp @pytest.mark.asyncio async def test_patch_eventprovider_not_found(er_client, not_found_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.patch(f"activity/eventprovider/{EVENTPROVIDER_ID}") route.return_value = httpx.Response(httpx.codes.NOT_FOUND, json=not_found_response) with pytest.raises(ERClientNotFound): @@ -220,7 +220,7 @@ async def test_patch_eventprovider_not_found(er_client, not_found_response): @pytest.mark.asyncio async def test_post_eventsource_success(er_client, eventsource_payload, eventsource_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.post(f"activity/eventprovider/{EVENTPROVIDER_ID}/eventsources") route.return_value = httpx.Response(httpx.codes.CREATED, json=eventsource_response) result = await er_client.post_eventsource(EVENTPROVIDER_ID, eventsource_payload) @@ -231,7 +231,7 @@ async def test_post_eventsource_success(er_client, eventsource_payload, eventsou @pytest.mark.asyncio async def test_post_eventsource_provider_not_found(er_client, eventsource_payload, not_found_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.post(f"activity/eventprovider/{EVENTPROVIDER_ID}/eventsources") route.return_value = httpx.Response(httpx.codes.NOT_FOUND, json=not_found_response) with pytest.raises(ERClientNotFound): @@ -242,7 +242,7 @@ async def test_post_eventsource_provider_not_found(er_client, eventsource_payloa @pytest.mark.asyncio async def test_get_eventsources_success(er_client, eventsources_list_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.get(f"activity/eventprovider/{EVENTPROVIDER_ID}/eventsources") route.return_value = httpx.Response(httpx.codes.OK, json=eventsources_list_response) result = await er_client.get_eventsources(EVENTPROVIDER_ID) @@ -254,7 +254,7 @@ async def test_get_eventsources_success(er_client, eventsources_list_response): @pytest.mark.asyncio async def test_get_eventsource_success(er_client, eventsource_detail_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.get(f"activity/eventsource/{EVENTSOURCE_ID}") route.return_value = httpx.Response(httpx.codes.OK, json=eventsource_detail_response) result = await er_client.get_eventsource(EVENTSOURCE_ID) @@ -266,7 +266,7 @@ async def test_get_eventsource_success(er_client, eventsource_detail_response): @pytest.mark.asyncio async def test_get_eventsource_not_found(er_client, not_found_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.get(f"activity/eventsource/{EVENTSOURCE_ID}") route.return_value = httpx.Response(httpx.codes.NOT_FOUND, json=not_found_response) with pytest.raises(ERClientNotFound): @@ -277,7 +277,7 @@ async def test_get_eventsource_not_found(er_client, not_found_response): @pytest.mark.asyncio async def test_patch_eventsource_success(er_client, eventsource_patched_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.patch(f"activity/eventsource/{EVENTSOURCE_ID}") route.return_value = httpx.Response(httpx.codes.OK, json=eventsource_patched_response) result = await er_client.patch_eventsource( @@ -291,7 +291,7 @@ async def test_patch_eventsource_success(er_client, eventsource_patched_response @pytest.mark.asyncio async def test_patch_eventsource_not_found(er_client, not_found_response): - async with respx.mock(base_url=er_client.service_root, assert_all_called=False) as respx_mock: + async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as respx_mock: route = respx_mock.patch(f"activity/eventsource/{EVENTSOURCE_ID}") route.return_value = httpx.Response(httpx.codes.NOT_FOUND, json=not_found_response) with pytest.raises(ERClientNotFound):