You've already forked tribes-plugin-supertest
forked from tribes/tribes-plugin-template
c20a3b4f71
Rename the Supertest fixture plugin to tribe-one-supertest across manifest, runtime API routes, metrics, e2e fixtures, and tests.
230 lines
7.4 KiB
Elixir
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
|