test: expand CoreComponents coverage for modal, table, list, back, simple_form
This commit is contained in:
parent
74cfb52808
commit
a843c91191
1 changed files with 208 additions and 0 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue