Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
12 kB · 342 lines
Elixir
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343defmodule GitSyncWeb.ConnectionControllerTest do use GitSyncWeb.ConnCase
alias GitSync.Connections alias GitSync.Forge.Token alias GitSync.KnotServer
setup :configure_forgejo
setup %{conn: conn, connection: connection} do {:ok, _connection} = GitSync.Connections.record_login(connection, "alice", Token.new("tok", nil, nil))
%{conn: init_test_session(conn, %{"operator" => "alice"})} end
test "shows the instance and how healthy it is, not its repositories", %{conn: conn} do Req.Test.stub(GitSync.Http, fn req_conn -> Req.Test.json(req_conn, [ %{ "full_name" => "alice/git-sync", "clone_url" => "https://forge.test/alice/git-sync.git", "private" => false } ]) end)
html = html_response(get(conn, ~p"/connections"), 200)
assert html =~ "https://forge.test" assert html =~ "Healthy" refute html =~ "alice/git-sync" end
test "reports why an instance is unhealthy", %{conn: conn} do Req.Test.stub(GitSync.Http, &Plug.Conn.send_resp(&1, 401, ""))
assert html_response(get(conn, ~p"/connections"), 200) =~ "Unreachable" end
describe "github" do test "offers the application form when no credentials are stored", %{conn: conn} do Req.Test.stub(GitSync.Http, &Plug.Conn.send_resp(&1, 401, ""))
html = html_response(get(conn, ~p"/connections"), 200)
assert html =~ "github-form" assert html =~ ~s(data-signals="{githubForm: true}") end
test "hides the form behind a button once credentials are stored", %{conn: conn} do Req.Test.stub(GitSync.Http, &Plug.Conn.send_resp(&1, 401, ""))
post(conn, ~p"/connections/github", %{ "connection" => %{"client_id" => "id-123", "client_secret" => "secret-456"} })
html = html_response(get(conn, ~p"/connections"), 200)
assert html =~ ~s(id="edit-github") assert html =~ ~s|data-on:click="$githubForm = !$githubForm"| assert html =~ ~s(data-signals="{githubForm: false}") assert html =~ "id-123" refute html =~ "secret-456" assert closed?(html, "github-application") end end
describe "pushin" do setup do Req.Test.stub(GitSync.Http, &Req.Test.json(&1, %{"login" => "alice", "id" => "user-1"})) :ok end
test "saves a PAT without asking for an account and never renders it", %{conn: conn} do saved = post(conn, ~p"/connections/pushin", %{ "connection" => %{"token" => "pushin-secret"} })
assert redirected_to(saved) == ~p"/connections" assert Connections.pushin().token == "pushin-secret"
html = html_response(get(conn, ~p"/connections"), 200) assert html =~ "Pushin.eu" assert html =~ ~s(id="disconnect-pushin") assert html =~ ~s(id="edit-pushin") refute html =~ "pushin-secret" assert html =~ ~s(type="password" name="connection[token]") end
test "rejects a blank replacement without exposing or clearing the saved PAT", %{conn: conn} do {:ok, pushin} = Connections.configure_pushin(%{"token" => "saved-pushin-secret"})
rejected = post(conn, ~p"/connections/pushin", %{"connection" => %{"token" => ""}}) html = html_response(rejected, 200)
assert html =~ "can't be blank" refute html =~ "saved-pushin-secret" assert Connections.pushin().token == pushin.token assert html =~ ~s(data-signals="{pushinForm: true}") end
test "replaces the PAT on the same connection", %{conn: conn} do {:ok, pushin} = Connections.configure_pushin(%{"token" => "old-pushin-secret"})
saved = post(conn, ~p"/connections/pushin", %{ "connection" => %{"token" => "replacement-pushin-secret"} })
assert redirected_to(saved) == ~p"/connections" assert Connections.pushin().id == pushin.id assert Connections.pushin().token == "replacement-pushin-secret"
html = html_response(get(conn, ~p"/connections"), 200) refute html =~ "old-pushin-secret" refute html =~ "replacement-pushin-secret" end
test "disconnects without deleting the connection and offers a new token", %{conn: conn} do {:ok, pushin} = Connections.configure_pushin(%{"token" => "pushin-secret"})
disconnected = delete(conn, ~p"/connections/pushin") assert redirected_to(disconnected) == ~p"/connections" assert Connections.pushin().id == pushin.id assert Connections.pushin().token == nil
html = html_response(get(conn, ~p"/connections"), 200) refute html =~ ~s(id="disconnect-pushin") assert html =~ ~s(data-health="disconnected") assert html =~ ~s(data-signals="{pushinForm: true}") end
test "requires an authenticated operator to save or disconnect", %{conn: conn} do anonymous = clear_session(conn)
rejected = post(anonymous, ~p"/connections/pushin", %{ "connection" => %{"token" => "pushin-secret"} })
assert redirected_to(rejected) == ~p"/login" assert Connections.pushin() == nil
{:ok, pushin} = Connections.configure_pushin(%{"token" => "pushin-secret"}) assert redirected_to(delete(anonymous, ~p"/connections/pushin")) == ~p"/login" assert Connections.pushin().token == pushin.token end end
describe "tangled" do setup %{conn: conn} do Req.Test.stub(GitSync.Http, &Plug.Conn.send_resp(&1, 401, ""))
%{conn: conn} end
test "offers a form for the account and nothing to paste", %{conn: conn} do html = html_response(get(conn, ~p"/connections"), 200)
assert html =~ "tangled-form" assert html =~ "connection[handle]" refute html =~ "connection[ssh_key]" assert html =~ ~s(data-signals="{tangledForm: true}") end
test "saving an account resolves it and reports its health", %{conn: conn} do stub_tangled()
saved = post(conn, ~p"/connections/tangled", %{"connection" => %{"handle" => "oppi.li"}})
assert redirected_to(saved) == ~p"/connections" assert Connections.tangled().did == "did:plc:abc"
html = html_response(get(conn, ~p"/connections"), 200)
assert html =~ "oppi.li" assert html =~ "Healthy" refute html =~ "knot1.tangled.sh/oppi.li/git-sync" end
test "hides the account form behind a button once an account is saved", %{conn: conn} do stub_tangled() post(conn, ~p"/connections/tangled", %{"connection" => %{"handle" => "oppi.li"}})
html = html_response(get(conn, ~p"/connections"), 200)
assert html =~ ~s(id="edit-tangled") assert html =~ ~s|data-on:click="$tangledForm = !$tangledForm"| assert html =~ ~s(data-signals="{tangledForm: false}") assert closed?(html, "tangled-account") end
test "an account already saved can be resolved again from its own form", %{conn: conn} do stub_tangled() post(conn, ~p"/connections/tangled", %{"connection" => %{"handle" => "oppi.li"}})
html = html_response(get(conn, ~p"/connections"), 200) form = html |> String.split(~s(id="tangled-form")) |> Enum.at(1)
refute form =~ ~s(name="_method")
again = post(conn, ~p"/connections/tangled", %{"connection" => %{"handle" => "oppi.li"}})
assert redirected_to(again) == ~p"/connections" end
test "an account that cannot be resolved re-renders the page", %{conn: conn} do conn = post(conn, ~p"/connections/tangled", %{"connection" => %{"handle" => "nobody"}})
assert html_response(conn, 200) =~ "No account could be found for nobody" refute Connections.tangled() end
test "reports when the account is unhealthy", %{conn: conn} do stub_tangled() post(conn, ~p"/connections/tangled", %{"connection" => %{"handle" => "oppi.li"}})
Req.Test.stub(GitSync.Http, &Plug.Conn.send_resp(&1, 502, ""))
assert html_response(get(conn, ~p"/connections"), 200) =~ "Unreachable" end
test "shows the fingerprints of the knots it has pinned", %{conn: conn} do stub_tangled() post(conn, ~p"/connections/tangled", %{"connection" => %{"handle" => "oppi.li"}})
GitSync.Repo.insert!(%GitSync.Knot{ connection_id: Connections.tangled().id, host: "knot1.tangled.sh", ssh_host: "tangled.org", host_key: "knot1.tangled.sh ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexample" })
html = html_response(get(conn, ~p"/connections"), 200)
assert html =~ "knot1.tangled.sh" assert html =~ "tangled.org" assert html =~ ~s(id="add-knot") assert html =~ ~s|data-on:click="$knotForm = !$knotForm"| assert closed?(html, "knot-pin") end
test "pinning a knot scans the endpoint the operator gives for it", %{conn: conn} do stub_tangled() post(conn, ~p"/connections/tangled", %{"connection" => %{"handle" => "oppi.li"}})
%{public: public} = KnotServer.serve()
pinned = post(conn, ~p"/connections/tangled/knots", %{ "knot" => %{"host" => "knot1.tangled.sh", "ssh_host" => "127.0.0.1"} })
assert redirected_to(pinned) == ~p"/connections"
html = html_response(get(conn, ~p"/connections"), 200)
assert html =~ "knot1.tangled.sh" assert html =~ KnotServer.fingerprint(public) end
test "a knot endpoint that cannot be scanned is reported", %{conn: conn} do stub_tangled() post(conn, ~p"/connections/tangled", %{"connection" => %{"handle" => "oppi.li"}})
KnotServer.refuse()
pinned = post(conn, ~p"/connections/tangled/knots", %{ "knot" => %{"host" => "knot1.tangled.sh", "ssh_host" => "127.0.0.1"} })
assert redirected_to(pinned) == ~p"/connections"
assert Phoenix.Flash.get(pinned.assigns.flash, :error) =~ "no host keys came back" end
test "generating a key shows the public half to copy", %{conn: conn} do stub_tangled() post(conn, ~p"/connections/tangled", %{"connection" => %{"handle" => "oppi.li"}})
generated = post(conn, ~p"/connections/tangled/key")
assert redirected_to(generated) == ~p"/connections"
html = html_response(get(conn, ~p"/connections"), 200)
assert html =~ Connections.tangled().public_key assert html =~ ~s(id="copy-tangled-public-key") assert html =~ ~s|data-on:click="navigator.clipboard.writeText($publicKey.textContent)"| refute html =~ "BEGIN OPENSSH PRIVATE KEY" end
test "there is nothing to generate a key for until an account is saved", %{conn: conn} do conn = post(conn, ~p"/connections/tangled/key")
assert redirected_to(conn) == ~p"/connections" assert Phoenix.Flash.get(conn.assigns.flash, :error) =~ "No Tangled account" end
defp stub_tangled do Req.Test.stub(GitSync.Http, fn conn -> case conn.host do "public.api.bsky.app" -> Req.Test.json(conn, %{"did" => "did:plc:abc"})
"plc.directory" -> Req.Test.json(conn, %{ "alsoKnownAs" => ["at://oppi.li"], "service" => [ %{ "type" => "AtprotoPersonalDataServer", "serviceEndpoint" => "https://pds.example" } ] })
"pds.example" -> Req.Test.json(conn, %{ "records" => [ %{ "uri" => "at://did:plc:abc/sh.tangled.repo/git-sync", "value" => %{"knot" => "knot1.tangled.sh"} } ] })
_forgejo -> Plug.Conn.send_resp(conn, 401, "") end end) end end
defp closed?(html, id) do [_before, rest] = String.split(html, ~s(id="#{id}"), parts: 2)
String.starts_with?(rest, ~s( data-show=)) endend