towerops/test/towerops/dashboard_test.exs
Graham McIntire de075ea8d9
Store billing subscriber/MRR data on integrations for dashboard
Each billing sync (Gaiia, Splynx, VISP, Sonar) already computes
subscriber counts and MRR but only stored them in sync messages.
Now persists them on the integrations table so the dashboard can
aggregate across all billing providers instead of only querying
Gaiia network sites (which were never populated).

Also fixes SnmpKit Config environment detection to use Mix.env()
as fallback when MIX_ENV env var is not set.
2026-02-15 16:51:33 -06:00

165 lines
5.2 KiB
Elixir

defmodule Towerops.DashboardTest do
use Towerops.DataCase, async: true
import Towerops.AccountsFixtures
import Towerops.DevicesFixtures
import Towerops.OrganizationsFixtures
alias Towerops.Dashboard
alias Towerops.Integrations
setup do
user = user_fixture()
org = organization_fixture(user.id)
%{org: org, user: user}
end
describe "get_dashboard_summary/1" do
test "returns correct structure with empty org", %{org: org} do
summary = Dashboard.get_dashboard_summary(org.id)
assert is_map(summary)
assert Map.has_key?(summary, :health_score)
assert Map.has_key?(summary, :devices)
assert Map.has_key?(summary, :alerts)
assert Map.has_key?(summary, :subscribers)
assert Map.has_key?(summary, :insights)
end
test "returns device counts", %{org: org} do
device = device_fixture(%{organization_id: org.id})
Towerops.Devices.update_device_status(device, :up)
summary = Dashboard.get_dashboard_summary(org.id)
assert summary.devices.total == 1
assert summary.devices.up == 1
assert summary.devices.down == 0
end
test "returns alert count", %{org: org} do
device = device_fixture(%{organization_id: org.id})
{:ok, _alert} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: :device_down,
triggered_at: DateTime.utc_now(),
message: "Device is down"
})
summary = Dashboard.get_dashboard_summary(org.id)
assert summary.alerts.active_count == 1
end
test "returns subscriber totals from billing integrations", %{org: org} do
{:ok, integration} =
Integrations.create_integration(org.id, %{provider: "gaiia", enabled: true})
{:ok, _} = Integrations.update_billing_totals(integration, 100, Decimal.new("5000.00"))
summary = Dashboard.get_dashboard_summary(org.id)
assert summary.subscribers.total == 100
assert Decimal.equal?(summary.subscribers.total_mrr, Decimal.new("5000.00"))
end
test "returns zero subscribers when no billing integrations", %{org: org} do
summary = Dashboard.get_dashboard_summary(org.id)
assert summary.subscribers.total == 0
end
test "returns insight counts by urgency", %{org: org} do
summary = Dashboard.get_dashboard_summary(org.id)
assert summary.insights.critical == 0
assert summary.insights.warning == 0
assert summary.insights.info == 0
end
end
describe "compute_health_score/1" do
test "returns 100 when all devices up, no alerts", %{org: org} do
device = device_fixture(%{organization_id: org.id})
Towerops.Devices.update_device_status(device, :up)
score = Dashboard.compute_health_score(org.id)
assert score == 100
end
test "returns lower score when devices down", %{org: org} do
d1 = device_fixture(%{organization_id: org.id})
d2 = device_fixture(%{organization_id: org.id})
Towerops.Devices.update_device_status(d1, :up)
Towerops.Devices.update_device_status(d2, :down)
score = Dashboard.compute_health_score(org.id)
assert score < 100
assert score > 0
end
test "returns 100 when no devices exist", %{org: org} do
score = Dashboard.compute_health_score(org.id)
assert score == 100
end
test "penalizes for critical alerts", %{org: org} do
device = device_fixture(%{organization_id: org.id})
Towerops.Devices.update_device_status(device, :up)
{:ok, _} =
Towerops.Alerts.create_alert(%{
device_id: device.id,
alert_type: :device_down,
triggered_at: DateTime.utc_now(),
message: "Device down"
})
score = Dashboard.compute_health_score(org.id)
assert score < 100
end
end
describe "get_org_subscriber_summary/1" do
test "returns totals from billing integrations", %{org: org} do
{:ok, i1} =
Integrations.create_integration(org.id, %{provider: "gaiia", enabled: true})
{:ok, _} = Integrations.update_billing_totals(i1, 50, Decimal.new("2500.00"))
{:ok, i2} =
Integrations.create_integration(org.id, %{provider: "splynx", enabled: true})
{:ok, _} = Integrations.update_billing_totals(i2, 30, Decimal.new("1500.00"))
result = Dashboard.get_org_subscriber_summary(org.id)
assert result.total == 80
assert Decimal.equal?(result.total_mrr, Decimal.new("4000.00"))
end
test "returns zeros when no billing integrations", %{org: org} do
result = Dashboard.get_org_subscriber_summary(org.id)
assert result.total == 0
assert Decimal.equal?(result.total_mrr, Decimal.new(0))
end
end
describe "list_site_summaries/1" do
test "returns enriched site data", %{org: org} do
{:ok, site} =
Towerops.Sites.create_site(%{
name: "Test Tower",
organization_id: org.id
})
device = device_fixture(%{organization_id: org.id, site_id: site.id})
Towerops.Devices.update_device_status(device, :up)
summaries = Dashboard.list_site_summaries(org.id)
assert summaries != []
summary = Enum.find(summaries, &(&1.site_id == site.id))
assert summary.name == "Test Tower"
assert summary.device_count >= 1
end
end
end