Integration tests for mastodon websocket
This commit is contained in:
parent
77b5154c82
commit
b12a904911
|
@ -4,7 +4,8 @@
|
||||||
# you can enable the server option below.
|
# you can enable the server option below.
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
http: [port: 4001],
|
http: [port: 4001],
|
||||||
server: false
|
url: [port: 4001],
|
||||||
|
server: true
|
||||||
|
|
||||||
# Print only warnings and errors during test
|
# Print only warnings and errors during test
|
||||||
config :logger, level: :warn
|
config :logger, level: :warn
|
||||||
|
|
3
mix.exs
3
mix.exs
|
@ -73,7 +73,8 @@ defp deps do
|
||||||
{:ex_doc, "> 0.18.3 and < 0.20.0", only: :dev, runtime: false},
|
{:ex_doc, "> 0.18.3 and < 0.20.0", only: :dev, runtime: false},
|
||||||
{:web_push_encryption, "~> 0.2.1"},
|
{:web_push_encryption, "~> 0.2.1"},
|
||||||
{:swoosh, "~> 0.20"},
|
{:swoosh, "~> 0.20"},
|
||||||
{:gen_smtp, "~> 0.13"}
|
{:gen_smtp, "~> 0.13"},
|
||||||
|
{:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
1
mix.lock
1
mix.lock
|
@ -59,4 +59,5 @@
|
||||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
|
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
|
||||||
"unsafe": {:hex, :unsafe, "1.0.0", "7c21742cd05380c7875546b023481d3a26f52df8e5dfedcb9f958f322baae305", [:mix], [], "hexpm"},
|
"unsafe": {:hex, :unsafe, "1.0.0", "7c21742cd05380c7875546b023481d3a26f52df8e5dfedcb9f958f322baae305", [:mix], [], "hexpm"},
|
||||||
"web_push_encryption": {:hex, :web_push_encryption, "0.2.1", "d42cecf73420d9dc0053ba3299cc8c8d6ff2be2487d67ca2a57265868e4d9a98", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:poison, "~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
|
"web_push_encryption": {:hex, :web_push_encryption, "0.2.1", "d42cecf73420d9dc0053ba3299cc8c8d6ff2be2487d67ca2a57265868e4d9a98", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:poison, "~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
"websocket_client": {:git, "https://github.com/jeremyong/websocket_client.git", "9a6f65d05ebf2725d62fb19262b21f1805a59fbf", []},
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
defmodule Pleroma.Integration.MastodonWebsocketTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.OAuth
|
||||||
|
alias Pleroma.Integration.WebsocketClient
|
||||||
|
alias Pleroma.Web.Streamer
|
||||||
|
|
||||||
|
@path Pleroma.Web.Endpoint.url()
|
||||||
|
|> URI.parse()
|
||||||
|
|> Map.put(:scheme, "ws")
|
||||||
|
|> Map.put(:path, "/api/v1/streaming")
|
||||||
|
|> URI.to_string()
|
||||||
|
|
||||||
|
setup do
|
||||||
|
GenServer.start(Streamer, %{}, name: Streamer)
|
||||||
|
|
||||||
|
on_exit(fn ->
|
||||||
|
if pid = Process.whereis(Streamer) do
|
||||||
|
Process.exit(pid, :kill)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_socket(qs \\ nil, headers \\ []) do
|
||||||
|
path =
|
||||||
|
case qs do
|
||||||
|
nil -> @path
|
||||||
|
qs -> @path <> qs
|
||||||
|
end
|
||||||
|
|
||||||
|
WebsocketClient.start_link(self(), path, headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "refuses invalid requests" do
|
||||||
|
assert {:error, {400, _}} = start_socket()
|
||||||
|
assert {:error, {404, _}} = start_socket("?stream=ncjdk")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "requires authentication and a valid token for protected streams" do
|
||||||
|
assert {:error, {403, _}} = start_socket("?stream=user&access_token=aaaaaaaaaaaa")
|
||||||
|
assert {:error, {403, _}} = start_socket("?stream=user")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "allows public streams without authentication" do
|
||||||
|
assert {:ok, _} = start_socket("?stream=public")
|
||||||
|
assert {:ok, _} = start_socket("?stream=public:local")
|
||||||
|
assert {:ok, _} = start_socket("?stream=hashtag&tag=lain")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "receives well formatted events" do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, _} = start_socket("?stream=public")
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "nice echo chamber"})
|
||||||
|
|
||||||
|
assert_receive {:text, raw_json}, 1_000
|
||||||
|
assert {:ok, json} = Jason.decode(raw_json)
|
||||||
|
|
||||||
|
assert "update" == json["event"]
|
||||||
|
assert json["payload"]
|
||||||
|
assert {:ok, json} = Jason.decode(json["payload"])
|
||||||
|
|
||||||
|
# Note: we remove the "statuses_count" from this result as it changes in the meantime
|
||||||
|
|
||||||
|
view_json =
|
||||||
|
Pleroma.Web.MastodonAPI.StatusView.render("status.json", activity: activity, for: nil)
|
||||||
|
|> Jason.encode!()
|
||||||
|
|> Jason.decode!()
|
||||||
|
|> put_in(["account", "statuses_count"], 0)
|
||||||
|
|
||||||
|
assert json == view_json
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with a valid user token" do
|
||||||
|
setup do
|
||||||
|
{:ok, app} =
|
||||||
|
Pleroma.Repo.insert(
|
||||||
|
OAuth.App.register_changeset(%OAuth.App{}, %{
|
||||||
|
client_name: "client",
|
||||||
|
scopes: "scope",
|
||||||
|
redirect_uris: "url"
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, auth} = OAuth.Authorization.create_authorization(app, user)
|
||||||
|
|
||||||
|
{:ok, token} = OAuth.Token.exchange_token(app, auth)
|
||||||
|
|
||||||
|
%{user: user, token: token}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "accepts valid tokens", state do
|
||||||
|
assert {:ok, _} = start_socket("?stream=user&access_token=#{state.token.token}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,58 @@
|
||||||
|
defmodule Pleroma.Integration.WebsocketClient do
|
||||||
|
# https://github.com/phoenixframework/phoenix/blob/master/test/support/websocket_client.exs
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Starts the WebSocket server for given ws URL. Received Socket.Message's
|
||||||
|
are forwarded to the sender pid
|
||||||
|
"""
|
||||||
|
def start_link(sender, url, headers \\ []) do
|
||||||
|
:crypto.start()
|
||||||
|
:ssl.start()
|
||||||
|
|
||||||
|
:websocket_client.start_link(
|
||||||
|
String.to_charlist(url),
|
||||||
|
__MODULE__,
|
||||||
|
[sender],
|
||||||
|
extra_headers: headers
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Closes the socket
|
||||||
|
"""
|
||||||
|
def close(socket) do
|
||||||
|
send(socket, :close)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Sends a low-level text message to the client.
|
||||||
|
"""
|
||||||
|
def send_text(server_pid, msg) do
|
||||||
|
send(server_pid, {:text, msg})
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def init([sender], _conn_state) do
|
||||||
|
{:ok, %{sender: sender}}
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def websocket_handle(frame, _conn_state, state) do
|
||||||
|
send(state.sender, frame)
|
||||||
|
{:ok, state}
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def websocket_info({:text, msg}, _conn_state, state) do
|
||||||
|
{:reply, {:text, msg}, state}
|
||||||
|
end
|
||||||
|
|
||||||
|
def websocket_info(:close, _conn_state, _state) do
|
||||||
|
{:close, <<>>, "done"}
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def websocket_terminate(_reason, _conn_state, _state) do
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,31 +0,0 @@
|
||||||
defmodule Pleroma.Web.MastodonApi.MastodonSocketTest do
|
|
||||||
use Pleroma.DataCase
|
|
||||||
|
|
||||||
alias Pleroma.Web.{Streamer, CommonAPI}
|
|
||||||
|
|
||||||
import Pleroma.Factory
|
|
||||||
|
|
||||||
test "public is working when non-authenticated" do
|
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
task =
|
|
||||||
Task.async(fn ->
|
|
||||||
assert_receive {:text, _}, 4_000
|
|
||||||
end)
|
|
||||||
|
|
||||||
fake_socket = %{
|
|
||||||
transport_pid: task.pid,
|
|
||||||
assigns: %{}
|
|
||||||
}
|
|
||||||
|
|
||||||
topics = %{
|
|
||||||
"public" => [fake_socket]
|
|
||||||
}
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Test"})
|
|
||||||
|
|
||||||
Streamer.push_to_socket(topics, "public", activity)
|
|
||||||
|
|
||||||
Task.await(task)
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in New Issue