refactor(V2): IBKR client read methods — defensive conid + sec_type DRY
Code review fixes (commit 611a269):
- resolve_conid validates conid key presence (was raw KeyError on malformed)
- _SEC_TYPE_MAP module constant — reused in get_ticker + get_bars
(also fixes get_bars previously missing "forex": "CASH")
- New tests: empty response + malformed response error paths
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import re
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import pytest
|
||||
from cerbero_mcp.exchanges.ibkr.client import IBKRClient
|
||||
from cerbero_mcp.exchanges.ibkr.client import IBKRClient, IBKRError
|
||||
from pytest_httpx import HTTPXMock
|
||||
|
||||
|
||||
@@ -130,3 +130,25 @@ async def test_get_ticker_resolves_and_fetches(httpx_mock: HTTPXMock, client):
|
||||
assert snap["last_price"] == 150.5
|
||||
assert snap["bid"] == 150.4
|
||||
assert snap["ask"] == 150.6
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_conid_empty_response_raises(httpx_mock: HTTPXMock, client):
|
||||
httpx_mock.add_response(url=re.compile(r".*/tickle"), json={})
|
||||
httpx_mock.add_response(
|
||||
url=re.compile(r".*/trsrv/secdef/search.*symbol=NOPE"),
|
||||
json=[],
|
||||
)
|
||||
with pytest.raises(IBKRError, match="IBKR_CONID_NOT_FOUND"):
|
||||
await client.resolve_conid("NOPE", "STK")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_conid_malformed_response_raises(httpx_mock: HTTPXMock, client):
|
||||
httpx_mock.add_response(url=re.compile(r".*/tickle"), json={})
|
||||
httpx_mock.add_response(
|
||||
url=re.compile(r".*/trsrv/secdef/search.*symbol=BAD"),
|
||||
json=[{"symbol": "BAD"}], # missing conid key
|
||||
)
|
||||
with pytest.raises(IBKRError, match="malformed"):
|
||||
await client.resolve_conid("BAD", "STK")
|
||||
|
||||
Reference in New Issue
Block a user