Files
robinhood/backend/tests/services/test_bullionvault_service.py
Krikorios 48e60d015f feat: Add Phase 4 advanced metrics and components
- Add advanced metrics dashboard with trade analytics
- Add new trading components (EntryTypeAnalysis, MultiDayPositionTracker, NewsEventTracker, etc.)
- Add strategy mode selector and trend confirmation
- Add risk automation panel and slippage correlation analysis
- Add daily trading plan enhancements with modal components
- Add custom hooks (useApi, useLocalStorage, useAdvancedTradeMetrics)
- Add broker service integration and trading API
- Add test setup and vitest configuration
- Include parquet data files for live market data
- Add comprehensive documentation in docs/ folder
2025-11-27 10:23:58 +02:00

106 lines
3.3 KiB
Python

from datetime import datetime, timezone
import httpx
import pytest
from app.services.metals.bullionvault_service import BullionVaultService
def _csv_response(rows: list[str]) -> str:
header = (
'"Date","High (kg)","Low (kg)","Close (kg)",,"High (troy oz)","Low (troy oz)","Close (troy oz)",\n'
)
return header + "".join(f"{row}\n" for row in rows)
def _mock_client(handler):
transport = httpx.MockTransport(handler)
return httpx.AsyncClient(transport=transport)
@pytest.mark.asyncio
async def test_get_current_gold_price_parses_csv() -> None:
csv = _csv_response(
[
'"12:00:00 23-Nov-2025",130702.99,130600.11,130650.10,,4065.32,4040.32,4050.55,',
'"11:50:00 23-Nov-2025",130600.99,130500.11,130550.10,,4055.32,4030.32,4040.55,',
]
)
async def handler(request: httpx.Request) -> httpx.Response:
return httpx.Response(200, text=csv)
async with _mock_client(handler) as client:
service = BullionVaultService(client=client, base_url="https://chart-data.bullionvault.com")
result = await service.get_current_gold_price("usd")
assert result["currency"] == "USD"
assert result["price"] == pytest.approx(4050.55, rel=0.001)
assert result["price_kg"] == pytest.approx(130650.10, rel=0.001)
assert result["data_points"] == 2
assert datetime.fromisoformat(result["timestamp"]).tzinfo == timezone.utc
@pytest.mark.asyncio
async def test_get_current_gold_price_raises_on_empty_data() -> None:
async def handler(_: httpx.Request) -> httpx.Response:
return httpx.Response(200, text='"Date",\n')
async with _mock_client(handler) as client:
service = BullionVaultService(client=client)
with pytest.raises(ValueError, match="No price data available"):
await service.get_current_gold_price()
@pytest.mark.asyncio
async def test_get_gold_history_applies_limit() -> None:
csv = _csv_response(
[
'"12:00:00 23-Nov-2025",130702.99,130600.11,130650.10,,4065.32,4040.32,4050.55,',
'"11:50:00 23-Nov-2025",130600.99,130500.11,130550.10,,4055.32,4030.32,4040.55,',
'"11:40:00 23-Nov-2025",130500.99,130400.11,130450.10,,4045.32,4020.32,4030.55,',
]
)
async def handler(_: httpx.Request) -> httpx.Response:
return httpx.Response(200, text=csv)
async with _mock_client(handler) as client:
service = BullionVaultService(client=client)
history = await service.get_gold_history(limit=2)
assert len(history) == 2
assert history[0]["close"] == pytest.approx(4050.55, rel=0.001)
assert history[1]["close"] == pytest.approx(4040.55, rel=0.001)
@pytest.mark.asyncio
async def test_get_multi_currency_prices_skips_failures() -> None:
csv = _csv_response(
[
'"12:00:00 23-Nov-2025",130702.99,130600.11,130650.10,,4065.32,4040.32,4050.55,',
]
)
retry_counts: dict[str, int] = {}
async def handler(request: httpx.Request) -> httpx.Response:
currency = request.url.path.split("/")[4]
retry_counts[currency] = retry_counts.get(currency, 0) + 1
if currency == "GBP":
return httpx.Response(500, text="error")
return httpx.Response(200, text=csv)
async with _mock_client(handler) as client:
service = BullionVaultService(client=client, max_retries=1)
prices = await service.get_multi_currency_prices()
# Only currencies served by successful responses should be included
assert "USD" in prices
assert "EUR" in prices
assert "GBP" not in prices
assert retry_counts["GBP"] == 1