feat: desktop connect-to-server over SSH tunnel (issue #26, phase 5)
This commit is contained in:
98
test/bds/desktop/remote_connection_test.exs
Normal file
98
test/bds/desktop/remote_connection_test.exs
Normal file
@@ -0,0 +1,98 @@
|
||||
defmodule BDS.Desktop.RemoteConnectionTest do
|
||||
use ExUnit.Case, async: false
|
||||
|
||||
alias BDS.Desktop.RemoteConnection
|
||||
|
||||
describe "parse_target/1" do
|
||||
test "parses user@host with default SSH port" do
|
||||
assert {:ok, %{user: "gb", host: "blog.example.com", port: 2222}} =
|
||||
RemoteConnection.parse_target("gb@blog.example.com")
|
||||
end
|
||||
|
||||
test "parses an explicit SSH port" do
|
||||
assert {:ok, %{user: "gb", host: "10.0.0.5", port: 2022}} =
|
||||
RemoteConnection.parse_target("gb@10.0.0.5:2022")
|
||||
end
|
||||
|
||||
test "trims whitespace" do
|
||||
assert {:ok, %{host: "h", user: "u"}} = RemoteConnection.parse_target(" u@h \n")
|
||||
end
|
||||
|
||||
test "rejects targets without a user or host" do
|
||||
assert {:error, :invalid_target} = RemoteConnection.parse_target("justahost")
|
||||
assert {:error, :invalid_target} = RemoteConnection.parse_target("@host")
|
||||
assert {:error, :invalid_target} = RemoteConnection.parse_target("user@")
|
||||
assert {:error, :invalid_target} = RemoteConnection.parse_target("user@host:notaport")
|
||||
end
|
||||
end
|
||||
|
||||
describe "connect/2 and disconnect/1 (fake ssh)" do
|
||||
setup do
|
||||
parent = self()
|
||||
|
||||
ssh_dir =
|
||||
Path.join(System.tmp_dir!(), "bds-remote-ssh-#{System.unique_integer([:positive])}")
|
||||
|
||||
on_exit(fn -> File.rm_rf!(ssh_dir) end)
|
||||
|
||||
fake = [
|
||||
ssh_dir_fun: fn -> ssh_dir end,
|
||||
connect_fun: fn host, port, opts ->
|
||||
send(parent, {:ssh_connect, host, port, opts})
|
||||
{:ok, spawn(fn -> Process.sleep(:infinity) end)}
|
||||
end,
|
||||
tunnel_fun: fn conn, _lhost, _lport, _rhost, rport, _timeout ->
|
||||
send(parent, {:tunnel, conn, rport})
|
||||
{:ok, 54_321}
|
||||
end,
|
||||
close_fun: fn conn -> send(parent, {:ssh_close, conn}) end
|
||||
]
|
||||
|
||||
start_supervised!({RemoteConnection, name: nil, test_overrides: fake})
|
||||
|> then(&{:ok, server: &1})
|
||||
end
|
||||
|
||||
test "connects with public-key auth and returns the tunneled URL", %{server: server} do
|
||||
assert {:ok, url} = RemoteConnection.connect(server, "gb@blog.example.com")
|
||||
assert url == "http://127.0.0.1:54321/"
|
||||
|
||||
assert_receive {:ssh_connect, ~c"blog.example.com", 2222, opts}
|
||||
assert opts[:user] == ~c"gb"
|
||||
assert opts[:auth_methods] == ~c"publickey"
|
||||
refute Keyword.has_key?(opts, :password)
|
||||
|
||||
assert_receive {:tunnel, _conn, 4010}
|
||||
assert {:connected, "gb@blog.example.com", "http://127.0.0.1:54321/"} =
|
||||
RemoteConnection.status(server)
|
||||
end
|
||||
|
||||
test "disconnect closes the SSH connection", %{server: server} do
|
||||
{:ok, _url} = RemoteConnection.connect(server, "gb@blog.example.com")
|
||||
assert :ok = RemoteConnection.disconnect(server)
|
||||
assert_receive {:ssh_close, _conn}
|
||||
assert :disconnected = RemoteConnection.status(server)
|
||||
end
|
||||
|
||||
test "connect errors surface as {:error, reason}", %{server: server} do
|
||||
assert {:error, :invalid_target} = RemoteConnection.connect(server, "nonsense")
|
||||
end
|
||||
end
|
||||
|
||||
describe "menu integration" do
|
||||
test "the File menu offers connect and disconnect" do
|
||||
file_group = Enum.find(BDS.UI.MenuBar.default_groups(), &(&1.id == :file))
|
||||
ids = Enum.map(file_group.items, &Map.get(&1, :id))
|
||||
|
||||
assert :connect_server in ids
|
||||
assert :disconnect_server in ids
|
||||
end
|
||||
end
|
||||
|
||||
describe "desktop auth" do
|
||||
test "required in desktop mode, skipped in server and tui modes" do
|
||||
assert BDS.Server.desktop_auth_required?(:desktop) == true
|
||||
assert BDS.Server.desktop_auth_required?(:server) == false
|
||||
assert BDS.Server.desktop_auth_required?(:tui) == false
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user