test fixes
This commit is contained in:
parent
756a6b4cd4
commit
b20a58aec4
13 changed files with 169 additions and 69 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
8
lib/towerops/snmp/profiles/vendors/epmp.ex
vendored
8
lib/towerops/snmp/profiles/vendors/epmp.ex
vendored
|
|
@ -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"]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -738,6 +738,46 @@
|
|||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<!-- Wireless Sensors (Frequency, Power, CCQ, etc.) -->
|
||||
<%= if @wireless_sensors && length(@wireless_sensors) > 0 do %>
|
||||
<div class="bg-white dark:bg-gray-800/50 rounded-lg border border-gray-200 dark:border-white/10">
|
||||
<div class="px-4 py-3 border-b border-gray-200 dark:border-white/10">
|
||||
<h3 class="text-sm font-semibold text-gray-900 dark:text-white">Wireless</h3>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<dl class="space-y-1">
|
||||
<%= for sensor <- @wireless_sensors do %>
|
||||
<div class="flex justify-between py-1.5 border-b border-gray-100 dark:border-white/5">
|
||||
<dt class="text-sm text-gray-600 dark:text-gray-400">
|
||||
<.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}
|
||||
</.link>
|
||||
</dt>
|
||||
<dd class="text-sm font-medium text-gray-900 dark:text-white">
|
||||
<%= 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 %>
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% "ports" -> %>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue