towerops/test/towerops_web/controllers/api/v1/integrations_controller_test.exs
2026-06-16 09:56:51 -05:00

262 lines
8.4 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"]) and byte_size(integration["id"]) > 0
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