From 5253ccc16e73cdfce68fc7b8deebb5c8b8d21b9d Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sat, 9 May 2026 12:34:17 -0500 Subject: [PATCH] test: DeviceLive.Index health/response helpers and discovered-device validation --- .../live/device_live/index_test.exs | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/test/towerops_web/live/device_live/index_test.exs b/test/towerops_web/live/device_live/index_test.exs index 1603dde4..df6c77cc 100644 --- a/test/towerops_web/live/device_live/index_test.exs +++ b/test/towerops_web/live/device_live/index_test.exs @@ -4,6 +4,7 @@ defmodule ToweropsWeb.DeviceLive.IndexTest do import Phoenix.LiveViewTest alias Towerops.Devices + alias Towerops.Monitoring.Check setup :register_and_log_in_user @@ -443,6 +444,171 @@ defmodule ToweropsWeb.DeviceLive.IndexTest do html = view |> element("#force-rediscover-all") |> render_click() assert html =~ "Discovery started" end + + test "add_discovered_device with invalid JSON identifier shows error flash", %{conn: conn} do + {:ok, view, _html} = live(conn, ~p"/devices?tab=discovered") + + html = render_hook(view, "add_discovered_device", %{"identifier" => "not-json"}) + assert html =~ "Invalid device identifier" + end + end + + describe "health and response time helpers" do + test "renders device with healthy passing check (worst_status=0)", %{ + conn: conn, + site: site, + organization: organization + } do + {:ok, device} = + Devices.create_device(%{ + name: "Healthy", + ip_address: "10.7.0.1", + site_id: site.id, + organization_id: organization.id + }) + + {:ok, check} = + Towerops.Monitoring.create_check(%{ + name: "Healthy ping", + check_type: "ping", + organization_id: organization.id, + device_id: device.id, + enabled: true, + config: %{"host" => "10.7.0.1"} + }) + + _ = + check + |> Check.state_changeset(%{ + current_state: 0, + last_check_at: DateTime.truncate(DateTime.utc_now(), :second) + }) + |> Towerops.Repo.update!() + + {:ok, _view, html} = live(conn, ~p"/devices") + assert html =~ "Healthy" + # health_dot_color worst_status=0 path + assert html =~ "bg-green-500" + end + + test "renders device with critical check (worst_status=2)", %{ + conn: conn, + site: site, + organization: organization + } do + {:ok, device} = + Devices.create_device(%{ + name: "Critical", + ip_address: "10.7.0.2", + site_id: site.id, + organization_id: organization.id + }) + + {:ok, check} = + Towerops.Monitoring.create_check(%{ + name: "Crit ping", + check_type: "ping", + organization_id: organization.id, + device_id: device.id, + enabled: true, + config: %{"host" => "10.7.0.2"} + }) + + _ = + check + |> Check.state_changeset(%{ + current_state: 2, + last_check_at: DateTime.truncate(DateTime.utc_now(), :second) + }) + |> Towerops.Repo.update!() + + {:ok, _view, html} = live(conn, ~p"/devices") + assert html =~ "Critical" + # Red dot for worst_status=2 + assert html =~ "bg-red-500" + end + + test "renders device with response_time_ms latency", %{ + conn: conn, + site: site, + organization: organization + } do + {:ok, device} = + Devices.create_device(%{ + name: "Latent", + ip_address: "10.7.0.3", + site_id: site.id, + organization_id: organization.id + }) + + {:ok, check} = + Towerops.Monitoring.create_check(%{ + name: "Lat ping", + check_type: "ping", + organization_id: organization.id, + device_id: device.id, + enabled: true, + current_state: 0, + last_check_at: DateTime.utc_now(), + config: %{"host" => "10.7.0.3"} + }) + + {:ok, _mc} = + Towerops.Monitoring.create_monitoring_check(%{ + device_id: device.id, + status: "ok", + response_time_ms: 15.0, + checked_at: DateTime.truncate(DateTime.utc_now(), :second) + }) + + _ = check + + {:ok, _view, html} = live(conn, ~p"/devices") + assert html =~ "Latent" + # Response time should appear as "15ms" (under 20 — green) + assert html =~ "15ms" or html =~ "ms" + end + + test "renders device with high latency (red branch)", %{ + conn: conn, + site: site, + organization: organization + } do + {:ok, device} = + Devices.create_device(%{ + name: "SlowDev", + ip_address: "10.7.0.4", + site_id: site.id, + organization_id: organization.id + }) + + {:ok, check} = + Towerops.Monitoring.create_check(%{ + name: "Slow ping", + check_type: "ping", + organization_id: organization.id, + device_id: device.id, + enabled: true, + current_state: 0, + last_check_at: DateTime.utc_now(), + config: %{"host" => "10.7.0.4"} + }) + + {:ok, _mc} = + Towerops.Monitoring.create_monitoring_check(%{ + device_id: device.id, + status: "ok", + response_time_ms: 1500.0, + checked_at: DateTime.truncate(DateTime.utc_now(), :second) + }) + + _ = check + + {:ok, _view, html} = live(conn, ~p"/devices") + assert html =~ "SlowDev" + # 1500ms gets formatted as "1.5s" (red branch) + assert html =~ "1.5s" + end end describe "search and status filter events" do