Add coverage tests for CoreComponents (input form/field, safe_row_id) and DataBuilder edge cases
This commit is contained in:
parent
d0296c9f4e
commit
4bf1a6b3b3
2 changed files with 144 additions and 0 deletions
|
|
@ -129,6 +129,96 @@ defmodule AprsmeWeb.CoreComponentsTest do
|
||||||
end
|
end
|
||||||
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
|
describe "input/1 checkbox" do
|
||||||
test "renders a checkbox with a hidden false companion input" do
|
test "renders a checkbox with a hidden false companion input" do
|
||||||
html =
|
html =
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,60 @@ defmodule AprsmeWeb.MapLive.DataBuilderExtrasTest do
|
||||||
end
|
end
|
||||||
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
|
describe "build_packet_data with string-typed weather values exercises convert_unit" do
|
||||||
test "string numeric weather values parse via Float.parse branch" do
|
test "string numeric weather values parse via Float.parse branch" do
|
||||||
packet = %{
|
packet = %{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue