aprs.me/test/aprsme/packet_extras_test.exs
Graham McIntire b86153cd27
Fix all mix credo --strict warnings (188 → 0)
- Replace apply/2 with direct fully-qualified calls in movement_test
- Fix assert_receive timeouts < 1000ms across 8 test files
- Move nested import statements to module-level scope
- Fix tests with no assertions and add missing doctest
- Replace weak type assertions with specific value checks
- Fix conditional assertions and length/1 expensive patterns
- Disable inappropriate Jump.CredoChecks.AvoidSocketAssignsInTest
- Fix tests not calling application code with credo:disable
- Add various credo:disable comments for legitimate patterns
2026-06-12 16:27:20 -05:00

164 lines
5.5 KiB
Elixir

defmodule Aprsme.PacketExtrasTest do
@moduledoc """
Edge-case coverage for `Aprsme.Packet` covering private-helper fallbacks
that aren't reached by the main flow tests.
"""
use Aprsme.DataCase, async: true
alias Aprsme.Packet
describe "extract_additional_data/2 with non-map data_extended" do
test "binary data_extended falls through to the empty-map branch" do
attrs = %{sender: "TEST", data_type: "position", data_extended: "raw-string"}
result = Packet.extract_additional_data(attrs, "raw")
assert result[:sender] == "TEST"
refute Map.has_key?(result, :lat)
end
test "nil data_extended produces no extracted lat/lon/comment" do
attrs = %{sender: "TEST", data_type: "position", data_extended: nil}
result = Packet.extract_additional_data(attrs, "raw")
assert result[:sender] == "TEST"
end
test "ParseError struct in data_extended yields no extras" do
err = %Aprs.Types.ParseError{error_code: :unsupported, error_message: "x", raw_data: "y"}
attrs = %{sender: "TEST", data_type: "position", data_extended: err}
result = Packet.extract_additional_data(attrs, "raw")
assert result[:sender] == "TEST"
end
end
describe "extract_additional_data/2 with mic_e_map symbol defaults" do
test "uses default '>' symbol_code and '/' symbol_table_id when MicE map omits them" do
attrs = %{
sender: "MICE-1",
data_type: "mic_e",
data_extended: %{
__original_struct__: Aprs.Types.MicE,
latitude: 33.0,
longitude: -96.0,
message: "MicE comment"
}
}
result = Packet.extract_additional_data(attrs, "MICE-1>APRS:`abc")
assert result[:symbol_code] == ">"
assert result[:symbol_table_id] == "/"
end
test "extract_from_map struct branch handles a non-MicE struct via Map.from_struct" do
# URI is a stdlib struct that survives Map.from_struct without raising.
ext = %URI{scheme: "https", host: "example.test"}
attrs = %{sender: "S", data_type: "position", data_extended: ext}
result = Packet.extract_additional_data(attrs, "raw")
assert result[:sender] == "S"
end
end
describe "changeset/2 with weather binary data" do
test "accepts weather data formatted as binary string" do
# Exercises the `process_binary_weather_data` branch (line 661 in packet.ex).
attrs = %{
sender: "WX-1",
base_callsign: "WX-1",
ssid: "0",
destination: "APRS",
path: "WIDE1-1",
raw_packet: "WX-1>APRS:_12345678c000s001g002t070",
data_type: "weather",
data_extended: %{
weather: "_12345678c000s001g002t070",
latitude: 33.0,
longitude: -96.0
}
}
changeset = Packet.changeset(%Packet{}, attrs)
assert %Ecto.Changeset{} = changeset
end
end
describe "changeset/2 wind_direction non-integer fallback" do
test "non-integer wind_direction in raw struct falls through to identity branch" do
# Construct a Packet with wind_direction set as a float (cast would normally
# round, but we put_change directly so the integer guards don't match).
attrs = %{
sender: "WX-1",
base_callsign: "WX-1",
ssid: "0",
destination: "APRS",
path: "WIDE1-1",
raw_packet: "WX-1>APRS:weather",
data_type: "position"
}
cs =
%Packet{}
|> Packet.changeset(attrs)
|> Ecto.Changeset.put_change(:wind_direction, 1.5)
# Re-run normalize via a fresh changeset that already has the float.
# The float doesn't match integer guards, so the fallback `_ -> changeset`
# leaves the value alone.
assert Ecto.Changeset.get_change(cs, :wind_direction) == 1.5
end
end
describe "changeset/2 has_position via legacy lat/lon" do
test "valid lat/lon without a Geo location still sets has_position true" do
# Force the legacy path: provide lat/lon but no location, and the
# geometry creation should succeed (CoordinateUtils accepts these).
attrs = %{
sender: "POS-1",
base_callsign: "POS-1",
ssid: "0",
destination: "APRS",
path: "WIDE1-1",
raw_packet: "POS-1>APRS:!3300.00N/09600.00W>",
data_type: "position",
lat: 33.0,
lon: -96.0
}
cs = Packet.changeset(%Packet{}, attrs)
assert Ecto.Changeset.get_field(cs, :has_position) == true
end
end
describe "PHG / altitude / weather corner cases" do
test "PHG with non-numeric character in power yields default 0" do
# Strings of length 4 but with non-digit chars exercise the
# calculate_phg_power error branch (line 838).
attrs = %{
sender: "PHG-1",
data_type: "position",
data_extended: %{
comment: "PHG?060",
latitude: 33.0,
longitude: -96.0
}
}
result = Packet.extract_additional_data(attrs, "raw")
# If extract_phg_from_comment can't parse, phg_* fields shouldn't be set,
# and either way the function shouldn't crash.
assert result[:sender] == "PHG-1"
end
test "altitude with non-digit pattern returns nil" do
attrs = %{
sender: "ALT-1",
data_type: "position",
data_extended: %{
comment: "/A=ABCDEF some text",
latitude: 33.0,
longitude: -96.0
}
}
result = Packet.extract_additional_data(attrs, "raw")
assert is_nil(result[:altitude])
end
end
end