Files
n8n-openai-adapter/test/router_test.exs
T
hermes-agent 72e18a0a0c Remove AGENTS env seeding; agents managed only via admin API
The store now starts empty and agents are added/removed exclusively through
the web admin page / admin API, persisted to AGENTS_FILE. No AGENTS env var
needed in the sops secret.
2026-09-10 07:06:26 +00:00

175 lines
4.9 KiB
Elixir

defmodule N8nOpenaiAdapter.RouterTest do
use ExUnit.Case, async: false
import Plug.Test
import Plug.Conn
alias N8nOpenaiAdapter.AgentRegistry
alias N8nOpenaiAdapter.Router
setup do
# The app starts with an empty store (no AGENTS env seeding). Seed the two
# test agents via the registry so the base tests have something to list.
AgentRegistry.put("scholar-agent", "https://n8n.bueso.eu/webhook/scholar-id/chat")
AgentRegistry.put("media-agent", "https://n8n.bueso.eu/webhook/media-id/chat")
:ok
end
test "GET /v1/models lists configured agents" do
conn =
conn(:get, "/v1/models")
|> put_req_header("authorization", "Bearer test-key")
|> Router.call(Router.init([]))
assert conn.status == 200
body = Jason.decode!(conn.resp_body)
assert body["object"] == "list"
ids = Enum.map(body["data"], & &1["id"])
assert "scholar-agent" in ids
assert "media-agent" in ids
end
test "GET /v1/models rejects a bad API key" do
conn =
conn(:get, "/v1/models")
|> put_req_header("authorization", "Bearer wrong")
|> Router.call(Router.init([]))
assert conn.status == 401
end
test "POST /v1/chat/completions with unknown model returns 400" do
conn =
conn(
:post,
"/v1/chat/completions",
Jason.encode!(%{
"model" => "nope",
"messages" => [%{"role" => "user", "content" => "hi"}]
})
)
|> put_req_header("authorization", "Bearer test-key")
|> put_req_header("content-type", "application/json")
|> Router.call(Router.init([]))
assert conn.status == 400
assert Jason.decode!(conn.resp_body)["error"]["message"] == "Unknown model: nope"
end
test "POST /v1/chat/completions without a user message returns 400" do
conn =
conn(
:post,
"/v1/chat/completions",
Jason.encode!(%{
"model" => "scholar-agent",
"messages" => [%{"role" => "assistant", "content" => "hi"}]
})
)
|> put_req_header("authorization", "Bearer test-key")
|> put_req_header("content-type", "application/json")
|> Router.call(Router.init([]))
assert conn.status == 400
end
test "GET /admin serves the web admin page (admin key)" do
conn =
conn(:get, "/admin")
|> put_req_header("authorization", "Bearer test-admin-key")
|> Router.call(Router.init([]))
assert conn.status == 200
assert conn.resp_body =~ "n8n OpenAI Adapter"
assert conn.resp_body =~ "admin/agents"
end
test "GET /admin rejects a non-admin key" do
conn =
conn(:get, "/admin")
|> put_req_header("authorization", "Bearer test-key")
|> Router.call(Router.init([]))
assert conn.status == 401
end
# --- Admin API ---
test "GET /admin/agents lists agents (admin key)" do
conn =
conn(:get, "/admin/agents")
|> put_req_header("authorization", "Bearer test-admin-key")
|> Router.call(Router.init([]))
assert conn.status == 200
body = Jason.decode!(conn.resp_body)
assert Map.has_key?(body["agents"], "scholar-agent")
end
test "GET /admin/agents rejects a non-admin key" do
conn =
conn(:get, "/admin/agents")
|> put_req_header("authorization", "Bearer test-key")
|> Router.call(Router.init([]))
assert conn.status == 401
end
test "POST /admin/agents adds an agent" do
conn =
conn(
:post,
"/admin/agents",
Jason.encode!(%{
"model" => "new-agent",
"webhook" => "https://n8n.bueso.eu/webhook/new/chat"
})
)
|> put_req_header("authorization", "Bearer test-admin-key")
|> put_req_header("content-type", "application/json")
|> Router.call(Router.init([]))
assert conn.status == 200
assert Jason.decode!(conn.resp_body)["ok"] == true
# now visible in /v1/models
conn2 =
conn(:get, "/v1/models")
|> put_req_header("authorization", "Bearer test-key")
|> Router.call(Router.init([]))
ids = Enum.map(Jason.decode!(conn2.resp_body)["data"], & &1["id"])
assert "new-agent" in ids
end
test "DELETE /admin/agents removes an agent" do
# add then delete
conn =
conn(
:post,
"/admin/agents",
Jason.encode!(%{
"model" => "temp-agent",
"webhook" => "https://n8n.bueso.eu/webhook/temp/chat"
})
)
|> put_req_header("authorization", "Bearer test-admin-key")
|> put_req_header("content-type", "application/json")
|> Router.call(Router.init([]))
assert conn.status == 200
conn2 =
conn(:delete, "/admin/agents/temp-agent")
|> put_req_header("authorization", "Bearer test-admin-key")
|> Router.call(Router.init([]))
assert conn2.status == 200
conn3 =
conn(:delete, "/admin/agents/temp-agent")
|> put_req_header("authorization", "Bearer test-admin-key")
|> Router.call(Router.init([]))
assert conn3.status == 404
end
end