phase1: add websocket edge and nostr message codec
This commit is contained in:
@@ -11,5 +11,10 @@ defmodule Parrhesia.ApplicationTest do
|
||||
assert is_pid(Process.whereis(Parrhesia.Policy.Supervisor))
|
||||
assert is_pid(Process.whereis(Parrhesia.Web.Endpoint))
|
||||
assert is_pid(Process.whereis(Parrhesia.Tasks.Supervisor))
|
||||
|
||||
assert Enum.any?(Supervisor.which_children(Parrhesia.Web.Endpoint), fn {_id, pid, _type,
|
||||
modules} ->
|
||||
is_pid(pid) and modules == [Bandit]
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
48
test/parrhesia/protocol_test.exs
Normal file
48
test/parrhesia/protocol_test.exs
Normal file
@@ -0,0 +1,48 @@
|
||||
defmodule Parrhesia.ProtocolTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Parrhesia.Protocol
|
||||
|
||||
test "decodes valid EVENT frame" do
|
||||
payload =
|
||||
Jason.encode!([
|
||||
"EVENT",
|
||||
%{
|
||||
"id" => String.duplicate("0", 64),
|
||||
"pubkey" => String.duplicate("1", 64),
|
||||
"created_at" => 1_715_000_000,
|
||||
"kind" => 1,
|
||||
"tags" => [["p", String.duplicate("2", 64)]],
|
||||
"content" => "hello",
|
||||
"sig" => String.duplicate("3", 128)
|
||||
}
|
||||
])
|
||||
|
||||
assert {:ok, {:event, event}} = Protocol.decode_client(payload)
|
||||
assert event["kind"] == 1
|
||||
assert event["content"] == "hello"
|
||||
end
|
||||
|
||||
test "decodes valid REQ and CLOSE frames" do
|
||||
req_payload = Jason.encode!(["REQ", "sub-1", %{"authors" => [String.duplicate("a", 64)]}])
|
||||
close_payload = Jason.encode!(["CLOSE", "sub-1"])
|
||||
|
||||
assert {:ok, {:req, "sub-1", [%{"authors" => [_author]}]}} =
|
||||
Protocol.decode_client(req_payload)
|
||||
|
||||
assert {:ok, {:close, "sub-1"}} = Protocol.decode_client(close_payload)
|
||||
end
|
||||
|
||||
test "returns decode errors for malformed messages" do
|
||||
assert {:error, :invalid_json} = Protocol.decode_client("not-json")
|
||||
assert {:error, :invalid_filters} = Protocol.decode_client(Jason.encode!(["REQ", "sub-1"]))
|
||||
|
||||
assert {:error, :invalid_event} =
|
||||
Protocol.decode_client(Jason.encode!(["EVENT", %{"id" => "nope"}]))
|
||||
end
|
||||
|
||||
test "encodes relay messages" do
|
||||
frame = Protocol.encode_relay({:closed, "sub-1", "closed: subscription closed"})
|
||||
assert Jason.decode!(frame) == ["CLOSED", "sub-1", "closed: subscription closed"]
|
||||
end
|
||||
end
|
||||
69
test/parrhesia/web/connection_test.exs
Normal file
69
test/parrhesia/web/connection_test.exs
Normal file
@@ -0,0 +1,69 @@
|
||||
defmodule Parrhesia.Web.ConnectionTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Parrhesia.Web.Connection
|
||||
|
||||
test "REQ registers subscription and replies with EOSE" do
|
||||
{:ok, state} = Connection.init(%{})
|
||||
|
||||
req_payload = Jason.encode!(["REQ", "sub-123", %{"kinds" => [1]}])
|
||||
|
||||
assert {:push, {:text, response}, next_state} =
|
||||
Connection.handle_in({req_payload, [opcode: :text]}, state)
|
||||
|
||||
assert MapSet.member?(next_state.subscriptions, "sub-123")
|
||||
assert Jason.decode!(response) == ["EOSE", "sub-123"]
|
||||
end
|
||||
|
||||
test "CLOSE removes subscription and replies with CLOSED" do
|
||||
{:ok, state} = Connection.init(%{})
|
||||
|
||||
req_payload = Jason.encode!(["REQ", "sub-123", %{"kinds" => [1]}])
|
||||
{:push, _, subscribed_state} = Connection.handle_in({req_payload, [opcode: :text]}, state)
|
||||
|
||||
close_payload = Jason.encode!(["CLOSE", "sub-123"])
|
||||
|
||||
assert {:push, {:text, response}, next_state} =
|
||||
Connection.handle_in({close_payload, [opcode: :text]}, subscribed_state)
|
||||
|
||||
refute MapSet.member?(next_state.subscriptions, "sub-123")
|
||||
assert Jason.decode!(response) == ["CLOSED", "sub-123", "closed: subscription closed"]
|
||||
end
|
||||
|
||||
test "invalid input returns NOTICE" do
|
||||
{:ok, state} = Connection.init(%{})
|
||||
|
||||
assert {:push, {:text, response}, ^state} =
|
||||
Connection.handle_in({"not-json", [opcode: :text]}, state)
|
||||
|
||||
assert Jason.decode!(response) == ["NOTICE", "error:invalid: malformed JSON"]
|
||||
end
|
||||
|
||||
test "EVENT currently replies with unsupported OK" do
|
||||
{:ok, state} = Connection.init(%{})
|
||||
|
||||
payload =
|
||||
Jason.encode!([
|
||||
"EVENT",
|
||||
%{
|
||||
"id" => String.duplicate("0", 64),
|
||||
"pubkey" => String.duplicate("1", 64),
|
||||
"created_at" => 1_715_000_000,
|
||||
"kind" => 1,
|
||||
"tags" => [],
|
||||
"content" => "hello",
|
||||
"sig" => String.duplicate("3", 128)
|
||||
}
|
||||
])
|
||||
|
||||
assert {:push, {:text, response}, ^state} =
|
||||
Connection.handle_in({payload, [opcode: :text]}, state)
|
||||
|
||||
assert Jason.decode!(response) == [
|
||||
"OK",
|
||||
String.duplicate("0", 64),
|
||||
false,
|
||||
"error:unsupported: EVENT ingest not implemented"
|
||||
]
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user