test: expand CoreComponents coverage for modal, table, list, back, simple_form

This commit is contained in:
Graham McIntire 2026-04-23 16:42:38 -05:00
parent 74cfb52808
commit a843c91191
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59

View file

@ -279,10 +279,218 @@ defmodule AprsmeWeb.CoreComponentsTest do
test "show_modal returns a JS struct" do
assert %JS{} = CoreComponents.show_modal("my-modal")
end
test "hide_modal returns a JS struct" do
assert %JS{} = CoreComponents.hide_modal("my-modal")
end
end
describe "translate_error/1" do
test "passes plain error tuples through gettext" do
# No :count opt → uses dgettext.
result = CoreComponents.translate_error({"is invalid", []})
assert is_binary(result)
assert result =~ "invalid"
end
test "uses dngettext for plural errors" do
result = CoreComponents.translate_error({"should be %{count} character(s)", [count: 5]})
assert is_binary(result)
assert result =~ "5"
end
end
describe "translate_errors/2" do
test "returns translated errors for the given field" do
errors = [
{:name, {"can't be blank", []}},
{:age, {"is not a number", []}},
{:name, {"is too short", []}}
]
name_errors = CoreComponents.translate_errors(errors, :name)
assert length(name_errors) == 2
assert Enum.all?(name_errors, &is_binary/1)
end
test "returns an empty list when no errors match the field" do
assert CoreComponents.translate_errors([{:other, {"x", []}}], :missing) == []
end
end
describe "modal/1" do
test "renders a modal with the inner block and close button" do
html =
render_component(&CoreComponents.modal/1, %{
id: "test-modal",
show: false,
inner_block: text_slot("Modal body content"),
title: [],
subtitle: [],
confirm: [],
cancel: [],
on_confirm: %JS{},
on_cancel: %JS{}
})
assert html =~ ~s(id="test-modal")
assert html =~ "Modal body content"
assert html =~ ~s(aria-modal="true")
assert html =~ ~s(aria-label="close")
end
test "renders the title and subtitle slots when supplied" do
html =
render_component(&CoreComponents.modal/1, %{
id: "sample-modal",
show: false,
inner_block: text_slot(""),
title: slot_with_text(:title, "My Modal Title"),
subtitle: slot_with_text(:subtitle, "My subtitle"),
confirm: [],
cancel: [],
on_confirm: %JS{},
on_cancel: %JS{}
})
assert html =~ "My Modal Title"
assert html =~ "My subtitle"
end
end
describe "table/1" do
test "renders a row for each entry in :rows" do
html =
render_component(&CoreComponents.table/1, %{
id: "users",
rows: [%{id: 1, name: "Alice"}, %{id: 2, name: "Bob"}],
row_click: nil,
col: [
%{
__slot__: :col,
label: "Name",
inner_block: fn _changed, user -> user.name end
}
],
action: []
})
assert html =~ "Alice"
assert html =~ "Bob"
assert html =~ ~s(id="users")
assert html =~ "Name"
end
test "renders action slot when provided" do
html =
render_component(&CoreComponents.table/1, %{
id: "users",
rows: [%{id: 1, name: "Alice"}],
row_click: nil,
col: [
%{
__slot__: :col,
label: "Name",
inner_block: fn _changed, user -> user.name end
}
],
action: [
%{
__slot__: :action,
inner_block: fn _changed, _user -> "Edit" end
}
]
})
assert html =~ "Edit"
end
end
describe "list/1" do
test "renders a description list with each item" do
html =
render_component(&CoreComponents.list/1, %{
item: [
%{
__slot__: :item,
title: "First",
inner_block: fn _changed, _ -> "alpha" end
},
%{
__slot__: :item,
title: "Second",
inner_block: fn _changed, _ -> "beta" end
}
]
})
assert html =~ "First"
assert html =~ "alpha"
assert html =~ "Second"
assert html =~ "beta"
end
end
describe "back/1" do
test "renders a back link with the given navigate target" do
html =
render_component(&CoreComponents.back/1, %{
navigate: "/somewhere",
inner_block: text_slot("Go back")
})
assert html =~ "Go back"
assert html =~ ~s(href="/somewhere")
end
end
describe "simple_form/1" do
test "renders a form with action buttons" do
html =
render_component(&CoreComponents.simple_form/1, %{
for: %{},
as: :user,
rest: %{},
inner_block: text_slot("form fields"),
actions: [
%{
__slot__: :actions,
inner_block: fn _changed, _ -> "Save" end
}
]
})
assert html =~ "<form"
assert html =~ "form fields"
assert html =~ "Save"
end
end
describe "header/1 with dev mode" do
test "shows the DEV badge when dev_mode is true" do
html = render_component(&CoreComponents.header/1, %{dev_mode: true})
assert html =~ "DEV"
end
test "omits the DEV badge by default" do
html = render_component(&CoreComponents.header/1, %{})
refute html =~ "\">DEV</"
end
end
describe "theme_selector/1" do
test "renders the theme dropdown" do
html = render_component(&CoreComponents.theme_selector/1, %{})
assert html =~ "theme-menu" or html =~ "theme"
end
end
# Helper: build a LiveView inner_block slot that just emits text.
defp text_slot(text) do
[%{__slot__: :inner_block, inner_block: fn _changed, _ -> text end}]
end
defp slot_with_text(name, text) do
[%{__slot__: name, inner_block: fn _changed, _ -> text end}]
end
end