"""Markdown formatter tests — no network, just JSON-in / markdown-out.""" from __future__ import annotations import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) from ag_bids_mcp import format as fmt def test_fmt_best_with_winner(): payload = { "commodity": "corn", "today": "2026-05-20", "best": { "source_name": "Mercer Landmark — St Henry", "delivery": "May 2026", "bid_cents": 491, "basis_cents": 33, "futures_contract": "ZCK26", "fetched_at": "2026-05-20T15:00:00+00:00", }, } out = fmt.fmt_best("corn", payload) assert "Mercer Landmark — St Henry" in out assert "$4.9100/bu" in out assert "May 2026" in out assert "+0.33" in out def test_fmt_best_no_winner(): payload = {"commodity": "wheat", "today": "2026-05-20", "best": None} out = fmt.fmt_best("wheat", payload) assert "No current-month" in out assert "wheat" in out def test_fmt_futures_with_changes(): payload = { "commodity": "corn", "delivery": "Jul 2026", "contract": "ZCN26", "symbol": "ZC", "quote": { "settle_date": "2026-05-29", "open_cents": 461, "last_cents": 455, "prev_close_cents": 460, "change_since_open_cents": -6, "change_on_day_cents": -5, "fetched_at": "2026-05-29T18:00:00+00:00", }, } out = fmt.fmt_futures(payload) assert "ZCN26" in out and "Jul 2026" in out assert "$4.5500" in out # last assert "$4.6100" in out # open assert "▼ -0.06" in out # change since open assert "▼ -0.05" in out # change on day def test_fmt_futures_no_open_yet(): payload = { "commodity": "soy", "delivery": None, "contract": "continuous", "symbol": "ZS=F", "quote": { "settle_date": "2026-05-29", "open_cents": None, "last_cents": 1180, "prev_close_cents": 1177, "change_since_open_cents": None, "change_on_day_cents": 3, "fetched_at": "2026-05-29T18:00:00+00:00", }, } out = fmt.fmt_futures(payload) assert "continuous nearby" in out assert "no open captured yet" in out assert "▲ +0.03" in out # change on day still shown def test_fmt_futures_no_quote(): out = fmt.fmt_futures({"commodity": "wheat", "delivery": None, "contract": "continuous", "quote": None}) assert "No futures quote on file" in out def test_fmt_inputs_lime_table(): payload = { "product": "lime", "count": 2, "rows": [ {"source_name": "Bob's Lime Quote", "commodity": "lime", "display_name": "Lime", "delivery": "spot", "bid_cents": 42000, "commodity_kind": "fertilizer", "fetched_at": "2026-05-20T15:00:00+00:00"}, {"source_name": "Coop X", "commodity": "lime", "display_name": "Lime", "delivery": "spot", "bid_cents": 45500, "commodity_kind": "fertilizer", "fetched_at": "2026-05-20T15:01:00+00:00"}, ], } out = fmt.fmt_inputs(payload) assert "LIME prices" in out assert "$420.00" in out assert "$455.00" in out assert "Bob's Lime Quote" in out def test_fmt_inputs_empty(): out = fmt.fmt_inputs({"product": "lime", "rows": []}) assert "No lime prices on file." in out def test_fmt_latest_table_picks_correct_unit(): payload = {"count": 2, "rows": [ {"source_name": "Bambauer", "commodity": "corn", "display_name": "Corn", "delivery": "May 2026", "bid_cents": 458, "basis_cents": 2, "commodity_kind": "grain", "futures_contract": "ZCN26", "fetched_at": "2026-05-20T15:00:00+00:00"}, {"source_name": "Coop X", "commodity": "lime", "display_name": "Lime", "delivery": "spot", "bid_cents": 42000, "basis_cents": None, "commodity_kind": "fertilizer", "futures_contract": None, "fetched_at": "2026-05-20T15:00:00+00:00"}, ]} out = fmt.fmt_latest(payload) assert "$4.5800" in out # grain in /bu (4 decimals) assert "$420.00" in out # fertilizer in /ton (2 decimals) def test_fmt_history_with_trend_arrow(): payload = { "commodity": "corn", "days": 7, "rows": [ {"source_name": "Andersons", "delivery": "May 2026", "bid_cents": 480, "basis_cents": 25, "fetched_at": "2026-05-15T15:00:00+00:00"}, {"source_name": "Andersons", "delivery": "May 2026", "bid_cents": 496, "basis_cents": 30, "fetched_at": "2026-05-20T15:00:00+00:00"}, ], } out = fmt.fmt_history(payload) assert "▲" in out assert "$4.8000" in out assert "$4.9600" in out # Basis trend is now surfaced in the summary line too. assert "basis +0.25 → +0.30" in out def _history_multi(): return { "commodity": None, "days": 7, "rows": [ {"source_name": "Minster", "commodity": "corn", "delivery": "Jul 2026", "bid_cents": 461, "basis_cents": 11, "futures_cents": 450, "fetched_at": "2026-05-23T15:00:00+00:00"}, {"source_name": "Minster", "commodity": "corn", "delivery": "Jul 2026", "bid_cents": 464, "basis_cents": 14, "futures_cents": 450, "fetched_at": "2026-05-29T15:00:00+00:00"}, {"source_name": "Minster", "commodity": "soy", "delivery": "Nov 2026", "bid_cents": 1145, "basis_cents": -50, "futures_cents": 1195, "fetched_at": "2026-05-23T15:00:00+00:00"}, {"source_name": "Minster", "commodity": "soy", "delivery": "Nov 2026", "bid_cents": 1148, "basis_cents": -45, "futures_cents": 1193, "fetched_at": "2026-05-29T15:00:00+00:00"}, ], } def test_fmt_history_spans_crops_and_shows_basis_futures(): out = fmt.fmt_history(_history_multi()) # No commodity filter → "all crops" scope, both crops present. assert "all crops" in out assert "corn" in out and "soy" in out # Futures column populated from futures_cents. assert "$4.5000" in out # Basis movement annotated per series. assert "+0.11 → +0.14" in out assert "-0.50 → -0.45" in out def test_fmt_basis_movement_aggregates_per_crop(): out = fmt.fmt_basis_movement(_history_multi()) assert "Basis movement" in out # corn basis 0.11 → 0.14 (stronger), soy -0.50 → -0.45 (stronger) assert "**corn**" in out and "**soy**" in out assert "stronger" in out assert "1 elevators, 1 series" in out def test_fmt_basis_movement_skips_non_grain_and_nulls(): payload = {"commodity": None, "days": 7, "rows": [ {"source_name": "Coop", "commodity": "lime", "delivery": "spot", "bid_cents": 42000, "basis_cents": None, "fetched_at": "2026-05-23T15:00:00+00:00"}, ]} out = fmt.fmt_basis_movement(payload) assert "No grain basis samples" in out def test_fmt_basis_detail_per_series(): out = fmt.fmt_basis_detail(_history_multi()) assert "Basis movement by elevator" in out # One row per (crop, elevator, delivery) assert "| corn | Minster | Jul 2026 |" in out assert "| soy | Minster | Nov 2026 |" in out assert "weaker" not in out # both strengthened in this fixture assert "stronger" in out def test_fmt_sources_table(): payload = {"sources": [ {"id": 1, "name": "Test Elev", "kind": "elevator", "city": "Ada", "state": "OH", "zip": "45810", "last_success_at": "2026-05-20T14:55:00+00:00", "consecutive_failures": 0, "last_error": None}, ]} out = fmt.fmt_sources(payload) assert "Test Elev" in out assert "elevator" in out assert "Ada, OH 45810" in out # location column def test_fmt_health_buckets(): payload = {"sources": [ {"name": "Healthy", "kind": "elevator", "last_success_at": "2026-05-20T14:55:00+00:00", "consecutive_failures": 0, "last_error": None}, {"name": "Stale", "kind": "elevator", "last_success_at": None, "consecutive_failures": 0, "last_error": None}, {"name": "Down", "kind": "elevator", "last_success_at": "2026-05-15T14:55:00+00:00", "consecutive_failures": 5, "last_error": "boom"}, ]} out = fmt.fmt_health(payload) assert "Healthy: **1**" in out assert "Stale (never succeeded): **1**" in out assert "Down" in out and "**1**" in out # Down section lists boom assert "boom" in out def test_fmt_deliveries(): out = fmt.fmt_deliveries({"commodity": "corn", "deliveries": ["May 2026", "Jul 2026"]}) assert "- May 2026" in out assert "- Jul 2026" in out def test_fmt_commodities_lists_all_six(): out = fmt.fmt_commodities() for name in ("corn", "soy", "wheat", "map", "potash", "lime"): assert name in out.lower() def test_fmt_summary_includes_best_for_today(): payload = { "today": "2026-05-20", "prev_trading_day": "2026-05-19", "commodities": [ {"symbol": "corn", "display_name": "Corn", "futures": {"contract": "ZC=F", "today_last_cents": 458, "prev_close_cents": 455, "change_cents": 3}, "best_for_today": { "source_name": "Mercer Landmark — St Henry", "delivery": "May 2026", "bid_cents": 491, "basis_cents": 33, }}, {"symbol": "soy", "display_name": "Soybeans", "futures": {"contract": "ZS=F", "today_last_cents": 1180, "prev_close_cents": 1177, "change_cents": 3}, "best_for_today": None}, ], } out = fmt.fmt_summary(payload) assert "Corn" in out and "Soybeans" in out assert "Mercer Landmark — St Henry" in out assert "$4.5800" in out # corn last assert "No current-month local bid posted" in out # soy fallback