"""Tests for the forward-only asking-price history store (price_history.py).""" from price_history import normalize_reason, update_history def test_first_sight_new_listing_records_listed_at_first_visible_date() -> None: history: dict = {} update_history( history, [{"id": "A", "price": 500000, "first_visible_date": "2026-07-01T09:00:00Z"}], "2026-07-12", ) assert history["A"] == [{"date": "2026-07-01", "price": 500000, "reason": "listed"}] def test_first_sight_already_reduced_uses_event_date_and_reason() -> None: history: dict = {} update_history( history, [ { "id": "B", "price": 425000, "first_visible_date": "2026-06-01T09:00:00Z", "listing_update_reason": "price_reduced", "listing_update_date": "2026-07-10T14:00:00Z", } ], "2026-07-12", ) assert history["B"] == [{"date": "2026-07-10", "price": 425000, "reason": "reduced"}] def test_later_run_appends_only_on_price_change_with_direction() -> None: history: dict = {} listing = {"id": "A", "price": 500000, "first_visible_date": "2026-07-01T09:00:00Z"} update_history(history, [listing], "2026-07-12") # Unchanged price -> no new point. update_history(history, [{"id": "A", "price": 500000}], "2026-07-19") assert len(history["A"]) == 1 # Reduced -> appended, dated to the run. update_history(history, [{"id": "A", "price": 480000}], "2026-07-26") # Increased -> appended. update_history(history, [{"id": "A", "price": 490000}], "2026-08-02") assert history["A"] == [ {"date": "2026-07-01", "price": 500000, "reason": "listed"}, {"date": "2026-07-26", "price": 480000, "reason": "reduced"}, {"date": "2026-08-02", "price": 490000, "reason": "increased"}, ] def test_zero_or_missing_price_and_id_are_skipped() -> None: history: dict = {} update_history( history, [ {"id": "POA", "price": 0}, {"id": "", "price": 100000}, {"price": 100000}, # no id ], "2026-07-12", ) assert history == {} def test_run_date_fallback_when_dates_absent() -> None: history: dict = {} update_history(history, [{"id": "A", "price": 300000}], "2026-07-12") assert history["A"] == [{"date": "2026-07-12", "price": 300000, "reason": "listed"}] def test_normalize_reason_maps_only_price_moves() -> None: assert normalize_reason("price_reduced") == "reduced" assert normalize_reason("price_increased") == "increased" assert normalize_reason("new") is None assert normalize_reason("under_offer") is None assert normalize_reason(None) is None