From b20a58aec4794b8e810cce149148058ca14a88be Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Mon, 26 Jan 2026 15:27:59 -0600 Subject: [PATCH] test fixes --- config/test.exs | 6 ++- lib/towerops/snmp/profiles/dynamic.ex | 20 +++++++- lib/towerops/snmp/profiles/vendors/epmp.ex | 8 ++-- lib/towerops_web/live/device_live/show.ex | 35 ++++++++++++++ .../live/device_live/show.html.heex | 40 ++++++++++++++++ lib/towerops_web/live/graph_live/show.ex | 1 + priv/profiles/os_discovery/airos.yaml | 2 + .../snmp/profiles/vendors/epmp_test.exs | 16 +++---- .../workers/discovery_worker_test.exs | 6 +-- .../live/agent_live/index_test.exs | 20 ++++---- test/towerops_web/live/agent_live_test.exs | 46 +++++++++---------- test/towerops_web/live/alert_live_test.exs | 36 +++++++-------- .../towerops_web/live/dashboard_live_test.exs | 2 +- 13 files changed, 169 insertions(+), 69 deletions(-) diff --git a/config/test.exs b/config/test.exs index 36750e7c..21ff5445 100644 --- a/config/test.exs +++ b/config/test.exs @@ -3,8 +3,10 @@ import Config # Only in tests, remove the complexity from the password hashing algorithm config :bcrypt_elixir, :log_rounds, 1 -# Print only warnings and errors during test -config :logger, level: :warning +# Suppress log output during tests (tests that need logs use capture_log) +config :logger, + level: :error, + backends: [] # Initialize plugs at runtime for faster test compilation config :phoenix, :plug_init_mode, :runtime diff --git a/lib/towerops/snmp/profiles/dynamic.ex b/lib/towerops/snmp/profiles/dynamic.ex index 27ce4f75..60c0a1cd 100644 --- a/lib/towerops/snmp/profiles/dynamic.ex +++ b/lib/towerops/snmp/profiles/dynamic.ex @@ -158,8 +158,26 @@ defmodule Towerops.Snmp.Profiles.Dynamic do end end + defp format_firmware_version(%{vendor: "Ubiquiti"}, device_data) do + # Extract version from format like "XW.v8.7.21.48401.251212.0939" + # Remove the ".v" prefix to get just "8.7.21.48401.251212.0939" + case Map.get(device_data, :firmware_version) do + nil -> + nil + + version when is_binary(version) -> + case Regex.run(~r/\.v(.*)$/, version) do + [_, extracted_version] -> extracted_version + _ -> version + end + + version -> + version + end + end + defp format_firmware_version(_profile, device_data) do - # For non-MikroTik devices, use raw firmware version + # For other devices, use raw firmware version Map.get(device_data, :firmware_version) end diff --git a/lib/towerops/snmp/profiles/vendors/epmp.ex b/lib/towerops/snmp/profiles/vendors/epmp.ex index 9fe24890..e7936c18 100644 --- a/lib/towerops/snmp/profiles/vendors/epmp.ex +++ b/lib/towerops/snmp/profiles/vendors/epmp.ex @@ -15,9 +15,11 @@ defmodule Towerops.Snmp.Profiles.Vendors.Epmp do alias Towerops.Snmp.Client alias Towerops.Snmp.Profiles.Vendors.Vendor - # OIDs for hardware detection - @interface_mode_oid "1.3.6.1.4.1.17713.21.1.1.1.0" - @sub_mode_oid "1.3.6.1.4.1.17713.21.1.1.2.0" + # OIDs for hardware detection (from CAMBIUM-PMP80211-MIB) + # wirelessInterfaceMode = { wirelessInterface 1 } = { { wireless 2 } 1 } = 1.3.6.1.4.1.17713.21.3.8.2.1 + @interface_mode_oid "1.3.6.1.4.1.17713.21.3.8.2.1.0" + # cambiumSubModeType = { cambiumGeneralStatus 33 } = 1.3.6.1.4.1.17713.21.1.1.33 + @sub_mode_oid "1.3.6.1.4.1.17713.21.1.1.33.0" @impl true def profile_names, do: ["epmp"] diff --git a/lib/towerops_web/live/device_live/show.ex b/lib/towerops_web/live/device_live/show.ex index 42fd9f0e..4c3027c4 100644 --- a/lib/towerops_web/live/device_live/show.ex +++ b/lib/towerops_web/live/device_live/show.ex @@ -171,6 +171,21 @@ defmodule ToweropsWeb.DeviceLive.Show do storage_volume_chart_data = load_storage_volume_chart_data(storage) traffic_chart_data = load_overall_traffic_chart_data(device_id) + # Wireless sensor chart data + wireless_chart_data = + load_sensor_chart_data(device_id, [ + "frequency", + "power", + "rssi", + "ccq", + "clients", + "distance", + "noise-floor", + "quality", + "rate", + "utilization" + ]) + # Filter sensors by type for temperature, voltage, storage, count, and transceivers # Separate transceiver sensors from general sensors {transceiver_sensors, non_transceiver_sensors} = @@ -187,6 +202,9 @@ defmodule ToweropsWeb.DeviceLive.Show do count_sensors = Enum.filter(non_transceiver_sensors, &(&1.sensor_type == "count")) + # Wireless sensors (frequency, power, rssi, ccq, etc.) + wireless_sensors = Enum.filter(non_transceiver_sensors, &wireless_sensor?/1) + # Group transceiver sensors by transceiver name grouped_transceivers = group_transceiver_sensors(transceiver_sensors) @@ -221,10 +239,12 @@ defmodule ToweropsWeb.DeviceLive.Show do |> assign(:storage_chart_data, storage_chart_data) |> assign(:storage_volume_chart_data, storage_volume_chart_data) |> assign(:traffic_chart_data, traffic_chart_data) + |> assign(:wireless_chart_data, wireless_chart_data) |> assign(:temperature_sensors, temperature_sensors) |> assign(:voltage_sensors, voltage_sensors) |> assign(:storage_sensors, storage_sensors) |> assign(:count_sensors, count_sensors) + |> assign(:wireless_sensors, wireless_sensors) |> assign(:grouped_transceivers, grouped_transceivers) |> assign(:agent_info, agent_info) end @@ -777,4 +797,19 @@ defmodule ToweropsWeb.DeviceLive.Show do sensor.sensor_descr && String.contains?(String.downcase(sensor.sensor_descr), "voltage") end + + defp wireless_sensor?(sensor) do + sensor.sensor_type in [ + "frequency", + "power", + "rssi", + "ccq", + "clients", + "distance", + "noise-floor", + "quality", + "rate", + "utilization" + ] + end end diff --git a/lib/towerops_web/live/device_live/show.html.heex b/lib/towerops_web/live/device_live/show.html.heex index 065084d2..2a18adf3 100644 --- a/lib/towerops_web/live/device_live/show.html.heex +++ b/lib/towerops_web/live/device_live/show.html.heex @@ -738,6 +738,46 @@ <% end %> + + <%= if @wireless_sensors && length(@wireless_sensors) > 0 do %> +
+
+

