towerops/test/towerops_web/controllers/api/v1/agents_controller_test.exs
2026-06-16 09:56:51 -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"]) and byte_size(agent["id"]) > 0
assert is_binary(agent["token"]) and byte_size(agent["token"]) > 0
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