| 1 | from uuid import uuid4 |
| 2 | import httpx |
| 3 | import pytest |
| 4 | from app.portfolio_orchestration import PortfolioResearchOrchestrator, PortfolioServiceUnavailableError |
| 5 | from app.repository import ResearchRepository |
| 6 | from app.settings import Settings |
| 7 | |
| 8 | @pytest.mark.asyncio |
| 9 | async def test_active_global_equities_uses_read_only_filtered_endpoint(): |
| 10 | instrument_id = str(uuid4()); requests = [] |
| 11 | def handler(request): |
| 12 | requests.append(request) |
| 13 | return httpx.Response(200, json={"instruments": [{"globalInstrumentId": instrument_id, "ticker": "MSFT", "exchange": "XNAS", "country": "US", "currency": "USD"}], "page": 0, "size": 100, "totalElements": 1}) |
| 14 | client = httpx.AsyncClient(transport=httpx.MockTransport(handler)) |
| 15 | result = await PortfolioResearchOrchestrator(ResearchRepository(Settings()), Settings(), client=client).active_global_equities() |
| 16 | assert result[0]["globalInstrumentId"] == instrument_id and result[0]["ticker"] == "MSFT" |
| 17 | assert requests[0].method == "GET" and requests[0].url.path == "/api/v1/instruments" |
| 18 | assert dict(requests[0].url.params) == {"status": "ACTIVE", "assetType": "EQUITY", "page": "0", "size": "500"} |
| 19 | await client.aclose() |
| 20 | |
| 21 | @pytest.mark.asyncio |
| 22 | async def test_active_global_equities_handles_empty_and_non_success_without_writes(): |
| 23 | client = httpx.AsyncClient(transport=httpx.MockTransport(lambda request: httpx.Response(200, json={"instruments": []}))) |
| 24 | assert await PortfolioResearchOrchestrator(ResearchRepository(Settings()), Settings(), client=client).active_global_equities() == [] |
| 25 | await client.aclose() |
| 26 | failed = httpx.AsyncClient(transport=httpx.MockTransport(lambda request: httpx.Response(503))) |
| 27 | with pytest.raises(PortfolioServiceUnavailableError): |
| 28 | await PortfolioResearchOrchestrator(ResearchRepository(Settings()), Settings(), client=failed).active_global_equities() |
| 29 | await failed.aclose() |
| 30 | |
| 31 | @pytest.mark.asyncio |
| 32 | async def test_active_global_equities_aggregates_later_page_with_get_only(): |
| 33 | requests=[]; later=str(uuid4()) |
| 34 | def handler(request): |
| 35 | requests.append(request) |
| 36 | page = request.url.params.get("page") |
| 37 | if page == "0": return httpx.Response(200, json={"instruments": [{"globalInstrumentId": str(uuid4())}] * 500, "totalElements": 501}) |
| 38 | return httpx.Response(200, json={"instruments": [{"globalInstrumentId": later, "ticker":"LATE"}], "totalElements": 501}) |
| 39 | client=httpx.AsyncClient(transport=httpx.MockTransport(handler)) |
| 40 | values=await PortfolioResearchOrchestrator(ResearchRepository(Settings()), Settings(), client=client).active_global_equities() |
| 41 | assert len(values)==501 and values[-1]["globalInstrumentId"]==later |
| 42 | assert [request.url.params.get("page") for request in requests] == ["0", "1"] |
| 43 | assert {request.method for request in requests} == {"GET"} |
| 44 | await client.aclose() |