aprs.me/test/aprsme/geo_utils_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

134 lines
4.8 KiB
Elixir

defmodule Aprsme.GeoUtilsTest do
use ExUnit.Case, async: true
use ExUnitProperties
alias Aprsme.GeoUtils
doctest GeoUtils
describe "haversine_distance/4" do
test "calculates zero distance for same point" do
assert GeoUtils.haversine_distance(33.16961, -96.4921, 33.16961, -96.4921) == 0.0
end
test "calculates small distances accurately" do
# About 1.1 meters north
distance = GeoUtils.haversine_distance(33.16961, -96.4921, 33.16962, -96.4921)
assert_in_delta distance, 1.11, 0.1
end
test "calculates GPS drift-like distances" do
# Typical GPS drift of ~5 meters
distance = GeoUtils.haversine_distance(33.16961, -96.4921, 33.169655, -96.4921)
assert_in_delta distance, 5.0, 0.5
end
test "calculates larger distances" do
# About 100 meters
distance = GeoUtils.haversine_distance(33.16961, -96.4921, 33.17061, -96.4921)
assert_in_delta distance, 111.2, 1.0
end
test "handles nil inputs" do
assert GeoUtils.haversine_distance(nil, -96.4921, 33.16962, -96.4921) == nil
assert GeoUtils.haversine_distance(33.16961, nil, 33.16962, -96.4921) == nil
assert GeoUtils.haversine_distance(33.16961, -96.4921, nil, -96.4921) == nil
assert GeoUtils.haversine_distance(33.16961, -96.4921, 33.16962, nil) == nil
end
test "handles non-numeric inputs" do
assert GeoUtils.haversine_distance("33.16961", -96.4921, 33.16962, -96.4921) == nil
assert GeoUtils.haversine_distance(33.16961, "invalid", 33.16962, -96.4921) == nil
end
end
describe "significant_movement?/5" do
test "returns false for no movement" do
refute GeoUtils.significant_movement?(33.16961, -96.4921, 33.16961, -96.4921)
end
test "returns false for GPS drift under default threshold" do
# About 5 meters - typical GPS drift
refute GeoUtils.significant_movement?(33.16961, -96.4921, 33.169655, -96.4921)
end
test "returns true for movement over default threshold" do
# About 55 meters movement (over 50m default threshold)
assert GeoUtils.significant_movement?(33.16961, -96.4921, 33.1701, -96.4921)
end
test "respects custom threshold" do
# About 5 meters movement
lat1 = 33.16961
lon1 = -96.4921
lat2 = 33.169655
lon2 = -96.4921
# With 3 meter threshold, should be significant
assert GeoUtils.significant_movement?(lat1, lon1, lat2, lon2, 3)
# With 10 meter threshold (default), should not be significant
refute GeoUtils.significant_movement?(lat1, lon1, lat2, lon2, 10)
# With 20 meter threshold, definitely not significant
refute GeoUtils.significant_movement?(lat1, lon1, lat2, lon2, 20)
end
test "handles nil inputs" do
refute GeoUtils.significant_movement?(nil, -96.4921, 33.16962, -96.4921)
refute GeoUtils.significant_movement?(33.16961, nil, 33.16962, -96.4921)
refute GeoUtils.significant_movement?(33.16961, -96.4921, nil, -96.4921)
refute GeoUtils.significant_movement?(33.16961, -96.4921, 33.16962, nil)
end
end
describe "property: haversine_distance" do
property "is always non-negative for numeric inputs" do
check all(
lat1 <- float(min: -89.0, max: 89.0),
lon1 <- float(min: -179.0, max: 179.0),
lat2 <- float(min: -89.0, max: 89.0),
lon2 <- float(min: -179.0, max: 179.0)
) do
assert GeoUtils.haversine_distance(lat1, lon1, lat2, lon2) >= 0
end
end
property "is symmetric: d(a,b) == d(b,a)" do
check all(
lat1 <- float(min: -89.0, max: 89.0),
lon1 <- float(min: -179.0, max: 179.0),
lat2 <- float(min: -89.0, max: 89.0),
lon2 <- float(min: -179.0, max: 179.0)
) do
a = GeoUtils.haversine_distance(lat1, lon1, lat2, lon2)
b = GeoUtils.haversine_distance(lat2, lon2, lat1, lon1)
assert_in_delta a, b, 0.01
end
end
property "d(p, p) == 0" do
check all(
lat <- float(min: -89.0, max: 89.0),
lon <- float(min: -179.0, max: 179.0)
) do
assert GeoUtils.haversine_distance(lat, lon, lat, lon) == 0.0
end
end
end
describe "property: significant_movement?" do
property "agrees with the haversine + threshold check" do
check all(
lat1 <- float(min: -89.0, max: 89.0),
lon1 <- float(min: -179.0, max: 179.0),
lat2 <- float(min: -89.0, max: 89.0),
lon2 <- float(min: -179.0, max: 179.0),
threshold <- integer(1..1000)
) do
d = GeoUtils.haversine_distance(lat1, lon1, lat2, lon2)
assert GeoUtils.significant_movement?(lat1, lon1, lat2, lon2, threshold) == d > threshold
end
end
end
end