Spaces:
Running
Running
| """Rule composition tests.""" | |
| from datetime import date | |
| from coastwise.data import get_rule_card | |
| from coastwise.rules import default_context, compose_safety_result | |
| from coastwise.schemas import CoastalRegion, HarvestStatus, RuleCard, UserIntent | |
| def test_rule_card_result_includes_status_sources_freshness_and_next_action(): | |
| result = compose_safety_result( | |
| get_rule_card("lingcod"), | |
| default_context(today=date(2026, 6, 13)), | |
| ) | |
| assert result.status is HarvestStatus.RULES_APPLY | |
| assert result.display_name == "Lingcod" | |
| assert result.source_links | |
| assert result.cache_dates | |
| assert "verify" in result.next_safe_action.lower() | |
| def test_unknown_result_is_observe_only_without_source_requirement(): | |
| result = compose_safety_result( | |
| get_rule_card("unknown"), | |
| default_context(today=date(2026, 6, 13)), | |
| ) | |
| assert result.status is HarvestStatus.OBSERVE_ONLY | |
| assert result.source_links == () | |
| assert "observe" in result.next_safe_action.lower() | |
| def test_stricter_exception_cards_do_not_fall_through_to_rules_apply(): | |
| for key in ("yelloweye_rockfish", "green_sturgeon", "ocean_salmon", "red_abalone"): | |
| result = compose_safety_result( | |
| get_rule_card(key), | |
| default_context( | |
| intent=UserIntent.THINKING_OF_HARVEST, | |
| region=CoastalRegion.POINT_ARENA_TO_PIGEON_POINT, | |
| today=date(2026, 6, 13), | |
| ), | |
| ) | |
| assert result.status is HarvestStatus.DO_NOT_HARVEST | |
| def test_mussel_harvest_during_quarantine_returns_do_not_harvest_warning(): | |
| result = compose_safety_result( | |
| get_rule_card("mussels"), | |
| default_context( | |
| intent=UserIntent.THINKING_OF_HARVEST, | |
| region=CoastalRegion.POINT_ARENA_TO_PIGEON_POINT, | |
| today=date(2026, 6, 13), | |
| ), | |
| ) | |
| assert result.status is HarvestStatus.DO_NOT_HARVEST | |
| assert any("cooking" in warning.lower() for warning in result.advisory_warnings) | |
| def test_stale_rules_apply_card_is_capped_at_verify_before_harvest(): | |
| card = RuleCard( | |
| key="demo_fish", | |
| display_name="Demo fish", | |
| category="fish", | |
| aliases=("demo fish",), | |
| covered_species=(), | |
| region_keys=("sf_coast_point_arena_to_pigeon_point",), | |
| photo_supported=False, | |
| default_status=HarvestStatus.RULES_APPLY, | |
| short_answer="Rules apply.", | |
| rule_notes=("Demo note.",), | |
| safety_warnings=(), | |
| source_names=("CDFW",), | |
| source_urls=("https://wildlife.ca.gov/Fishing/Ocean/Regulations",), | |
| cache_date=date(2026, 1, 1), | |
| ) | |
| result = compose_safety_result( | |
| card, | |
| default_context(today=date(2026, 6, 13)), | |
| ) | |
| assert result.stale | |
| assert result.status is HarvestStatus.VERIFY_BEFORE_HARVEST | |
| def test_san_francisco_bay_context_for_sf_coast_card_requires_verification(): | |
| result = compose_safety_result( | |
| get_rule_card("lingcod"), | |
| default_context( | |
| intent=UserIntent.THINKING_OF_HARVEST, | |
| region=CoastalRegion.SAN_FRANCISCO_BAY, | |
| today=date(2026, 6, 13), | |
| ), | |
| ) | |
| assert result.status is HarvestStatus.VERIFY_BEFORE_HARVEST | |
| assert any("bay" in warning.lower() for warning in result.advisory_warnings) | |