Add coverage tests for CoreComponents (input form/field, safe_row_id) and DataBuilder edge cases

This commit is contained in:
Graham McIntire 2026-05-08 12:11:14 -05:00
parent d0296c9f4e
commit 4bf1a6b3b3
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59
2 changed files with 144 additions and 0 deletions

View file

@ -129,6 +129,96 @@ defmodule AprsmeWeb.CoreComponentsTest do
end
end
describe "table/1 row id branches via safe_row_id" do
test "uses string-keyed 'id' when present" do
html =
render_component(&CoreComponents.table/1, %{
id: "rows",
rows: [%{"id" => "row-string", "name" => "X"}],
col: [%{label: "Name", inner_block: fn _, row -> Map.get(row, "name") end}],
action: [],
row_click: nil,
row_id: nil,
row_item: & &1,
rest: %{}
})
assert html =~ "row-string"
end
test "falls back to MD5 hash when row map has no id key" do
html =
render_component(&CoreComponents.table/1, %{
id: "rows-noid",
rows: [%{name: "noid"}],
col: [%{label: "Name", inner_block: fn _, row -> Map.get(row, :name) end}],
action: [],
row_click: nil,
row_id: nil,
row_item: & &1,
rest: %{}
})
# The rendered HTML must include the rows table without crashing.
assert html =~ "rows-noid"
end
test "delegates non-map rows to Phoenix.Param" do
# Phoenix.Param.to_param("string-row") returns the string itself.
html =
render_component(&CoreComponents.table/1, %{
id: "string-rows",
rows: ["alpha", "beta"],
col: [%{label: "Value", inner_block: fn _, row -> row end}],
action: [],
row_click: nil,
row_id: nil,
row_item: & &1,
rest: %{}
})
assert html =~ "alpha"
assert html =~ "beta"
end
end
describe "input/1 with a {form, field} tuple" do
test "extracts name/id/value/errors from the form via the {form, field} clause" do
# Builds a Phoenix.HTML.Form via Plug.Conn-less helpers — Form.from_struct
# gives a minimal form value to thread through input/1's first clause.
f = Phoenix.Component.to_form(%{"username" => "alice"}, as: :user)
html =
render_component(&CoreComponents.input/1, %{
field: {f, :username},
type: "text",
label: "Username",
multiple: false,
errors: []
})
assert html =~ ~s(name="user[username]")
assert html =~ "alice"
end
test "appends [] to the name when multiple is true" do
f = Phoenix.Component.to_form(%{"tags" => []}, as: :user)
html =
render_component(&CoreComponents.input/1, %{
field: {f, :tags},
type: "select",
label: "Tags",
multiple: true,
options: [{"Foo", "foo"}, {"Bar", "bar"}],
errors: [],
prompt: nil
})
assert html =~ ~s(name="user[tags][])
end
end
describe "input/1 checkbox" do
test "renders a checkbox with a hidden false companion input" do
html =

View file

@ -102,6 +102,60 @@ defmodule AprsmeWeb.MapLive.DataBuilderExtrasTest do
end
end
describe "build_packet_data with invalid coordinates" do
test "returns nil when lat is out of range" do
packet = %{
"id" => "bad-1",
"sender" => "BAD-1",
"callsign" => "BAD-1",
"received_at" => DateTime.utc_now(),
"lat" => 99.9,
"lon" => -96.0
}
assert is_nil(DataBuilder.build_packet_data(packet, true))
end
test "returns nil when lat/lon are non-numeric" do
packet = %{
"id" => "bad-2",
"sender" => "BAD-2",
"callsign" => "BAD-2",
"received_at" => DateTime.utc_now(),
"lat" => "not-a-number",
"lon" => "also-bad"
}
assert is_nil(DataBuilder.build_packet_data(packet, true))
end
end
describe "build_packet_data_list/1 with empty groups" do
test "returns [] for an empty list" do
assert DataBuilder.build_packet_data_list([]) == []
end
test "deduplicates packets with the same callsign_group" do
now = DateTime.utc_now()
packets =
for i <- 1..3 do
%{
"id" => "dup-#{i}",
"sender" => "DUP-1",
"callsign" => "DUP-1",
"callsign_group" => "DUP-1",
"received_at" => DateTime.add(now, -i * 60, :second),
"lat" => 33.0 + i * 0.001,
"lon" => -96.0 + i * 0.001
}
end
result = DataBuilder.build_packet_data_list(packets)
assert is_list(result)
end
end
describe "build_packet_data with string-typed weather values exercises convert_unit" do
test "string numeric weather values parse via Float.parse branch" do
packet = %{