defmodule SnmpKit.SnmpLib.DashboardTest do use ExUnit.Case, async: false alias SnmpKit.SnmpLib.Dashboard doctest Dashboard @moduletag :dashboard_test setup do # Ensure dashboard process is stopped before each test if Process.whereis(Dashboard) do try do GenServer.stop(Dashboard, :normal, 1000) catch :exit, _ -> :ok end end :timer.sleep(10) :ok end describe "Dashboard.start_link/1" do test "starts with default configuration" do assert {:ok, pid} = Dashboard.start_link() assert Process.alive?(pid) try do GenServer.stop(Dashboard) catch :exit, _ -> :ok end end test "starts with custom configuration" do opts = [ port: 8080, prometheus_enabled: true, retention_days: 14 ] assert {:ok, pid} = Dashboard.start_link(opts) assert Process.alive?(pid) try do GenServer.stop(Dashboard) catch :exit, _ -> :ok end end end describe "Dashboard.record_metric/3" do setup do {:ok, _pid} = Dashboard.start_link() on_exit(fn -> if Process.whereis(Dashboard) do try do GenServer.stop(Dashboard, :normal, 1000) catch :exit, _ -> :ok end end end) :ok end test "records simple metrics" do assert :ok = Dashboard.record_metric(:test_metric, 100) assert :ok = Dashboard.record_metric(:test_metric, 200, %{device: "test_device"}) # Allow time for async processing :timer.sleep(10) end test "records SNMP operation metrics" do assert :ok = Dashboard.record_metric(:snmp_response_time, 125, %{ device: "192.168.1.1", operation: "get", status: :success }) assert :ok = Dashboard.record_metric(:snmp_errors, 1, %{ device: "192.168.1.1", error_type: "timeout" }) end end describe "Dashboard.create_alert/3" do setup do {:ok, _pid} = Dashboard.start_link() on_exit(fn -> if Process.whereis(Dashboard) do try do GenServer.stop(Dashboard, :normal, 1000) catch :exit, _ -> :ok end end end) :ok end test "creates alerts with different levels" do assert :ok = Dashboard.create_alert(:test_info, :info, %{message: "Info alert"}) assert :ok = Dashboard.create_alert(:test_warning, :warning, %{message: "Warning alert"}) assert :ok = Dashboard.create_alert(:test_critical, :critical, %{message: "Critical alert"}) # Allow time for async processing :timer.sleep(10) end test "creates device-specific alerts" do assert :ok = Dashboard.create_alert(:device_unreachable, :critical, %{ device: "192.168.1.1", last_seen: DateTime.utc_now(), consecutive_failures: 5 }) assert :ok = Dashboard.create_alert(:slow_response, :warning, %{ device: "192.168.1.1", avg_response_time: 5000, threshold: 2000 }) end end describe "Dashboard.get_metrics_summary/0" do setup do {:ok, _pid} = Dashboard.start_link() on_exit(fn -> if Process.whereis(Dashboard) do try do GenServer.stop(Dashboard, :normal, 1000) catch :exit, _ -> :ok end end end) :ok end test "returns metrics summary" do # Record some test metrics Dashboard.record_metric(:snmp_response_time, 100, %{device: "device1", status: :success}) Dashboard.record_metric(:snmp_response_time, 200, %{device: "device2", status: :success}) Dashboard.record_metric(:snmp_errors, 1, %{device: "device3", status: :error}) :timer.sleep(10) summary = Dashboard.get_metrics_summary() assert Map.has_key?(summary, :total_operations) assert Map.has_key?(summary, :success_rate) assert Map.has_key?(summary, :avg_response_time) assert Map.has_key?(summary, :active_devices) assert Map.has_key?(summary, :pool_utilization) assert Map.has_key?(summary, :error_rates) assert is_number(summary.total_operations) assert is_float(summary.success_rate) assert is_float(summary.avg_response_time) end end describe "Dashboard.get_device_metrics/1" do setup do {:ok, _pid} = Dashboard.start_link() on_exit(fn -> if Process.whereis(Dashboard) do try do GenServer.stop(Dashboard, :normal, 1000) catch :exit, _ -> :ok end end end) :ok end test "returns device-specific metrics" do device_id = "192.168.1.1" # Record some metrics for the device Dashboard.record_metric(:snmp_response_time, 150, %{device: device_id}) Dashboard.record_metric(:snmp_response_time, 175, %{device: device_id}) :timer.sleep(10) device_metrics = Dashboard.get_device_metrics(device_id) assert Map.has_key?(device_metrics, :device_id) assert Map.has_key?(device_metrics, :total_operations) assert Map.has_key?(device_metrics, :response_times) assert Map.has_key?(device_metrics, :error_count) assert Map.has_key?(device_metrics, :last_seen) assert device_metrics.device_id == device_id end end describe "Dashboard.get_active_alerts/1" do setup do {:ok, _pid} = Dashboard.start_link() on_exit(fn -> if Process.whereis(Dashboard) do try do GenServer.stop(Dashboard, :normal, 1000) catch :exit, _ -> :ok end end end) :ok end test "returns all active alerts" do # Create some test alerts Dashboard.create_alert(:test_alert1, :warning, %{device: "device1"}) Dashboard.create_alert(:test_alert2, :critical, %{device: "device2"}) :timer.sleep(10) alerts = Dashboard.get_active_alerts() assert is_list(alerts) and alerts != [] end test "filters alerts by level" do # Create alerts with different levels Dashboard.create_alert(:test_warning, :warning, %{device: "device1"}) Dashboard.create_alert(:test_critical, :critical, %{device: "device2"}) :timer.sleep(10) critical_alerts = Dashboard.get_active_alerts(level: :critical) assert is_list(critical_alerts) and critical_alerts != [] end end describe "Dashboard.acknowledge_alert/2" do setup do {:ok, _pid} = Dashboard.start_link() on_exit(fn -> if Process.whereis(Dashboard) do try do GenServer.stop(Dashboard, :normal, 1000) catch :exit, _ -> :ok end end end) :ok end test "acknowledges device alerts" do # Create an alert Dashboard.create_alert(:device_down, :critical, %{device: "192.168.1.1"}) :timer.sleep(10) # Acknowledge the alert assert :ok = Dashboard.acknowledge_alert(:device_down, "192.168.1.1") end end describe "Dashboard.export_prometheus/0" do setup do {:ok, _pid} = Dashboard.start_link() on_exit(fn -> if Process.whereis(Dashboard) do try do GenServer.stop(Dashboard, :normal, 1000) catch :exit, _ -> :ok end end end) :ok end test "exports metrics in Prometheus format" do # Record some metrics Dashboard.record_metric(:snmp_response_time, 100, %{status: :success}) Dashboard.record_metric(:snmp_response_time, 200, %{status: :success}) :timer.sleep(10) prometheus_data = Dashboard.export_prometheus() assert String.contains?(prometheus_data, "snmp_lib_total_operations") assert String.contains?(prometheus_data, "snmp_lib_success_rate") assert String.contains?(prometheus_data, "snmp_lib_avg_response_time") end end describe "Dashboard.get_timeseries/3" do setup do {:ok, _pid} = Dashboard.start_link() on_exit(fn -> if Process.whereis(Dashboard) do try do GenServer.stop(Dashboard, :normal, 1000) catch :exit, _ -> :ok end end end) :ok end test "returns timeseries data for metrics" do # Record some metrics Dashboard.record_metric(:snmp_response_time, 100, %{device: "device1"}) Dashboard.record_metric(:snmp_response_time, 200, %{device: "device1"}) :timer.sleep(10) # Get timeseries data timeseries = Dashboard.get_timeseries(:snmp_response_time, 3_600_000) assert is_list(timeseries) and timeseries != [] # Get filtered timeseries data device_timeseries = Dashboard.get_timeseries(:snmp_response_time, 3_600_000, %{device: "device1"}) assert is_list(device_timeseries) and device_timeseries != [] end end end