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

182 lines
5.9 KiB
Elixir

defmodule ToweropsWeb.AlertLive.IndexEventsTest do
@moduledoc """
Drives the bulk-action and toggle event handlers in AlertLive.Index that
aren't exercised by the existing render-focused test file.
"""
use ToweropsWeb.ConnCase, async: true
import Phoenix.LiveViewTest
alias Towerops.Alerts
setup :register_and_log_in_user
setup %{user: user} do
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Bulk Org"}, user.id)
{:ok, site} = Towerops.Sites.create_site(%{name: "Site 1", organization_id: organization.id})
{:ok, device} =
Towerops.Devices.create_device(%{
name: "Router 1",
ip_address: "10.0.0.1",
site_id: site.id,
organization_id: organization.id
})
{:ok, alert1} =
Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_down",
triggered_at: DateTime.truncate(DateTime.utc_now(), :second),
severity: 1
})
{:ok, alert2} =
Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_down",
triggered_at: DateTime.truncate(DateTime.utc_now(), :second),
severity: 2
})
%{organization: organization, site: site, device: device, alert1: alert1, alert2: alert2}
end
describe "acknowledge / resolve event handlers" do
test "acknowledge flashes success and stamps the alert", %{
conn: conn,
alert1: alert1
} do
{:ok, view, _html} = live(conn, ~p"/alerts")
html = render_hook(view, "acknowledge", %{"id" => alert1.id})
assert html =~ ~r/acknowledged|Alert/
assert Alerts.get_alert!(alert1.id).acknowledged_at
end
test "acknowledge with unknown id flashes 'not found'", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/alerts")
html = render_hook(view, "acknowledge", %{"id" => Ecto.UUID.generate()})
assert html =~ ~r/not found|Alert/
end
test "resolve flashes success and resolves the alert", %{
conn: conn,
alert1: alert1
} do
{:ok, view, _html} = live(conn, ~p"/alerts")
_ = render_hook(view, "resolve", %{"id" => alert1.id})
assert Alerts.get_alert!(alert1.id).resolved_at
end
test "resolve with unknown id flashes 'not found'", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/alerts")
html = render_hook(view, "resolve", %{"id" => Ecto.UUID.generate()})
assert html =~ ~r/not found|Alert/
end
test "acknowledge of an alert from another org is rejected as unauthorized", %{conn: conn} do
# Create a foreign alert outside the user's org.
foreign_user = Towerops.AccountsFixtures.user_fixture()
foreign_org = Towerops.OrganizationsFixtures.organization_fixture(foreign_user.id)
{:ok, foreign_site} = Towerops.Sites.create_site(%{name: "FS", organization_id: foreign_org.id})
{:ok, foreign_device} =
Towerops.Devices.create_device(%{
name: "Foreign",
ip_address: "10.99.99.99",
site_id: foreign_site.id,
organization_id: foreign_org.id
})
{:ok, foreign_alert} =
Alerts.create_alert(%{
device_id: foreign_device.id,
alert_type: "device_down",
triggered_at: DateTime.truncate(DateTime.utc_now(), :second),
severity: 1
})
{:ok, view, _html} = live(conn, ~p"/alerts")
html = render_hook(view, "acknowledge", %{"id" => foreign_alert.id})
valid? = html =~ ~r/access|not found/ or html =~ "Alert"
assert valid?
end
end
describe "toggle_alert" do
test "expands and collapses an alert row", %{conn: conn, alert1: alert1} do
{:ok, view, _html} = live(conn, ~p"/alerts")
_ = render_hook(view, "toggle_alert", %{"id" => alert1.id})
_ = render_hook(view, "toggle_alert", %{"id" => alert1.id})
assert Process.alive?(view.pid)
end
end
describe "select_all + select_none" do
test "selects then deselects all visible alerts", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/alerts")
_ = render_hook(view, "select_all", %{})
_ = render_hook(view, "select_none", %{})
assert Process.alive?(view.pid)
end
end
describe "toggle_select" do
test "toggles a single alert in the selection set", %{conn: conn, alert1: alert1} do
{:ok, view, _html} = live(conn, ~p"/alerts")
_ = render_hook(view, "toggle_select", %{"id" => alert1.id})
_ = render_hook(view, "toggle_select", %{"id" => alert1.id})
assert Process.alive?(view.pid)
end
end
describe "bulk_acknowledge" do
test "acknowledges every selected alert and clears the selection", %{
conn: conn,
alert1: alert1,
alert2: alert2
} do
{:ok, view, _html} = live(conn, ~p"/alerts")
_ = render_hook(view, "toggle_select", %{"id" => alert1.id})
_ = render_hook(view, "toggle_select", %{"id" => alert2.id})
_ = render_hook(view, "bulk_acknowledge", %{})
assert Towerops.Repo.get!(Alerts.Alert, alert1.id).acknowledged_at
assert Towerops.Repo.get!(Alerts.Alert, alert2.id).acknowledged_at
end
end
describe "bulk_resolve" do
test "resolves every selected alert and clears the selection", %{
conn: conn,
alert1: alert1,
alert2: alert2
} do
{:ok, view, _html} = live(conn, ~p"/alerts")
_ = render_hook(view, "select_all", %{})
_ = render_hook(view, "bulk_resolve", %{})
assert Towerops.Repo.get!(Alerts.Alert, alert1.id).resolved_at
assert Towerops.Repo.get!(Alerts.Alert, alert2.id).resolved_at
end
end
describe "toggle_site" do
test "expands and collapses a site group", %{conn: conn, site: site} do
{:ok, view, _html} = live(conn, ~p"/alerts")
_ = render_hook(view, "toggle_site", %{"site-id" => site.id})
_ = render_hook(view, "toggle_site", %{"site-id" => site.id})
assert Process.alive?(view.pid)
end
end
end