"""Tests for ACARS message translator.""" from utils.acars_translator import ( classify_message_type, parse_engine_data, parse_oooi, parse_position_report, parse_weather_data, translate_label, translate_message, ) # --- translate_label --- class TestTranslateLabel: def test_known_labels(self): assert translate_label("H1") == "Position report (HF data link)" assert translate_label("DF") == "Engine data / DFDR" assert translate_label("_d") == "Demand mode (link test)" assert translate_label("5Z") == "OOOI (gate times)" assert translate_label("B9") == "ATC message" assert translate_label("SQ") == "Squawk assignment" def test_unknown_label(self): assert translate_label("ZZ") == "Label ZZ" def test_empty_label(self): assert translate_label("") == "Unknown label" def test_none_label(self): assert translate_label(None) == "Unknown label" def test_q_prefix_unknown(self): """Q-prefix labels not in table should get generic link management desc.""" assert "Link management" in translate_label("QZ") def test_whitespace_stripped(self): assert translate_label(" H1 ") == "Position report (HF data link)" # --- classify_message_type --- class TestClassifyMessageType: def test_h1_is_position(self): assert classify_message_type("H1") == "position" def test_df_is_engine_data(self): assert classify_message_type("DF") == "engine_data" def test_h2_is_weather(self): assert classify_message_type("H2") == "weather" def test_b9_is_ats(self): assert classify_message_type("B9") == "ats" def test_5z_is_oooi(self): assert classify_message_type("5Z") == "oooi" def test_sq_is_squawk(self): assert classify_message_type("SQ") == "squawk" def test_underscore_d_is_handshake(self): assert classify_message_type("_d") == "handshake" def test_q0_is_link_test(self): assert classify_message_type("Q0") == "link_test" def test_aa_is_cpdlc(self): assert classify_message_type("AA") == "cpdlc" def test_unknown_is_other(self): assert classify_message_type("ZZ") == "other" def test_none_is_other(self): assert classify_message_type(None) == "other" def test_text_with_bpos_override(self): """H1 with #M1BPOS text should be position.""" assert classify_message_type("H1", "#M1BPOSN42411W086034") == "position" # --- parse_position_report --- class TestParsePositionReport: def test_real_h1_bpos(self): text = "#M1BPOSN42411W086034,CSG,070852,340,N42441W087074,DTW,0757,224A8C" result = parse_position_report(text) assert result is not None assert result["lat"] > 42 assert result["lon"] < -86 assert result["waypoint"] == "CSG" assert result["flight_level"] == "FL340" assert result["destination"] == "DTW" def test_none_text(self): assert parse_position_report(None) is None def test_empty_text(self): assert parse_position_report("") is None def test_no_bpos_data(self): assert parse_position_report("SOME RANDOM TEXT") is None def test_temperature_field(self): text = "#M1BPOSN42411W086034,CSG,070852,340,N42441W087074,DTW,0757/TSM045" result = parse_position_report(text) assert result is not None assert result.get("temperature") == "-045 C" def test_southern_hemisphere(self): text = "#M1BPOSS33500E018200,CPT,120000,350,S33500E018200,CPT,1230,ABC123" result = parse_position_report(text) assert result is not None assert result["lat"] < 0 # South # --- parse_engine_data --- class TestParseEngineData: def test_real_dfdr_message(self): text = "#DFB SM/0 AC0/85.2 AC1/84.9 FL/350 FU/12450 ES/15" result = parse_engine_data(text) assert result is not None assert "AC0" in result assert result["AC0"]["value"] == "85.2" assert "FL" in result assert result["FL"]["value"] == "350" def test_none_text(self): assert parse_engine_data(None) is None def test_empty_text(self): assert parse_engine_data("") is None def test_no_engine_keys(self): assert parse_engine_data("HELLO WORLD") is None def test_n1_n2_values(self): text = "N1/92.3 N2/88.1 EGT/425" result = parse_engine_data(text) assert result is not None assert result["N1"]["value"] == "92.3" assert result["N2"]["value"] == "88.1" assert result["EGT"]["value"] == "425" # --- parse_weather_data --- class TestParseWeatherData: def test_wind_data(self): text = "WND270015 KJFK VIS10" result = parse_weather_data(text) assert result is not None assert result["wind_dir"] == "270 deg" assert result["wind_speed"] == "015 kts" def test_airports(self): text = "/WX KJFK KLAX TMP24" result = parse_weather_data(text) assert result is not None assert "KJFK" in result["airports"] assert "KLAX" in result["airports"] def test_none_text(self): assert parse_weather_data(None) is None def test_empty_text(self): assert parse_weather_data("") is None # --- parse_oooi --- class TestParseOooi: def test_full_oooi(self): text = "KJFK KLAX 1423 1435 1812 1824" result = parse_oooi(text) assert result is not None assert result["origin"] == "KJFK" assert result["destination"] == "KLAX" assert result["out"] == "1423" assert result["off"] == "1435" assert result["on"] == "1812" assert result["in"] == "1824" def test_partial_oooi(self): text = "KJFK KLAX 1423 1435" result = parse_oooi(text) assert result is not None assert result["origin"] == "KJFK" assert result["destination"] == "KLAX" def test_none_text(self): assert parse_oooi(None) is None def test_empty_text(self): assert parse_oooi("") is None # --- translate_message (integration) --- class TestTranslateMessage: def test_h1_position(self): msg = { "label": "H1", "text": "#M1BPOSN42411W086034,CSG,070852,340,N42441W087074,DTW,0757,224A8C", } result = translate_message(msg) assert result["label_description"] == "Position report (HF data link)" assert result["message_type"] == "position" assert result["parsed"] is not None assert "lat" in result["parsed"] def test_df_engine(self): msg = { "label": "DF", "text": "#DFB SM/0 AC0/85.2 AC1/84.9 FL/350", } result = translate_message(msg) assert result["message_type"] == "engine_data" assert result["parsed"] is not None assert "AC0" in result["parsed"] def test_underscore_d_handshake(self): msg = {"label": "_d", "text": ""} result = translate_message(msg) assert result["label_description"] == "Demand mode (link test)" assert result["message_type"] == "handshake" def test_unknown_label(self): msg = {"label": "ZZ", "text": "SOME DATA"} result = translate_message(msg) assert result["label_description"] == "Label ZZ" assert result["message_type"] == "other" assert result["parsed"] is None def test_missing_fields(self): """Handles messages with no label or text gracefully.""" result = translate_message({}) assert result["label_description"] == "Unknown label" assert result["message_type"] == "other" assert result["parsed"] is None def test_msg_field_fallback(self): """Uses 'msg' field when 'text' is missing.""" msg = { "label": "DF", "msg": "#DFB N1/92.3 N2/88.1", } result = translate_message(msg) assert result["parsed"] is not None assert "N1" in result["parsed"] def test_5z_oooi(self): msg = { "label": "5Z", "text": "KJFK KLAX 1423 1435 1812 1824", } result = translate_message(msg) assert result["message_type"] == "oooi" assert result["parsed"] is not None assert result["parsed"]["origin"] == "KJFK"