From 9bdbcfe8ff227c2edd0be0831b0680766bdecdb2 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 22 Mar 2026 17:35:58 -0300 Subject: [PATCH] add fake slingshot server to tests --- appview/lib/atvouch/slingshot.ex | 8 ++- appview/test/atvouch/pull_handler_test.exs | 26 +++++++- appview/test/support/fake_slingshot_server.ex | 64 +++++++++++++++++++ 3 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 appview/test/support/fake_slingshot_server.ex diff --git a/appview/lib/atvouch/slingshot.ex b/appview/lib/atvouch/slingshot.ex index 25e5ef3..8509605 100644 --- a/appview/lib/atvouch/slingshot.ex +++ b/appview/lib/atvouch/slingshot.ex @@ -5,14 +5,18 @@ defmodule Atvouch.Slingshot do require Logger - @slingshot_url "https://slingshot.microcosm.blue" + @default_url "https://slingshot.microcosm.blue" + + defp slingshot_url do + Application.get_env(:atvouch, :slingshot_url, @default_url) + end @doc """ Resolve a single DID to a handle via slingshot. Returns `{:ok, handle}` or `:error`. """ def resolve_did(did) do - url = "#{@slingshot_url}/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=#{URI.encode_www_form(did)}" + url = "#{slingshot_url()}/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=#{URI.encode_www_form(did)}" request = %Tesla.Env{ method: :get, diff --git a/appview/test/atvouch/pull_handler_test.exs b/appview/test/atvouch/pull_handler_test.exs index af74f0e..7e63f55 100644 --- a/appview/test/atvouch/pull_handler_test.exs +++ b/appview/test/atvouch/pull_handler_test.exs @@ -48,13 +48,33 @@ defmodule Atvouch.PullHandlerTest do bot_password: "test-password" ) + # Start fake slingshot server with test identities + {slingshot_pid, slingshot_port, _slingshot_agent} = + Atvouch.Test.FakeSlingshotServer.start(%{ + "did:plc:maintainer1" => "maintainer1.test", + "did:plc:maintainer2" => "maintainer2.test", + "did:plc:author" => "author.test", + "did:plc:middle" => "middle.test", + "did:plc:repoowner" => "repoowner.test", + "did:plc:repoowner2" => "repoowner2.test" + }) + + prev_slingshot_url = Application.get_env(:atvouch, :slingshot_url) + Application.put_env(:atvouch, :slingshot_url, "http://127.0.0.1:#{slingshot_port}") + # Start fake TAP server {tap_pid, tap_port} = Atvouch.Test.FakeTapServer.start(self()) on_exit(fn -> Application.put_env(:atvouch, :tangled, prev_tangled) - for pid <- [pds_pid, tangled_pid, tap_pid] do + if prev_slingshot_url do + Application.put_env(:atvouch, :slingshot_url, prev_slingshot_url) + else + Application.delete_env(:atvouch, :slingshot_url) + end + + for pid <- [pds_pid, tangled_pid, tap_pid, slingshot_pid] do try do Supervisor.stop(pid, :normal, 1_000) catch @@ -216,10 +236,10 @@ defmodule Atvouch.PullHandlerTest do assert comment.handle == "repoowner.test" assert comment.rkey == "testrepo" assert comment.number == 1 - assert comment.body =~ "atvouch routes for [@author.test](https://bsky.app/profile/did:plc:author)" assert comment.body =~ "[@maintainer1.test](https://bsky.app/profile/did:plc:maintainer1)" - assert comment.body =~ "direct vouch" assert comment.body =~ "[@maintainer2.test](https://bsky.app/profile/did:plc:maintainer2)" + assert comment.body =~ "[@author.test](https://bsky.app/profile/did:plc:author)" + assert comment.body =~ "generated by [atvouch](https://atvouch.dev)" # Verify dedup record was created assert Atvouch.BotComment.exists?(repo_at_uri, 1) diff --git a/appview/test/support/fake_slingshot_server.ex b/appview/test/support/fake_slingshot_server.ex new file mode 100644 index 0000000..fbd4533 --- /dev/null +++ b/appview/test/support/fake_slingshot_server.ex @@ -0,0 +1,64 @@ +defmodule Atvouch.Test.FakeSlingshotServer do + @moduledoc """ + Fake slingshot identity service for testing DID-to-handle resolution. + """ + + defmodule Router do + use Plug.Router + + plug(:match) + plug(:dispatch) + + get "/xrpc/com.bad-example.identity.resolveMiniDoc" do + conn = Plug.Conn.fetch_query_params(conn) + did = conn.query_params["identifier"] + identities = conn.private[:identities] + + case Map.get(identities, did) do + nil -> + conn + |> put_resp_content_type("application/json") + |> send_resp(404, Jason.encode!(%{"error" => "not_found"})) + + handle -> + conn + |> put_resp_content_type("application/json") + |> send_resp(200, Jason.encode!(%{"handle" => handle})) + end + end + + match _ do + send_resp(conn, 404, "not found") + end + end + + defmodule PlugWithState do + @behaviour Plug + + def init(opts), do: opts + + def call(conn, opts) do + conn + |> Plug.Conn.put_private(:identities, Agent.get(opts[:state_agent], & &1)) + |> Router.call(Router.init([])) + end + end + + def start(identities \\ %{}) do + {:ok, state_agent} = Agent.start_link(fn -> identities end) + + {:ok, server_pid} = + Bandit.start_link( + plug: {PlugWithState, state_agent: state_agent}, + port: 0, + ip: {127, 0, 0, 1} + ) + + {:ok, {_ip, port}} = ThousandIsland.listener_info(server_pid) + {server_pid, port, state_agent} + end + + def set_identities(state_agent, identities) do + Agent.update(state_agent, fn _ -> identities end) + end +end -- 2.51.2