- 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).
- get_coordinates_from_mic_e: replace two inline `if direction == ...`
rebinds with a reusable apply_hemisphere_sign/3 helper; the final
range check becomes maybe_return_coords/2 with a guarded clause that
yields {lat, lon} or {nil, nil}.
- has_position_data?: the boolean short-circuit collapses from an
explicit if/else to a single `or` expression.
All 37 CoordinateUtils tests (4 properties) still pass.
The original get_status/0 had a nested case/try that duplicated the
"disconnected" status map across two branches. Split into:
- status_from/1 with nil + is_pid heads for the "no GenServer" and
"GenServer alive" paths. The alive path isolates the catch :exit, _
fallback for a non-responding process.
- disconnected_status/1 builds the shared status map once, parameterised
on the default server string to preserve the original branch-specific
fallback behavior.
Removes ~20 duplicated lines; all 61 Is tests still pass.
- get_cluster_aprs_status: fetch_cluster_status/1 dispatches on the
clustering flag — true fans out cluster-wide, false goes straight to
the local Aprsme.Is status.
- init/1: extract schedule_initial_election/1 with true/false heads.
The clustered branch sets up the check-and-backstop timers; the
non-clustered branch queues an immediate election. Makes the two
startup paths obvious from the function signatures.
No behavior change; all 17 LeaderElection tests still pass.
- 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.
- encoding_info/1 (binary clause): extract build_encoding_info/2 with
true/false heads on String.valid?/1, so the valid-UTF-8 and invalid
branches each own their map literal.
- try_utf8_conversion/1: convert_to_utf8/2 dispatches on String.valid?/1
so the latin1 → UTF-8 fallback is a function head, not an inline if.
No behavior change; all 34 Encoding tests still pass.
build_search_pattern/1 picks between SQL-wildcard (when the query
contains `*`) and prefix-match (SSID-friendly) forms via two function
heads instead of an inline `if`. The transform is now isolated and
obviously boolean-dispatched at the call site.
- Three-way cond (known-table / overlay-capable char / fallback) becomes
three function heads: a guard-matched clause for the canonical
"/"/"\\"/"]" tables, an is_binary clause that decides via regex match
whether the input is a single alphanumeric overlay character, and a
catch-all fallback.
Cluster.ConnectionManager.handle_info({:leadership_change, ...}) used
a cond on the (became_leader, node, connection_started) triple. Split
into handle_leadership_change/3 with three clauses:
- became_leader=true, us=true, not already started → start APRS-IS
- became_leader=false, us=true, already started → stop APRS-IS
- everything else → no-op
Makes the three state transitions visible in the function heads and
eliminates one more cond from the codebase.
The original handle_cast had nested `if`s: outer branch on demand > 0,
inner branch on buffer-over-capacity. Split into:
- handle_cast with a `when demand > 0` guard for the hot path that
skips the buffer entirely.
- A fallback clause that computes whether the new size would overflow
and delegates to buffer_packet/3.
- buffer_packet/3 has two clauses — one for the drop-oldest path
(with telemetry + warning) and one for the simple append path. Both
share the final `maybe_activate_backpressure |> reply_noemit` step.
All 19 existing PacketProducer tests pass; dialyzer stays clean.
- do_hash_password/3: move the changeset.valid? branch out of the
`if` into apply_hash/3, dispatched on the boolean. The bcrypt 72-byte
cap and plaintext-scrubbing steps now live in one clear function head.
- validate_current_password/2: dispatch on valid_password?/2 via
check_current_password/2 so the add_error branch is its own clause.
No behavior change; all 24 Accounts tests still pass and dialyzer stays
clean.
- 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.