towerops/test/towerops_web/live/graph_live/show_test.exs
Graham McIntire a6fb2ef833
Change 'Ping Latency' to 'ICMP Latency' throughout codebase
Updated all references to use the more technically accurate term 'ICMP Latency'
instead of 'Ping Latency' in:
- Graph titles and labels
- HTML comments
- Test assertions
2026-01-17 17:13:02 -06:00

343 lines
9.5 KiB
Elixir

defmodule ToweropsWeb.GraphLive.ShowTest do
use ToweropsWeb.ConnCase
import Phoenix.LiveViewTest
alias Towerops.Monitoring
alias Towerops.Organizations
alias Towerops.Sites
alias Towerops.Snmp
setup :register_and_log_in_user
setup %{user: user} do
{:ok, organization} = Organizations.create_organization(%{name: "Test Org"}, user.id)
{:ok, site} =
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,
snmp_enabled: true
})
# Create SNMP device for sensor tests
{:ok, snmp_device} =
Snmp.create_snmp_device(%{
device_id: device.id,
sys_name: "test-router",
sys_descr: "Test Router",
sys_object_id: "1.3.6.1.4.1.9"
})
%{organization: organization, site: site, device: device, snmp_device: snmp_device}
end
describe "Latency graph" do
test "renders latency graph page with correct assigns", %{
conn: conn,
device: device,
organization: org
} do
# Create monitoring checks
Monitoring.create_check(%{
device_id: device.id,
status: :success,
response_time_ms: 10.5,
checked_at: DateTime.utc_now()
})
{:ok, view, html} = live(conn, ~p"/orgs/#{org.slug}/devices/#{device.id}/graph/latency")
# Verify page renders
assert html =~ "ICMP Latency"
assert html =~ device.name
# Verify correct assigns are set
assert view.assigns.current_organization.id == org.id
assert view.assigns.device_id == device.id
assert view.assigns.sensor_type == "latency"
assert view.assigns.range == "24h"
end
test "uses current_organization in back link", %{
conn: conn,
device: device,
organization: org
} do
{:ok, _view, html} = live(conn, ~p"/orgs/#{org.slug}/devices/#{device.id}/graph/latency")
# Verify back link uses organization slug (this was the bug)
assert html =~ ~s[/orgs/#{org.slug}/devices/#{device.id}]
end
test "displays empty state when no latency data", %{
conn: conn,
device: device,
organization: org
} do
{:ok, _view, html} = live(conn, ~p"/orgs/#{org.slug}/devices/#{device.id}/graph/latency")
assert html =~ "No sensor data available"
end
end
describe "Processor graph" do
test "renders processor graph page", %{
conn: conn,
device: device,
organization: org,
snmp_device: snmp_device
} do
# Create a CPU sensor
{:ok, sensor} =
Snmp.create_sensor(%{
snmp_device_id: snmp_device.id,
sensor_type: "cpu_load",
sensor_index: 1,
sensor_descr: "CPU 1",
sensor_unit: "%"
})
# Create sensor reading
Snmp.create_sensor_reading(%{
sensor_id: sensor.id,
value: 45.2,
checked_at: DateTime.utc_now()
})
{:ok, view, html} =
live(conn, ~p"/orgs/#{org.slug}/devices/#{device.id}/graph/processors")
assert html =~ "Processor Usage"
assert html =~ device.name
# Verify correct assigns
assert view.assigns.current_organization.id == org.id
assert view.assigns.sensor_type == "processors"
assert view.assigns.unit == "%"
end
end
describe "Memory graph" do
test "renders memory graph page", %{
conn: conn,
device: device,
organization: org,
snmp_device: snmp_device
} do
# Create a memory sensor
{:ok, sensor} =
Snmp.create_sensor(%{
snmp_device_id: snmp_device.id,
sensor_type: "memory_usage",
sensor_index: 1,
sensor_descr: "Memory",
sensor_unit: "%"
})
# Create sensor reading
Snmp.create_sensor_reading(%{
sensor_id: sensor.id,
value: 75.5,
checked_at: DateTime.utc_now()
})
{:ok, view, html} = live(conn, ~p"/orgs/#{org.slug}/devices/#{device.id}/graph/memory")
assert html =~ "Memory Usage"
assert html =~ device.name
# Verify correct assigns
assert view.assigns.current_organization.id == org.id
assert view.assigns.sensor_type == "memory"
assert view.assigns.unit == "%"
end
end
describe "Traffic graph" do
test "renders overall traffic graph page", %{
conn: conn,
device: device,
organization: org,
snmp_device: snmp_device
} do
# Create an interface
{:ok, interface} =
Snmp.create_interface(%{
snmp_device_id: snmp_device.id,
if_index: 1,
if_descr: "eth0",
if_name: "eth0",
if_oper_status: "up",
if_speed: 1_000_000_000
})
# Create interface stats
Snmp.create_interface_stat(%{
interface_id: interface.id,
if_in_octets: 1000,
if_out_octets: 2000,
checked_at: DateTime.utc_now()
})
{:ok, view, html} = live(conn, ~p"/orgs/#{org.slug}/devices/#{device.id}/graph/traffic")
assert html =~ "Overall Traffic"
assert html =~ device.name
# Verify correct assigns
assert view.assigns.current_organization.id == org.id
assert view.assigns.sensor_type == "traffic"
assert view.assigns.unit == "bps"
assert view.assigns.show_zero_line == true
end
test "renders specific interface traffic graph", %{
conn: conn,
device: device,
organization: org,
snmp_device: snmp_device
} do
# Create an interface
{:ok, interface} =
Snmp.create_interface(%{
snmp_device_id: snmp_device.id,
if_index: 1,
if_descr: "eth0",
if_name: "eth0",
if_oper_status: "up",
if_speed: 1_000_000_000
})
# Create interface stats
Snmp.create_interface_stat(%{
interface_id: interface.id,
if_in_octets: 1000,
if_out_octets: 2000,
checked_at: DateTime.utc_now()
})
{:ok, view, html} =
live(
conn,
~p"/orgs/#{org.slug}/devices/#{device.id}/graph/traffic?interface_id=#{interface.id}"
)
assert html =~ "Overall Traffic"
assert html =~ device.name
# Verify correct assigns including interface_id
assert view.assigns.current_organization.id == org.id
assert view.assigns.interface_id == interface.id
end
end
describe "Time range selection" do
test "defaults to 24h range", %{conn: conn, device: device, organization: org} do
{:ok, view, _html} = live(conn, ~p"/orgs/#{org.slug}/devices/#{device.id}/graph/latency")
assert view.assigns.range == "24h"
end
test "accepts custom range parameter", %{conn: conn, device: device, organization: org} do
{:ok, view, _html} =
live(conn, ~p"/orgs/#{org.slug}/devices/#{device.id}/graph/latency?range=1h")
assert view.assigns.range == "1h"
end
test "changes range when user clicks range button", %{
conn: conn,
device: device,
organization: org
} do
{:ok, view, _html} = live(conn, ~p"/orgs/#{org.slug}/devices/#{device.id}/graph/latency")
# Initially 24h
assert view.assigns.range == "24h"
# Change to 1h
view
|> element("button", "1 Hour")
|> render_click()
assert view.assigns.range == "1h"
end
test "preserves interface_id when changing range", %{
conn: conn,
device: device,
organization: org,
snmp_device: snmp_device
} do
# Create an interface
{:ok, interface} =
Snmp.create_interface(%{
snmp_device_id: snmp_device.id,
if_index: 1,
if_descr: "eth0",
if_name: "eth0",
if_oper_status: "up",
if_speed: 1_000_000_000
})
{:ok, view, _html} =
live(
conn,
~p"/orgs/#{org.slug}/devices/#{device.id}/graph/traffic?interface_id=#{interface.id}"
)
# Change range
view
|> element("button", "1 Hour")
|> render_click()
# Interface ID should be preserved
assert view.assigns.interface_id == interface.id
assert view.assigns.range == "1h"
end
end
describe "Assign validation" do
test "ensures current_organization assign exists, not organization", %{
conn: conn,
device: device,
organization: org
} do
{:ok, view, _html} = live(conn, ~p"/orgs/#{org.slug}/devices/#{device.id}/graph/latency")
# current_organization should exist
assert Map.has_key?(view.assigns, :current_organization)
assert view.assigns.current_organization.id == org.id
# organization should NOT exist (this was the bug)
refute Map.has_key?(view.assigns, :organization)
end
test "has all required assigns for rendering", %{
conn: conn,
device: device,
organization: org
} do
{:ok, view, _html} = live(conn, ~p"/orgs/#{org.slug}/devices/#{device.id}/graph/latency")
# All required assigns should be present
assert Map.has_key?(view.assigns, :current_organization)
assert Map.has_key?(view.assigns, :device)
assert Map.has_key?(view.assigns, :device_id)
assert Map.has_key?(view.assigns, :sensor_type)
assert Map.has_key?(view.assigns, :range)
assert Map.has_key?(view.assigns, :chart_title)
assert Map.has_key?(view.assigns, :unit)
assert Map.has_key?(view.assigns, :auto_scale)
assert Map.has_key?(view.assigns, :show_zero_line)
end
end
end