diff options
| -rw-r--r-- | config/test.exs | 3 | ||||
| -rw-r--r-- | mix.exs | 3 | ||||
| -rw-r--r-- | mix.lock | 1 | ||||
| -rw-r--r-- | test/integration/mastodon_websocket_test.exs | 100 | ||||
| -rw-r--r-- | test/support/websocket_client.ex | 58 | ||||
| -rw-r--r-- | test/web/mastodon_api/mastodon_socket_test.exs | 31 | 
6 files changed, 163 insertions, 33 deletions
diff --git a/config/test.exs b/config/test.exs index 5c6acfead..8f4a2dc17 100644 --- a/config/test.exs +++ b/config/test.exs @@ -4,7 +4,8 @@ use Mix.Config  # you can enable the server option below.  config :pleroma, Pleroma.Web.Endpoint,    http: [port: 4001], -  server: false +  url: [port: 4001], +  server: true  # Print only warnings and errors during test  config :logger, level: :warn @@ -73,7 +73,8 @@ defmodule Pleroma.Mixfile do        {:ex_doc, "> 0.18.3 and < 0.20.0", only: :dev, runtime: false},        {:web_push_encryption, "~> 0.2.1"},        {:swoosh, "~> 0.20"}, -      {:gen_smtp, "~> 0.13"} +      {:gen_smtp, "~> 0.13"}, +      {:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test}      ]    end @@ -59,4 +59,5 @@    "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "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"}, +  "websocket_client": {:git, "https://github.com/jeremyong/websocket_client.git", "9a6f65d05ebf2725d62fb19262b21f1805a59fbf", []},  } diff --git a/test/integration/mastodon_websocket_test.exs b/test/integration/mastodon_websocket_test.exs new file mode 100644 index 000000000..b5f3d3a47 --- /dev/null +++ b/test/integration/mastodon_websocket_test.exs @@ -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 diff --git a/test/support/websocket_client.ex b/test/support/websocket_client.ex new file mode 100644 index 000000000..57e9bb17f --- /dev/null +++ b/test/support/websocket_client.ex @@ -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 diff --git a/test/web/mastodon_api/mastodon_socket_test.exs b/test/web/mastodon_api/mastodon_socket_test.exs deleted file mode 100644 index 5d9b96861..000000000 --- a/test/web/mastodon_api/mastodon_socket_test.exs +++ /dev/null @@ -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  | 
