mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-08-26 17:31:34 +00:00
Adds meshai.notifications.evac_phase.detect_phase, wired into the IPAWS formatter/adapter, to classify READY/SET/GO evacuation phases from real FEMA IPAWS alert headline/CMAMtext strings. Includes explicit false-positive guards since a wrong GO detection would broadcast an evacuation order that was never issued.
76 lines
2.9 KiB
Python
76 lines
2.9 KiB
Python
"""Tests for meshai.notifications.evac_phase.detect_phase.
|
|
|
|
Cases are drawn from REAL FEMA IPAWS alert headline/CMAMtext/description
|
|
strings (see tests/fixtures/ipaws/) plus explicit false-positive guards, since
|
|
a wrong GO detection would broadcast an evacuation order that was never
|
|
issued.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from meshai.notifications.evac_phase import detect_phase
|
|
|
|
|
|
# ============================================================
|
|
# real strings -> expected phase
|
|
# ============================================================
|
|
|
|
@pytest.mark.parametrize("text, expected", [
|
|
("LEVEL 1 READY - Evacuation Status", "READY"),
|
|
("Level 2 Set Alert", "SET"),
|
|
("LEVEL I SET Alert", "SET"), # word beats numeral; err upward
|
|
("Level 3 - Go Now", "GO"),
|
|
("Level 3- Go Now", "GO"),
|
|
("Ohio Gulch GO Evacuation Status", "GO"),
|
|
("Indian Creek Set to GO.", "GO"), # highest wins, NOT SET
|
|
("Immediate Evacuation", "GO"),
|
|
("Prepare to Evacuate", "SET"),
|
|
("BRUSH FIRE", None),
|
|
("Owyhee County Closure Area", None),
|
|
("Endangered Missing Person Alert", None),
|
|
(
|
|
"Jackson County Sheriff's Office- Level 3 GO NOW evacuation notice "
|
|
"UPGRADED for JAC-126",
|
|
"GO",
|
|
),
|
|
])
|
|
def test_detect_phase_real_strings(text, expected):
|
|
assert detect_phase(text) == expected
|
|
|
|
|
|
# ============================================================
|
|
# false-positive guards — bare lowercase / narrative usage must NOT match
|
|
# ============================================================
|
|
|
|
@pytest.mark.parametrize("text", [
|
|
"residents should go to the Blaine County Fairgrounds",
|
|
"crews are set to arrive by 0600",
|
|
"evacuate via Go Creek Road",
|
|
])
|
|
def test_detect_phase_false_positive_guards(text):
|
|
assert detect_phase(text) is None
|
|
|
|
|
|
# ============================================================
|
|
# precedence + multi-arg scanning
|
|
# ============================================================
|
|
|
|
def test_precedence_highest_always_wins_regardless_of_arg_order():
|
|
# SET language in the first text, GO language in the second — GO must win.
|
|
assert detect_phase("Prepare to Evacuate", "Level 3 - Go Now") == "GO"
|
|
# Same phrases, arguments reversed — still GO (order-independent).
|
|
assert detect_phase("Level 3 - Go Now", "Prepare to Evacuate") == "GO"
|
|
|
|
|
|
def test_detect_phase_scans_all_texts_together():
|
|
# No single text alone carries a phase; combined they do (SET here,
|
|
# since "LEVEL 2" is an explicit SET phrase and no GO phrase is present).
|
|
assert detect_phase("Jackson County Sheriff's Office", "Level 2 Set Alert") == "SET"
|
|
|
|
|
|
def test_detect_phase_none_texts_and_empty_input_are_safe():
|
|
assert detect_phase(None, None) is None
|
|
assert detect_phase() is None
|
|
assert detect_phase("") is None
|
|
assert detect_phase(None, "BRUSH FIRE", None) is None
|