towerops/test/towerops_web/live/components/global_search_component_test.exs
2026-06-15 11:15:46 -05:00

131 lines
3.6 KiB
Elixir

defmodule ToweropsWeb.Live.Components.GlobalSearchComponentTest do
use ToweropsWeb.ConnCase, async: true
import Phoenix.LiveViewTest
setup :register_and_log_in_user
setup %{conn: conn, user: user} do
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test ISP"}, user.id)
{:ok, site} =
Towerops.Sites.create_site(%{
name: "Tower Alpha",
organization_id: organization.id
})
{:ok, _device} =
Towerops.Devices.create_device(%{
name: "Core Router",
ip_address: "10.0.0.1",
site_id: site.id,
organization_id: organization.id,
snmp_enabled: true
})
conn = Plug.Conn.put_session(conn, :current_organization_id, organization.id)
%{conn: conn, organization: organization}
end
describe "global search" do
test "search event with value param finds results", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/dashboard")
html =
view
|> element("#global-search")
|> render_hook("open", %{})
assert html =~ "Search devices"
html =
view
|> element("#global-search")
|> render_hook("search", %{"value" => "Core Router"})
assert html =~ "Core Router"
assert html =~ "Devices"
end
test "search event with value param finds sites", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/dashboard")
view
|> element("#global-search")
|> render_hook("open", %{})
html =
view
|> element("#global-search")
|> render_hook("search", %{"value" => "Tower"})
assert html =~ "Tower Alpha"
assert html =~ "Sites"
end
test "short query returns no results", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/dashboard")
view
|> element("#global-search")
|> render_hook("open", %{})
html =
view
|> element("#global-search")
|> render_hook("search", %{"value" => "a"})
assert html =~ "No results found"
end
test "close hides the overlay", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/dashboard")
view
|> element("#global-search")
|> render_hook("open", %{})
html =
view
|> element("#global-search")
|> render_hook("close", %{})
refute html =~ "Search devices"
end
test "ArrowDown / ArrowUp keyboard navigation cycles selected index",
%{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/dashboard")
view |> element("#global-search") |> render_hook("open", %{})
view |> element("#global-search") |> render_hook("search", %{"value" => "Core"})
# Arrows shouldn't crash even at boundaries
view |> element("#global-search") |> render_hook("keydown", %{"key" => "ArrowDown"})
view |> element("#global-search") |> render_hook("keydown", %{"key" => "ArrowDown"})
view |> element("#global-search") |> render_hook("keydown", %{"key" => "ArrowUp"})
# An unrelated key is a no-op
html =
view
|> element("#global-search")
|> render_hook("keydown", %{"key" => "Tab"})
assert html =~ "Core"
end
test "Enter on an empty result list is a no-op", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/dashboard")
view |> element("#global-search") |> render_hook("open", %{})
html =
view
|> element("#global-search")
|> render_hook("keydown", %{"key" => "Enter"})
# No navigation, view stays alive
assert is_binary(html) and byte_size(html) > 0
assert Process.alive?(view.pid)
end
end
end