towerops/test/towerops_web/controllers/api/v1/members_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

155 lines
4.3 KiB
Elixir

defmodule ToweropsWeb.Api.V1.MembersControllerTest do
use ToweropsWeb.ConnCase, async: true
import Towerops.AccountsFixtures
import Towerops.OrganizationsFixtures
alias Towerops.ApiTokens
alias Towerops.Organizations
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
defp add_member(organization, role \\ :technician) do
other_user = user_fixture()
{:ok, _membership} =
Organizations.create_membership(%{
organization_id: organization.id,
user_id: other_user.id,
role: role
})
other_user
end
describe "index/2" do
test "lists members including owner", %{conn: conn, user: user} do
conn = get(conn, ~p"/api/v1/members")
assert %{"data" => members} = json_response(conn, 200)
assert [_ | _] = members
owner = Enum.find(members, &(&1["id"] == user.id))
assert owner["email"] == user.email
assert owner["role"] == "owner"
assert Map.has_key?(owner, "inserted_at")
end
test "lists multiple members", %{conn: conn, organization: organization} do
other_user = add_member(organization, :technician)
conn = get(conn, ~p"/api/v1/members")
assert %{"data" => members} = json_response(conn, 200)
assert length(members) == 2
member_ids = Enum.map(members, & &1["id"])
assert other_user.id in member_ids
end
end
describe "update/2" do
test "changes member role", %{conn: conn, organization: organization} do
other_user = add_member(organization, :technician)
conn =
patch(conn, ~p"/api/v1/members/#{other_user.id}", %{
"role" => "admin"
})
assert %{"data" => data} = json_response(conn, 200)
assert data["id"] == other_user.id
assert data["role"] == "admin"
end
test "returns 403 when changing owner role", %{conn: conn, user: user} do
conn =
patch(conn, ~p"/api/v1/members/#{user.id}", %{
"role" => "technician"
})
assert %{"error" => "Cannot change owner role"} = json_response(conn, 403)
end
test "returns 404 for non-member", %{conn: conn} do
fake_id = Ecto.UUID.generate()
conn =
patch(conn, ~p"/api/v1/members/#{fake_id}", %{
"role" => "admin"
})
assert %{"error" => "Member not found"} = json_response(conn, 404)
end
test "returns 400 without role param", %{conn: conn, organization: organization} do
other_user = add_member(organization)
conn = patch(conn, ~p"/api/v1/members/#{other_user.id}", %{})
assert %{"error" => "Missing 'role' parameter"} = json_response(conn, 400)
end
end
describe "delete/2" do
test "removes member", %{conn: conn, organization: organization} do
other_user = add_member(organization)
conn = delete(conn, ~p"/api/v1/members/#{other_user.id}")
assert response(conn, 204)
end
test "returns 403 when removing owner", %{conn: conn, user: user} do
conn = delete(conn, ~p"/api/v1/members/#{user.id}")
assert %{"error" => "Cannot remove owner"} = json_response(conn, 403)
end
test "returns 404 for non-member", %{conn: conn} do
fake_id = Ecto.UUID.generate()
conn = delete(conn, ~p"/api/v1/members/#{fake_id}")
assert %{"error" => "Member 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/members")
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/members")
assert %{"error" => _message} = json_response(conn, 401)
end
end
end