towerops/test/towerops_web/controllers/api/v1/agents_controller_test.exs
Graham McIntire 7613a4dde5
add missing REST API controller tests
Tests for agents, alerts, integrations, organization, members, and
invitations controllers. Refactor alert filters to reduce complexity.
75 new tests, all passing.
2026-03-11 14:43:17 -05:00

187 lines
5.7 KiB
Elixir

defmodule ToweropsWeb.Api.V1.AgentsControllerTest do
use ToweropsWeb.ConnCase, async: true
import Towerops.AccountsFixtures
import Towerops.AgentsFixtures
import Towerops.OrganizationsFixtures
alias Towerops.ApiTokens
setup do
user = user_fixture()
organization = organization_fixture(user.id)
{:ok, {_token, raw_token}} =
ApiTokens.create_api_token(%{
organization_id: organization.id,
user_id: user.id,
name: "Test Token"
})
conn =
build_conn()
|> put_req_header("authorization", "Bearer #{raw_token}")
|> put_req_header("accept", "application/json")
%{
conn: conn,
user: user,
organization: organization
}
end
describe "index/2" do
test "lists agents for the authenticated organization", %{
conn: conn,
organization: organization
} do
{:ok, agent1, _raw1} = agent_token_fixture(organization.id, "Agent Alpha")
{:ok, agent2, _raw2} = agent_token_fixture(organization.id, "Agent Beta")
conn = get(conn, ~p"/api/v1/agents")
assert %{"data" => agents} = json_response(conn, 200)
assert length(agents) == 2
agent_ids = Enum.map(agents, & &1["id"])
assert agent1.id in agent_ids
assert agent2.id in agent_ids
agent_json = List.first(agents)
assert Map.has_key?(agent_json, "id")
assert Map.has_key?(agent_json, "name")
assert Map.has_key?(agent_json, "enabled")
assert Map.has_key?(agent_json, "last_seen_at")
assert Map.has_key?(agent_json, "last_ip")
assert Map.has_key?(agent_json, "metadata")
assert Map.has_key?(agent_json, "inserted_at")
end
test "returns empty list when organization has no agents", %{conn: conn} do
conn = get(conn, ~p"/api/v1/agents")
assert %{"data" => []} = json_response(conn, 200)
end
test "does not return agents from other organizations", %{conn: conn} do
other_user = user_fixture()
other_org = organization_fixture(other_user.id)
{:ok, _other_agent, _raw} = agent_token_fixture(other_org.id)
conn = get(conn, ~p"/api/v1/agents")
assert %{"data" => agents} = json_response(conn, 200)
assert Enum.empty?(agents)
end
end
describe "create/2" do
test "creates agent with valid name and returns token", %{
conn: conn,
organization: organization
} do
conn = post(conn, ~p"/api/v1/agents", %{"name" => "New Agent"})
assert %{"data" => agent} = json_response(conn, 201)
assert agent["name"] == "New Agent"
assert is_binary(agent["id"])
assert is_binary(agent["token"])
assert agent["enabled"] == true
# Verify the agent was created in the correct organization
created = Towerops.Agents.get_agent_token!(agent["id"])
assert created.organization_id == organization.id
end
test "returns 400 without name parameter", %{conn: conn} do
conn = post(conn, ~p"/api/v1/agents", %{})
assert %{"error" => "Missing 'name' parameter"} = json_response(conn, 400)
end
end
describe "show/2" do
test "returns agent with device_count", %{conn: conn, organization: organization} do
{:ok, agent, _raw} = agent_token_fixture(organization.id, "Show Agent")
conn = get(conn, ~p"/api/v1/agents/#{agent.id}")
assert %{"data" => data} = json_response(conn, 200)
assert data["id"] == agent.id
assert data["name"] == "Show Agent"
assert Map.has_key?(data, "device_count")
assert data["device_count"] == 0
end
test "returns 404 for non-existent agent", %{conn: conn} do
conn = get(conn, ~p"/api/v1/agents/#{Ecto.UUID.generate()}")
assert %{"error" => "Agent not found"} = json_response(conn, 404)
end
test "returns 404 for agent in another organization", %{conn: conn} do
other_user = user_fixture()
other_org = organization_fixture(other_user.id)
{:ok, other_agent, _raw} = agent_token_fixture(other_org.id)
conn = get(conn, ~p"/api/v1/agents/#{other_agent.id}")
assert %{"error" => "Agent not found"} = json_response(conn, 404)
end
end
describe "delete/2" do
test "removes agent and returns 204", %{conn: conn, organization: organization} do
{:ok, agent, _raw} = agent_token_fixture(organization.id)
conn = delete(conn, ~p"/api/v1/agents/#{agent.id}")
assert response(conn, 204)
# Verify the agent was deleted
assert_raise Ecto.NoResultsError, fn ->
Towerops.Agents.get_agent_token!(agent.id)
end
end
test "returns 404 for non-existent agent", %{conn: conn} do
conn = delete(conn, ~p"/api/v1/agents/#{Ecto.UUID.generate()}")
assert %{"error" => "Agent not found"} = json_response(conn, 404)
end
test "returns 404 for agent in another organization", %{conn: conn} do
other_user = user_fixture()
other_org = organization_fixture(other_user.id)
{:ok, other_agent, _raw} = agent_token_fixture(other_org.id)
conn = delete(conn, ~p"/api/v1/agents/#{other_agent.id}")
assert %{"error" => "Agent not found"} = json_response(conn, 404)
end
end
describe "authentication" do
test "returns 401 without authorization header" do
conn =
build_conn()
|> put_req_header("accept", "application/json")
|> get(~p"/api/v1/agents")
assert %{"error" => _message} = json_response(conn, 401)
end
test "returns 401 with invalid token" do
conn =
build_conn()
|> put_req_header("authorization", "Bearer towerops_invalid_token")
|> put_req_header("accept", "application/json")
|> get(~p"/api/v1/agents")
assert %{"error" => _message} = json_response(conn, 401)
end
end
end