diff --git a/test/towerops_web/graphql/resolvers/agent_test.exs b/test/towerops_web/graphql/resolvers/agent_test.exs new file mode 100644 index 00000000..e77938d9 --- /dev/null +++ b/test/towerops_web/graphql/resolvers/agent_test.exs @@ -0,0 +1,86 @@ +defmodule ToweropsWeb.GraphQL.Resolvers.AgentTest do + use Towerops.DataCase, async: true + + import Towerops.AccountsFixtures + import Towerops.OrganizationsFixtures + + alias ToweropsWeb.GraphQL.Resolvers.Agent, as: Resolver + + setup do + user = user_fixture() + org = organization_fixture(user.id) + other_user = user_fixture() + other_org = organization_fixture(other_user.id) + + %{user: user, org: org, other_org: other_org, ctx: %{organization_id: org.id}} + end + + describe "list/3" do + test "returns agent tokens for the org", %{org: org, ctx: ctx} do + {:ok, _t, _raw} = Towerops.Agents.create_agent_token(org.id, "Agent 1") + assert {:ok, agents} = Resolver.list(nil, %{}, %{context: ctx}) + refute Enum.empty?(agents) + end + + test "without org context returns auth error" do + assert {:error, _} = Resolver.list(nil, %{}, %{}) + end + end + + describe "get/3" do + test "returns agent in same org", %{org: org, ctx: ctx} do + {:ok, t, _raw} = Towerops.Agents.create_agent_token(org.id, "X") + assert {:ok, found} = Resolver.get(nil, %{id: t.id}, %{context: ctx}) + assert found.id == t.id + end + + test "returns 'not found' for cross-org agent", + %{other_org: other_org, ctx: ctx} do + {:ok, foreign, _raw} = Towerops.Agents.create_agent_token(other_org.id, "F") + assert {:error, "Agent not found"} = Resolver.get(nil, %{id: foreign.id}, %{context: ctx}) + end + + test "without org context returns auth error" do + assert {:error, _} = Resolver.get(nil, %{id: Ecto.UUID.generate()}, %{}) + end + end + + describe "create/3" do + test "creates a token and returns name + raw token", %{ctx: ctx} do + assert {:ok, %{name: "Created", token: raw, id: id}} = + Resolver.create(nil, %{name: "Created"}, %{context: ctx}) + + assert is_binary(raw) + assert is_binary(id) + end + + test "returns formatted errors when name is invalid", %{ctx: ctx} do + # An empty name fails the name presence check + assert {:error, errors} = Resolver.create(nil, %{name: ""}, %{context: ctx}) + assert is_list(errors) or is_binary(errors) or is_map(errors) + end + + test "without org context returns auth error" do + assert {:error, _} = Resolver.create(nil, %{name: "x"}, %{}) + end + end + + describe "delete/3" do + test "removes an agent in the org", %{org: org, ctx: ctx} do + {:ok, t, _raw} = Towerops.Agents.create_agent_token(org.id, "ToDelete") + assert {:ok, %{success: true}} = Resolver.delete(nil, %{id: t.id}, %{context: ctx}) + end + + test "returns 'not found' for cross-org agent", + %{other_org: other_org, ctx: ctx} do + {:ok, foreign, _raw} = Towerops.Agents.create_agent_token(other_org.id, "F") + + assert {:error, "Agent not found"} = + Resolver.delete(nil, %{id: foreign.id}, %{context: ctx}) + end + + test "without org context returns auth error" do + assert {:error, _} = Resolver.delete(nil, %{id: Ecto.UUID.generate()}, %{}) + end + end +end