Wireless

+
+
+
+ <%= for sensor <- @wireless_sensors do %> +
+
+ <.link + navigate={ + ~p"/devices/#{@device.id}/graph/wireless?sensor_id=#{sensor.id}" + } + class="hover:text-blue-600 dark:hover:text-blue-400 hover:underline" + > + {sensor.sensor_descr} + +
+
+ <%= if sensor.latest_reading do %> + <%= if sensor.sensor_type in ["clients", "ccq", "utilization"] do %> + {trunc(sensor.latest_reading.value)} + <% else %> + {Float.round(sensor.latest_reading.value, 1)} + <% end %> + <%= if sensor.sensor_unit && sensor.sensor_unit != "" do %> + {sensor.sensor_unit} + <% end %> + <% else %> + N/A + <% end %> +
+
+ <% end %> +
+
+
+ <% end %> <% "ports" -> %> diff --git a/lib/towerops_web/live/graph_live/show.ex b/lib/towerops_web/live/graph_live/show.ex index 3e7a7b57..940bf68a 100644 --- a/lib/towerops_web/live/graph_live/show.ex +++ b/lib/towerops_web/live/graph_live/show.ex @@ -146,6 +146,7 @@ defmodule ToweropsWeb.GraphLive.Show do defp get_chart_config("count"), do: {"Count", "", true} defp get_chart_config("pppoe_sessions"), do: {"PPPoE Sessions", "", true} defp get_chart_config("connections"), do: {"Connections", "", true} + defp get_chart_config("wireless"), do: {"Wireless Metrics", "", true} # Humanize unknown sensor types for title defp get_chart_config(sensor_type), do: {humanize_sensor_type(sensor_type), "", true} diff --git a/priv/profiles/os_discovery/airos.yaml b/priv/profiles/os_discovery/airos.yaml index 34adc637..34b83fa8 100644 --- a/priv/profiles/os_discovery/airos.yaml +++ b/priv/profiles/os_discovery/airos.yaml @@ -1,6 +1,8 @@ mib: UBNT-AirMAX-MIB modules: os: + hardware: IEEE802dot11-MIB::dot11manufacturerProductName.5 + version: IEEE802dot11-MIB::dot11manufacturerProductVersion.5 lat: UBNT-AirMAX-MIB::ubntGpsLat.0 long: UBNT-AirMAX-MIB::ubntGpsLon.0 processors: diff --git a/test/towerops/snmp/profiles/vendors/epmp_test.exs b/test/towerops/snmp/profiles/vendors/epmp_test.exs index 8bdbd19b..72a28087 100644 --- a/test/towerops/snmp/profiles/vendors/epmp_test.exs +++ b/test/towerops/snmp/profiles/vendors/epmp_test.exs @@ -24,29 +24,29 @@ defmodule Towerops.Snmp.Profiles.Vendors.EpmpTest do describe "detect_hardware/1" do test "returns ePMP AP when interface mode is 1" do - expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.1.0", _ -> {:ok, 1} end) - expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.2.0", _ -> {:ok, 1} end) + expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.3.8.2.1.0", _ -> {:ok, 1} end) + expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.33.0", _ -> {:ok, 1} end) assert Epmp.detect_hardware(@client_opts) == "ePMP AP" end test "returns ePTP Master when interface mode is 1 and sub mode is 5" do - expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.1.0", _ -> {:ok, 1} end) - expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.2.0", _ -> {:ok, 5} end) + expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.3.8.2.1.0", _ -> {:ok, 1} end) + expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.33.0", _ -> {:ok, 5} end) assert Epmp.detect_hardware(@client_opts) == "ePTP Master" end test "returns ePMP SM when interface mode is 2" do - expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.1.0", _ -> {:ok, 2} end) - expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.2.0", _ -> {:ok, 1} end) + expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.3.8.2.1.0", _ -> {:ok, 2} end) + expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.33.0", _ -> {:ok, 1} end) assert Epmp.detect_hardware(@client_opts) == "ePMP SM" end test "returns ePTP Slave when interface mode is 2 and sub mode is 4" do - expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.1.0", _ -> {:ok, 2} end) - expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.2.0", _ -> {:ok, 4} end) + expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.3.8.2.1.0", _ -> {:ok, 2} end) + expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.21.1.1.33.0", _ -> {:ok, 4} end) assert Epmp.detect_hardware(@client_opts) == "ePTP Slave" end diff --git a/test/towerops/workers/discovery_worker_test.exs b/test/towerops/workers/discovery_worker_test.exs index 4ba5bb8f..7176d70c 100644 --- a/test/towerops/workers/discovery_worker_test.exs +++ b/test/towerops/workers/discovery_worker_test.exs @@ -70,10 +70,10 @@ defmodule Towerops.Workers.DiscoveryWorkerTest do assert snmp_device.sys_name == "test-device" end - test "returns error when device not found" do + test "returns :discard when device not found" do non_existent_id = Ecto.UUID.generate() - assert {:error, :device_not_found} = + assert :discard = DiscoveryWorker.perform(%Oban.Job{args: %{"device_id" => non_existent_id}}) end @@ -127,7 +127,7 @@ defmodule Towerops.Workers.DiscoveryWorkerTest do DiscoveryWorker.perform(%Oban.Job{args: %{"device_id" => device.id}}) end) - assert log =~ "SNMP discovery failed for device #{device.id}" + assert log =~ "SNMP discovery failed from Phoenix cluster for device #{device.id}" end end end diff --git a/test/towerops_web/live/agent_live/index_test.exs b/test/towerops_web/live/agent_live/index_test.exs index e4c93128..44d56a31 100644 --- a/test/towerops_web/live/agent_live/index_test.exs +++ b/test/towerops_web/live/agent_live/index_test.exs @@ -144,7 +144,7 @@ defmodule ToweropsWeb.AgentLive.IndexTest do test "shows Never connected for agents without last_seen_at", %{ conn: conn, user: user, - organization: _organization + organization: organization } do {:ok, agent_token, _token} = Agents.create_agent_token(organization.id, "Never Seen") @@ -165,7 +165,7 @@ defmodule ToweropsWeb.AgentLive.IndexTest do test "shows agent status information in the page", %{ conn: conn, user: user, - organization: _organization + organization: organization } do {:ok, agent_token, _token} = Agents.create_agent_token(organization.id, "Status Agent") @@ -257,7 +257,7 @@ defmodule ToweropsWeb.AgentLive.IndexTest do test "non-superadmin cannot create cloud poller", %{ conn: conn, user: user, - organization: _organization + organization: organization } do conn = conn @@ -289,7 +289,7 @@ defmodule ToweropsWeb.AgentLive.IndexTest do test "superadmin can create regular agent by not checking cloud poller", %{ conn: conn, superadmin: superadmin, - organization: _organization + organization: organization } do conn = conn @@ -430,7 +430,7 @@ defmodule ToweropsWeb.AgentLive.IndexTest do test "superadmin can delete cloud poller", %{ conn: conn, superadmin: superadmin, - organization: organization, + organization: _organization, cloud_poller: cloud_poller } do conn = @@ -452,7 +452,7 @@ defmodule ToweropsWeb.AgentLive.IndexTest do test "superadmin can regenerate cloud poller token", %{ conn: conn, superadmin: superadmin, - organization: organization, + organization: _organization, cloud_poller: cloud_poller } do conn = @@ -471,7 +471,7 @@ defmodule ToweropsWeb.AgentLive.IndexTest do test "superadmin can view cloud poller setup instructions", %{ conn: conn, superadmin: superadmin, - organization: organization, + organization: _organization, cloud_poller: cloud_poller } do conn = @@ -515,7 +515,7 @@ defmodule ToweropsWeb.AgentLive.IndexTest do test "superadmin can set global default cloud poller with validation", %{ conn: conn, superadmin: superadmin, - organization: organization, + organization: _organization, cloud_poller: cloud_poller } do conn = @@ -571,7 +571,7 @@ defmodule ToweropsWeb.AgentLive.IndexTest do test "superadmin can clear global default cloud poller", %{ conn: conn, superadmin: superadmin, - organization: organization, + organization: _organization, cloud_poller: cloud_poller } do # First set a global default @@ -602,7 +602,7 @@ defmodule ToweropsWeb.AgentLive.IndexTest do test "deleting cloud poller clears it from global default", %{ conn: conn, superadmin: superadmin, - organization: organization, + organization: _organization, cloud_poller: cloud_poller } do # Set as global default diff --git a/test/towerops_web/live/agent_live_test.exs b/test/towerops_web/live/agent_live_test.exs index 73e65adf..0e7a933c 100644 --- a/test/towerops_web/live/agent_live_test.exs +++ b/test/towerops_web/live/agent_live_test.exs @@ -19,21 +19,21 @@ defmodule ToweropsWeb.AgentLiveTest do test "lists all agent tokens", %{conn: conn, organization: organization} do {:ok, _agent_token, _token} = Agents.create_agent_token(organization.id, "Agent 1") - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/agents") + {:ok, _view, html} = live(conn, ~p"/agents") assert html =~ "Remote Agents" assert html =~ "Agent 1" end - test "displays empty state when no agents", %{conn: conn, organization: organization} do - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/agents") + test "displays empty state when no agents", %{conn: conn, organization: _organization} do + {:ok, _view, html} = live(conn, ~p"/agents") assert html =~ "No agents" assert html =~ "Get started by creating your first remote agent" end - test "creates new agent and shows token modal", %{conn: conn, organization: organization} do - {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/agents") + test "creates new agent and shows token modal", %{conn: conn, organization: _organization} do + {:ok, view, _html} = live(conn, ~p"/agents") html = view @@ -48,7 +48,7 @@ defmodule ToweropsWeb.AgentLiveTest do test "deletes agent", %{conn: conn, organization: organization} do {:ok, agent_token, _token} = Agents.create_agent_token(organization.id, "Agent 1") - {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/agents") + {:ok, view, _html} = live(conn, ~p"/agents") html = view @@ -61,8 +61,8 @@ defmodule ToweropsWeb.AgentLiveTest do assert is_nil(Towerops.Repo.get(Agents.AgentToken, agent_token.id)) end - test "closes token modal", %{conn: conn, organization: organization} do - {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/agents") + test "closes token modal", %{conn: conn, organization: _organization} do + {:ok, view, _html} = live(conn, ~p"/agents") # Create agent to show modal view @@ -78,9 +78,9 @@ defmodule ToweropsWeb.AgentLiveTest do refute html =~ "Agent Created Successfully" end - test "requires authentication", %{organization: organization} do + test "requires authentication", %{organization: _organization} do conn = build_conn() - {:error, redirect} = live(conn, ~p"/orgs/#{organization.slug}/agents") + {:error, redirect} = live(conn, ~p"/agents") assert {:redirect, %{to: path}} = redirect assert path == ~p"/users/log-in" @@ -99,7 +99,7 @@ defmodule ToweropsWeb.AgentLiveTest do set: [last_seen_at: three_minutes_ago] ) - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/agents") + {:ok, _view, html} = live(conn, ~p"/agents") assert html =~ "Warning" assert html =~ "3m ago" @@ -118,7 +118,7 @@ defmodule ToweropsWeb.AgentLiveTest do set: [last_seen_at: ten_minutes_ago] ) - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/agents") + {:ok, _view, html} = live(conn, ~p"/agents") assert html =~ "Offline" assert html =~ "10m ago" @@ -137,7 +137,7 @@ defmodule ToweropsWeb.AgentLiveTest do set: [last_seen_at: two_hours_ago] ) - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/agents") + {:ok, _view, html} = live(conn, ~p"/agents") assert html =~ "2h ago" end @@ -155,7 +155,7 @@ defmodule ToweropsWeb.AgentLiveTest do set: [last_seen_at: two_days_ago] ) - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/agents") + {:ok, _view, html} = live(conn, ~p"/agents") assert html =~ "2d ago" end @@ -165,7 +165,7 @@ defmodule ToweropsWeb.AgentLiveTest do test "loads edit page with existing agent name", %{conn: conn, organization: organization} do {:ok, agent_token, _token} = Agents.create_agent_token(organization.id, "Old Agent Name") - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/agents/#{agent_token.id}/edit") + {:ok, _view, html} = live(conn, ~p"/agents/#{agent_token.id}/edit") assert html =~ "Edit Agent" assert html =~ "Old Agent Name" @@ -175,7 +175,7 @@ defmodule ToweropsWeb.AgentLiveTest do test "validates empty name shows error on submit", %{conn: conn, organization: organization} do {:ok, agent_token, _token} = Agents.create_agent_token(organization.id, "Test Agent") - {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/agents/#{agent_token.id}/edit") + {:ok, view, _html} = live(conn, ~p"/agents/#{agent_token.id}/edit") html = view @@ -195,14 +195,14 @@ defmodule ToweropsWeb.AgentLiveTest do } do {:ok, agent_token, _token} = Agents.create_agent_token(organization.id, "Old Name") - {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/agents/#{agent_token.id}/edit") + {:ok, view, _html} = live(conn, ~p"/agents/#{agent_token.id}/edit") view |> form("#edit-agent-form", agent_token: %{name: "New Name"}) |> render_submit() # Verify redirect to show page with flash message - assert_redirect(view, ~p"/orgs/#{organization.slug}/agents/#{agent_token.id}") + assert_redirect(view, ~p"/agents/#{agent_token.id}") # Verify agent was updated updated_agent = Agents.get_agent_token!(agent_token.id) @@ -212,26 +212,26 @@ defmodule ToweropsWeb.AgentLiveTest do test "cancel button navigates back to show page", %{conn: conn, organization: organization} do {:ok, agent_token, _token} = Agents.create_agent_token(organization.id, "Test Agent") - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/agents/#{agent_token.id}/edit") + {:ok, _view, html} = live(conn, ~p"/agents/#{agent_token.id}/edit") assert html =~ "Cancel" # Find cancel link and verify it points to show page assert html =~ - ~p"/orgs/#{organization.slug}/agents/#{agent_token.id}" + ~p"/agents/#{agent_token.id}" end test "requires authentication", %{organization: organization} do {:ok, agent_token, _token} = Agents.create_agent_token(organization.id, "Test Agent") conn = build_conn() - {:error, redirect} = live(conn, ~p"/orgs/#{organization.slug}/agents/#{agent_token.id}/edit") + {:error, redirect} = live(conn, ~p"/agents/#{agent_token.id}/edit") assert {:redirect, %{to: path}} = redirect assert path == ~p"/users/log-in" end - test "verifies agent belongs to organization", %{conn: conn, organization: organization, user: user} do + test "verifies agent belongs to organization", %{conn: conn, organization: _organization, user: user} do # Create another organization {:ok, other_org} = Towerops.Organizations.create_organization(%{name: "Other Org"}, user.id) {:ok, agent_token, _token} = Agents.create_agent_token(other_org.id, "Other Agent") @@ -239,7 +239,7 @@ defmodule ToweropsWeb.AgentLiveTest do # Try to edit agent from other organization - capture_log suppresses expected Router exception log capture_log(fn -> assert_raise Ecto.NoResultsError, fn -> - live(conn, ~p"/orgs/#{organization.slug}/agents/#{agent_token.id}/edit") + live(conn, ~p"/agents/#{agent_token.id}/edit") end end) end diff --git a/test/towerops_web/live/alert_live_test.exs b/test/towerops_web/live/alert_live_test.exs index c7feacec..7aca0288 100644 --- a/test/towerops_web/live/alert_live_test.exs +++ b/test/towerops_web/live/alert_live_test.exs @@ -25,20 +25,20 @@ defmodule ToweropsWeb.AlertLive.IndexTest do end describe "Index" do - test "displays alerts page", %{conn: conn, organization: organization} do - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/alerts") + test "displays alerts page", %{conn: conn, organization: _organization} do + {:ok, _view, html} = live(conn, ~p"/alerts") assert html =~ "Alerts" assert html =~ "Monitor and acknowledge system alerts" end - test "displays empty state when no alerts", %{conn: conn, organization: organization} do - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/alerts") + test "displays empty state when no alerts", %{conn: conn, organization: _organization} do + {:ok, _view, html} = live(conn, ~p"/alerts") assert html =~ "No alerts" end - test "lists all alerts", %{conn: conn, organization: organization, device: device} do + test "lists all alerts", %{conn: conn, organization: _organization, device: device} do {:ok, _alert} = Towerops.Alerts.create_alert(%{ device_id: device.id, @@ -47,14 +47,14 @@ defmodule ToweropsWeb.AlertLive.IndexTest do message: "Device is down" }) - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/alerts") + {:ok, _view, html} = live(conn, ~p"/alerts") assert html =~ "Test Router" assert html =~ "Device is down" assert html =~ "Device Down" end - test "filters active alerts", %{conn: conn, organization: organization, device: device} do + test "filters active alerts", %{conn: conn, organization: _organization, device: device} do # Create an active equipment_down alert {:ok, _active_alert} = Towerops.Alerts.create_alert(%{ @@ -74,7 +74,7 @@ defmodule ToweropsWeb.AlertLive.IndexTest do }) {:ok, _view, html} = - live(conn, ~p"/orgs/#{organization.slug}/alerts?filter=active") + live(conn, ~p"/alerts?filter=active") # Should show equipment_down alert assert html =~ "Device is down" @@ -82,7 +82,7 @@ defmodule ToweropsWeb.AlertLive.IndexTest do refute html =~ "Device recovered" end - test "acknowledges an alert", %{conn: conn, organization: organization, device: device} do + test "acknowledges an alert", %{conn: conn, organization: _organization, device: device} do {:ok, alert} = Towerops.Alerts.create_alert(%{ device_id: device.id, @@ -91,7 +91,7 @@ defmodule ToweropsWeb.AlertLive.IndexTest do message: "Device is down" }) - {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/alerts") + {:ok, view, _html} = live(conn, ~p"/alerts") html = view @@ -103,7 +103,7 @@ defmodule ToweropsWeb.AlertLive.IndexTest do test "does not show acknowledge button for device_up alerts", %{ conn: conn, - organization: organization, + organization: _organization, device: device } do {:ok, _alert} = @@ -114,7 +114,7 @@ defmodule ToweropsWeb.AlertLive.IndexTest do message: "Device recovered" }) - {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/alerts") + {:ok, _view, html} = live(conn, ~p"/alerts") # Should not show acknowledge button for device_up alerts refute html =~ "Acknowledge" @@ -122,10 +122,10 @@ defmodule ToweropsWeb.AlertLive.IndexTest do test "updates in real-time when new alert is created", %{ conn: conn, - organization: organization, + organization: _organization, device: device } do - {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/alerts") + {:ok, view, _html} = live(conn, ~p"/alerts") # Broadcast new alert event Phoenix.PubSub.broadcast( @@ -140,7 +140,7 @@ defmodule ToweropsWeb.AlertLive.IndexTest do test "updates in real-time when alert is resolved", %{ conn: conn, - organization: organization, + organization: _organization, device: device } do {:ok, alert} = @@ -151,7 +151,7 @@ defmodule ToweropsWeb.AlertLive.IndexTest do message: "Device is down" }) - {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/alerts") + {:ok, view, _html} = live(conn, ~p"/alerts") # Resolve the alert and broadcast Towerops.Alerts.resolve_alert(alert) @@ -166,9 +166,9 @@ defmodule ToweropsWeb.AlertLive.IndexTest do assert render(view) end - test "requires authentication", %{organization: organization} do + test "requires authentication", %{organization: _organization} do conn = build_conn() - {:error, redirect} = live(conn, ~p"/orgs/#{organization.slug}/alerts") + {:error, redirect} = live(conn, ~p"/alerts") assert {:redirect, %{to: path}} = redirect assert path == ~p"/users/log-in" diff --git a/test/towerops_web/live/dashboard_live_test.exs b/test/towerops_web/live/dashboard_live_test.exs index 96eda78a..59dd85d6 100644 --- a/test/towerops_web/live/dashboard_live_test.exs +++ b/test/towerops_web/live/dashboard_live_test.exs @@ -119,7 +119,7 @@ defmodule ToweropsWeb.DashboardLiveTest do # Check for navigation links assert html =~ ~p"/sites" assert html =~ ~p"/devices" - assert html =~ ~p"/orgs/#{organization.slug}/alerts" + assert html =~ ~p"/alerts" end test "requires authentication", %{organization: organization} do