Files
self c20a3b4f71 feat: prefix Supertest plugin slug
Rename the Supertest fixture plugin to tribe-one-supertest across manifest, runtime API routes, metrics, e2e fixtures, and tests.
2026-06-17 22:33:39 +02:00

230 lines
7.4 KiB
Elixir

defmodule TribeOne.TribesPlugin.Supertest.APITest do
use ExUnit.Case, async: false
setup tags do
tribes_owner = Ecto.Adapters.SQL.Sandbox.start_owner!(Tribes.Repo, shared: not tags[:async])
parrhesia_owner =
Ecto.Adapters.SQL.Sandbox.start_owner!(Parrhesia.Repo, shared: not tags[:async])
on_exit(fn ->
Ecto.Adapters.SQL.Sandbox.stop_owner(parrhesia_owner)
Ecto.Adapters.SQL.Sandbox.stop_owner(tribes_owner)
end)
:ok
end
test "reports health and schema state" do
assert {:ok, %{ok: true, plugin: "tribe-one-supertest"}} =
TribeOne.TribesPlugin.Supertest.API.health()
assert {:ok, %{ok: true, schema: %{tables: %{cases: true, events: true}}}} =
TribeOne.TribesPlugin.Supertest.API.schema()
end
test "creates linked Ash resources and lists state by run" do
run_id = "api-test-#{System.unique_integer([:positive])}"
assert {:ok, %{ok: true, case: test_case}} =
TribeOne.TribesPlugin.Supertest.API.create_case(%{
"run_id" => run_id,
"name" => "primary",
"payload" => %{"source" => "api-test"}
})
assert test_case.counter == 0
assert test_case.payload == %{"source" => "api-test"}
assert {:ok, %{ok: true, event: event}} =
TribeOne.TribesPlugin.Supertest.API.create_event(%{
"case_id" => test_case.id,
"run_id" => run_id,
"sequence" => 1,
"body" => "created",
"payload" => %{"case" => test_case.name}
})
assert event.case_id == test_case.id
assert {:ok, %{ok: true, case: incremented}} =
TribeOne.TribesPlugin.Supertest.API.increment_case(%{
"id" => test_case.id,
"delta" => 3
})
assert incremented.counter == 3
assert {:ok, %{ok: true, cases: [listed_case], events: [listed_event]}} =
TribeOne.TribesPlugin.Supertest.API.state(%{"run_id" => run_id})
assert listed_case.id == test_case.id
assert listed_case.counter == 3
assert listed_event.id == event.id
end
test "reset soft-deletes state for one run" do
run_id = "reset-test-#{System.unique_integer([:positive])}"
assert {:ok, %{case: test_case}} =
TribeOne.TribesPlugin.Supertest.API.create_case(%{
"run_id" => run_id,
"name" => "reset"
})
assert {:ok, %{event: _event}} =
TribeOne.TribesPlugin.Supertest.API.create_event(%{
"case_id" => test_case.id,
"run_id" => run_id,
"sequence" => 1,
"body" => "before reset"
})
assert {:ok, %{ok: true, deleted: %{cases: 1, events: 1}}} =
TribeOne.TribesPlugin.Supertest.API.reset(%{"run_id" => run_id})
assert {:ok, %{ok: true, cases: [], events: []}} =
TribeOne.TribesPlugin.Supertest.API.state(%{"run_id" => run_id})
end
test "broadcasts and records cluster pubsub probe messages" do
pubsub = :"supertest_cluster_pubsub_#{System.unique_integer([:positive])}"
start_supervised!({Phoenix.PubSub, name: pubsub})
start_supervised!({TribeOne.TribesPlugin.Supertest.ClusterPubSubProbe, pubsub: pubsub})
run_id = "cluster-pubsub-test-#{System.unique_integer([:positive])}"
assert {:ok, %{ok: true, message: message}} =
TribeOne.TribesPlugin.Supertest.API.broadcast_cluster_pubsub(%{
"run_id" => run_id,
"payload" => %{"phase" => "api-test"}
})
assert message.run_id == run_id
assert message.payload == %{"phase" => "api-test"}
eventually(fn ->
assert {:ok, %{ok: true, messages: [received]}} =
TribeOne.TribesPlugin.Supertest.API.received_cluster_pubsub(%{"run_id" => run_id})
assert received.id == message.id
assert received.payload == %{"phase" => "api-test"}
end)
assert {:ok, %{ok: true}} =
TribeOne.TribesPlugin.Supertest.API.reset_cluster_pubsub(%{"run_id" => run_id})
assert {:ok, %{ok: true, messages: []}} =
TribeOne.TribesPlugin.Supertest.API.received_cluster_pubsub(%{"run_id" => run_id})
end
test "echoes plugin management context" do
context = %Tribes.Plugin.ManagementContext{
plugin: "tribe-one-supertest",
method: "supertest.echo",
version: "1",
actor_pubkey: String.duplicate("a", 64),
admin?: true
}
assert {:ok,
%{
ok: true,
plugin: "tribe-one-supertest",
method: "supertest.echo",
version: "1",
admin: true,
actor_pubkey: actor_pubkey,
params: %{"probe" => true}
}} = TribeOne.TribesPlugin.Supertest.API.management_echo(context, %{"probe" => true})
assert actor_pubkey == String.duplicate("a", 64)
end
test "records scheduler probe executions" do
run_id = "scheduler-test-#{System.unique_integer([:positive])}"
assert {:ok, %{ok: true, control: control}} =
TribeOne.TribesPlugin.Supertest.API.start_scheduler_probe(%{
"run_id" => run_id,
"expected_nodes" => 2
})
assert control.name == "scheduler:control"
assert control.status == "active"
assert :ok =
TribeOne.TribesPlugin.Supertest.Scheduler.SingletonCounterWorker.perform(
scheduler_job("node-a")
)
assert :ok =
TribeOne.TribesPlugin.Supertest.Scheduler.AllNodesCounterWorker.perform(
scheduler_job("node-a")
)
assert :ok =
TribeOne.TribesPlugin.Supertest.Scheduler.AllNodesCounterWorker.perform(
scheduler_job("node-b")
)
assert {:ok,
%{
ok: true,
expected_nodes: 2,
passed?: true,
singleton: %{counter: 1, node_ids: ["node-a"]},
all_nodes: %{counter: 2, node_ids: ["node-a", "node-b"]}
}} = TribeOne.TribesPlugin.Supertest.API.scheduler_probe(%{"run_id" => run_id})
assert {:ok, %{ok: true, stopped: true}} =
TribeOne.TribesPlugin.Supertest.API.stop_scheduler_probe(%{"run_id" => run_id})
end
test "emits metrics probe telemetry" do
ref = make_ref()
:telemetry.attach(
"supertest-api-metrics-probe-test",
[:supertest, :metrics, :probe],
fn _event, measurements, metadata, pid ->
send(pid, {ref, measurements, metadata})
end,
self()
)
on_exit(fn -> :telemetry.detach("supertest-api-metrics-probe-test") end)
assert {:ok, %{ok: true, value: 41}} =
TribeOne.TribesPlugin.Supertest.API.emit_metrics_probe(%{"value" => 41})
assert_receive {^ref, %{value: 41}, %{}}
end
defp scheduler_job(node_id) do
%Tribes.Plugin.Scheduler.Job{
id: "job-#{node_id}",
plugin: "tribe-one-supertest",
cron_id: "plugin:tribe-one-supertest:scheduler",
scheduled_at: ~U[2026-05-28 12:00:00Z],
attempt_id: "attempt-#{node_id}",
attempt_token: "token-#{node_id}",
node_id: node_id,
payload: %{},
requirements: %{}
}
end
defp eventually(assertion, attempts \\ 20)
defp eventually(assertion, attempts) when attempts > 0 do
assertion.()
rescue
_error in [ExUnit.AssertionError] ->
Process.sleep(10)
eventually(assertion, attempts - 1)
end
defp eventually(assertion, 0), do: assertion.()
end