dev vouch dev on at. thats about it atvouch.dev
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

add fake tap server for testing

+205
+6
Makefile
··· 26 26 27 27 lexgen: 28 28 ~/other.git/indigo/lexgen --build-file ./atvouch_lexicons.json ./lexicons 29 + 30 + appview-auth: 31 + cd ./appview/auth && go build -o ./atvouch-auth 32 + 33 + appview: 34 + cd ./appview && mix deps.get && mix compile
+4
appview/mix.exs
··· 6 6 app: :atvouch, 7 7 version: "0.1.0", 8 8 elixir: "~> 1.17", 9 + elixirc_paths: elixirc_paths(Mix.env()), 9 10 start_permanent: Mix.env() == :prod, 10 11 deps: deps() 11 12 ] ··· 17 18 mod: {Atvouch.Application, []} 18 19 ] 19 20 end 21 + 22 + defp elixirc_paths(:test), do: ["lib", "test/support"] 23 + defp elixirc_paths(_), do: ["lib"] 20 24 21 25 defp deps do 22 26 [
+109
appview/test/atvouch/tap/socket_test.exs
··· 1 + defmodule Atvouch.Tap.SocketTest do 2 + use ExUnit.Case 3 + 4 + defmodule TestHandler do 5 + @behaviour Atvouch.Tap.Handler 6 + 7 + @impl true 8 + def handle_record(event) do 9 + send(:tap_socket_test, {:handle_record, event}) 10 + :ok 11 + end 12 + 13 + @impl true 14 + def handle_identity(event) do 15 + send(:tap_socket_test, {:handle_identity, event}) 16 + :ok 17 + end 18 + 19 + @impl true 20 + def handle_connect do 21 + send(:tap_socket_test, :handle_connect) 22 + :ok 23 + end 24 + end 25 + 26 + setup do 27 + Process.register(self(), :tap_socket_test) 28 + {server_pid, port} = Atvouch.Test.FakeTapServer.start(self()) 29 + 30 + on_exit(fn -> 31 + try do 32 + Supervisor.stop(server_pid, :normal, 1_000) 33 + catch 34 + :exit, _ -> :ok 35 + end 36 + end) 37 + 38 + {:ok, port: port} 39 + end 40 + 41 + test "connects and receives record events", %{port: port} do 42 + {:ok, _pid} = 43 + Atvouch.Tap.Socket.start_link( 44 + uri: "ws://localhost:#{port}/channel", 45 + handler: TestHandler, 46 + password: "123", 47 + name: :"tap_test_#{port}" 48 + ) 49 + 50 + assert_receive :handle_connect, 5_000 51 + assert_receive {:ws_connected, ws_pid}, 5_000 52 + 53 + Atvouch.Test.FakeTapServer.send_event(ws_pid, %{ 54 + "id" => 1, 55 + "type" => "record", 56 + "record" => %{ 57 + "did" => "did:plc:abc", 58 + "rev" => "rev1", 59 + "collection" => "dev.atvouch.vouch", 60 + "rkey" => "self", 61 + "action" => "create", 62 + "live" => true 63 + } 64 + }) 65 + 66 + assert_receive {:handle_record, event}, 5_000 67 + assert event.id == 1 68 + assert event.action == :create 69 + assert event.did == "did:plc:abc" 70 + assert event.collection == "dev.atvouch.vouch" 71 + assert event.live == true 72 + 73 + # auto-ack 74 + assert_receive {:ws_message, %{"type" => "ack", "id" => 1}}, 5_000 75 + end 76 + 77 + test "connects and receives identity events", %{port: port} do 78 + {:ok, _pid} = 79 + Atvouch.Tap.Socket.start_link( 80 + uri: "ws://localhost:#{port}/channel", 81 + handler: TestHandler, 82 + password: "123", 83 + name: :"tap_test_identity_#{port}" 84 + ) 85 + 86 + assert_receive :handle_connect, 5_000 87 + assert_receive {:ws_connected, ws_pid}, 5_000 88 + 89 + Atvouch.Test.FakeTapServer.send_event(ws_pid, %{ 90 + "id" => 2, 91 + "type" => "identity", 92 + "identity" => %{ 93 + "did" => "did:plc:xyz", 94 + "handle" => "test.bsky.social", 95 + "is_active" => true, 96 + "status" => "active" 97 + } 98 + }) 99 + 100 + assert_receive {:handle_identity, event}, 5_000 101 + assert event.id == 2 102 + assert event.did == "did:plc:xyz" 103 + assert event.handle == "test.bsky.social" 104 + assert event.is_active == true 105 + assert event.status == "active" 106 + 107 + assert_receive {:ws_message, %{"type" => "ack", "id" => 2}}, 5_000 108 + end 109 + end
+86
appview/test/support/fake_tap_server.ex
··· 1 + defmodule Atvouch.Test.FakeTapServer do 2 + @moduledoc false 3 + 4 + defmodule WebSocketHandler do 5 + @behaviour WebSock 6 + 7 + @impl true 8 + def init(state) do 9 + send(state.test_pid, {:ws_connected, self()}) 10 + {:ok, state} 11 + end 12 + 13 + @impl true 14 + def handle_in({text, opcode: :text}, state) do 15 + case Jason.decode(text) do 16 + {:ok, msg} -> 17 + send(state.test_pid, {:ws_message, msg}) 18 + 19 + _ -> 20 + :ok 21 + end 22 + 23 + {:ok, state} 24 + end 25 + 26 + @impl true 27 + def handle_info({:send_event, event}, state) do 28 + {:push, {:text, Jason.encode!(event)}, state} 29 + end 30 + 31 + def handle_info(_msg, state) do 32 + {:ok, state} 33 + end 34 + 35 + @impl true 36 + def terminate(_reason, _state) do 37 + :ok 38 + end 39 + end 40 + 41 + defmodule Router do 42 + use Plug.Router 43 + 44 + plug(:match) 45 + plug(:dispatch) 46 + 47 + get "/channel" do 48 + test_pid = conn.private[:test_pid] 49 + 50 + conn 51 + |> upgrade_adapter(:websocket, {WebSocketHandler, %{test_pid: test_pid}, []}) 52 + end 53 + 54 + match _ do 55 + send_resp(conn, 404, "not found") 56 + end 57 + end 58 + 59 + defmodule PlugWithPid do 60 + @behaviour Plug 61 + 62 + def init(opts), do: opts 63 + 64 + def call(conn, opts) do 65 + conn 66 + |> Plug.Conn.put_private(:test_pid, opts[:test_pid]) 67 + |> Router.call(Router.init([])) 68 + end 69 + end 70 + 71 + def start(test_pid) do 72 + {:ok, server_pid} = 73 + Bandit.start_link( 74 + plug: {PlugWithPid, test_pid: test_pid}, 75 + port: 0, 76 + ip: {127, 0, 0, 1} 77 + ) 78 + 79 + {:ok, {_ip, port}} = ThousandIsland.listener_info(server_pid) 80 + {server_pid, port} 81 + end 82 + 83 + def send_event(ws_pid, event) do 84 + send(ws_pid, {:send_event, event}) 85 + end 86 + end