Tests for agents, alerts, integrations, organization, members, and invitations controllers. Refactor alert filters to reduce complexity. 75 new tests, all passing.
144 lines
4.3 KiB
Elixir
144 lines
4.3 KiB
Elixir
defmodule ToweropsWeb.Api.V1.InvitationsControllerTest 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 create_test_invitation(organization, user, email \\ "invited@example.com") do
|
|
{:ok, invitation} =
|
|
Organizations.create_invitation(%{
|
|
organization_id: organization.id,
|
|
email: email,
|
|
role: :technician,
|
|
invited_by_id: user.id,
|
|
token: Ecto.UUID.generate(),
|
|
expires_at: DateTime.utc_now() |> DateTime.add(7 * 86_400, :second) |> DateTime.truncate(:second)
|
|
})
|
|
|
|
invitation
|
|
end
|
|
|
|
describe "index/2" do
|
|
test "lists pending invitations", %{
|
|
conn: conn,
|
|
organization: organization,
|
|
user: user
|
|
} do
|
|
invitation = create_test_invitation(organization, user)
|
|
|
|
conn = get(conn, ~p"/api/v1/invitations")
|
|
|
|
assert %{"data" => invitations} = json_response(conn, 200)
|
|
assert length(invitations) == 1
|
|
|
|
inv = List.first(invitations)
|
|
assert inv["id"] == invitation.id
|
|
assert inv["email"] == "invited@example.com"
|
|
assert inv["role"] == "technician"
|
|
assert Map.has_key?(inv, "expires_at")
|
|
assert Map.has_key?(inv, "invited_by_email")
|
|
assert Map.has_key?(inv, "inserted_at")
|
|
end
|
|
|
|
test "returns empty list when no invitations exist", %{conn: conn} do
|
|
conn = get(conn, ~p"/api/v1/invitations")
|
|
|
|
assert %{"data" => []} = json_response(conn, 200)
|
|
end
|
|
end
|
|
|
|
describe "create/2" do
|
|
test "creates invitation", %{conn: conn} do
|
|
params = %{
|
|
"email" => "newuser@example.com",
|
|
"role" => "technician"
|
|
}
|
|
|
|
conn = post(conn, ~p"/api/v1/invitations", params)
|
|
|
|
assert %{"data" => data} = json_response(conn, 201)
|
|
assert data["email"] == "newuser@example.com"
|
|
assert data["role"] == "technician"
|
|
assert Map.has_key?(data, "id")
|
|
assert Map.has_key?(data, "expires_at")
|
|
assert Map.has_key?(data, "inserted_at")
|
|
end
|
|
|
|
test "returns 400 without required params", %{conn: conn} do
|
|
conn = post(conn, ~p"/api/v1/invitations", %{})
|
|
|
|
assert %{"error" => "Missing 'email' and 'role' parameters"} = json_response(conn, 400)
|
|
end
|
|
end
|
|
|
|
describe "delete/2" do
|
|
test "removes invitation", %{conn: conn, organization: organization, user: user} do
|
|
invitation = create_test_invitation(organization, user)
|
|
|
|
conn = delete(conn, ~p"/api/v1/invitations/#{invitation.id}")
|
|
|
|
assert response(conn, 204)
|
|
end
|
|
|
|
test "returns 404 for invitation in different organization", %{conn: conn} do
|
|
other_user = user_fixture()
|
|
other_org = organization_fixture(other_user.id)
|
|
invitation = create_test_invitation(other_org, other_user, "other@example.com")
|
|
|
|
conn = delete(conn, ~p"/api/v1/invitations/#{invitation.id}")
|
|
|
|
assert %{"error" => "Invitation not found"} = json_response(conn, 404)
|
|
end
|
|
|
|
test "returns 404 for non-existent invitation", %{conn: conn} do
|
|
fake_id = Ecto.UUID.generate()
|
|
|
|
conn = delete(conn, ~p"/api/v1/invitations/#{fake_id}")
|
|
|
|
assert %{"error" => "Invitation 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/invitations")
|
|
|
|
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/invitations")
|
|
|
|
assert %{"error" => _message} = json_response(conn, 401)
|
|
end
|
|
end
|
|
end
|