diff options
Diffstat (limited to 'test')
34 files changed, 1639 insertions, 931 deletions
| diff --git a/test/conversation/participation_test.exs b/test/conversation/participation_test.exs index a27167d42..f430bdf75 100644 --- a/test/conversation/participation_test.exs +++ b/test/conversation/participation_test.exs @@ -6,6 +6,7 @@ defmodule Pleroma.Conversation.ParticipationTest do    use Pleroma.DataCase    import Pleroma.Factory    alias Pleroma.Conversation.Participation +  alias Pleroma.User    alias Pleroma.Web.CommonAPI    test "getting a participation will also preload things" do @@ -30,6 +31,8 @@ defmodule Pleroma.Conversation.ParticipationTest do      {:ok, activity} =        CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"}) +    user = User.get_cached_by_id(user.id) +    other_user = User.get_cached_by_id(user.id)      [participation] = Participation.for_user(user)      participation = Pleroma.Repo.preload(participation, :recipients) @@ -155,6 +158,7 @@ defmodule Pleroma.Conversation.ParticipationTest do      [participation] = Participation.for_user_with_last_activity_id(user)      participation = Repo.preload(participation, :recipients) +    user = User.get_cached_by_id(user.id)      assert participation.recipients |> length() == 1      assert user in participation.recipients diff --git a/test/fixtures/bogus-mastodon-announce.json b/test/fixtures/bogus-mastodon-announce.json new file mode 100644 index 000000000..0485b80b9 --- /dev/null +++ b/test/fixtures/bogus-mastodon-announce.json @@ -0,0 +1,43 @@ +{ +  "type": "Announce", +  "to": [ +    "https://www.w3.org/ns/activitystreams#Public" +  ], +  "published": "2018-02-17T19:39:15Z", +  "object": { +    "type": "Note", +    "id": "https://mastodon.social/users/emelie/statuses/101849165031453404", +    "attributedTo": "https://mastodon.social/users/emelie", +    "content": "this is a public toot", +    "to": [ +      "https://www.w3.org/ns/activitystreams#Public" +    ], +    "cc": [ +      "https://mastodon.social/users/emelie", +      "https://mastodon.social/users/emelie/followers" +    ] +  }, +  "id": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity", +  "cc": [ +    "http://mastodon.example.org/users/admin", +    "http://mastodon.example.org/users/admin/followers" +  ], +  "atomUri": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity", +  "actor": "http://mastodon.example.org/users/admin", +  "@context": [ +    "https://www.w3.org/ns/activitystreams", +    "https://w3id.org/security/v1", +    { +      "toot": "http://joinmastodon.org/ns#", +      "sensitive": "as:sensitive", +      "ostatus": "http://ostatus.org#", +      "movedTo": "as:movedTo", +      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", +      "inReplyToAtomUri": "ostatus:inReplyToAtomUri", +      "conversation": "ostatus:conversation", +      "atomUri": "ostatus:atomUri", +      "Hashtag": "as:Hashtag", +      "Emoji": "toot:Emoji" +    } +  ] +} diff --git a/test/fixtures/mastodon-announce-private.json b/test/fixtures/mastodon-announce-private.json new file mode 100644 index 000000000..9b868b13d --- /dev/null +++ b/test/fixtures/mastodon-announce-private.json @@ -0,0 +1,35 @@ +{ +  "type": "Announce", +  "to": [ +    "http://mastodon.example.org/users/admin/followers" +  ], +  "published": "2018-02-17T19:39:15Z", +  "object": { +    "type": "Note", +    "id": "http://mastodon.example.org/@admin/99541947525187368", +    "attributedTo": "http://mastodon.example.org/users/admin", +    "content": "this is a private toot", +    "to": [ +      "http://mastodon.example.org/users/admin/followers" +    ] +  }, +  "id": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity", +  "atomUri": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity", +  "actor": "http://mastodon.example.org/users/admin", +  "@context": [ +    "https://www.w3.org/ns/activitystreams", +    "https://w3id.org/security/v1", +    { +      "toot": "http://joinmastodon.org/ns#", +      "sensitive": "as:sensitive", +      "ostatus": "http://ostatus.org#", +      "movedTo": "as:movedTo", +      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", +      "inReplyToAtomUri": "ostatus:inReplyToAtomUri", +      "conversation": "ostatus:conversation", +      "atomUri": "ostatus:atomUri", +      "Hashtag": "as:Hashtag", +      "Emoji": "toot:Emoji" +    } +  ] +} diff --git a/test/fixtures/mastodon-undo-like-compact-object.json b/test/fixtures/mastodon-undo-like-compact-object.json new file mode 100644 index 000000000..ae66a0d19 --- /dev/null +++ b/test/fixtures/mastodon-undo-like-compact-object.json @@ -0,0 +1,29 @@ +{ +  "type": "Undo", +  "signature": { +    "type": "RsaSignature2017", +    "signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==", +    "creator": "http://mastodon.example.org/users/admin#main-key", +    "created": "2018-05-19T16:36:58Z" +  }, +  "object": "http://mastodon.example.org/users/admin#likes/2", +  "nickname": "lain", +  "id": "http://mastodon.example.org/users/admin#likes/2/undo", +  "actor": "http://mastodon.example.org/users/admin", +  "@context": [ +    "https://www.w3.org/ns/activitystreams", +    "https://w3id.org/security/v1", +    { +      "toot": "http://joinmastodon.org/ns#", +      "sensitive": "as:sensitive", +      "ostatus": "http://ostatus.org#", +      "movedTo": "as:movedTo", +      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", +      "inReplyToAtomUri": "ostatus:inReplyToAtomUri", +      "conversation": "ostatus:conversation", +      "atomUri": "ostatus:atomUri", +      "Hashtag": "as:Hashtag", +      "Emoji": "toot:Emoji" +    } +  ] +} diff --git a/test/healthcheck_test.exs b/test/healthcheck_test.exs index 6bb8d5b7f..66d5026ff 100644 --- a/test/healthcheck_test.exs +++ b/test/healthcheck_test.exs @@ -9,7 +9,14 @@ defmodule Pleroma.HealthcheckTest do    test "system_info/0" do      result = Healthcheck.system_info() |> Map.from_struct() -    assert Map.keys(result) == [:active, :healthy, :idle, :memory_used, :pool_size] +    assert Map.keys(result) == [ +             :active, +             :healthy, +             :idle, +             :job_queue_stats, +             :memory_used, +             :pool_size +           ]    end    describe "check_health/1" do diff --git a/test/job_queue_monitor_test.exs b/test/job_queue_monitor_test.exs new file mode 100644 index 000000000..17c6f3246 --- /dev/null +++ b/test/job_queue_monitor_test.exs @@ -0,0 +1,70 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.JobQueueMonitorTest do +  use ExUnit.Case, async: true + +  alias Pleroma.JobQueueMonitor + +  @success {:process_event, :success, 1337, +            %{ +              args: %{"op" => "refresh_subscriptions"}, +              attempt: 1, +              id: 339, +              max_attempts: 5, +              queue: "federator_outgoing", +              worker: "Pleroma.Workers.SubscriberWorker" +            }} + +  @failure {:process_event, :failure, 22_521_134, +            %{ +              args: %{"op" => "force_password_reset", "user_id" => "9nJG6n6Nbu7tj9GJX6"}, +              attempt: 1, +              error: %RuntimeError{message: "oops"}, +              id: 345, +              kind: :exception, +              max_attempts: 1, +              queue: "background", +              stack: [ +                {Pleroma.Workers.BackgroundWorker, :perform, 2, +                 [file: 'lib/pleroma/workers/background_worker.ex', line: 31]}, +                {Oban.Queue.Executor, :safe_call, 1, +                 [file: 'lib/oban/queue/executor.ex', line: 42]}, +                {:timer, :tc, 3, [file: 'timer.erl', line: 197]}, +                {Oban.Queue.Executor, :call, 2, [file: 'lib/oban/queue/executor.ex', line: 23]}, +                {Task.Supervised, :invoke_mfa, 2, [file: 'lib/task/supervised.ex', line: 90]}, +                {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]} +              ], +              worker: "Pleroma.Workers.BackgroundWorker" +            }} + +  test "stats/0" do +    assert %{processed_jobs: _, queues: _, workers: _} = JobQueueMonitor.stats() +  end + +  test "handle_cast/2" do +    state = %{workers: %{}, queues: %{}, processed_jobs: 0} + +    assert {:noreply, state} = JobQueueMonitor.handle_cast(@success, state) +    assert {:noreply, state} = JobQueueMonitor.handle_cast(@failure, state) +    assert {:noreply, state} = JobQueueMonitor.handle_cast(@success, state) +    assert {:noreply, state} = JobQueueMonitor.handle_cast(@failure, state) + +    assert state == %{ +             processed_jobs: 4, +             queues: %{ +               "background" => %{failure: 2, processed_jobs: 2, success: 0}, +               "federator_outgoing" => %{failure: 0, processed_jobs: 2, success: 2} +             }, +             workers: %{ +               "Pleroma.Workers.BackgroundWorker" => %{ +                 "force_password_reset" => %{failure: 2, processed_jobs: 2, success: 0} +               }, +               "Pleroma.Workers.SubscriberWorker" => %{ +                 "refresh_subscriptions" => %{failure: 0, processed_jobs: 2, success: 2} +               } +             } +           } +  end +end diff --git a/test/reverse_proxy_test.exs b/test/reverse_proxy_test.exs index 3a83c4c48..0672f57db 100644 --- a/test/reverse_proxy_test.exs +++ b/test/reverse_proxy_test.exs @@ -42,6 +42,18 @@ defmodule Pleroma.ReverseProxyTest do      end)    end +  describe "reverse proxy" do +    test "do not track successful request", %{conn: conn} do +      user_agent_mock("hackney/1.15.1", 2) +      url = "/success" + +      conn = ReverseProxy.call(conn, url) + +      assert conn.status == 200 +      assert Cachex.get(:failed_proxy_url_cache, url) == {:ok, nil} +    end +  end +    describe "user-agent" do      test "don't keep", %{conn: conn} do        user_agent_mock("hackney/1.15.1", 2) @@ -71,9 +83,15 @@ defmodule Pleroma.ReverseProxyTest do        user_agent_mock("hackney/1.15.1", 0)        assert capture_log(fn -> -               ReverseProxy.call(conn, "/user-agent", max_body_length: 4) +               ReverseProxy.call(conn, "/huge-file", max_body_length: 4)               end) =~ -               "[error] Elixir.Pleroma.ReverseProxy: request to \"/user-agent\" failed: :body_too_large" +               "[error] Elixir.Pleroma.ReverseProxy: request to \"/huge-file\" failed: :body_too_large" + +      assert {:ok, true} == Cachex.get(:failed_proxy_url_cache, "/huge-file") + +      assert capture_log(fn -> +               ReverseProxy.call(conn, "/huge-file", max_body_length: 4) +             end) == ""      end      defp stream_mock(invokes, with_close? \\ false) do @@ -140,28 +158,54 @@ defmodule Pleroma.ReverseProxyTest do    describe "returns error on" do      test "500", %{conn: conn} do        error_mock(500) +      url = "/status/500" -      capture_log(fn -> ReverseProxy.call(conn, "/status/500") end) =~ +      capture_log(fn -> ReverseProxy.call(conn, url) end) =~          "[error] Elixir.Pleroma.ReverseProxy: request to /status/500 failed with HTTP status 500" + +      assert Cachex.get(:failed_proxy_url_cache, url) == {:ok, true} + +      {:ok, ttl} = Cachex.ttl(:failed_proxy_url_cache, url) +      assert ttl <= 60_000      end      test "400", %{conn: conn} do        error_mock(400) +      url = "/status/400" -      capture_log(fn -> ReverseProxy.call(conn, "/status/400") end) =~ +      capture_log(fn -> ReverseProxy.call(conn, url) end) =~          "[error] Elixir.Pleroma.ReverseProxy: request to /status/400 failed with HTTP status 400" + +      assert Cachex.get(:failed_proxy_url_cache, url) == {:ok, true} +      assert Cachex.ttl(:failed_proxy_url_cache, url) == {:ok, nil} +    end + +    test "403", %{conn: conn} do +      error_mock(403) +      url = "/status/403" + +      capture_log(fn -> +        ReverseProxy.call(conn, url, failed_request_ttl: :timer.seconds(120)) +      end) =~ +        "[error] Elixir.Pleroma.ReverseProxy: request to /status/403 failed with HTTP status 403" + +      {:ok, ttl} = Cachex.ttl(:failed_proxy_url_cache, url) +      assert ttl > 100_000      end      test "204", %{conn: conn} do -      ClientMock -      |> expect(:request, fn :get, "/status/204", _, _, _ -> {:ok, 204, [], %{}} end) +      url = "/status/204" +      expect(ClientMock, :request, fn :get, _url, _, _, _ -> {:ok, 204, [], %{}} end)        capture_log(fn -> -        conn = ReverseProxy.call(conn, "/status/204") +        conn = ReverseProxy.call(conn, url)          assert conn.resp_body == "Request failed: No Content"          assert conn.halted        end) =~          "[error] Elixir.Pleroma.ReverseProxy: request to \"/status/204\" failed with HTTP status 204" + +      assert Cachex.get(:failed_proxy_url_cache, url) == {:ok, true} +      assert Cachex.ttl(:failed_proxy_url_cache, url) == {:ok, nil}      end    end diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index 5506c0626..b825a9307 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -46,6 +46,14 @@ defmodule HttpRequestMock do       }}    end +  def get("https://mastodon.social/users/emelie/statuses/101849165031453404", _, _, _) do +    {:ok, +     %Tesla.Env{ +       status: 404, +       body: "" +     }} +  end +    def get("https://mastodon.social/users/emelie", _, _, _) do      {:ok,       %Tesla.Env{ @@ -349,6 +357,14 @@ defmodule HttpRequestMock do       }}    end +  def get("http://mastodon.example.org/@admin/99541947525187368", _, _, _) do +    {:ok, +     %Tesla.Env{ +       status: 404, +       body: "" +     }} +  end +    def get("https://shitposter.club/notice/7369654", _, _, _) do      {:ok,       %Tesla.Env{ diff --git a/test/user_test.exs b/test/user_test.exs index 126bd69e8..1bc853c94 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -1725,4 +1725,61 @@ defmodule Pleroma.UserTest do      assert %{info: %{hide_follows: true}} = Repo.get(User, user.id)      assert {:ok, %{info: %{hide_follows: true}}} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")    end + +  describe "get_cached_by_nickname_or_id" do +    setup do +      limit_to_local_content = Pleroma.Config.get([:instance, :limit_to_local_content]) +      local_user = insert(:user) +      remote_user = insert(:user, nickname: "nickname@example.com", local: false) + +      on_exit(fn -> +        Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local_content) +      end) + +      [local_user: local_user, remote_user: remote_user] +    end + +    test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{ +      remote_user: remote_user +    } do +      Pleroma.Config.put([:instance, :limit_to_local_content], false) +      assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id) + +      Pleroma.Config.put([:instance, :limit_to_local_content], true) +      assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id) + +      Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated) +      assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id) +    end + +    test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated", +         %{remote_user: remote_user} do +      Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated) +      assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname) +    end + +    test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated", +         %{remote_user: remote_user, local_user: local_user} do +      Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated) +      assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user) +    end + +    test "disallows getting remote users by nickname when :limit_to_local_content is set to true", +         %{remote_user: remote_user} do +      Pleroma.Config.put([:instance, :limit_to_local_content], true) +      assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname) +    end + +    test "allows getting local users by nickname no matter what :limit_to_local_content is set to", +         %{local_user: local_user} do +      Pleroma.Config.put([:instance, :limit_to_local_content], false) +      assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname) + +      Pleroma.Config.put([:instance, :limit_to_local_content], true) +      assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname) + +      Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated) +      assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname) +    end +  end  end diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs index 1ffa91b70..6a3e48b5e 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -225,69 +225,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do      end    end -  describe "/object/:uuid/likes" do -    setup do -      like = insert(:like_activity) -      like_object_ap_id = Object.normalize(like).data["id"] - -      uuid = -        like_object_ap_id -        |> String.split("/") -        |> List.last() - -      [id: like.data["id"], uuid: uuid] -    end - -    test "it returns the like activities in a collection", %{conn: conn, id: id, uuid: uuid} do -      result = -        conn -        |> put_req_header("accept", "application/activity+json") -        |> get("/objects/#{uuid}/likes") -        |> json_response(200) - -      assert List.first(result["first"]["orderedItems"])["id"] == id -      assert result["type"] == "OrderedCollection" -      assert result["totalItems"] == 1 -      refute result["first"]["next"] -    end - -    test "it does not crash when page number is exceeded total pages", %{conn: conn, uuid: uuid} do -      result = -        conn -        |> put_req_header("accept", "application/activity+json") -        |> get("/objects/#{uuid}/likes?page=2") -        |> json_response(200) - -      assert result["type"] == "OrderedCollectionPage" -      assert result["totalItems"] == 1 -      refute result["next"] -      assert Enum.empty?(result["orderedItems"]) -    end - -    test "it contains the next key when likes count is more than 10", %{conn: conn} do -      note = insert(:note_activity) -      insert_list(11, :like_activity, note_activity: note) - -      uuid = -        note -        |> Object.normalize() -        |> Map.get(:data) -        |> Map.get("id") -        |> String.split("/") -        |> List.last() - -      result = -        conn -        |> put_req_header("accept", "application/activity+json") -        |> get("/objects/#{uuid}/likes?page=1") -        |> json_response(200) - -      assert result["totalItems"] == 11 -      assert length(result["orderedItems"]) == 10 -      assert result["next"] -    end -  end -    describe "/activities/:uuid" do      test "it returns a json representation of the activity", %{conn: conn} do        activity = insert(:note_activity) diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index a203d1d30..c9f2a92e7 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -811,10 +811,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        {:ok, like_activity, object} = ActivityPub.like(user, object)        assert object.data["like_count"] == 1 -      {:ok, _, _, object} = ActivityPub.unlike(user, object) +      {:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object)        assert object.data["like_count"] == 0        assert Activity.get_by_id(like_activity.id) == nil +      assert note_activity.actor in unlike_activity.recipients      end    end @@ -839,6 +840,39 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do      end    end +  describe "announcing a private object" do +    test "adds an announce activity to the db if the audience is not widened" do +      user = insert(:user) +      {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) +      object = Object.normalize(note_activity) + +      {:ok, announce_activity, object} = ActivityPub.announce(user, object, nil, true, false) + +      assert announce_activity.data["to"] == [User.ap_followers(user)] + +      assert announce_activity.data["object"] == object.data["id"] +      assert announce_activity.data["actor"] == user.ap_id +      assert announce_activity.data["context"] == object.data["context"] +    end + +    test "does not add an announce activity to the db if the audience is widened" do +      user = insert(:user) +      {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) +      object = Object.normalize(note_activity) + +      assert {:error, _} = ActivityPub.announce(user, object, nil, true, true) +    end + +    test "does not add an announce activity to the db if the announcer is not the author" do +      user = insert(:user) +      announcer = insert(:user) +      {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) +      object = Object.normalize(note_activity) + +      assert {:error, _} = ActivityPub.announce(announcer, object, nil, true, false) +    end +  end +    describe "unannouncing an object" do      test "unannouncing a previously announced object" do        note_activity = insert(:note_activity) @@ -857,7 +891,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert unannounce_activity.data["to"] == [                 User.ap_followers(user), -               announce_activity.data["actor"] +               object.data["actor"]               ]        assert unannounce_activity.data["type"] == "Undo" diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 193d6d301..50c0bfb84 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -378,6 +378,31 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2"      end +    test "it works for incoming unlikes with an existing like activity and a compact object" do +      user = insert(:user) +      {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"}) + +      like_data = +        File.read!("test/fixtures/mastodon-like.json") +        |> Poison.decode!() +        |> Map.put("object", activity.data["object"]) + +      {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data) + +      data = +        File.read!("test/fixtures/mastodon-undo-like.json") +        |> Poison.decode!() +        |> Map.put("object", like_data["id"]) +        |> Map.put("actor", like_data["actor"]) + +      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +      assert data["actor"] == "http://mastodon.example.org/users/admin" +      assert data["type"] == "Undo" +      assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo" +      assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2" +    end +      test "it works for incoming announces" do        data = File.read!("test/fixtures/mastodon-announce.json") |> Poison.decode!() @@ -417,6 +442,33 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert Activity.get_create_by_object_ap_id(data["object"]).id == activity.id      end +    test "it works for incoming announces with an inlined activity" do +      data = +        File.read!("test/fixtures/mastodon-announce-private.json") +        |> Poison.decode!() + +      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +      assert data["actor"] == "http://mastodon.example.org/users/admin" +      assert data["type"] == "Announce" + +      assert data["id"] == +               "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity" + +      object = Object.normalize(data["object"]) + +      assert object.data["id"] == "http://mastodon.example.org/@admin/99541947525187368" +      assert object.data["content"] == "this is a private toot" +    end + +    test "it rejects incoming announces with an inlined activity from another origin" do +      data = +        File.read!("test/fixtures/bogus-mastodon-announce.json") +        |> Poison.decode!() + +      assert :error = Transmogrifier.handle_incoming(data) +    end +      test "it does not clobber the addressing on announce activities" do        user = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"}) @@ -521,6 +573,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data) +      assert data["id"] == update_data["id"] +        user = User.get_cached_by_ap_id(data["actor"])        assert user.name == "gargle" @@ -1051,6 +1105,19 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do    end    describe "prepare outgoing" do +    test "it inlines private announced objects" do +      user = insert(:user) + +      {:ok, activity} = CommonAPI.post(user, %{"status" => "hey", "visibility" => "private"}) + +      {:ok, announce_activity, _} = CommonAPI.repeat(activity.id, user) + +      {:ok, modified} = Transmogrifier.prepare_outgoing(announce_activity.data) + +      assert modified["object"]["content"] == "hey" +      assert modified["object"]["actor"] == modified["object"]["attributedTo"] +    end +      test "it turns mentions into tags" do        user = insert(:user)        other_user = insert(:user) diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs index b1c1d6f71..c57ea7eb9 100644 --- a/test/web/activity_pub/utils_test.exs +++ b/test/web/activity_pub/utils_test.exs @@ -106,11 +106,13 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do        user = insert(:user)        like_activity = insert(:like_activity, data_attrs: %{"context" => "test context"}) +      object = Object.normalize(like_activity.data["object"]) +        assert Utils.make_unlike_data(user, like_activity, nil) == %{                 "type" => "Undo",                 "actor" => user.ap_id,                 "object" => like_activity.data, -               "to" => [user.follower_address, like_activity.data["actor"]], +               "to" => [user.follower_address, object.data["actor"]],                 "cc" => [Pleroma.Constants.as_public()],                 "context" => like_activity.data["context"]               } @@ -119,7 +121,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do                 "type" => "Undo",                 "actor" => user.ap_id,                 "object" => like_activity.data, -               "to" => [user.follower_address, like_activity.data["actor"]], +               "to" => [user.follower_address, object.data["actor"]],                 "cc" => [Pleroma.Constants.as_public()],                 "context" => like_activity.data["context"],                 "id" => "9mJEZK0tky1w2xD2vY" diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index 0f4a5eb25..83df44c36 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -14,6 +14,8 @@ defmodule Pleroma.Web.CommonAPITest do    import Pleroma.Factory +  require Pleroma.Constants +    clear_config([:instance, :safe_dm_mentions])    clear_config([:instance, :limit])    clear_config([:instance, :max_pinned_statuses]) @@ -96,11 +98,13 @@ defmodule Pleroma.Web.CommonAPITest do    test "it adds emoji when updating profiles" do      user = insert(:user, %{name: ":firefox:"}) -    CommonAPI.update(user) +    {:ok, activity} = CommonAPI.update(user)      user = User.get_cached_by_ap_id(user.ap_id)      [firefox] = user.info.source_data["tag"]      assert firefox["name"] == ":firefox:" + +    assert Pleroma.Constants.as_public() in activity.recipients    end    describe "posting" do @@ -231,6 +235,18 @@ defmodule Pleroma.Web.CommonAPITest do        {:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, user)      end +    test "repeating a status privately" do +      user = insert(:user) +      other_user = insert(:user) + +      {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) + +      {:ok, %Activity{} = announce_activity, _} = +        CommonAPI.repeat(activity.id, user, %{"visibility" => "private"}) + +      assert Visibility.is_private?(announce_activity) +    end +      test "favoriting a status" do        user = insert(:user)        other_user = insert(:user) diff --git a/test/web/masto_fe_controller_test.exs b/test/web/masto_fe_controller_test.exs new file mode 100644 index 000000000..ab9dab352 --- /dev/null +++ b/test/web/masto_fe_controller_test.exs @@ -0,0 +1,84 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.MastoFEController do +  use Pleroma.Web.ConnCase + +  alias Pleroma.Config +  alias Pleroma.User + +  import Pleroma.Factory + +  clear_config([:instance, :public]) + +  test "put settings", %{conn: conn} do +    user = insert(:user) + +    conn = +      conn +      |> assign(:user, user) +      |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}}) + +    assert _result = json_response(conn, 200) + +    user = User.get_cached_by_ap_id(user.ap_id) +    assert user.info.settings == %{"programming" => "socks"} +  end + +  describe "index/2 redirections" do +    setup %{conn: conn} do +      session_opts = [ +        store: :cookie, +        key: "_test", +        signing_salt: "cooldude" +      ] + +      conn = +        conn +        |> Plug.Session.call(Plug.Session.init(session_opts)) +        |> fetch_session() + +      test_path = "/web/statuses/test" +      %{conn: conn, path: test_path} +    end + +    test "redirects not logged-in users to the login page", %{conn: conn, path: path} do +      conn = get(conn, path) + +      assert conn.status == 302 +      assert redirected_to(conn) == "/web/login" +    end + +    test "redirects not logged-in users to the login page on private instances", %{ +      conn: conn, +      path: path +    } do +      Config.put([:instance, :public], false) + +      conn = get(conn, path) + +      assert conn.status == 302 +      assert redirected_to(conn) == "/web/login" +    end + +    test "does not redirect logged in users to the login page", %{conn: conn, path: path} do +      token = insert(:oauth_token) + +      conn = +        conn +        |> assign(:user, token.user) +        |> put_session(:oauth_token, token.token) +        |> get(path) + +      assert conn.status == 200 +    end + +    test "saves referer path to session", %{conn: conn, path: path} do +      conn = get(conn, path) +      return_to = Plug.Conn.get_session(conn, :return_to) + +      assert return_to == path +    end +  end +end diff --git a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs index 560f55137..599cd61c8 100644 --- a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs +++ b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs @@ -328,7 +328,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        account =          conn          |> assign(:user, user) -        |> patch("/api/v1/accounts/update_credentials", %{"fields" => fields}) +        |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})          |> json_response(200)        assert account["fields"] == [ @@ -344,6 +344,35 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do                 %{"name" => "link", "value" => "cofe.io"}               ] +      fields = +        [ +          "fields_attributes[1][name]=link", +          "fields_attributes[1][value]=cofe.io", +          "fields_attributes[0][name]=<a href=\"http://google.com\">foo</a>", +          "fields_attributes[0][value]=bar" +        ] +        |> Enum.join("&") + +      account = +        conn +        |> put_req_header("content-type", "application/x-www-form-urlencoded") +        |> assign(:user, user) +        |> patch("/api/v1/accounts/update_credentials", fields) +        |> json_response(200) + +      assert account["fields"] == [ +               %{"name" => "foo", "value" => "bar"}, +               %{"name" => "link", "value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)} +             ] + +      assert account["source"]["fields"] == [ +               %{ +                 "name" => "<a href=\"http://google.com\">foo</a>", +                 "value" => "bar" +               }, +               %{"name" => "link", "value" => "cofe.io"} +             ] +        name_limit = Pleroma.Config.get([:instance, :account_field_name_length])        value_limit = Pleroma.Config.get([:instance, :account_field_value_length]) @@ -354,7 +383,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert %{"error" => "Invalid request"} ==                 conn                 |> assign(:user, user) -               |> patch("/api/v1/accounts/update_credentials", %{"fields" => fields}) +               |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})                 |> json_response(403)        long_name = Enum.map(0..name_limit, fn _ -> "x" end) |> Enum.join() @@ -364,7 +393,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert %{"error" => "Invalid request"} ==                 conn                 |> assign(:user, user) -               |> patch("/api/v1/accounts/update_credentials", %{"fields" => fields}) +               |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})                 |> json_response(403)        Pleroma.Config.put([:instance, :max_account_fields], 1) @@ -377,8 +406,23 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert %{"error" => "Invalid request"} ==                 conn                 |> assign(:user, user) -               |> patch("/api/v1/accounts/update_credentials", %{"fields" => fields}) +               |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})                 |> json_response(403) + +      fields = [ +        %{"name" => "foo", "value" => ""}, +        %{"name" => "", "value" => "bar"} +      ] + +      account = +        conn +        |> assign(:user, user) +        |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields}) +        |> json_response(200) + +      assert account["fields"] == [ +               %{"name" => "foo", "value" => ""} +             ]      end    end  end diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs index 8c8017838..6a59c3d94 100644 --- a/test/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -849,4 +849,34 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do        assert [] = json_response(conn, 200)      end    end + +  test "getting a list of mutes", %{conn: conn} do +    user = insert(:user) +    other_user = insert(:user) + +    {:ok, user} = User.mute(user, other_user) + +    conn = +      conn +      |> assign(:user, user) +      |> get("/api/v1/mutes") + +    other_user_id = to_string(other_user.id) +    assert [%{"id" => ^other_user_id}] = json_response(conn, 200) +  end + +  test "getting a list of blocks", %{conn: conn} do +    user = insert(:user) +    other_user = insert(:user) + +    {:ok, user} = User.block(user, other_user) + +    conn = +      conn +      |> assign(:user, user) +      |> get("/api/v1/blocks") + +    other_user_id = to_string(other_user.id) +    assert [%{"id" => ^other_user_id}] = json_response(conn, 200) +  end  end diff --git a/test/web/mastodon_api/controllers/app_controller_test.exs b/test/web/mastodon_api/controllers/app_controller_test.exs new file mode 100644 index 000000000..51788155b --- /dev/null +++ b/test/web/mastodon_api/controllers/app_controller_test.exs @@ -0,0 +1,60 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.AppControllerTest do +  use Pleroma.Web.ConnCase, async: true + +  alias Pleroma.Repo +  alias Pleroma.Web.OAuth.App +  alias Pleroma.Web.Push + +  import Pleroma.Factory + +  test "apps/verify_credentials", %{conn: conn} do +    token = insert(:oauth_token) + +    conn = +      conn +      |> assign(:user, token.user) +      |> assign(:token, token) +      |> get("/api/v1/apps/verify_credentials") + +    app = Repo.preload(token, :app).app + +    expected = %{ +      "name" => app.client_name, +      "website" => app.website, +      "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key) +    } + +    assert expected == json_response(conn, 200) +  end + +  test "creates an oauth app", %{conn: conn} do +    user = insert(:user) +    app_attrs = build(:oauth_app) + +    conn = +      conn +      |> assign(:user, user) +      |> post("/api/v1/apps", %{ +        client_name: app_attrs.client_name, +        redirect_uris: app_attrs.redirect_uris +      }) + +    [app] = Repo.all(App) + +    expected = %{ +      "name" => app.client_name, +      "website" => app.website, +      "client_id" => app.client_id, +      "client_secret" => app.client_secret, +      "id" => app.id |> to_string(), +      "redirect_uri" => app.redirect_uris, +      "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key) +    } + +    assert expected == json_response(conn, 200) +  end +end diff --git a/test/web/mastodon_api/controllers/auth_controller_test.exs b/test/web/mastodon_api/controllers/auth_controller_test.exs new file mode 100644 index 000000000..98b2a82e7 --- /dev/null +++ b/test/web/mastodon_api/controllers/auth_controller_test.exs @@ -0,0 +1,121 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.AuthControllerTest do +  use Pleroma.Web.ConnCase + +  alias Pleroma.Config +  alias Pleroma.Repo +  alias Pleroma.Tests.ObanHelpers + +  import Pleroma.Factory +  import Swoosh.TestAssertions + +  describe "GET /web/login" do +    setup %{conn: conn} do +      session_opts = [ +        store: :cookie, +        key: "_test", +        signing_salt: "cooldude" +      ] + +      conn = +        conn +        |> Plug.Session.call(Plug.Session.init(session_opts)) +        |> fetch_session() + +      test_path = "/web/statuses/test" +      %{conn: conn, path: test_path} +    end + +    test "redirects to the saved path after log in", %{conn: conn, path: path} do +      app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".") +      auth = insert(:oauth_authorization, app: app) + +      conn = +        conn +        |> put_session(:return_to, path) +        |> get("/web/login", %{code: auth.token}) + +      assert conn.status == 302 +      assert redirected_to(conn) == path +    end + +    test "redirects to the getting-started page when referer is not present", %{conn: conn} do +      app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".") +      auth = insert(:oauth_authorization, app: app) + +      conn = get(conn, "/web/login", %{code: auth.token}) + +      assert conn.status == 302 +      assert redirected_to(conn) == "/web/getting-started" +    end +  end + +  describe "POST /auth/password, with valid parameters" do +    setup %{conn: conn} do +      user = insert(:user) +      conn = post(conn, "/auth/password?email=#{user.email}") +      %{conn: conn, user: user} +    end + +    test "it returns 204", %{conn: conn} do +      assert json_response(conn, :no_content) +    end + +    test "it creates a PasswordResetToken record for user", %{user: user} do +      token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id) +      assert token_record +    end + +    test "it sends an email to user", %{user: user} do +      ObanHelpers.perform_all() +      token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id) + +      email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token) +      notify_email = Config.get([:instance, :notify_email]) +      instance_name = Config.get([:instance, :name]) + +      assert_email_sent( +        from: {instance_name, notify_email}, +        to: {user.name, user.email}, +        html_body: email.html_body +      ) +    end +  end + +  describe "POST /auth/password, with invalid parameters" do +    setup do +      user = insert(:user) +      {:ok, user: user} +    end + +    test "it returns 404 when user is not found", %{conn: conn, user: user} do +      conn = post(conn, "/auth/password?email=nonexisting_#{user.email}") +      assert conn.status == 404 +      assert conn.resp_body == "" +    end + +    test "it returns 400 when user is not local", %{conn: conn, user: user} do +      {:ok, user} = Repo.update(Ecto.Changeset.change(user, local: false)) +      conn = post(conn, "/auth/password?email=#{user.email}") +      assert conn.status == 400 +      assert conn.resp_body == "" +    end +  end + +  describe "DELETE /auth/sign_out" do +    test "redirect to root page", %{conn: conn} do +      user = insert(:user) + +      conn = +        conn +        |> assign(:user, user) +        |> delete("/auth/sign_out") + +      assert conn.status == 302 +      assert redirected_to(conn) == "/" +    end +  end +end diff --git a/test/web/mastodon_api/controllers/conversation_controller_test.exs b/test/web/mastodon_api/controllers/conversation_controller_test.exs index 7117fc76a..a308a7620 100644 --- a/test/web/mastodon_api/controllers/conversation_controller_test.exs +++ b/test/web/mastodon_api/controllers/conversation_controller_test.exs @@ -10,19 +10,23 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do    import Pleroma.Factory -  test "Conversations", %{conn: conn} do +  test "returns a list of conversations", %{conn: conn} do      user_one = insert(:user)      user_two = insert(:user)      user_three = insert(:user)      {:ok, user_two} = User.follow(user_two, user_one) +    assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 0 +      {:ok, direct} =        CommonAPI.post(user_one, %{          "status" => "Hi @#{user_two.nickname}, @#{user_three.nickname}!",          "visibility" => "direct"        }) +    assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 1 +      {:ok, _follower_only} =        CommonAPI.post(user_one, %{          "status" => "Hi @#{user_two.nickname}!", @@ -52,23 +56,100 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do      assert is_binary(res_id)      assert unread == true      assert res_last_status["id"] == direct.id +    assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 +  end -    # Apparently undocumented API endpoint -    res_conn = +  test "updates the last_status on reply", %{conn: conn} do +    user_one = insert(:user) +    user_two = insert(:user) + +    {:ok, direct} = +      CommonAPI.post(user_one, %{ +        "status" => "Hi @#{user_two.nickname}", +        "visibility" => "direct" +      }) + +    {:ok, direct_reply} = +      CommonAPI.post(user_two, %{ +        "status" => "reply", +        "visibility" => "direct", +        "in_reply_to_status_id" => direct.id +      }) + +    [%{"last_status" => res_last_status}] =        conn        |> assign(:user, user_one) -      |> post("/api/v1/conversations/#{res_id}/read") +      |> get("/api/v1/conversations") +      |> json_response(200) -    assert response = json_response(res_conn, 200) -    assert length(response["accounts"]) == 2 -    assert response["last_status"]["id"] == direct.id -    assert response["unread"] == false +    assert res_last_status["id"] == direct_reply.id +  end + +  test "the user marks a conversation as read", %{conn: conn} do +    user_one = insert(:user) +    user_two = insert(:user) + +    {:ok, direct} = +      CommonAPI.post(user_one, %{ +        "status" => "Hi @#{user_two.nickname}", +        "visibility" => "direct" +      }) + +    [%{"id" => direct_conversation_id, "unread" => true}] = +      conn +      |> assign(:user, user_one) +      |> get("/api/v1/conversations") +      |> json_response(200) + +    %{"unread" => false} = +      conn +      |> assign(:user, user_one) +      |> post("/api/v1/conversations/#{direct_conversation_id}/read") +      |> json_response(200) + +    assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 0 + +    # The conversation is marked as unread on reply +    {:ok, _} = +      CommonAPI.post(user_two, %{ +        "status" => "reply", +        "visibility" => "direct", +        "in_reply_to_status_id" => direct.id +      }) + +    [%{"unread" => true}] = +      conn +      |> assign(:user, user_one) +      |> get("/api/v1/conversations") +      |> json_response(200) + +    assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 + +    # A reply doesn't increment the user's unread_conversation_count if the conversation is unread +    {:ok, _} = +      CommonAPI.post(user_two, %{ +        "status" => "reply", +        "visibility" => "direct", +        "in_reply_to_status_id" => direct.id +      }) + +    assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 +  end + +  test "(vanilla) Mastodon frontend behaviour", %{conn: conn} do +    user_one = insert(:user) +    user_two = insert(:user) + +    {:ok, direct} = +      CommonAPI.post(user_one, %{ +        "status" => "Hi @#{user_two.nickname}!", +        "visibility" => "direct" +      }) -    # (vanilla) Mastodon frontend behaviour      res_conn =        conn        |> assign(:user, user_one) -      |> get("/api/v1/statuses/#{res_last_status["id"]}/context") +      |> get("/api/v1/statuses/#{direct.id}/context")      assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)    end diff --git a/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs b/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs new file mode 100644 index 000000000..2d988b0b8 --- /dev/null +++ b/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs @@ -0,0 +1,22 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.CustomEmojiControllerTest do +  use Pleroma.Web.ConnCase, async: true + +  test "with tags", %{conn: conn} do +    [emoji | _body] = +      conn +      |> get("/api/v1/custom_emojis") +      |> json_response(200) + +    assert Map.has_key?(emoji, "shortcode") +    assert Map.has_key?(emoji, "static_url") +    assert Map.has_key?(emoji, "tags") +    assert is_list(emoji["tags"]) +    assert Map.has_key?(emoji, "category") +    assert Map.has_key?(emoji, "url") +    assert Map.has_key?(emoji, "visible_in_picker") +  end +end diff --git a/test/web/mastodon_api/controllers/instance_controller_test.exs b/test/web/mastodon_api/controllers/instance_controller_test.exs new file mode 100644 index 000000000..f8049f81f --- /dev/null +++ b/test/web/mastodon_api/controllers/instance_controller_test.exs @@ -0,0 +1,84 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do +  use Pleroma.Web.ConnCase + +  alias Pleroma.User +  import Pleroma.Factory + +  test "get instance information", %{conn: conn} do +    conn = get(conn, "/api/v1/instance") +    assert result = json_response(conn, 200) + +    email = Pleroma.Config.get([:instance, :email]) +    # Note: not checking for "max_toot_chars" since it's optional +    assert %{ +             "uri" => _, +             "title" => _, +             "description" => _, +             "version" => _, +             "email" => from_config_email, +             "urls" => %{ +               "streaming_api" => _ +             }, +             "stats" => _, +             "thumbnail" => _, +             "languages" => _, +             "registrations" => _, +             "poll_limits" => _, +             "upload_limit" => _, +             "avatar_upload_limit" => _, +             "background_upload_limit" => _, +             "banner_upload_limit" => _ +           } = result + +    assert email == from_config_email +  end + +  test "get instance stats", %{conn: conn} do +    user = insert(:user, %{local: true}) + +    user2 = insert(:user, %{local: true}) +    {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated) + +    insert(:user, %{local: false, nickname: "u@peer1.com"}) +    insert(:user, %{local: false, nickname: "u@peer2.com"}) + +    {:ok, _} = Pleroma.Web.CommonAPI.post(user, %{"status" => "cofe"}) + +    # Stats should count users with missing or nil `info.deactivated` value + +    {:ok, _user} = +      user.id +      |> User.get_cached_by_id() +      |> User.update_info(&Ecto.Changeset.change(&1, %{deactivated: nil})) + +    Pleroma.Stats.force_update() + +    conn = get(conn, "/api/v1/instance") + +    assert result = json_response(conn, 200) + +    stats = result["stats"] + +    assert stats +    assert stats["user_count"] == 1 +    assert stats["status_count"] == 1 +    assert stats["domain_count"] == 2 +  end + +  test "get peers", %{conn: conn} do +    insert(:user, %{local: false, nickname: "u@peer1.com"}) +    insert(:user, %{local: false, nickname: "u@peer2.com"}) + +    Pleroma.Stats.force_update() + +    conn = get(conn, "/api/v1/instance/peers") + +    assert result = json_response(conn, 200) + +    assert ["peer1.com", "peer2.com"] == Enum.sort(result) +  end +end diff --git a/test/web/mastodon_api/controllers/media_controller_test.exs b/test/web/mastodon_api/controllers/media_controller_test.exs new file mode 100644 index 000000000..06c6a1cb3 --- /dev/null +++ b/test/web/mastodon_api/controllers/media_controller_test.exs @@ -0,0 +1,92 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do +  use Pleroma.Web.ConnCase + +  alias Pleroma.Object +  alias Pleroma.User +  alias Pleroma.Web.ActivityPub.ActivityPub + +  import Pleroma.Factory + +  describe "media upload" do +    setup do +      user = insert(:user) + +      conn = +        build_conn() +        |> assign(:user, user) + +      image = %Plug.Upload{ +        content_type: "image/jpg", +        path: Path.absname("test/fixtures/image.jpg"), +        filename: "an_image.jpg" +      } + +      [conn: conn, image: image] +    end + +    clear_config([:media_proxy]) +    clear_config([Pleroma.Upload]) + +    test "returns uploaded image", %{conn: conn, image: image} do +      desc = "Description of the image" + +      media = +        conn +        |> post("/api/v1/media", %{"file" => image, "description" => desc}) +        |> json_response(:ok) + +      assert media["type"] == "image" +      assert media["description"] == desc +      assert media["id"] + +      object = Object.get_by_id(media["id"]) +      assert object.data["actor"] == User.ap_id(conn.assigns[:user]) +    end +  end + +  describe "PUT /api/v1/media/:id" do +    setup do +      actor = insert(:user) + +      file = %Plug.Upload{ +        content_type: "image/jpg", +        path: Path.absname("test/fixtures/image.jpg"), +        filename: "an_image.jpg" +      } + +      {:ok, %Object{} = object} = +        ActivityPub.upload( +          file, +          actor: User.ap_id(actor), +          description: "test-m" +        ) + +      [actor: actor, object: object] +    end + +    test "updates name of media", %{conn: conn, actor: actor, object: object} do +      media = +        conn +        |> assign(:user, actor) +        |> put("/api/v1/media/#{object.id}", %{"description" => "test-media"}) +        |> json_response(:ok) + +      assert media["description"] == "test-media" +      assert refresh_record(object).data["name"] == "test-media" +    end + +    test "returns error wheb request is bad", %{conn: conn, actor: actor, object: object} do +      media = +        conn +        |> assign(:user, actor) +        |> put("/api/v1/media/#{object.id}", %{}) +        |> json_response(400) + +      assert media == %{"error" => "bad_request"} +    end +  end +end diff --git a/test/web/mastodon_api/controllers/poll_controller_test.exs b/test/web/mastodon_api/controllers/poll_controller_test.exs new file mode 100644 index 000000000..40cf3e879 --- /dev/null +++ b/test/web/mastodon_api/controllers/poll_controller_test.exs @@ -0,0 +1,184 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.PollControllerTest do +  use Pleroma.Web.ConnCase + +  alias Pleroma.Object +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "GET /api/v1/polls/:id" do +    test "returns poll entity for object id", %{conn: conn} do +      user = insert(:user) + +      {:ok, activity} = +        CommonAPI.post(user, %{ +          "status" => "Pleroma does", +          "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20} +        }) + +      object = Object.normalize(activity) + +      conn = +        conn +        |> assign(:user, user) +        |> get("/api/v1/polls/#{object.id}") + +      response = json_response(conn, 200) +      id = to_string(object.id) +      assert %{"id" => ^id, "expired" => false, "multiple" => false} = response +    end + +    test "does not expose polls for private statuses", %{conn: conn} do +      user = insert(:user) +      other_user = insert(:user) + +      {:ok, activity} = +        CommonAPI.post(user, %{ +          "status" => "Pleroma does", +          "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20}, +          "visibility" => "private" +        }) + +      object = Object.normalize(activity) + +      conn = +        conn +        |> assign(:user, other_user) +        |> get("/api/v1/polls/#{object.id}") + +      assert json_response(conn, 404) +    end +  end + +  describe "POST /api/v1/polls/:id/votes" do +    test "votes are added to the poll", %{conn: conn} do +      user = insert(:user) +      other_user = insert(:user) + +      {:ok, activity} = +        CommonAPI.post(user, %{ +          "status" => "A very delicious sandwich", +          "poll" => %{ +            "options" => ["Lettuce", "Grilled Bacon", "Tomato"], +            "expires_in" => 20, +            "multiple" => true +          } +        }) + +      object = Object.normalize(activity) + +      conn = +        conn +        |> assign(:user, other_user) +        |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]}) + +      assert json_response(conn, 200) +      object = Object.get_by_id(object.id) + +      assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} -> +               total_items == 1 +             end) +    end + +    test "author can't vote", %{conn: conn} do +      user = insert(:user) + +      {:ok, activity} = +        CommonAPI.post(user, %{ +          "status" => "Am I cute?", +          "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20} +        }) + +      object = Object.normalize(activity) + +      assert conn +             |> assign(:user, user) +             |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [1]}) +             |> json_response(422) == %{"error" => "Poll's author can't vote"} + +      object = Object.get_by_id(object.id) + +      refute Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 1 +    end + +    test "does not allow multiple choices on a single-choice question", %{conn: conn} do +      user = insert(:user) +      other_user = insert(:user) + +      {:ok, activity} = +        CommonAPI.post(user, %{ +          "status" => "The glass is", +          "poll" => %{"options" => ["half empty", "half full"], "expires_in" => 20} +        }) + +      object = Object.normalize(activity) + +      assert conn +             |> assign(:user, other_user) +             |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1]}) +             |> json_response(422) == %{"error" => "Too many choices"} + +      object = Object.get_by_id(object.id) + +      refute Enum.any?(object.data["oneOf"], fn %{"replies" => %{"totalItems" => total_items}} -> +               total_items == 1 +             end) +    end + +    test "does not allow choice index to be greater than options count", %{conn: conn} do +      user = insert(:user) +      other_user = insert(:user) + +      {:ok, activity} = +        CommonAPI.post(user, %{ +          "status" => "Am I cute?", +          "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20} +        }) + +      object = Object.normalize(activity) + +      conn = +        conn +        |> assign(:user, other_user) +        |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]}) + +      assert json_response(conn, 422) == %{"error" => "Invalid indices"} +    end + +    test "returns 404 error when object is not exist", %{conn: conn} do +      user = insert(:user) + +      conn = +        conn +        |> assign(:user, user) +        |> post("/api/v1/polls/1/votes", %{"choices" => [0]}) + +      assert json_response(conn, 404) == %{"error" => "Record not found"} +    end + +    test "returns 404 when poll is private and not available for user", %{conn: conn} do +      user = insert(:user) +      other_user = insert(:user) + +      {:ok, activity} = +        CommonAPI.post(user, %{ +          "status" => "Am I cute?", +          "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}, +          "visibility" => "private" +        }) + +      object = Object.normalize(activity) + +      conn = +        conn +        |> assign(:user, other_user) +        |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]}) + +      assert json_response(conn, 404) == %{"error" => "Record not found"} +    end +  end +end diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index b194feae6..a4bbfe055 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -547,6 +547,24 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do        assert to_string(activity.id) == id      end +    test "reblogs privately and returns the reblogged status", %{conn: conn} do +      activity = insert(:note_activity) +      user = insert(:user) + +      conn = +        conn +        |> assign(:user, user) +        |> post("/api/v1/statuses/#{activity.id}/reblog", %{"visibility" => "private"}) + +      assert %{ +               "reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}, +               "reblogged" => true, +               "visibility" => "private" +             } = json_response(conn, 200) + +      assert to_string(activity.id) == id +    end +      test "reblogged status for another user", %{conn: conn} do        activity = insert(:note_activity)        user1 = insert(:user) @@ -1149,6 +1167,23 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do        assert Enum.empty?(response)      end +    test "does not return users who have reblogged the status privately", %{ +      conn: %{assigns: %{user: user}} = conn, +      activity: activity +    } do +      other_user = insert(:user) + +      {:ok, _, _} = CommonAPI.repeat(activity.id, other_user, %{"visibility" => "private"}) + +      response = +        conn +        |> assign(:user, user) +        |> get("/api/v1/statuses/#{activity.id}/reblogged_by") +        |> json_response(:ok) + +      assert Enum.empty?(response) +    end +      test "does not fail on an unauthenticated request", %{conn: conn, activity: activity} do        other_user = insert(:user)        {:ok, _, _} = CommonAPI.repeat(activity.id, other_user) @@ -1207,4 +1242,51 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do               "descendants" => [%{"id" => ^id4}, %{"id" => ^id5}]             } = response    end + +  test "returns the favorites of a user", %{conn: conn} do +    user = insert(:user) +    other_user = insert(:user) + +    {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"}) +    {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"}) + +    {:ok, _, _} = CommonAPI.favorite(activity.id, user) + +    first_conn = +      conn +      |> assign(:user, user) +      |> get("/api/v1/favourites") + +    assert [status] = json_response(first_conn, 200) +    assert status["id"] == to_string(activity.id) + +    assert [{"link", _link_header}] = +             Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end) + +    # Honours query params +    {:ok, second_activity} = +      CommonAPI.post(other_user, %{ +        "status" => +          "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful." +      }) + +    {:ok, _, _} = CommonAPI.favorite(second_activity.id, user) + +    last_like = status["id"] + +    second_conn = +      conn +      |> assign(:user, user) +      |> get("/api/v1/favourites?since_id=#{last_like}") + +    assert [second_status] = json_response(second_conn, 200) +    assert second_status["id"] == to_string(second_activity.id) + +    third_conn = +      conn +      |> assign(:user, user) +      |> get("/api/v1/favourites?limit=0") + +    assert [] = json_response(third_conn, 200) +  end  end diff --git a/test/web/mastodon_api/controllers/suggestion_controller_test.exs b/test/web/mastodon_api/controllers/suggestion_controller_test.exs new file mode 100644 index 000000000..78620a873 --- /dev/null +++ b/test/web/mastodon_api/controllers/suggestion_controller_test.exs @@ -0,0 +1,92 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do +  use Pleroma.Web.ConnCase + +  alias Pleroma.Config + +  import ExUnit.CaptureLog +  import Pleroma.Factory +  import Tesla.Mock + +  setup do +    user = insert(:user) +    other_user = insert(:user) +    host = Config.get([Pleroma.Web.Endpoint, :url, :host]) +    url500 = "http://test500?#{host}&#{user.nickname}" +    url200 = "http://test200?#{host}&#{user.nickname}" + +    mock(fn +      %{method: :get, url: ^url500} -> +        %Tesla.Env{status: 500, body: "bad request"} + +      %{method: :get, url: ^url200} -> +        %Tesla.Env{ +          status: 200, +          body: +            ~s([{"acct":"yj455","avatar":"https://social.heldscal.la/avatar/201.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/201.jpeg"}, {"acct":"#{ +              other_user.ap_id +            }","avatar":"https://social.heldscal.la/avatar/202.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/202.jpeg"}]) +        } +    end) + +    [user: user, other_user: other_user] +  end + +  clear_config(:suggestions) + +  test "returns empty result when suggestions disabled", %{conn: conn, user: user} do +    Config.put([:suggestions, :enabled], false) + +    res = +      conn +      |> assign(:user, user) +      |> get("/api/v1/suggestions") +      |> json_response(200) + +    assert res == [] +  end + +  test "returns error", %{conn: conn, user: user} do +    Config.put([:suggestions, :enabled], true) +    Config.put([:suggestions, :third_party_engine], "http://test500?{{host}}&{{user}}") + +    assert capture_log(fn -> +             res = +               conn +               |> assign(:user, user) +               |> get("/api/v1/suggestions") +               |> json_response(500) + +             assert res == "Something went wrong" +           end) =~ "Could not retrieve suggestions" +  end + +  test "returns suggestions", %{conn: conn, user: user, other_user: other_user} do +    Config.put([:suggestions, :enabled], true) +    Config.put([:suggestions, :third_party_engine], "http://test200?{{host}}&{{user}}") + +    res = +      conn +      |> assign(:user, user) +      |> get("/api/v1/suggestions") +      |> json_response(200) + +    assert res == [ +             %{ +               "acct" => "yj455", +               "avatar" => "https://social.heldscal.la/avatar/201.jpeg", +               "avatar_static" => "https://social.heldscal.la/avatar/s/201.jpeg", +               "id" => 0 +             }, +             %{ +               "acct" => other_user.ap_id, +               "avatar" => "https://social.heldscal.la/avatar/202.jpeg", +               "avatar_static" => "https://social.heldscal.la/avatar/s/202.jpeg", +               "id" => other_user.id +             } +           ] +  end +end diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index feeaf079b..42a8779c0 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -5,21 +5,11 @@  defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do    use Pleroma.Web.ConnCase -  alias Ecto.Changeset -  alias Pleroma.Config    alias Pleroma.Notification -  alias Pleroma.Object    alias Pleroma.Repo -  alias Pleroma.Tests.ObanHelpers -  alias Pleroma.User -  alias Pleroma.Web.ActivityPub.ActivityPub    alias Pleroma.Web.CommonAPI -  alias Pleroma.Web.OAuth.App -  alias Pleroma.Web.Push -  import ExUnit.CaptureLog    import Pleroma.Factory -  import Swoosh.TestAssertions    import Tesla.Mock    setup do @@ -27,123 +17,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do      :ok    end -  clear_config([:instance, :public])    clear_config([:rich_media, :enabled]) -  test "apps/verify_credentials", %{conn: conn} do -    token = insert(:oauth_token) - -    conn = -      conn -      |> assign(:user, token.user) -      |> assign(:token, token) -      |> get("/api/v1/apps/verify_credentials") - -    app = Repo.preload(token, :app).app - -    expected = %{ -      "name" => app.client_name, -      "website" => app.website, -      "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key) -    } - -    assert expected == json_response(conn, 200) -  end - -  test "creates an oauth app", %{conn: conn} do -    user = insert(:user) -    app_attrs = build(:oauth_app) - -    conn = -      conn -      |> assign(:user, user) -      |> post("/api/v1/apps", %{ -        client_name: app_attrs.client_name, -        redirect_uris: app_attrs.redirect_uris -      }) - -    [app] = Repo.all(App) - -    expected = %{ -      "name" => app.client_name, -      "website" => app.website, -      "client_id" => app.client_id, -      "client_secret" => app.client_secret, -      "id" => app.id |> to_string(), -      "redirect_uri" => app.redirect_uris, -      "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key) -    } - -    assert expected == json_response(conn, 200) -  end - -  describe "media upload" do -    setup do -      user = insert(:user) - -      conn = -        build_conn() -        |> assign(:user, user) - -      image = %Plug.Upload{ -        content_type: "image/jpg", -        path: Path.absname("test/fixtures/image.jpg"), -        filename: "an_image.jpg" -      } - -      [conn: conn, image: image] -    end - -    clear_config([:media_proxy]) -    clear_config([Pleroma.Upload]) - -    test "returns uploaded image", %{conn: conn, image: image} do -      desc = "Description of the image" - -      media = -        conn -        |> post("/api/v1/media", %{"file" => image, "description" => desc}) -        |> json_response(:ok) - -      assert media["type"] == "image" -      assert media["description"] == desc -      assert media["id"] - -      object = Repo.get(Object, media["id"]) -      assert object.data["actor"] == User.ap_id(conn.assigns[:user]) -    end -  end - -  test "getting a list of mutes", %{conn: conn} do -    user = insert(:user) -    other_user = insert(:user) - -    {:ok, user} = User.mute(user, other_user) - -    conn = -      conn -      |> assign(:user, user) -      |> get("/api/v1/mutes") - -    other_user_id = to_string(other_user.id) -    assert [%{"id" => ^other_user_id}] = json_response(conn, 200) -  end - -  test "getting a list of blocks", %{conn: conn} do -    user = insert(:user) -    other_user = insert(:user) - -    {:ok, user} = User.block(user, other_user) - -    conn = -      conn -      |> assign(:user, user) -      |> get("/api/v1/blocks") - -    other_user_id = to_string(other_user.id) -    assert [%{"id" => ^other_user_id}] = json_response(conn, 200) -  end -    test "unimplemented follow_requests, blocks, domain blocks" do      user = insert(:user) @@ -158,137 +33,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do      end)    end -  test "returns the favorites of a user", %{conn: conn} do -    user = insert(:user) -    other_user = insert(:user) - -    {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"}) -    {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"}) - -    {:ok, _, _} = CommonAPI.favorite(activity.id, user) - -    first_conn = -      conn -      |> assign(:user, user) -      |> get("/api/v1/favourites") - -    assert [status] = json_response(first_conn, 200) -    assert status["id"] == to_string(activity.id) - -    assert [{"link", _link_header}] = -             Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end) - -    # Honours query params -    {:ok, second_activity} = -      CommonAPI.post(other_user, %{ -        "status" => -          "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful." -      }) - -    {:ok, _, _} = CommonAPI.favorite(second_activity.id, user) - -    last_like = status["id"] - -    second_conn = -      conn -      |> assign(:user, user) -      |> get("/api/v1/favourites?since_id=#{last_like}") - -    assert [second_status] = json_response(second_conn, 200) -    assert second_status["id"] == to_string(second_activity.id) - -    third_conn = -      conn -      |> assign(:user, user) -      |> get("/api/v1/favourites?limit=0") - -    assert [] = json_response(third_conn, 200) -  end - -  test "get instance information", %{conn: conn} do -    conn = get(conn, "/api/v1/instance") -    assert result = json_response(conn, 200) - -    email = Config.get([:instance, :email]) -    # Note: not checking for "max_toot_chars" since it's optional -    assert %{ -             "uri" => _, -             "title" => _, -             "description" => _, -             "version" => _, -             "email" => from_config_email, -             "urls" => %{ -               "streaming_api" => _ -             }, -             "stats" => _, -             "thumbnail" => _, -             "languages" => _, -             "registrations" => _, -             "poll_limits" => _ -           } = result - -    assert email == from_config_email -  end - -  test "get instance stats", %{conn: conn} do -    user = insert(:user, %{local: true}) - -    user2 = insert(:user, %{local: true}) -    {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated) - -    insert(:user, %{local: false, nickname: "u@peer1.com"}) -    insert(:user, %{local: false, nickname: "u@peer2.com"}) - -    {:ok, _} = CommonAPI.post(user, %{"status" => "cofe"}) - -    # Stats should count users with missing or nil `info.deactivated` value - -    {:ok, _user} = -      user.id -      |> User.get_cached_by_id() -      |> User.update_info(&Changeset.change(&1, %{deactivated: nil})) - -    Pleroma.Stats.force_update() - -    conn = get(conn, "/api/v1/instance") - -    assert result = json_response(conn, 200) - -    stats = result["stats"] - -    assert stats -    assert stats["user_count"] == 1 -    assert stats["status_count"] == 1 -    assert stats["domain_count"] == 2 -  end - -  test "get peers", %{conn: conn} do -    insert(:user, %{local: false, nickname: "u@peer1.com"}) -    insert(:user, %{local: false, nickname: "u@peer2.com"}) - -    Pleroma.Stats.force_update() - -    conn = get(conn, "/api/v1/instance/peers") - -    assert result = json_response(conn, 200) - -    assert ["peer1.com", "peer2.com"] == Enum.sort(result) -  end - -  test "put settings", %{conn: conn} do -    user = insert(:user) - -    conn = -      conn -      |> assign(:user, user) -      |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}}) - -    assert _result = json_response(conn, 200) - -    user = User.get_cached_by_ap_id(user.ap_id) -    assert user.info.settings == %{"programming" => "socks"} -  end -    describe "link headers" do      test "preserves parameters in link headers", %{conn: conn} do        user = insert(:user) @@ -321,463 +65,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do      end    end -  describe "custom emoji" do -    test "with tags", %{conn: conn} do -      [emoji | _body] = -        conn -        |> get("/api/v1/custom_emojis") -        |> json_response(200) - -      assert Map.has_key?(emoji, "shortcode") -      assert Map.has_key?(emoji, "static_url") -      assert Map.has_key?(emoji, "tags") -      assert is_list(emoji["tags"]) -      assert Map.has_key?(emoji, "category") -      assert Map.has_key?(emoji, "url") -      assert Map.has_key?(emoji, "visible_in_picker") -    end -  end - -  describe "index/2 redirections" do -    setup %{conn: conn} do -      session_opts = [ -        store: :cookie, -        key: "_test", -        signing_salt: "cooldude" -      ] - -      conn = -        conn -        |> Plug.Session.call(Plug.Session.init(session_opts)) -        |> fetch_session() - -      test_path = "/web/statuses/test" -      %{conn: conn, path: test_path} -    end - -    test "redirects not logged-in users to the login page", %{conn: conn, path: path} do -      conn = get(conn, path) - -      assert conn.status == 302 -      assert redirected_to(conn) == "/web/login" -    end - -    test "redirects not logged-in users to the login page on private instances", %{ -      conn: conn, -      path: path -    } do -      Config.put([:instance, :public], false) - -      conn = get(conn, path) - -      assert conn.status == 302 -      assert redirected_to(conn) == "/web/login" -    end - -    test "does not redirect logged in users to the login page", %{conn: conn, path: path} do -      token = insert(:oauth_token) - -      conn = -        conn -        |> assign(:user, token.user) -        |> put_session(:oauth_token, token.token) -        |> get(path) - -      assert conn.status == 200 -    end - -    test "saves referer path to session", %{conn: conn, path: path} do -      conn = get(conn, path) -      return_to = Plug.Conn.get_session(conn, :return_to) - -      assert return_to == path -    end - -    test "redirects to the saved path after log in", %{conn: conn, path: path} do -      app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".") -      auth = insert(:oauth_authorization, app: app) - -      conn = -        conn -        |> put_session(:return_to, path) -        |> get("/web/login", %{code: auth.token}) - -      assert conn.status == 302 -      assert redirected_to(conn) == path -    end - -    test "redirects to the getting-started page when referer is not present", %{conn: conn} do -      app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".") -      auth = insert(:oauth_authorization, app: app) - -      conn = get(conn, "/web/login", %{code: auth.token}) - -      assert conn.status == 302 -      assert redirected_to(conn) == "/web/getting-started" -    end -  end - -  describe "GET /api/v1/polls/:id" do -    test "returns poll entity for object id", %{conn: conn} do -      user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          "status" => "Pleroma does", -          "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20} -        }) - -      object = Object.normalize(activity) - -      conn = -        conn -        |> assign(:user, user) -        |> get("/api/v1/polls/#{object.id}") - -      response = json_response(conn, 200) -      id = to_string(object.id) -      assert %{"id" => ^id, "expired" => false, "multiple" => false} = response -    end - -    test "does not expose polls for private statuses", %{conn: conn} do -      user = insert(:user) -      other_user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          "status" => "Pleroma does", -          "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20}, -          "visibility" => "private" -        }) - -      object = Object.normalize(activity) - -      conn = -        conn -        |> assign(:user, other_user) -        |> get("/api/v1/polls/#{object.id}") - -      assert json_response(conn, 404) -    end -  end - -  describe "POST /api/v1/polls/:id/votes" do -    test "votes are added to the poll", %{conn: conn} do -      user = insert(:user) -      other_user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          "status" => "A very delicious sandwich", -          "poll" => %{ -            "options" => ["Lettuce", "Grilled Bacon", "Tomato"], -            "expires_in" => 20, -            "multiple" => true -          } -        }) - -      object = Object.normalize(activity) - -      conn = -        conn -        |> assign(:user, other_user) -        |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]}) - -      assert json_response(conn, 200) -      object = Object.get_by_id(object.id) - -      assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} -> -               total_items == 1 -             end) -    end - -    test "author can't vote", %{conn: conn} do -      user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          "status" => "Am I cute?", -          "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20} -        }) - -      object = Object.normalize(activity) - -      assert conn -             |> assign(:user, user) -             |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [1]}) -             |> json_response(422) == %{"error" => "Poll's author can't vote"} - -      object = Object.get_by_id(object.id) - -      refute Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 1 -    end - -    test "does not allow multiple choices on a single-choice question", %{conn: conn} do -      user = insert(:user) -      other_user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          "status" => "The glass is", -          "poll" => %{"options" => ["half empty", "half full"], "expires_in" => 20} -        }) - -      object = Object.normalize(activity) - -      assert conn -             |> assign(:user, other_user) -             |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1]}) -             |> json_response(422) == %{"error" => "Too many choices"} - -      object = Object.get_by_id(object.id) - -      refute Enum.any?(object.data["oneOf"], fn %{"replies" => %{"totalItems" => total_items}} -> -               total_items == 1 -             end) -    end - -    test "does not allow choice index to be greater than options count", %{conn: conn} do -      user = insert(:user) -      other_user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          "status" => "Am I cute?", -          "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20} -        }) - -      object = Object.normalize(activity) - -      conn = -        conn -        |> assign(:user, other_user) -        |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]}) - -      assert json_response(conn, 422) == %{"error" => "Invalid indices"} -    end - -    test "returns 404 error when object is not exist", %{conn: conn} do -      user = insert(:user) - -      conn = -        conn -        |> assign(:user, user) -        |> post("/api/v1/polls/1/votes", %{"choices" => [0]}) - -      assert json_response(conn, 404) == %{"error" => "Record not found"} -    end - -    test "returns 404 when poll is private and not available for user", %{conn: conn} do -      user = insert(:user) -      other_user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          "status" => "Am I cute?", -          "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}, -          "visibility" => "private" -        }) - -      object = Object.normalize(activity) - -      conn = -        conn -        |> assign(:user, other_user) -        |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]}) - -      assert json_response(conn, 404) == %{"error" => "Record not found"} -    end -  end - -  describe "POST /auth/password, with valid parameters" do -    setup %{conn: conn} do -      user = insert(:user) -      conn = post(conn, "/auth/password?email=#{user.email}") -      %{conn: conn, user: user} -    end - -    test "it returns 204", %{conn: conn} do -      assert json_response(conn, :no_content) -    end - -    test "it creates a PasswordResetToken record for user", %{user: user} do -      token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id) -      assert token_record -    end - -    test "it sends an email to user", %{user: user} do -      ObanHelpers.perform_all() -      token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id) - -      email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token) -      notify_email = Config.get([:instance, :notify_email]) -      instance_name = Config.get([:instance, :name]) - -      assert_email_sent( -        from: {instance_name, notify_email}, -        to: {user.name, user.email}, -        html_body: email.html_body -      ) -    end -  end - -  describe "POST /auth/password, with invalid parameters" do -    setup do -      user = insert(:user) -      {:ok, user: user} -    end - -    test "it returns 404 when user is not found", %{conn: conn, user: user} do -      conn = post(conn, "/auth/password?email=nonexisting_#{user.email}") -      assert conn.status == 404 -      assert conn.resp_body == "" -    end - -    test "it returns 400 when user is not local", %{conn: conn, user: user} do -      {:ok, user} = Repo.update(Changeset.change(user, local: false)) -      conn = post(conn, "/auth/password?email=#{user.email}") -      assert conn.status == 400 -      assert conn.resp_body == "" -    end -  end - -  describe "GET /api/v1/suggestions" do -    setup do -      user = insert(:user) -      other_user = insert(:user) -      host = Config.get([Pleroma.Web.Endpoint, :url, :host]) -      url500 = "http://test500?#{host}&#{user.nickname}" -      url200 = "http://test200?#{host}&#{user.nickname}" - -      mock(fn -        %{method: :get, url: ^url500} -> -          %Tesla.Env{status: 500, body: "bad request"} - -        %{method: :get, url: ^url200} -> -          %Tesla.Env{ -            status: 200, -            body: -              ~s([{"acct":"yj455","avatar":"https://social.heldscal.la/avatar/201.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/201.jpeg"}, {"acct":"#{ -                other_user.ap_id -              }","avatar":"https://social.heldscal.la/avatar/202.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/202.jpeg"}]) -          } -      end) - -      [user: user, other_user: other_user] -    end - -    clear_config(:suggestions) - -    test "returns empty result when suggestions disabled", %{conn: conn, user: user} do -      Config.put([:suggestions, :enabled], false) - -      res = -        conn -        |> assign(:user, user) -        |> get("/api/v1/suggestions") -        |> json_response(200) - -      assert res == [] -    end - -    test "returns error", %{conn: conn, user: user} do -      Config.put([:suggestions, :enabled], true) -      Config.put([:suggestions, :third_party_engine], "http://test500?{{host}}&{{user}}") - -      assert capture_log(fn -> -               res = -                 conn -                 |> assign(:user, user) -                 |> get("/api/v1/suggestions") -                 |> json_response(500) - -               assert res == "Something went wrong" -             end) =~ "Could not retrieve suggestions" -    end - -    test "returns suggestions", %{conn: conn, user: user, other_user: other_user} do -      Config.put([:suggestions, :enabled], true) -      Config.put([:suggestions, :third_party_engine], "http://test200?{{host}}&{{user}}") - -      res = -        conn -        |> assign(:user, user) -        |> get("/api/v1/suggestions") -        |> json_response(200) - -      assert res == [ -               %{ -                 "acct" => "yj455", -                 "avatar" => "https://social.heldscal.la/avatar/201.jpeg", -                 "avatar_static" => "https://social.heldscal.la/avatar/s/201.jpeg", -                 "id" => 0 -               }, -               %{ -                 "acct" => other_user.ap_id, -                 "avatar" => "https://social.heldscal.la/avatar/202.jpeg", -                 "avatar_static" => "https://social.heldscal.la/avatar/s/202.jpeg", -                 "id" => other_user.id -               } -             ] -    end -  end - -  describe "PUT /api/v1/media/:id" do -    setup do -      actor = insert(:user) - -      file = %Plug.Upload{ -        content_type: "image/jpg", -        path: Path.absname("test/fixtures/image.jpg"), -        filename: "an_image.jpg" -      } - -      {:ok, %Object{} = object} = -        ActivityPub.upload( -          file, -          actor: User.ap_id(actor), -          description: "test-m" -        ) - -      [actor: actor, object: object] -    end - -    test "updates name of media", %{conn: conn, actor: actor, object: object} do -      media = -        conn -        |> assign(:user, actor) -        |> put("/api/v1/media/#{object.id}", %{"description" => "test-media"}) -        |> json_response(:ok) - -      assert media["description"] == "test-media" -      assert refresh_record(object).data["name"] == "test-media" -    end - -    test "returns error wheb request is bad", %{conn: conn, actor: actor, object: object} do -      media = -        conn -        |> assign(:user, actor) -        |> put("/api/v1/media/#{object.id}", %{}) -        |> json_response(400) - -      assert media == %{"error" => "bad_request"} -    end -  end - -  describe "DELETE /auth/sign_out" do -    test "redirect to root page", %{conn: conn} do -      user = insert(:user) - -      conn = -        conn -        |> assign(:user, user) -        |> delete("/auth/sign_out") - -      assert conn.status == 302 -      assert redirected_to(conn) == "/" -    end -  end -    describe "empty_array, stubs for mastodon api" do      test "GET /api/v1/accounts/:id/identity_proofs", %{conn: conn} do        user = insert(:user) diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index 62b2ab7e3..b7a4938a6 100644 --- a/test/web/mastodon_api/views/account_view_test.exs +++ b/test/web/mastodon_api/views/account_view_test.exs @@ -418,6 +418,27 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do                 following_count: 1               } = AccountView.render("show.json", %{user: user, for: user})      end + +    test "shows unread_conversation_count only to the account owner" do +      user = insert(:user) +      other_user = insert(:user) + +      {:ok, _activity} = +        CommonAPI.post(user, %{ +          "status" => "Hey @#{other_user.nickname}.", +          "visibility" => "direct" +        }) + +      user = User.get_cached_by_ap_id(user.ap_id) + +      assert AccountView.render("show.json", %{user: user, for: other_user})[:pleroma][ +               :unread_conversation_count +             ] == nil + +      assert AccountView.render("show.json", %{user: user, for: user})[:pleroma][ +               :unread_conversation_count +             ] == 1 +    end    end    describe "follow requests counter" do diff --git a/test/web/mastodon_api/views/notification_view_test.exs b/test/web/mastodon_api/views/notification_view_test.exs index 81ab82e2b..c9043a69a 100644 --- a/test/web/mastodon_api/views/notification_view_test.exs +++ b/test/web/mastodon_api/views/notification_view_test.exs @@ -100,5 +100,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do        NotificationView.render("index.json", %{notifications: [notification], for: followed})      assert [expected] == result + +    User.perform(:delete, follower) +    notification = Notification |> Repo.one() |> Repo.preload(:activity) + +    assert [] == +             NotificationView.render("index.json", %{notifications: [notification], for: followed})    end  end diff --git a/test/web/mastodon_api/views/poll_view_test.exs b/test/web/mastodon_api/views/poll_view_test.exs new file mode 100644 index 000000000..8cd7636a5 --- /dev/null +++ b/test/web/mastodon_api/views/poll_view_test.exs @@ -0,0 +1,126 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.PollViewTest do +  use Pleroma.DataCase + +  alias Pleroma.Object +  alias Pleroma.Web.CommonAPI +  alias Pleroma.Web.MastodonAPI.PollView + +  import Pleroma.Factory +  import Tesla.Mock + +  setup do +    mock(fn env -> apply(HttpRequestMock, :request, [env]) end) +    :ok +  end + +  test "renders a poll" do +    user = insert(:user) + +    {:ok, activity} = +      CommonAPI.post(user, %{ +        "status" => "Is Tenshi eating a corndog cute?", +        "poll" => %{ +          "options" => ["absolutely!", "sure", "yes", "why are you even asking?"], +          "expires_in" => 20 +        } +      }) + +    object = Object.normalize(activity) + +    expected = %{ +      emojis: [], +      expired: false, +      id: to_string(object.id), +      multiple: false, +      options: [ +        %{title: "absolutely!", votes_count: 0}, +        %{title: "sure", votes_count: 0}, +        %{title: "yes", votes_count: 0}, +        %{title: "why are you even asking?", votes_count: 0} +      ], +      voted: false, +      votes_count: 0 +    } + +    result = PollView.render("show.json", %{object: object}) +    expires_at = result.expires_at +    result = Map.delete(result, :expires_at) + +    assert result == expected + +    expires_at = NaiveDateTime.from_iso8601!(expires_at) +    assert NaiveDateTime.diff(expires_at, NaiveDateTime.utc_now()) in 15..20 +  end + +  test "detects if it is multiple choice" do +    user = insert(:user) + +    {:ok, activity} = +      CommonAPI.post(user, %{ +        "status" => "Which Mastodon developer is your favourite?", +        "poll" => %{ +          "options" => ["Gargron", "Eugen"], +          "expires_in" => 20, +          "multiple" => true +        } +      }) + +    object = Object.normalize(activity) + +    assert %{multiple: true} = PollView.render("show.json", %{object: object}) +  end + +  test "detects emoji" do +    user = insert(:user) + +    {:ok, activity} = +      CommonAPI.post(user, %{ +        "status" => "What's with the smug face?", +        "poll" => %{ +          "options" => [":blank: sip", ":blank::blank: sip", ":blank::blank::blank: sip"], +          "expires_in" => 20 +        } +      }) + +    object = Object.normalize(activity) + +    assert %{emojis: [%{shortcode: "blank"}]} = PollView.render("show.json", %{object: object}) +  end + +  test "detects vote status" do +    user = insert(:user) +    other_user = insert(:user) + +    {:ok, activity} = +      CommonAPI.post(user, %{ +        "status" => "Which input devices do you use?", +        "poll" => %{ +          "options" => ["mouse", "trackball", "trackpoint"], +          "multiple" => true, +          "expires_in" => 20 +        } +      }) + +    object = Object.normalize(activity) + +    {:ok, _, object} = CommonAPI.vote(other_user, object, [1, 2]) + +    result = PollView.render("show.json", %{object: object, for: other_user}) + +    assert result[:voted] == true +    assert Enum.at(result[:options], 1)[:votes_count] == 1 +    assert Enum.at(result[:options], 2)[:votes_count] == 1 +  end + +  test "does not crash on polls with no end date" do +    object = Object.normalize("https://skippers-bin.com/notes/7x9tmrp97i") +    result = PollView.render("show.json", %{object: object}) + +    assert result[:expires_at] == nil +    assert result[:expired] == false +  end +end diff --git a/test/web/mastodon_api/views/status_view_test.exs b/test/web/mastodon_api/views/status_view_test.exs index 8df23d0a8..1d5a6e956 100644 --- a/test/web/mastodon_api/views/status_view_test.exs +++ b/test/web/mastodon_api/views/status_view_test.exs @@ -451,116 +451,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do      end    end -  describe "poll view" do -    test "renders a poll" do -      user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          "status" => "Is Tenshi eating a corndog cute?", -          "poll" => %{ -            "options" => ["absolutely!", "sure", "yes", "why are you even asking?"], -            "expires_in" => 20 -          } -        }) - -      object = Object.normalize(activity) - -      expected = %{ -        emojis: [], -        expired: false, -        id: to_string(object.id), -        multiple: false, -        options: [ -          %{title: "absolutely!", votes_count: 0}, -          %{title: "sure", votes_count: 0}, -          %{title: "yes", votes_count: 0}, -          %{title: "why are you even asking?", votes_count: 0} -        ], -        voted: false, -        votes_count: 0 -      } - -      result = StatusView.render("poll.json", %{object: object}) -      expires_at = result.expires_at -      result = Map.delete(result, :expires_at) - -      assert result == expected - -      expires_at = NaiveDateTime.from_iso8601!(expires_at) -      assert NaiveDateTime.diff(expires_at, NaiveDateTime.utc_now()) in 15..20 -    end - -    test "detects if it is multiple choice" do -      user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          "status" => "Which Mastodon developer is your favourite?", -          "poll" => %{ -            "options" => ["Gargron", "Eugen"], -            "expires_in" => 20, -            "multiple" => true -          } -        }) - -      object = Object.normalize(activity) - -      assert %{multiple: true} = StatusView.render("poll.json", %{object: object}) -    end - -    test "detects emoji" do -      user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          "status" => "What's with the smug face?", -          "poll" => %{ -            "options" => [":blank: sip", ":blank::blank: sip", ":blank::blank::blank: sip"], -            "expires_in" => 20 -          } -        }) - -      object = Object.normalize(activity) - -      assert %{emojis: [%{shortcode: "blank"}]} = -               StatusView.render("poll.json", %{object: object}) -    end - -    test "detects vote status" do -      user = insert(:user) -      other_user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          "status" => "Which input devices do you use?", -          "poll" => %{ -            "options" => ["mouse", "trackball", "trackpoint"], -            "multiple" => true, -            "expires_in" => 20 -          } -        }) - -      object = Object.normalize(activity) - -      {:ok, _, object} = CommonAPI.vote(other_user, object, [1, 2]) - -      result = StatusView.render("poll.json", %{object: object, for: other_user}) - -      assert result[:voted] == true -      assert Enum.at(result[:options], 1)[:votes_count] == 1 -      assert Enum.at(result[:options], 2)[:votes_count] == 1 -    end - -    test "does not crash on polls with no end date" do -      object = Object.normalize("https://skippers-bin.com/notes/7x9tmrp97i") -      result = StatusView.render("poll.json", %{object: object}) - -      assert result[:expires_at] == nil -      assert result[:expired] == false -    end -  end -    test "embeds a relationship in the account" do      user = insert(:user)      other_user = insert(:user) diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs index 0cf755806..4d0741d14 100644 --- a/test/web/oauth/oauth_controller_test.exs +++ b/test/web/oauth/oauth_controller_test.exs @@ -852,6 +852,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do        assert resp = json_response(conn, 403)        assert resp["error"] == "Password reset is required" +      assert resp["identifier"] == "password_reset_required"        refute Map.has_key?(resp, "access_token")      end diff --git a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs index 7eaeda4a0..8a6528cbb 100644 --- a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs +++ b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs @@ -8,6 +8,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do    alias Pleroma.Conversation.Participation    alias Pleroma.Notification    alias Pleroma.Repo +  alias Pleroma.User    alias Pleroma.Web.CommonAPI    import Pleroma.Factory @@ -73,6 +74,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      participation = Repo.preload(participation, :recipients) +    user = User.get_cached_by_id(user.id)      assert [user] == participation.recipients      assert other_user not in participation.recipients diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs index b8fcd41fa..d33eb1e42 100644 --- a/test/web/streamer/streamer_test.exs +++ b/test/web/streamer/streamer_test.exs @@ -233,30 +233,68 @@ defmodule Pleroma.Web.StreamerTest do      end    end -  test "it doesn't send to blocked users" do -    user = insert(:user) -    blocked_user = insert(:user) -    {:ok, user} = User.block(user, blocked_user) +  describe "blocks" do +    test "it doesn't send messages involving blocked users" do +      user = insert(:user) +      blocked_user = insert(:user) +      {:ok, user} = User.block(user, blocked_user) -    task = -      Task.async(fn -> -        refute_receive {:text, _}, 1_000 -      end) +      task = +        Task.async(fn -> +          refute_receive {:text, _}, 1_000 +        end) -    fake_socket = %StreamerSocket{ -      transport_pid: task.pid, -      user: user -    } +      fake_socket = %StreamerSocket{ +        transport_pid: task.pid, +        user: user +      } -    {:ok, activity} = CommonAPI.post(blocked_user, %{"status" => "Test"}) +      {:ok, activity} = CommonAPI.post(blocked_user, %{"status" => "Test"}) -    topics = %{ -      "public" => [fake_socket] -    } +      topics = %{ +        "public" => [fake_socket] +      } -    Worker.push_to_socket(topics, "public", activity) +      Worker.push_to_socket(topics, "public", activity) -    Task.await(task) +      Task.await(task) +    end + +    test "it doesn't send messages transitively involving blocked users" do +      blocker = insert(:user) +      blockee = insert(:user) +      friend = insert(:user) + +      task = +        Task.async(fn -> +          refute_receive {:text, _}, 1_000 +        end) + +      fake_socket = %StreamerSocket{ +        transport_pid: task.pid, +        user: blocker +      } + +      topics = %{ +        "public" => [fake_socket] +      } + +      {:ok, blocker} = User.block(blocker, blockee) + +      {:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey! @#{blockee.nickname}"}) + +      Worker.push_to_socket(topics, "public", activity_one) + +      {:ok, activity_two} = CommonAPI.post(blockee, %{"status" => "hey! @#{friend.nickname}"}) + +      Worker.push_to_socket(topics, "public", activity_two) + +      {:ok, activity_three} = CommonAPI.post(blockee, %{"status" => "hey! @#{blocker.nickname}"}) + +      Worker.push_to_socket(topics, "public", activity_three) + +      Task.await(task) +    end    end    test "it doesn't send unwanted DMs to list" do | 
