- CoreComponents.input/1: expanded coverage to include the select,
textarea, generic-text, and unchecked-checkbox branches, plus
error-vs-no-error border styling.
- PostgresNotifier: handle_info forwards pg_notify payload to
Aprsme.PubSub and ignores unrelated messages.
Coverage 69.56 → 70.11%.
Four properties exercise haversine_distance / significant_movement?:
- non-negativity across any in-range coordinate pair
- symmetry: d(a, b) == d(b, a) within a tight tolerance
- identity: d(p, p) == 0.0
- significance agrees with (haversine > threshold) for any integer
threshold in 1..1000
Total: +4 properties, coverage stays clean (dialyzer: 0 new errors).
- supported_locales/0 returns the declared ~w(en es de fr) list.
- put_locale/1 sets the Gettext process locale for each supported
value and raises FunctionClauseError for unsupported input.
3 tests, async:false because they mutate process-wide Gettext state.
- parse_path_element_with_link splits its fat `if`/or-chain into three
focused helpers: linkable_callsign?/1 (regex + alias check),
path_alias?/1 (four String.starts_with guards), and
classify_path_element/2 (link vs. text dispatched on the boolean).
- display_for_element/2 chooses the callsign form with/without the
asterisk via two function heads instead of an inline `if`.
Adds 7 tests covering the parse_path_with_links/1 public API — plain
callsigns, heard-via asterisk preservation, non-linkable aliases
(WIDE/TRACE/RELAY/TCPIP), q-constructs, whitespace trimming, and mixed
paths.
- handle_call(:shutdown, _, state): split into a shutting_down=true
fast-path clause and a normal initiate_shutdown clause. No more
`if state.shutting_down` inside the callback body.
- terminate/2: extract graceful_shutdown_needed?/1 (four function
heads on the reason tag) and maybe_graceful_drain/2 (guarded on
state.shutting_down) so the shutdown side-effects are isolated to
a single, pattern-matched entry point.
Adds 4 unit tests for the pure callback paths
(shutting_down?, shutdown-already-in-progress, EXIT pass-through,
rescue fallback on unavailable GenServer).
- CoreComponents.safe_row_id: four function heads dispatch on the row
shape (atom-key map, string-key map, other map fallback, non-map)
instead of a cond with Map.has_key? checks.
- Api.V1.CallsignController.validate_callsign: check_callsign_format/2
splits the validation success/failure branches into two clauses; the
binary-vs-everything-else dispatch stays in validate_callsign/1.
Adds 5 integration tests for the CallsignController covering invalid,
not-found, success, case-normalization, and length-limit paths. The
test file is async:false because it shares the rate-limiter ETS with
other API tests and could otherwise trip the 100/min per-IP cap.
- Aprsme.Packet.put_phg_fields: dispatch on the shape of the phg value
(map / 4-char binary / anything else) via put_phg_fields_for/2.
- Aprsme.Packet.get_field_value: remove the catch-all nil clause. After
the put_phg_fields refactor, dialyzer can prove every call site passes
a map and flagged the fallback as unreachable — so it's gone, and
a future mistyped caller now fails loudly instead of silently.
- LogSanitizer.sanitize_map: extract redact_field/2 for readability.
- DeviceIdentification.pattern_matches?: match_pattern/3 dispatched on
String.contains?/2 keeps the rescue tight around the regex path.
- InfoLive.Show: get_received_at pattern-matches on key shape;
format_distance splits locale × range via four format_*_distance
helpers; calculate_course pipes through normalize_bearing/1.
Adds 15 tests exercising the InfoLive.Show helpers (imperial vs. metric
formatting, cardinal bearings, haversine symmetry, Decimal inputs).
Coverage 67.43 → 67.72%.
- HealthCheck.check_health(:readiness): collapse the 3-branch cond into
readiness_status/2 dispatched on (health_status, shutting_down?).
- HealthCheck.shutting_down?: the whereis + alive? + try/catch nest
becomes a small pipeline of function heads (ask_shutting_down?/1 +
ask_if_alive/2), with the catch isolated to the single place it fires.
- EncodingUtils.sanitize_string_fields and sanitize_nested_map shared a
three-branch atom-or-string key lookup. Extract update_existing_key/3
+ first_present_key/3 + nil_aware/1 helpers; the original functions
become two-liners.
- StatusLive.Index.format_uptime: splits the cond into
format_uptime_parts/4 clauses with numeric guards.
- StatusLive.Index.calculate_health_score: struct-shape pattern match
on %{connected: false} / %{uptime_seconds: s} guards replaces the cond.
- StatusLive.Index.format_time_ago: pipe the diff through
format_seconds_ago/1 with four clauses.
Adds tests for the four public StatusLive.Index helpers
(format_uptime, format_time_ago, get_health_description, format_number).
Coverage 67.29 → 67.43%.
- TimeHelpers.to_datetime: `cond` with match?/2 guards becomes five
function heads dispatched by input type — DateTime passes through,
NaiveDateTime anchors to UTC, integer is a millisecond Unix epoch,
binary tries ISO 8601, everything else is nil.
- PageController.health: the three-branch `cond` + inner `if db_healthy`
becomes a chain of small respond_* helpers, each pattern-matched on a
single axis (health_status, shutting_down?, db_healthy?). db_healthy?/0
isolates the rescue.
- format_uptime splits the cond into four format_uptime_parts/4 clauses.
Adds tests for the PageController actions (health 200 / 503-draining,
ready, sitemap.xml, .well-known/api-catalog, status.json). Coverage
66.81 → 67.29%.
- SharedPacketHandler.handle_packet_update: dispatch on filter-result,
and use maybe_enrich/2 dispatched on the enrich? boolean instead of
an inner `if`. lookup_device_info/1 is now a trio of function heads.
- Cluster.Topology.child_spec: build_spec/3 dispatches on
(cluster_enabled?, topologies) tuples — no more nested `if`.
- Cluster.PacketDistributor.distribute_packet: maybe_broadcast/2
dispatches on the leader-and-enabled check; the non-leader / disabled
paths return :ok explicitly instead of relying on an `if` expression's
implicit nil.
Adds tests for SharedPacketHandler (filter/enrich/match paths,
callsign_filter + callsign_and_weather_filter factories) and extends
Cluster.Topology tests to cover the nil-topology and opts-merge cases.
Coverage 66.41 → 66.81%.
- 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%.
- DeviceCache.pattern_matches?: replace a 3-branch `cond` with a
two-clause `case` on `String.contains?(pattern, "?")`. The old `*`
branch was dead code (it did the same exact-match compare as the
fallback), so it's removed.
- Telemetry.DatabaseMetrics.collect_postgres_metrics: dispatch on
environment atom via multi-clause private functions instead of
`if Application.get_env(...) == :test`.
New tests:
- DeviceCache wildcard/exact lookup paths exercised via a seeded cache.
- MobileUserSocket connect/3 for x_headers/peer_data/empty info and
rate-limit deny.
- DatabaseMetrics pool-metrics emission captured via :telemetry handler
and the :test-env short-circuit.