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