towerops/test/towerops_web/live/alert_live_test.exs

265 lines
7.3 KiB
Elixir
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

defmodule ToweropsWeb.AlertLive.IndexTest do
use ToweropsWeb.ConnCase
import Phoenix.LiveViewTest
setup :register_and_log_in_user
setup %{user: user} do
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
{:ok, site} =
Towerops.Sites.create_site(%{
name: "Test Site",
organization_id: organization.id
})
{:ok, device} =
Towerops.Devices.create_device(%{
name: "Test Router",
ip_address: "192.168.1.1",
site_id: site.id,
organization_id: organization.id
})
%{organization: organization, site: site, device: device}
end
describe "Index" do
test "displays alerts page", %{conn: conn, organization: _organization} do
{:ok, _view, html} = live(conn, ~p"/alerts")
assert html =~ "Alerts"
end
test "displays empty state when no alerts", %{conn: conn, organization: _organization} do
{:ok, _view, html} = live(conn, ~p"/alerts")
assert html =~ "No active alerts"
end
@tag :skip
test "lists all alerts", %{conn: conn, organization: _organization, device: device} do
{:ok, _alert} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_down",
triggered_at: DateTime.utc_now(),
message: "Device is down"
})
{:ok, _view, html} = live(conn, ~p"/alerts")
assert html =~ "Test Router"
assert html =~ "Device is down"
# Alert type badge shows "Down" for device_down alerts
assert html =~ "DOWN"
end
test "renders alerts with different severity ages (drives severity_badge_class branches)",
%{conn: conn, device: device} do
now = DateTime.utc_now()
# Yellow: <= 15 min old
{:ok, _yellow} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_down",
triggered_at: DateTime.add(now, -5, :minute),
message: "Recent"
})
# Orange: 1560 min old
{:ok, _orange} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_down",
triggered_at: DateTime.add(now, -30, :minute),
message: "Half hour"
})
# Red: > 60 min old
{:ok, _red} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_down",
triggered_at: DateTime.add(now, -2, :hour),
message: "Two hours"
})
{:ok, _view, html} = live(conn, ~p"/alerts")
assert html =~ "bg-yellow-500"
assert html =~ "bg-orange-500"
assert html =~ "bg-red-500"
end
test "filters critical alerts", %{conn: conn, organization: _organization, device: device} do
# Create a critical device_down alert (unresolved)
{:ok, _active_alert} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_down",
triggered_at: DateTime.utc_now(),
message: "Device is down"
})
# Create a recovery alert (device_up)
{:ok, _recovery_alert} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_up",
triggered_at: DateTime.utc_now(),
message: "Device recovered"
})
{:ok, _view, html} =
live(conn, ~p"/alerts?filter=critical")
# Should show device_down alert
assert html =~ "Device is down"
# Should NOT show device_up alert in critical filter
refute html =~ "Device recovered"
end
@tag :skip
test "acknowledges an alert", %{conn: conn, organization: _organization, device: device} do
{:ok, alert} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_down",
triggered_at: DateTime.utc_now(),
message: "Device is down"
})
{:ok, view, _html} = live(conn, ~p"/alerts")
html =
view
|> element("button", "Ack")
|> render_click(%{"id" => alert.id})
assert html =~ "Alert acknowledged"
end
test "does not show acknowledge button for device_up alerts", %{
conn: conn,
organization: _organization,
device: device
} do
{:ok, _alert} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_up",
triggered_at: DateTime.utc_now(),
message: "Device recovered"
})
{:ok, _view, html} = live(conn, ~p"/alerts")
# Should not show acknowledge button for device_up alerts
# The button text in the template is "Ack" (short for Acknowledge)
refute html =~ "phx-click=\"acknowledge\""
end
test "updates in real-time when new alert is created", %{
conn: conn,
organization: organization,
device: device
} do
{:ok, view, _html} = live(conn, ~p"/alerts")
# Broadcast new alert event on org-scoped topic
Phoenix.PubSub.broadcast(
Towerops.PubSub,
"alerts:org:#{organization.id}:new",
{:new_alert, device.id, :device_down}
)
# View should update
assert render(view)
end
test "updates in real-time when alert is resolved", %{
conn: conn,
organization: organization,
device: device
} do
{:ok, alert} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_down",
triggered_at: DateTime.utc_now(),
message: "Device is down"
})
{:ok, view, _html} = live(conn, ~p"/alerts")
# Resolve the alert and broadcast
Towerops.Alerts.resolve_alert(alert)
Phoenix.PubSub.broadcast(
Towerops.PubSub,
"alerts:org:#{organization.id}:resolved",
{:alert_resolved, device.id, :device_down}
)
# View should update
assert render(view)
end
test "requires authentication", %{organization: _organization} do
conn = build_conn()
{:error, redirect} = live(conn, ~p"/alerts")
assert {:redirect, %{to: path}} = redirect
assert path == ~p"/users/log-in"
end
test "shows site subscriber context when Gaiia mapped", %{
conn: conn,
organization: organization,
site: site,
device: device
} do
{:ok, _alert} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_down",
triggered_at: DateTime.utc_now(),
message: "Device is down"
})
{:ok, _} =
Towerops.Gaiia.upsert_network_site(organization.id, %{
gaiia_id: "ns-alert-test",
name: "Tower",
account_count: 75,
total_mrr: Decimal.new("3750.00"),
site_id: site.id
})
{:ok, _view, html} = live(conn, ~p"/alerts")
assert html =~ "75"
end
test "hides site subscriber context when no Gaiia mapping", %{
conn: conn,
device: device
} do
{:ok, _alert} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: "device_down",
triggered_at: DateTime.utc_now(),
message: "Device is down"
})
{:ok, _view, html} = live(conn, ~p"/alerts")
refute html =~ "subscribers"
refute html =~ "MRR"
end
end
end