| """ |
| Depth tier β chart_planner deterministic functions. |
| |
| The code that turns messy LLM/scraped tables into chart props β where chart bugs |
| (the flicker/wrong-figure class) originate. Pure input->output; outputs verified |
| against the real functions before asserting. |
| """ |
| import pytest |
|
|
| from app.services.chart_planner import ( |
| _parse_number, |
| is_candlestick_table, |
| normalize_chart_table, |
| ) |
|
|
| pytestmark = pytest.mark.depth |
|
|
|
|
| |
|
|
| @pytest.mark.parametrize("value,expected", [ |
| (5, 5.0), |
| (3.5, 3.5), |
| ("1234.56", 1234.56), |
| ("1,234", 1234.0), |
| ("Rs. 484,500", 484500.0), |
| ("(20)", -20.0), |
| ]) |
| def test_parse_number__valid(value, expected): |
| assert _parse_number(value) == expected |
|
|
|
|
| @pytest.mark.parametrize("value", [ |
| "range-bound prose", |
| "+15% initial, -15% decline", |
| "Apr 10, 26", |
| "", |
| None, |
| ]) |
| def test_parse_number__rejects_non_numeric(value): |
| |
| assert _parse_number(value) is None |
|
|
|
|
| |
|
|
| def test_is_candlestick__ohlc_with_date__true(): |
| assert is_candlestick_table({"headers": ["Date", "Open", "High", "Low", "Close"]}) is True |
|
|
|
|
| def test_is_candlestick__ohlc_without_date__false(): |
| |
| assert is_candlestick_table({"headers": ["Symbol", "Open", "High", "Low", "Close"]}) is False |
|
|
|
|
| def test_is_candlestick__plain_table__false(): |
| assert is_candlestick_table({"headers": ["Name", "Price"]}) is False |
|
|
|
|
| |
|
|
| def test_normalize__valid_table_cleaned(): |
| out = normalize_chart_table({"headers": ["A", "B"], "rows": [["1", "2"], ["3", "4"]]}) |
| assert out == {"headers": ["A", "B"], "rows": [["1", "2"], ["3", "4"]]} |
|
|
|
|
| @pytest.mark.parametrize("bad", [ |
| None, |
| {"headers": "not-a-list", "rows": []}, |
| {"headers": ["A"], "rows": []}, |
| ]) |
| def test_normalize__invalid_returns_none(bad): |
| assert normalize_chart_table(bad) is None |
|
|