99 lines
3.5 KiB
Elixir
99 lines
3.5 KiB
Elixir
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
|