towerops/test/towerops/preseem_test.exs

174 lines
5.4 KiB
Elixir

defmodule Towerops.PreseemTest do
use Towerops.DataCase, async: true
import Towerops.AccountsFixtures
import Towerops.DevicesFixtures
import Towerops.OrganizationsFixtures
alias Towerops.Preseem
alias Towerops.Preseem.AccessPoint
alias Towerops.Preseem.SubscriberMetric
setup do
user = user_fixture()
org = organization_fixture(user.id)
%{organization: org}
end
defp insert_access_point!(org, attrs \\ %{}) do
default = %{
organization_id: org.id,
preseem_id: "ap-#{System.unique_integer([:positive])}",
name: "Test AP"
}
{:ok, ap} =
%AccessPoint{}
|> AccessPoint.changeset(Map.merge(default, attrs))
|> Repo.insert()
ap
end
defp insert_metric!(ap, attrs) do
default = %{
preseem_access_point_id: ap.id,
recorded_at: DateTime.truncate(DateTime.utc_now(), :second)
}
{:ok, metric} =
%SubscriberMetric{}
|> SubscriberMetric.changeset(Map.merge(default, attrs))
|> Repo.insert()
metric
end
describe "get_access_point_for_device/1" do
test "returns nil when no AP linked to device" do
assert is_nil(Preseem.get_access_point_for_device(Ecto.UUID.generate()))
end
test "returns AP when linked to device", %{organization: org} do
device = device_fixture(%{organization_id: org.id})
ap =
insert_access_point!(org, %{
device_id: device.id,
match_confidence: "auto_ip"
})
result = Preseem.get_access_point_for_device(device.id)
assert result.id == ap.id
end
end
describe "list_access_points/1" do
test "returns all APs for an organization ordered by name", %{organization: org} do
insert_access_point!(org, %{name: "Bravo AP"})
insert_access_point!(org, %{name: "Alpha AP"})
aps = Preseem.list_access_points(org.id)
assert length(aps) == 2
assert Enum.map(aps, & &1.name) == ["Alpha AP", "Bravo AP"]
end
test "does not return APs from other organizations", %{organization: org} do
other_user = user_fixture()
other_org = organization_fixture(other_user.id)
insert_access_point!(org, %{name: "Our AP"})
insert_access_point!(other_org, %{name: "Their AP"})
aps = Preseem.list_access_points(org.id)
assert length(aps) == 1
assert hd(aps).name == "Our AP"
end
end
describe "list_unmatched_access_points/1" do
test "returns only unmatched and ambiguous APs", %{organization: org} do
insert_access_point!(org, %{name: "Matched", match_confidence: "auto_mac"})
insert_access_point!(org, %{name: "Unmatched", match_confidence: "unmatched"})
insert_access_point!(org, %{name: "Ambiguous", match_confidence: "ambiguous"})
insert_access_point!(org, %{name: "Manual", match_confidence: "manual"})
unmatched = Preseem.list_unmatched_access_points(org.id)
assert length(unmatched) == 2
names = unmatched |> Enum.map(& &1.name) |> Enum.sort()
assert names == ["Ambiguous", "Unmatched"]
end
end
describe "list_subscriber_metrics/2" do
test "returns metrics ordered by recorded_at desc", %{organization: org} do
ap = insert_access_point!(org)
now = DateTime.truncate(DateTime.utc_now(), :second)
old = DateTime.add(now, -3600, :second)
insert_metric!(ap, %{recorded_at: old, avg_latency: 10.0})
insert_metric!(ap, %{recorded_at: now, avg_latency: 20.0})
metrics = Preseem.list_subscriber_metrics(ap.id)
assert length(metrics) == 2
assert hd(metrics).avg_latency == 20.0
end
test "respects limit option", %{organization: org} do
ap = insert_access_point!(org)
now = DateTime.truncate(DateTime.utc_now(), :second)
for i <- 1..5 do
insert_metric!(ap, %{
recorded_at: DateTime.add(now, -i, :second),
avg_latency: i * 1.0
})
end
metrics = Preseem.list_subscriber_metrics(ap.id, limit: 2)
assert length(metrics) == 2
end
test "defaults to 100 limit", %{organization: org} do
ap = insert_access_point!(org)
# Just verify the function works with default
metrics = Preseem.list_subscriber_metrics(ap.id)
assert is_list(metrics)
end
end
describe "link_access_point/2" do
test "links AP to device with manual confidence", %{organization: org} do
ap = insert_access_point!(org, %{match_confidence: "unmatched"})
device = device_fixture(%{organization_id: org.id})
assert {:ok, linked} = Preseem.link_access_point(ap.id, device.id)
assert linked.device_id == device.id
assert linked.match_confidence == "manual"
end
test "returns error for non-existent AP" do
assert {:error, :not_found} = Preseem.link_access_point(Ecto.UUID.generate(), Ecto.UUID.generate())
end
end
describe "unlink_access_point/1" do
test "unlinks AP and resets to unmatched", %{organization: org} do
device = device_fixture(%{organization_id: org.id})
ap =
insert_access_point!(org, %{
device_id: device.id,
match_confidence: "manual"
})
assert {:ok, unlinked} = Preseem.unlink_access_point(ap.id)
assert is_nil(unlinked.device_id)
assert unlinked.match_confidence == "unmatched"
end
test "returns error for non-existent AP" do
assert {:error, :not_found} = Preseem.unlink_access_point(Ecto.UUID.generate())
end
end
end