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

262 lines
8.3 KiB
Elixir

defmodule ToweropsWeb.Api.V1.IntegrationsControllerTest do
use ToweropsWeb.ConnCase, async: true
import Towerops.AccountsFixtures
import Towerops.IntegrationsFixtures
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 all integrations for authenticated organization", %{
conn: conn,
organization: organization
} do
integration1 = integration_fixture(organization.id, %{provider: "preseem"})
integration2 = integration_fixture(organization.id, %{provider: "gaiia"})
conn = get(conn, ~p"/api/v1/integrations")
assert %{"data" => integrations} = json_response(conn, 200)
assert length(integrations) == 2
ids = Enum.map(integrations, & &1["id"])
assert integration1.id in ids
assert integration2.id in ids
integration_json = List.first(integrations)
assert Map.has_key?(integration_json, "id")
assert Map.has_key?(integration_json, "provider")
assert Map.has_key?(integration_json, "enabled")
assert Map.has_key?(integration_json, "sync_interval_minutes")
assert Map.has_key?(integration_json, "last_synced_at")
assert Map.has_key?(integration_json, "last_sync_status")
assert Map.has_key?(integration_json, "last_sync_message")
assert Map.has_key?(integration_json, "inserted_at")
assert Map.has_key?(integration_json, "updated_at")
end
test "returns empty list when organization has no integrations", %{conn: conn} do
conn = get(conn, ~p"/api/v1/integrations")
assert %{"data" => []} = json_response(conn, 200)
end
test "does not return integrations from other organizations", %{conn: conn} do
other_user = user_fixture()
other_org = organization_fixture(other_user.id)
_other_integration = integration_fixture(other_org.id)
conn = get(conn, ~p"/api/v1/integrations")
assert %{"data" => integrations} = json_response(conn, 200)
assert Enum.empty?(integrations)
end
end
describe "create/2" do
test "creates integration with valid params", %{conn: conn} do
params = %{
"integration" => %{
"provider" => "preseem",
"enabled" => true,
"credentials" => %{"api_key" => "test-key-123"}
}
}
conn = post(conn, ~p"/api/v1/integrations", params)
assert %{"data" => integration} = json_response(conn, 201)
assert integration["provider"] == "preseem"
assert integration["enabled"] == true
assert is_binary(integration["id"])
end
test "returns 400 when integration parameter is missing", %{conn: conn} do
conn = post(conn, ~p"/api/v1/integrations", %{})
assert %{"error" => "Missing 'integration' parameter"} = json_response(conn, 400)
end
end
describe "show/2" do
test "returns integration when it belongs to organization", %{
conn: conn,
organization: organization
} do
integration = integration_fixture(organization.id, %{provider: "preseem"})
conn = get(conn, ~p"/api/v1/integrations/#{integration.id}")
assert %{"data" => data} = json_response(conn, 200)
assert data["id"] == integration.id
assert data["provider"] == "preseem"
assert data["enabled"] == true
end
test "returns 404 when integration belongs to different organization", %{conn: conn} do
other_user = user_fixture()
other_org = organization_fixture(other_user.id)
other_integration = integration_fixture(other_org.id)
conn = get(conn, ~p"/api/v1/integrations/#{other_integration.id}")
assert %{"error" => "Integration not found"} = json_response(conn, 404)
end
test "returns 404 when integration does not exist", %{conn: conn} do
conn = get(conn, ~p"/api/v1/integrations/#{Ecto.UUID.generate()}")
assert %{"error" => "Integration not found"} = json_response(conn, 404)
end
end
describe "update/2" do
test "updates integration with valid attributes", %{
conn: conn,
organization: organization
} do
integration = integration_fixture(organization.id, %{provider: "preseem", enabled: true})
update_params = %{
"integration" => %{
"enabled" => false
}
}
conn = patch(conn, ~p"/api/v1/integrations/#{integration.id}", update_params)
assert %{"data" => data} = json_response(conn, 200)
assert data["id"] == integration.id
assert data["enabled"] == false
end
test "returns 400 when integration parameter is missing", %{
conn: conn,
organization: organization
} do
integration = integration_fixture(organization.id)
conn = patch(conn, ~p"/api/v1/integrations/#{integration.id}", %{})
assert %{"error" => "Missing 'integration' parameter"} = json_response(conn, 400)
end
test "returns 404 when integration belongs to different organization", %{conn: conn} do
other_user = user_fixture()
other_org = organization_fixture(other_user.id)
other_integration = integration_fixture(other_org.id)
update_params = %{
"integration" => %{
"enabled" => false
}
}
conn = patch(conn, ~p"/api/v1/integrations/#{other_integration.id}", update_params)
assert %{"error" => "Integration not found"} = json_response(conn, 404)
end
end
describe "delete/2" do
test "deletes integration successfully", %{conn: conn, organization: organization} do
integration = integration_fixture(organization.id)
conn = delete(conn, ~p"/api/v1/integrations/#{integration.id}")
assert response(conn, 204)
end
test "returns 404 when integration belongs to different organization", %{conn: conn} do
other_user = user_fixture()
other_org = organization_fixture(other_user.id)
other_integration = integration_fixture(other_org.id)
conn = delete(conn, ~p"/api/v1/integrations/#{other_integration.id}")
assert %{"error" => "Integration not found"} = json_response(conn, 404)
end
test "returns 404 when integration does not exist", %{conn: conn} do
conn = delete(conn, ~p"/api/v1/integrations/#{Ecto.UUID.generate()}")
assert %{"error" => "Integration not found"} = json_response(conn, 404)
end
end
describe "test_connection/2" do
test "returns ok status for valid integration", %{
conn: conn,
organization: organization
} do
integration = integration_fixture(organization.id, %{provider: "preseem"})
conn = post(conn, ~p"/api/v1/integrations/#{integration.id}/test")
assert %{"data" => %{"status" => "ok", "provider" => "preseem"}} =
json_response(conn, 200)
end
test "returns 404 when integration belongs to different organization", %{conn: conn} do
other_user = user_fixture()
other_org = organization_fixture(other_user.id)
other_integration = integration_fixture(other_org.id)
conn = post(conn, ~p"/api/v1/integrations/#{other_integration.id}/test")
assert %{"error" => "Integration not found"} = json_response(conn, 404)
end
test "returns 404 when integration does not exist", %{conn: conn} do
conn = post(conn, ~p"/api/v1/integrations/#{Ecto.UUID.generate()}/test")
assert %{"error" => "Integration 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/integrations")
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/integrations")
assert %{"error" => _message} = json_response(conn, 401)
end
end
end