defmodule ToweropsWeb.Admin.AgentLive.IndexTest do use ToweropsWeb.ConnCase import Phoenix.LiveViewTest alias Towerops.Agents describe "admin agents page" do setup [:register_and_log_in_superuser] test "renders page with all agents across organizations", %{conn: conn, user: user} do {:ok, org1} = Towerops.Organizations.create_organization(%{name: "Org Alpha"}, user.id) {:ok, org2} = Towerops.Organizations.create_organization(%{name: "Org Beta"}, user.id, bypass_limits: true) {:ok, _agent1, _} = Agents.create_agent_token(org1.id, "Alpha Agent") {:ok, _agent2, _} = Agents.create_agent_token(org2.id, "Beta Agent") {:ok, _cloud, _} = Agents.create_cloud_poller("Cloud Poller 1") {:ok, _view, html} = live(conn, ~p"/admin/agents") assert html =~ "All Agents" assert html =~ "Alpha Agent" assert html =~ "Beta Agent" assert html =~ "Cloud Poller 1" assert html =~ "Org Alpha" assert html =~ "Org Beta" assert html =~ "Cloud Poller" end test "shows cloud badge for cloud pollers", %{conn: conn} do {:ok, _cloud, _} = Agents.create_cloud_poller("My Cloud Poller") {:ok, _view, html} = live(conn, ~p"/admin/agents") assert html =~ "Cloud" assert html =~ "My Cloud Poller" end test "shows debug badge for debug-enabled agents", %{conn: conn, user: user} do {:ok, org} = Towerops.Organizations.create_organization(%{name: "Debug Org"}, user.id) {:ok, agent, _} = Agents.create_agent_token(org.id, "Debug Agent") {:ok, _} = Agents.update_agent_token(agent, %{allow_remote_debug: true}) {:ok, _view, html} = live(conn, ~p"/admin/agents") assert html =~ "Debug" end test "shows status badges", %{conn: conn, user: user} do {:ok, org} = Towerops.Organizations.create_organization(%{name: "Status Org"}, user.id) {:ok, _agent, _} = Agents.create_agent_token(org.id, "Status Agent") {:ok, _view, html} = live(conn, ~p"/admin/agents") assert html =~ "Never connected" end test "shows version when available", %{conn: conn, user: user} do {:ok, org} = Towerops.Organizations.create_organization(%{name: "Version Org"}, user.id) {:ok, agent, _} = Agents.create_agent_token(org.id, "Versioned Agent") Agents.update_agent_token_heartbeat(agent.id, "10.0.0.1", %{"version" => "1.2.3"}) {:ok, _view, html} = live(conn, ~p"/admin/agents") assert html =~ "v1.2.3" end end describe "real-time updates" do setup [:register_and_log_in_superuser] test "updates when a new agent is created", %{conn: conn, user: user} do {:ok, view, _html} = live(conn, ~p"/admin/agents") {:ok, org} = Towerops.Organizations.create_organization(%{name: "New Org"}, user.id) {:ok, _agent, _} = Agents.create_agent_token(org.id, "Dynamic Agent") html = render(view) assert html =~ "Dynamic Agent" assert html =~ "New Org" end test "updates when a new cloud poller is created", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/agents") {:ok, _cloud, _} = Agents.create_cloud_poller("Dynamic Cloud Poller") html = render(view) assert html =~ "Dynamic Cloud Poller" end test "updates when an agent is deleted", %{conn: conn, user: user} do {:ok, org} = Towerops.Organizations.create_organization(%{name: "Delete Org"}, user.id) {:ok, agent, _} = Agents.create_agent_token(org.id, "Doomed Agent") {:ok, view, html} = live(conn, ~p"/admin/agents") assert html =~ "Doomed Agent" {:ok, _} = Agents.delete_agent_token(agent.id) html = render(view) refute html =~ "Doomed Agent" end end describe "non-superuser access" do setup [:register_and_log_in_user] test "redirects non-superusers", %{conn: conn} do assert {:error, {:redirect, %{to: "/orgs"}}} = live(conn, ~p"/admin/agents") end end defp register_and_log_in_superuser(%{conn: conn}) do user = Towerops.AccountsFixtures.user_fixture(enable_totp: true) user = Towerops.Repo.update!(Ecto.Changeset.change(user, is_superuser: true)) %{conn: log_in_user(conn, user), user: user} end end