Coverage:
- Adds focused tests across 13 files covering previously-uncovered
branches: Packet changeset normalisation (course, wind_direction,
struct data_extended); Packets store_packet edge cases (nested
position shapes, ssid handling, string-keyed raw_packet);
DeviceIdentification HTTP success/404 via Req plug stub; ResendAdapter
catch-all body, deliver_many, nil/binary formatters; ApiDocsLive
packets with missing fields; AprsSymbol normalize helpers;
BadPacketsLive refresh and postgres_notify; MobileChannel handle_info
catch-all and postgres_packet path; PacketProcessor existing-marker
movement detection; PacketReplay sanitize_value type clauses;
InsertOptimizer GenServer lifecycle and negative-duration metric;
PageController shutdown-handler integration; UrlParams delegated
helpers.
- mix.exs: configure test_coverage with summary threshold of 87 and
ignore_modules for test fixtures and macro-only template modules.
Bug fix:
- MapLive.Index handle_info: add a clause for the raw {:new_deployment,
_} tuple. Phoenix.PubSub.broadcast delivers the raw payload to plain
subscribers, but the existing handler only matched the %Broadcast{}
fast-lane wrapper. DeploymentNotifier broadcasts via the raw path,
which crashed the LiveView under test concurrency.
Submodule:
- Update .gitmodules vendor/aprs URL from
https://github.com/aprsme/aprs.git to
ssh://git@codeberg.org/gmcintire/aprs.git.
- render_for_zoom/3: zoom ≤ 8 uses heatmap; high zoom with marker_data
pushes to the client; high zoom + nil marker_data is a no-op. Each
branch is now a separate function head.
- push_new_packet/3: a boolean-dispatched pair replaces the popup-open
conditional on the push_event payload.
- prepare_packet_state: the two rebinding `if`s turn into a pipeline
through prune_if_over_cap/1 (pattern-matched on map_size/1) and
build_marker_data/5 with a zoom ≤ 8 short-circuit clause, plus
maybe_tag_convert_from/3 for the replacement-marker tag.
- moved_significantly?/3: the duplicated guard check between
dispatch_visibility and batch_dispatch collapses into one helper that
pattern-matches on the coordinate tuple returned by CoordinateUtils.
Adds extra tests covering the new significance / stale-coords branches
and the connection card LiveComponent render paths. Coverage 65.89 → 66.41%.
Swaps `if`/`cond` branches for multi-clause function heads or head-pattern
matching, making the control flow visible in the function signatures:
- Navigation.determine_map_location: resolve_location/4 now dispatches on
the shape of the geolocation input and whether URL params are explicit.
- Navigation.handle_callsign_tracking: per-case clauses for empty callsign
and explicit-URL-params short-circuits, plus a final clause that does the
DB lookup and rescues once.
- Navigation.handle_callsign_search: dispatch_callsign_search/3 separates
the valid/invalid callsign branches.
- InsertOptimizer.optimize_based_on_performance: pattern-match on
[_, _, _ | _] to require ≥3 samples without calling length/1.
- InsertOptimizer.calculate_insert_options and throughput helpers split
into guarded clauses instead of inline `if`.
- maybe_emit_optimization uses same-var pattern matching to skip the
telemetry hit when nothing changed.
Adds unit tests covering every branch of both modules plus SignalHandler,
LocaleHook, and the InsertOptimizer's :noproc fallback path. Coverage
64.69% → 65.72%.
Adds ~800 new tests (incl. 27 StreamData properties) across 22 modules
that previously had little or no coverage. Highlights:
- Pure utility modules (LogSanitizer, PacketFieldWhitelist,
PacketSanitizer, DeviceParser, CoordinateUtils, BoundsUtils,
ParamUtils, Convert, WeatherUnits) get thorough unit + property
coverage including UTF-8 truncation boundaries, antimeridian
longitude wrap, Haversine symmetry, and unit-conversion inverses.
- JSON view modules (CallsignJSON, ErrorJSON, ChangesetJSON) verified
for envelope shape and error templating.
- Plugs (HealthCheck, RateLimiter, ApiCSRF) exercised for happy-path
and halt paths.
- GenServer modules (RegexCache, CleanupScheduler, DeploymentNotifier)
tested without touching the supervised singleton where possible.
- Drops the orphaned map_live/map_helpers_test.exs whose module name
collided with the new live/shared/coordinate_utils_test.exs.
Objects and items now display with their own names on the map instead of
the originating station's callsign. This prevents confusion where stations
creating objects (like repeaters) appear at multiple locations.
For example, CALGRY creates repeater objects (147.06-WC, 146.85-NH) which
were appearing on the map labeled as "CALGRY" at the repeater locations
instead of showing the actual object names.
Changes:
- Updated map_label() to return object_name for object packets
- Updated map_label() to return item_name for item packets
- Position packets continue to show the sender callsign
- Updated tests to expect object/item names instead of sender
This matches APRS.fi behavior where objects are displayed separately
from their originating station.
- Modified handle_zoom_threshold_crossing to detect tracked_callsign
- Show trail line instead of heat map when tracking at zoom ≤ 8
- Maintain heat map behavior when not tracking
- Maintain marker behavior at zoom > 8
- Filters packets by tracked callsign and time threshold
- Sorts packets chronologically by received_at
- Pushes show_trail_line event with coordinates
- Returns socket unchanged when no packets found
- Strip Mic-E telemetry from comments before database storage
- Show sender callsign on map labels instead of object names for clarity
- Object names still used for grouping to maintain trail organization
- Add comprehensive tests for new encoding utilities
Fixes display issues where weather balloon "X3234025" was shown
instead of station "WA0YMH", and Mic-E telemetry bytes like "!w>`!"
were appearing in comments.
- Replace N+1 get_latest_packet_for_callsign calls in RF path loading
with single get_latest_packets_for_callsigns batch query (DISTINCT ON)
- Change batch packet processing to collect marker removal IDs and push
one remove_markers_batch event instead of individual remove_marker calls
- Add callsignIndex reverse map (callsign_group → Set<markerID>) for O(1)
lookup in new_packet/new_packets handlers instead of scanning all markers
- Server tracks callsign replacements in prepare_packet_state, sends
convert_to_historical list so JS skips full markerStates scan
- Historical packets get red dot HTML server-side in build_minimal_packet_data
instead of JS createMarkerIcon generating it
- Add callsign_group field to all packet data output; server pre-sorts
by group with chronological order so JS iterates directly
- Normalize heat map intensity in Clustering.cluster_packets (min/50, cap 1.0)
instead of JS doing it per-point
- Remove buildPopupContent JS fallback and unused escapeHtml import;
server already provides popup in all data paths