Spaces:
Running
Running
| """Note-to-signal parser tests. | |
| Verifies that free-text trigger notes and chat messages are translated into | |
| typed weather / transit signals + fatigue offset, so the rest of the fusion | |
| pipeline can react. Anything the parser misses still drives a `user_request` | |
| trigger via `pref_changes`; these tests cover only the keyword-mapped path. | |
| """ | |
| from datetime import datetime | |
| import pytest | |
| from adaptivetouragent.signals.note_parser import ( | |
| FATIGUE_BOOST_PER_INJECTION, | |
| interpret_note, | |
| note_to_signals, | |
| ) | |
| def _at() -> datetime: | |
| return datetime(2026, 5, 16, 12, 0) | |
| def test_interpret_note_reflects_intent(note: str, expected_substring: str) -> None: | |
| assert expected_substring in interpret_note(note).lower() | |
| def test_interpret_note_never_silent_on_nonempty() -> None: | |
| # Even an unrecognised note gets a non-empty, honest interpretation. | |
| assert interpret_note("the vibe is off today") != "" | |
| assert interpret_note(" ") == "" | |
| def test_rain_keyword_yields_rain_weather() -> None: | |
| batch, fatigue = note_to_signals(note="It started raining heavily", at=_at(), upcoming_poi_ids=["a", "b"]) | |
| assert batch.weather is not None | |
| assert batch.weather.condition == "rain" | |
| assert batch.weather.precip_mm_per_h > 0 | |
| assert batch.weather.source == "manual" | |
| assert fatigue == 0.0 | |
| def test_storm_keyword_yields_storm_weather() -> None: | |
| batch, _ = note_to_signals(note="Big thunderstorm rolling in", at=_at(), upcoming_poi_ids=["a", "b"]) | |
| assert batch.weather is not None | |
| assert batch.weather.condition == "storm" | |
| def test_tired_keyword_yields_fatigue_boost() -> None: | |
| batch, fatigue = note_to_signals(note="The kids are tired", at=_at(), upcoming_poi_ids=["a", "b"]) | |
| assert fatigue == FATIGUE_BOOST_PER_INJECTION | |
| assert batch.weather is None | |
| assert not batch.transit | |
| def test_delay_keyword_yields_transit_disruption_on_next_edge() -> None: | |
| batch, _ = note_to_signals(note="MRT delay reported", at=_at(), upcoming_poi_ids=["a", "b", "c"]) | |
| assert ("a", "b") in batch.transit | |
| reading = batch.transit[("a", "b")] | |
| assert reading.disruption | |
| assert reading.source == "manual" | |
| def test_delay_skipped_when_no_upcoming_edge() -> None: | |
| batch, _ = note_to_signals(note="MRT delay reported", at=_at(), upcoming_poi_ids=[]) | |
| assert not batch.transit | |
| batch_single, _ = note_to_signals(note="MRT delay reported", at=_at(), upcoming_poi_ids=["a"]) | |
| assert not batch_single.transit | |
| def test_unmatched_note_is_empty() -> None: | |
| batch, fatigue = note_to_signals( | |
| note="skip the next museum, find dinner instead", | |
| at=_at(), | |
| upcoming_poi_ids=["a", "b"], | |
| ) | |
| assert batch.weather is None | |
| assert not batch.transit | |
| assert fatigue == 0.0 | |
| def test_empty_note_is_no_op() -> None: | |
| batch, fatigue = note_to_signals(note=" ", at=_at(), upcoming_poi_ids=["a", "b"]) | |
| assert batch.weather is None | |
| assert not batch.transit | |
| assert fatigue == 0.0 | |
| def test_rain_variants(phrase: str) -> None: | |
| batch, _ = note_to_signals(note=phrase, at=_at(), upcoming_poi_ids=["a", "b"]) | |
| assert batch.weather is not None | |
| assert batch.weather.condition == "rain" | |