from __future__ import annotations import pytest from cerbero_mcp.common.candles import Candle, validate_candles from fastapi import HTTPException def test_valid_candle(): c = Candle(timestamp=1_700_000_000_000, open=100.0, high=110.0, low=95.0, close=105.0, volume=12.5) assert c.high == 110.0 def test_high_below_close_rejected(): with pytest.raises(ValueError): Candle(timestamp=1, open=100, high=90, low=80, close=95, volume=1) def test_high_below_open_rejected(): with pytest.raises(ValueError): Candle(timestamp=1, open=100, high=90, low=80, close=85, volume=1) def test_low_above_close_rejected(): with pytest.raises(ValueError): Candle(timestamp=1, open=100, high=110, low=105, close=102, volume=1) def test_low_above_open_rejected(): with pytest.raises(ValueError): Candle(timestamp=1, open=95, high=110, low=100, close=105, volume=1) def test_negative_volume_rejected(): with pytest.raises(ValueError): Candle(timestamp=1, open=100, high=110, low=90, close=105, volume=-1) def test_non_positive_timestamp_rejected(): with pytest.raises(ValueError): Candle(timestamp=0, open=100, high=110, low=90, close=105, volume=1) def test_validate_candles_sorts_by_timestamp(): raw = [ {"timestamp": 3, "open": 1, "high": 2, "low": 1, "close": 1, "volume": 0}, {"timestamp": 1, "open": 1, "high": 2, "low": 1, "close": 1, "volume": 0}, {"timestamp": 2, "open": 1, "high": 2, "low": 1, "close": 1, "volume": 0}, ] out = validate_candles(raw) assert [c["timestamp"] for c in out] == [1, 2, 3] def test_validate_candles_coerces_string_numerics(): raw = [{"timestamp": "1", "open": "100", "high": "110", "low": "90", "close": "105", "volume": "10"}] out = validate_candles(raw) assert out[0]["open"] == 100.0 assert isinstance(out[0]["volume"], float) def test_validate_candles_malformed_raises_http_502(): raw = [{"timestamp": 1, "open": 100, "high": 50, "low": 90, "close": 105, "volume": 1}] with pytest.raises(HTTPException) as exc_info: validate_candles(raw) assert exc_info.value.status_code == 502 assert "candle" in str(exc_info.value.detail).lower() def test_validate_candles_empty_list(): assert validate_candles([]) == []