diff options
Diffstat (limited to 'test')
55 files changed, 1838 insertions, 507 deletions
diff --git a/test/config/transfer_task_test.exs b/test/config/transfer_task_test.exs index 0265a6156..473899d1d 100644 --- a/test/config/transfer_task_test.exs +++ b/test/config/transfer_task_test.exs @@ -16,6 +16,8 @@ defmodule Pleroma.Config.TransferTaskTest do      refute Application.get_env(:pleroma, :test_key)      refute Application.get_env(:idna, :test_key)      refute Application.get_env(:quack, :test_key) +    refute Application.get_env(:postgrex, :test_key) +    initial = Application.get_env(:logger, :level)      ConfigDB.create(%{        group: ":pleroma", @@ -35,16 +37,28 @@ defmodule Pleroma.Config.TransferTaskTest do        value: [:test_value1, :test_value2]      }) +    ConfigDB.create(%{ +      group: ":postgrex", +      key: ":test_key", +      value: :value +    }) + +    ConfigDB.create(%{group: ":logger", key: ":level", value: :debug}) +      TransferTask.start_link([])      assert Application.get_env(:pleroma, :test_key) == [live: 2, com: 3]      assert Application.get_env(:idna, :test_key) == [live: 15, com: 35]      assert Application.get_env(:quack, :test_key) == [:test_value1, :test_value2] +    assert Application.get_env(:logger, :level) == :debug +    assert Application.get_env(:postgrex, :test_key) == :value      on_exit(fn ->        Application.delete_env(:pleroma, :test_key)        Application.delete_env(:idna, :test_key)        Application.delete_env(:quack, :test_key) +      Application.delete_env(:postgrex, :test_key) +      Application.put_env(:logger, :level, initial)      end)    end @@ -78,8 +92,8 @@ defmodule Pleroma.Config.TransferTaskTest do    end    test "transfer config values with full subkey update" do -    emoji = Application.get_env(:pleroma, :emoji) -    assets = Application.get_env(:pleroma, :assets) +    clear_config(:emoji) +    clear_config(:assets)      ConfigDB.create(%{        group: ":pleroma", @@ -99,11 +113,6 @@ defmodule Pleroma.Config.TransferTaskTest do      assert emoji_env[:groups] == [a: 1, b: 2]      assets_env = Application.get_env(:pleroma, :assets)      assert assets_env[:mascots] == [a: 1, b: 2] - -    on_exit(fn -> -      Application.put_env(:pleroma, :emoji, emoji) -      Application.put_env(:pleroma, :assets, assets) -    end)    end    describe "pleroma restart" do @@ -112,8 +121,7 @@ defmodule Pleroma.Config.TransferTaskTest do      end      test "don't restart if no reboot time settings were changed" do -      emoji = Application.get_env(:pleroma, :emoji) -      on_exit(fn -> Application.put_env(:pleroma, :emoji, emoji) end) +      clear_config(:emoji)        ConfigDB.create(%{          group: ":pleroma", @@ -128,8 +136,7 @@ defmodule Pleroma.Config.TransferTaskTest do      end      test "on reboot time key" do -      chat = Application.get_env(:pleroma, :chat) -      on_exit(fn -> Application.put_env(:pleroma, :chat, chat) end) +      clear_config(:chat)        ConfigDB.create(%{          group: ":pleroma", @@ -141,8 +148,7 @@ defmodule Pleroma.Config.TransferTaskTest do      end      test "on reboot time subkey" do -      captcha = Application.get_env(:pleroma, Pleroma.Captcha) -      on_exit(fn -> Application.put_env(:pleroma, Pleroma.Captcha, captcha) end) +      clear_config(Pleroma.Captcha)        ConfigDB.create(%{          group: ":pleroma", @@ -154,13 +160,8 @@ defmodule Pleroma.Config.TransferTaskTest do      end      test "don't restart pleroma on reboot time key and subkey if there is false flag" do -      chat = Application.get_env(:pleroma, :chat) -      captcha = Application.get_env(:pleroma, Pleroma.Captcha) - -      on_exit(fn -> -        Application.put_env(:pleroma, :chat, chat) -        Application.put_env(:pleroma, Pleroma.Captcha, captcha) -      end) +      clear_config(:chat) +      clear_config(Pleroma.Captcha)        ConfigDB.create(%{          group: ":pleroma", diff --git a/test/emoji/formatter_test.exs b/test/emoji/formatter_test.exs index 3bfee9420..12af6cd8b 100644 --- a/test/emoji/formatter_test.exs +++ b/test/emoji/formatter_test.exs @@ -3,7 +3,6 @@  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Emoji.FormatterTest do -  alias Pleroma.Emoji    alias Pleroma.Emoji.Formatter    use Pleroma.DataCase @@ -32,30 +31,19 @@ defmodule Pleroma.Emoji.FormatterTest do      end    end -  describe "get_emoji" do +  describe "get_emoji_map" do      test "it returns the emoji used in the text" do -      text = "I love :firefox:" - -      assert Formatter.get_emoji(text) == [ -               {"firefox", -                %Emoji{ -                  code: "firefox", -                  file: "/emoji/Firefox.gif", -                  tags: ["Gif", "Fun"], -                  safe_code: "firefox", -                  safe_file: "/emoji/Firefox.gif" -                }} -             ] +      assert Formatter.get_emoji_map("I love :firefox:") == %{ +               "firefox" => "http://localhost:4001/emoji/Firefox.gif" +             }      end      test "it returns a nice empty result when no emojis are present" do -      text = "I love moominamma" -      assert Formatter.get_emoji(text) == [] +      assert Formatter.get_emoji_map("I love moominamma") == %{}      end      test "it doesn't die when text is absent" do -      text = nil -      assert Formatter.get_emoji(text) == [] +      assert Formatter.get_emoji_map(nil) == %{}      end    end  end diff --git a/test/fixtures/config/temp.secret.exs b/test/fixtures/config/temp.secret.exs index f4686c101..dc950ca30 100644 --- a/test/fixtures/config/temp.secret.exs +++ b/test/fixtures/config/temp.secret.exs @@ -7,3 +7,5 @@ config :pleroma, :second_setting, key: "value2", key2: ["Activity"]  config :quack, level: :info  config :pleroma, Pleroma.Repo, pool: Ecto.Adapters.SQL.Sandbox + +config :postgrex, :json_library, Poison diff --git a/test/following_relationship_test.exs b/test/following_relationship_test.exs index 865bb3838..17a468abb 100644 --- a/test/following_relationship_test.exs +++ b/test/following_relationship_test.exs @@ -15,28 +15,28 @@ defmodule Pleroma.FollowingRelationshipTest do      test "returns following addresses without internal.fetch" do        user = insert(:user)        fetch_actor = InternalFetchActor.get_actor() -      FollowingRelationship.follow(fetch_actor, user, "accept") +      FollowingRelationship.follow(fetch_actor, user, :follow_accept)        assert FollowingRelationship.following(fetch_actor) == [user.follower_address]      end      test "returns following addresses without relay" do        user = insert(:user)        relay_actor = Relay.get_actor() -      FollowingRelationship.follow(relay_actor, user, "accept") +      FollowingRelationship.follow(relay_actor, user, :follow_accept)        assert FollowingRelationship.following(relay_actor) == [user.follower_address]      end      test "returns following addresses without remote user" do        user = insert(:user)        actor = insert(:user, local: false) -      FollowingRelationship.follow(actor, user, "accept") +      FollowingRelationship.follow(actor, user, :follow_accept)        assert FollowingRelationship.following(actor) == [user.follower_address]      end      test "returns following addresses with local user" do        user = insert(:user)        actor = insert(:user, local: true) -      FollowingRelationship.follow(actor, user, "accept") +      FollowingRelationship.follow(actor, user, :follow_accept)        assert FollowingRelationship.following(actor) == [                 actor.follower_address, diff --git a/test/formatter_test.exs b/test/formatter_test.exs index cf8441cf6..bef5a2c28 100644 --- a/test/formatter_test.exs +++ b/test/formatter_test.exs @@ -140,7 +140,7 @@ defmodule Pleroma.FormatterTest do        archaeme =          insert(:user,            nickname: "archa_eme_", -          source_data: %{"url" => "https://archeme/@archa_eme_"} +          uri: "https://archeme/@archa_eme_"          )        archaeme_remote = insert(:user, %{nickname: "archaeme@archae.me"}) @@ -150,13 +150,13 @@ defmodule Pleroma.FormatterTest do        assert length(mentions) == 3        expected_text = -        ~s(<span class="h-card"><a data-user="#{gsimg.id}" class="u-url mention" href="#{ +        ~s(<span class="h-card"><a class="u-url mention" data-user="#{gsimg.id}" href="#{            gsimg.ap_id -        }" rel="ugc">@<span>gsimg</span></a></span> According to <span class="h-card"><a data-user="#{ +        }" rel="ugc">@<span>gsimg</span></a></span> According to <span class="h-card"><a class="u-url mention" data-user="#{            archaeme.id -        }" class="u-url mention" href="#{"https://archeme/@archa_eme_"}" rel="ugc">@<span>archa_eme_</span></a></span>, that is @daggsy. Also hello <span class="h-card"><a data-user="#{ +        }" href="#{"https://archeme/@archa_eme_"}" rel="ugc">@<span>archa_eme_</span></a></span>, that is @daggsy. Also hello <span class="h-card"><a class="u-url mention" data-user="#{            archaeme_remote.id -        }" class="u-url mention" href="#{archaeme_remote.ap_id}" rel="ugc">@<span>archaeme</span></a></span>) +        }" href="#{archaeme_remote.ap_id}" rel="ugc">@<span>archaeme</span></a></span>)        assert expected_text == text      end @@ -171,7 +171,7 @@ defmodule Pleroma.FormatterTest do        assert length(mentions) == 1        expected_text = -        ~s(<span class="h-card"><a data-user="#{mike.id}" class="u-url mention" href="#{ +        ~s(<span class="h-card"><a class="u-url mention" data-user="#{mike.id}" href="#{            mike.ap_id          }" rel="ugc">@<span>mike</span></a></span> test) @@ -187,7 +187,7 @@ defmodule Pleroma.FormatterTest do        assert length(mentions) == 1        expected_text = -        ~s(<span class="h-card"><a data-user="#{o.id}" class="u-url mention" href="#{o.ap_id}" rel="ugc">@<span>o</span></a></span> hi) +        ~s(<span class="h-card"><a class="u-url mention" data-user="#{o.id}" href="#{o.ap_id}" rel="ugc">@<span>o</span></a></span> hi)        assert expected_text == text      end @@ -209,17 +209,13 @@ defmodule Pleroma.FormatterTest do        assert mentions == [{"@#{user.nickname}", user}, {"@#{other_user.nickname}", other_user}]        assert expected_text == -               ~s(<span class="h-card"><a data-user="#{user.id}" class="u-url mention" href="#{ +               ~s(<span class="h-card"><a class="u-url mention" data-user="#{user.id}" href="#{                   user.ap_id -               }" rel="ugc">@<span>#{user.nickname}</span></a></span> <span class="h-card"><a data-user="#{ +               }" rel="ugc">@<span>#{user.nickname}</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{                   other_user.id -               }" class="u-url mention" href="#{other_user.ap_id}" rel="ugc">@<span>#{ -                 other_user.nickname -               }</span></a></span> hey dudes i hate <span class="h-card"><a data-user="#{ +               }" href="#{other_user.ap_id}" rel="ugc">@<span>#{other_user.nickname}</span></a></span> hey dudes i hate <span class="h-card"><a class="u-url mention" data-user="#{                   third_user.id -               }" class="u-url mention" href="#{third_user.ap_id}" rel="ugc">@<span>#{ -                 third_user.nickname -               }</span></a></span>) +               }" href="#{third_user.ap_id}" rel="ugc">@<span>#{third_user.nickname}</span></a></span>)      end      test "given the 'safe_mention' option, it will still work without any mention" do diff --git a/test/notification_test.exs b/test/notification_test.exs index 837a9dacd..a7f53e319 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -8,11 +8,13 @@ defmodule Pleroma.NotificationTest do    import Pleroma.Factory    import Mock +  alias Pleroma.FollowingRelationship    alias Pleroma.Notification    alias Pleroma.Tests.ObanHelpers    alias Pleroma.User    alias Pleroma.Web.ActivityPub.Transmogrifier    alias Pleroma.Web.CommonAPI +  alias Pleroma.Web.MastodonAPI.NotificationView    alias Pleroma.Web.Push    alias Pleroma.Web.Streamer @@ -272,16 +274,6 @@ defmodule Pleroma.NotificationTest do        refute Notification.create_notification(activity, author)      end -    test "it doesn't create a notification for follow-unfollow-follow chains" do -      user = insert(:user) -      followed_user = insert(:user) -      {:ok, _, _, activity} = CommonAPI.follow(user, followed_user) -      Notification.create_notification(activity, followed_user) -      CommonAPI.unfollow(user, followed_user) -      {:ok, _, _, activity_dupe} = CommonAPI.follow(user, followed_user) -      refute Notification.create_notification(activity_dupe, followed_user) -    end -      test "it doesn't create duplicate notifications for follow+subscribed users" do        user = insert(:user)        subscriber = insert(:user) @@ -304,6 +296,74 @@ defmodule Pleroma.NotificationTest do      end    end +  describe "follow / follow_request notifications" do +    test "it creates `follow` notification for approved Follow activity" do +      user = insert(:user) +      followed_user = insert(:user, locked: false) + +      {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user) +      assert FollowingRelationship.following?(user, followed_user) +      assert [notification] = Notification.for_user(followed_user) + +      assert %{type: "follow"} = +               NotificationView.render("show.json", %{ +                 notification: notification, +                 for: followed_user +               }) +    end + +    test "if `follow_request` notifications are enabled, " <> +           "it creates `follow_request` notification for pending Follow activity" do +      clear_config([:notifications, :enable_follow_request_notifications], true) +      user = insert(:user) +      followed_user = insert(:user, locked: true) + +      {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user) +      refute FollowingRelationship.following?(user, followed_user) +      assert [notification] = Notification.for_user(followed_user) + +      render_opts = %{notification: notification, for: followed_user} +      assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts) + +      # After request is accepted, the same notification is rendered with type "follow": +      assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user) + +      notification_id = notification.id +      assert [%{id: ^notification_id}] = Notification.for_user(followed_user) +      assert %{type: "follow"} = NotificationView.render("show.json", render_opts) +    end + +    test "if `follow_request` notifications are disabled, " <> +           "it does NOT create `follow*` notification for pending Follow activity" do +      clear_config([:notifications, :enable_follow_request_notifications], false) +      user = insert(:user) +      followed_user = insert(:user, locked: true) + +      {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user) +      refute FollowingRelationship.following?(user, followed_user) +      assert [] = Notification.for_user(followed_user) + +      # After request is accepted, no new notifications are generated: +      assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user) +      assert [] = Notification.for_user(followed_user) +    end + +    test "it doesn't create a notification for follow-unfollow-follow chains" do +      user = insert(:user) +      followed_user = insert(:user, locked: false) + +      {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user) +      assert FollowingRelationship.following?(user, followed_user) +      assert [notification] = Notification.for_user(followed_user) + +      CommonAPI.unfollow(user, followed_user) +      {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user) + +      notification_id = notification.id +      assert [%{id: ^notification_id}] = Notification.for_user(followed_user) +    end +  end +    describe "get notification" do      test "it gets a notification that belongs to the user" do        user = insert(:user) diff --git a/test/plugs/authentication_plug_test.exs b/test/plugs/authentication_plug_test.exs index ae2f3f8ec..646bda9d3 100644 --- a/test/plugs/authentication_plug_test.exs +++ b/test/plugs/authentication_plug_test.exs @@ -6,6 +6,8 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do    use Pleroma.Web.ConnCase, async: true    alias Pleroma.Plugs.AuthenticationPlug +  alias Pleroma.Plugs.OAuthScopesPlug +  alias Pleroma.Plugs.PlugHelper    alias Pleroma.User    import ExUnit.CaptureLog @@ -36,13 +38,16 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do      assert ret_conn == conn    end -  test "with a correct password in the credentials, it assigns the auth_user", %{conn: conn} do +  test "with a correct password in the credentials, " <> +         "it assigns the auth_user and marks OAuthScopesPlug as skipped", +       %{conn: conn} do      conn =        conn        |> assign(:auth_credentials, %{password: "guy"})        |> AuthenticationPlug.call(%{})      assert conn.assigns.user == conn.assigns.auth_user +    assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)    end    test "with a wrong password in the credentials, it does nothing", %{conn: conn} do diff --git a/test/plugs/legacy_authentication_plug_test.exs b/test/plugs/legacy_authentication_plug_test.exs index 7559de7d3..3b8c07627 100644 --- a/test/plugs/legacy_authentication_plug_test.exs +++ b/test/plugs/legacy_authentication_plug_test.exs @@ -8,6 +8,8 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do    import Pleroma.Factory    alias Pleroma.Plugs.LegacyAuthenticationPlug +  alias Pleroma.Plugs.OAuthScopesPlug +  alias Pleroma.Plugs.PlugHelper    alias Pleroma.User    setup do @@ -36,7 +38,8 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do    end    @tag :skip_on_mac -  test "it authenticates the auth_user if present and password is correct and resets the password", +  test "if `auth_user` is present and password is correct, " <> +         "it authenticates the user, resets the password, marks OAuthScopesPlug as skipped",         %{           conn: conn,           user: user @@ -49,6 +52,7 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do      conn = LegacyAuthenticationPlug.call(conn, %{})      assert conn.assigns.user.id == user.id +    assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)    end    @tag :skip_on_mac diff --git a/test/plugs/oauth_scopes_plug_test.exs b/test/plugs/oauth_scopes_plug_test.exs index e79ecf263..edbc94227 100644 --- a/test/plugs/oauth_scopes_plug_test.exs +++ b/test/plugs/oauth_scopes_plug_test.exs @@ -16,6 +16,18 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do      :ok    end +  test "is not performed if marked as skipped", %{conn: conn} do +    with_mock OAuthScopesPlug, [:passthrough], perform: &passthrough([&1, &2]) do +      conn = +        conn +        |> OAuthScopesPlug.skip_plug() +        |> OAuthScopesPlug.call(%{scopes: ["random_scope"]}) + +      refute called(OAuthScopesPlug.perform(:_, :_)) +      refute conn.halted +    end +  end +    test "if `token.scopes` fulfills specified 'any of' conditions, " <>           "proceeds with no op",         %{conn: conn} do diff --git a/test/plugs/rate_limiter_test.exs b/test/plugs/rate_limiter_test.exs index 0ce9f3a0a..4d3d694f4 100644 --- a/test/plugs/rate_limiter_test.exs +++ b/test/plugs/rate_limiter_test.exs @@ -5,8 +5,10 @@  defmodule Pleroma.Plugs.RateLimiterTest do    use Pleroma.Web.ConnCase +  alias Phoenix.ConnTest    alias Pleroma.Config    alias Pleroma.Plugs.RateLimiter +  alias Plug.Conn    import Pleroma.Factory    import Pleroma.Tests.Helpers, only: [clear_config: 1, clear_config: 2] @@ -36,8 +38,15 @@ defmodule Pleroma.Plugs.RateLimiterTest do    end    test "it is disabled if it remote ip plug is enabled but no remote ip is found" do -    Config.put([Pleroma.Web.Endpoint, :http, :ip], {127, 0, 0, 1}) -    assert RateLimiter.disabled?(Plug.Conn.assign(build_conn(), :remote_ip_found, false)) +    assert RateLimiter.disabled?(Conn.assign(build_conn(), :remote_ip_found, false)) +  end + +  test "it is enabled if remote ip found" do +    refute RateLimiter.disabled?(Conn.assign(build_conn(), :remote_ip_found, true)) +  end + +  test "it is enabled if remote_ip_found flag doesn't exist" do +    refute RateLimiter.disabled?(build_conn())    end    test "it restricts based on config values" do @@ -58,7 +67,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do      end      conn = RateLimiter.call(conn, plug_opts) -    assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests) +    assert %{"error" => "Throttled"} = ConnTest.json_response(conn, :too_many_requests)      assert conn.halted      Process.sleep(50) @@ -68,7 +77,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do      conn = RateLimiter.call(conn, plug_opts)      assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts) -    refute conn.status == Plug.Conn.Status.code(:too_many_requests) +    refute conn.status == Conn.Status.code(:too_many_requests)      refute conn.resp_body      refute conn.halted    end @@ -98,7 +107,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do        plug_opts = RateLimiter.init(name: limiter_name, params: ["id"])        conn = build_conn(:get, "/?id=1") -      conn = Plug.Conn.fetch_query_params(conn) +      conn = Conn.fetch_query_params(conn)        conn_2 = build_conn(:get, "/?id=2")        RateLimiter.call(conn, plug_opts) @@ -119,7 +128,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do        id = "100"        conn = build_conn(:get, "/?id=#{id}") -      conn = Plug.Conn.fetch_query_params(conn) +      conn = Conn.fetch_query_params(conn)        conn_2 = build_conn(:get, "/?id=#{101}")        RateLimiter.call(conn, plug_opts) @@ -147,13 +156,13 @@ defmodule Pleroma.Plugs.RateLimiterTest do        conn = RateLimiter.call(conn, plug_opts) -      assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests) +      assert %{"error" => "Throttled"} = ConnTest.json_response(conn, :too_many_requests)        assert conn.halted        conn_2 = RateLimiter.call(conn_2, plug_opts)        assert {1, 4} = RateLimiter.inspect_bucket(conn_2, limiter_name, plug_opts) -      refute conn_2.status == Plug.Conn.Status.code(:too_many_requests) +      refute conn_2.status == Conn.Status.code(:too_many_requests)        refute conn_2.resp_body        refute conn_2.halted      end @@ -187,7 +196,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do        conn = RateLimiter.call(conn, plug_opts) -      assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests) +      assert %{"error" => "Throttled"} = ConnTest.json_response(conn, :too_many_requests)        assert conn.halted      end @@ -210,12 +219,12 @@ defmodule Pleroma.Plugs.RateLimiterTest do        end        conn = RateLimiter.call(conn, plug_opts) -      assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests) +      assert %{"error" => "Throttled"} = ConnTest.json_response(conn, :too_many_requests)        assert conn.halted        conn_2 = RateLimiter.call(conn_2, plug_opts)        assert {1, 4} = RateLimiter.inspect_bucket(conn_2, limiter_name, plug_opts) -      refute conn_2.status == Plug.Conn.Status.code(:too_many_requests) +      refute conn_2.status == Conn.Status.code(:too_many_requests)        refute conn_2.resp_body        refute conn_2.halted      end diff --git a/test/signature_test.exs b/test/signature_test.exs index 04736d8b9..d5a2a62c4 100644 --- a/test/signature_test.exs +++ b/test/signature_test.exs @@ -19,12 +19,7 @@ defmodule Pleroma.SignatureTest do    @private_key "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEA48qb4v6kqigZutO9Ot0wkp27GIF2LiVaADgxQORZozZR63jH\nTaoOrS3Xhngbgc8SSOhfXET3omzeCLqaLNfXnZ8OXmuhJfJSU6mPUvmZ9QdT332j\nfN/g3iWGhYMf/M9ftCKh96nvFVO/tMruzS9xx7tkrfJjehdxh/3LlJMMImPtwcD7\nkFXwyt1qZTAU6Si4oQAJxRDQXHp1ttLl3Ob829VM7IKkrVmY8TD+JSlV0jtVJPj6\n1J19ytKTx/7UaucYvb9HIiBpkuiy5n/irDqKLVf5QEdZoNCdojOZlKJmTLqHhzKP\n3E9TxsUjhrf4/EqegNc/j982RvOxeu4i40zMQwIDAQABAoIBAQDH5DXjfh21i7b4\ncXJuw0cqget617CDUhemdakTDs9yH+rHPZd3mbGDWuT0hVVuFe4vuGpmJ8c+61X0\nRvugOlBlavxK8xvYlsqTzAmPgKUPljyNtEzQ+gz0I+3mH2jkin2rL3D+SksZZgKm\nfiYMPIQWB2WUF04gB46DDb2mRVuymGHyBOQjIx3WC0KW2mzfoFUFRlZEF+Nt8Ilw\nT+g/u0aZ1IWoszbsVFOEdghgZET0HEarum0B2Je/ozcPYtwmU10iBANGMKdLqaP/\nj954BPunrUf6gmlnLZKIKklJj0advx0NA+cL79+zeVB3zexRYSA5o9q0WPhiuTwR\n/aedWHnBAoGBAP0sDWBAM1Y4TRAf8ZI9PcztwLyHPzfEIqzbObJJnx1icUMt7BWi\n+/RMOnhrlPGE1kMhOqSxvXYN3u+eSmWTqai2sSH5Hdw2EqnrISSTnwNUPINX7fHH\njEkgmXQ6ixE48SuBZnb4w1EjdB/BA6/sjL+FNhggOc87tizLTkMXmMtTAoGBAOZV\n+wPuAMBDBXmbmxCuDIjoVmgSlgeRunB1SA8RCPAFAiUo3+/zEgzW2Oz8kgI+xVwM\n33XkLKrWG1Orhpp6Hm57MjIc5MG+zF4/YRDpE/KNG9qU1tiz0UD5hOpIU9pP4bR/\ngxgPxZzvbk4h5BfHWLpjlk8UUpgk6uxqfti48c1RAoGBALBOKDZ6HwYRCSGMjUcg\n3NPEUi84JD8qmFc2B7Tv7h2he2ykIz9iFAGpwCIyETQsJKX1Ewi0OlNnD3RhEEAy\nl7jFGQ+mkzPSeCbadmcpYlgIJmf1KN/x7fDTAepeBpCEzfZVE80QKbxsaybd3Dp8\nCfwpwWUFtBxr4c7J+gNhAGe/AoGAPn8ZyqkrPv9wXtyfqFjxQbx4pWhVmNwrkBPi\nZ2Qh3q4dNOPwTvTO8vjghvzIyR8rAZzkjOJKVFgftgYWUZfM5gE7T2mTkBYq8W+U\n8LetF+S9qAM2gDnaDx0kuUTCq7t87DKk6URuQ/SbI0wCzYjjRD99KxvChVGPBHKo\n1DjqMuECgYEAgJGNm7/lJCS2wk81whfy/ttKGsEIkyhPFYQmdGzSYC5aDc2gp1R3\nxtOkYEvdjfaLfDGEa4UX8CHHF+w3t9u8hBtcdhMH6GYb9iv6z0VBTt4A/11HUR49\n3Z7TQ18Iyh3jAUCzFV9IJlLIExq5Y7P4B3ojWFBN607sDCt8BMPbDYs=\n-----END RSA PRIVATE KEY-----" -  @public_key %{ -    "id" => "https://mastodon.social/users/lambadalambda#main-key", -    "owner" => "https://mastodon.social/users/lambadalambda", -    "publicKeyPem" => -      "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0P/Tq4gb4G/QVuMGbJo\nC/AfMNcv+m7NfrlOwkVzcU47jgESuYI4UtJayissCdBycHUnfVUd9qol+eznSODz\nCJhfJloqEIC+aSnuEPGA0POtWad6DU0E6/Ho5zQn5WAWUwbRQqowbrsm/GHo2+3v\neR5jGenwA6sYhINg/c3QQbksyV0uJ20Umyx88w8+TJuv53twOfmyDWuYNoQ3y5cc\nHKOZcLHxYOhvwg3PFaGfFHMFiNmF40dTXt9K96r7sbzc44iLD+VphbMPJEjkMuf8\nPGEFOBzy8pm3wJZw2v32RNW2VESwMYyqDzwHXGSq1a73cS7hEnc79gXlELsK04L9\nQQIDAQAB\n-----END PUBLIC KEY-----\n" -  } +  @public_key "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0P/Tq4gb4G/QVuMGbJo\nC/AfMNcv+m7NfrlOwkVzcU47jgESuYI4UtJayissCdBycHUnfVUd9qol+eznSODz\nCJhfJloqEIC+aSnuEPGA0POtWad6DU0E6/Ho5zQn5WAWUwbRQqowbrsm/GHo2+3v\neR5jGenwA6sYhINg/c3QQbksyV0uJ20Umyx88w8+TJuv53twOfmyDWuYNoQ3y5cc\nHKOZcLHxYOhvwg3PFaGfFHMFiNmF40dTXt9K96r7sbzc44iLD+VphbMPJEjkMuf8\nPGEFOBzy8pm3wJZw2v32RNW2VESwMYyqDzwHXGSq1a73cS7hEnc79gXlELsK04L9\nQQIDAQAB\n-----END PUBLIC KEY-----\n"    @rsa_public_key {      :RSAPublicKey, @@ -42,7 +37,7 @@ defmodule Pleroma.SignatureTest do      test "it returns key" do        expected_result = {:ok, @rsa_public_key} -      user = insert(:user, source_data: %{"publicKey" => @public_key}) +      user = insert(:user, public_key: @public_key)        assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == expected_result      end @@ -53,8 +48,8 @@ defmodule Pleroma.SignatureTest do               end) =~ "[error] Could not decode user"      end -    test "it returns error if public key is empty" do -      user = insert(:user, source_data: %{"publicKey" => %{}}) +    test "it returns error if public key is nil" do +      user = insert(:user, public_key: nil)        assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == {:error, :error}      end diff --git a/test/stat_test.exs b/test/stats_test.exs index bccc1c8d0..c1aeb2c7f 100644 --- a/test/stat_test.exs +++ b/test/stats_test.exs @@ -2,11 +2,21 @@  # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only -defmodule Pleroma.StateTest do +defmodule Pleroma.StatsTest do    use Pleroma.DataCase    import Pleroma.Factory    alias Pleroma.Web.CommonAPI +  describe "user count" do +    test "it ignores internal users" do +      _user = insert(:user, local: true) +      _internal = insert(:user, local: true, nickname: nil) +      _internal = Pleroma.Web.ActivityPub.Relay.get_actor() + +      assert match?(%{stats: %{user_count: 1}}, Pleroma.Stats.calculate_stat_data()) +    end +  end +    describe "status visibility count" do      test "on new status" do        user = insert(:user) diff --git a/test/support/api_spec_helpers.ex b/test/support/api_spec_helpers.ex new file mode 100644 index 000000000..80c69c788 --- /dev/null +++ b/test/support/api_spec_helpers.ex @@ -0,0 +1,57 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Tests.ApiSpecHelpers do +  @moduledoc """ +  OpenAPI spec test helpers +  """ + +  import ExUnit.Assertions + +  alias OpenApiSpex.Cast.Error +  alias OpenApiSpex.Reference +  alias OpenApiSpex.Schema + +  def assert_schema(value, schema) do +    api_spec = Pleroma.Web.ApiSpec.spec() + +    case OpenApiSpex.cast_value(value, schema, api_spec) do +      {:ok, data} -> +        data + +      {:error, errors} -> +        errors = +          Enum.map(errors, fn error -> +            message = Error.message(error) +            path = Error.path_to_string(error) +            "#{message} at #{path}" +          end) + +        flunk( +          "Value does not conform to schema #{schema.title}: #{Enum.join(errors, "\n")}\n#{ +            inspect(value) +          }" +        ) +    end +  end + +  def resolve_schema(%Schema{} = schema), do: schema + +  def resolve_schema(%Reference{} = ref) do +    schemas = Pleroma.Web.ApiSpec.spec().components.schemas +    Reference.resolve_schema(ref, schemas) +  end + +  def api_operations do +    paths = Pleroma.Web.ApiSpec.spec().paths + +    Enum.flat_map(paths, fn {_, path_item} -> +      path_item +      |> Map.take([:delete, :get, :head, :options, :patch, :post, :put, :trace]) +      |> Map.values() +      |> Enum.reject(&is_nil/1) +      |> Enum.uniq() +    end) +  end +end diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index 064874201..781622476 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -51,6 +51,42 @@ defmodule Pleroma.Web.ConnCase do          %{user: user, token: token, conn: conn}        end +      defp json_response_and_validate_schema(conn, status \\ nil) do +        content_type = +          conn +          |> Plug.Conn.get_resp_header("content-type") +          |> List.first() +          |> String.split(";") +          |> List.first() + +        status = status || conn.status + +        %{private: %{open_api_spex: %{operation_id: op_id, operation_lookup: lookup, spec: spec}}} = +          conn + +        schema = lookup[op_id].responses[status].content[content_type].schema +        json = json_response(conn, status) + +        case OpenApiSpex.cast_value(json, schema, spec) do +          {:ok, _data} -> +            json + +          {:error, errors} -> +            errors = +              Enum.map(errors, fn error -> +                message = OpenApiSpex.Cast.Error.message(error) +                path = OpenApiSpex.Cast.Error.path_to_string(error) +                "#{message} at #{path}" +              end) + +            flunk( +              "Response does not conform to schema of #{op_id} operation: #{ +                Enum.join(errors, "\n") +              }\n#{inspect(json)}" +            ) +        end +      end +        defp ensure_federating_or_authenticated(conn, url, user) do          initial_setting = Config.get([:instance, :federating])          on_exit(fn -> Config.put([:instance, :federating], initial_setting) end) diff --git a/test/support/factory.ex b/test/support/factory.ex index af639b6cd..f0b797fd4 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -294,7 +294,7 @@ defmodule Pleroma.Factory do    def oauth_app_factory do      %Pleroma.Web.OAuth.App{ -      client_name: "Some client", +      client_name: sequence(:client_name, &"Some client #{&1}"),        redirect_uris: "https://example.com/callback",        scopes: ["read", "write", "follow", "push", "admin"],        website: "https://example.com", diff --git a/test/tasks/app_test.exs b/test/tasks/app_test.exs new file mode 100644 index 000000000..b8f03566d --- /dev/null +++ b/test/tasks/app_test.exs @@ -0,0 +1,65 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.AppTest do +  use Pleroma.DataCase, async: true + +  setup_all do +    Mix.shell(Mix.Shell.Process) + +    on_exit(fn -> +      Mix.shell(Mix.Shell.IO) +    end) +  end + +  describe "creates new app" do +    test "with default scopes" do +      name = "Some name" +      redirect = "https://example.com" +      Mix.Tasks.Pleroma.App.run(["create", "-n", name, "-r", redirect]) + +      assert_app(name, redirect, ["read", "write", "follow", "push"]) +    end + +    test "with custom scopes" do +      name = "Another name" +      redirect = "https://example.com" + +      Mix.Tasks.Pleroma.App.run([ +        "create", +        "-n", +        name, +        "-r", +        redirect, +        "-s", +        "read,write,follow,push,admin" +      ]) + +      assert_app(name, redirect, ["read", "write", "follow", "push", "admin"]) +    end +  end + +  test "with errors" do +    Mix.Tasks.Pleroma.App.run(["create"]) +    {:mix_shell, :error, ["Creating failed:"]} +    {:mix_shell, :error, ["name: can't be blank"]} +    {:mix_shell, :error, ["redirect_uris: can't be blank"]} +  end + +  defp assert_app(name, redirect, scopes) do +    app = Repo.get_by(Pleroma.Web.OAuth.App, client_name: name) + +    assert_received {:mix_shell, :info, [message]} +    assert message == "#{name} successfully created:" + +    assert_received {:mix_shell, :info, [message]} +    assert message == "App client_id: #{app.client_id}" + +    assert_received {:mix_shell, :info, [message]} +    assert message == "App client_secret: #{app.client_secret}" + +    assert app.scopes == scopes +    assert app.redirect_uris == redirect +  end +end diff --git a/test/tasks/config_test.exs b/test/tasks/config_test.exs index 3dee4f082..04bc947a9 100644 --- a/test/tasks/config_test.exs +++ b/test/tasks/config_test.exs @@ -38,7 +38,7 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do        on_exit(fn -> Application.put_env(:quack, :level, initial) end)      end -    test "settings are migrated to db" do +    test "filtered settings are migrated to db" do        assert Repo.all(ConfigDB) == []        Mix.Tasks.Pleroma.Config.migrate_to_db("test/fixtures/config/temp.secret.exs") @@ -47,6 +47,7 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do        config2 = ConfigDB.get_by_params(%{group: ":pleroma", key: ":second_setting"})        config3 = ConfigDB.get_by_params(%{group: ":quack", key: ":level"})        refute ConfigDB.get_by_params(%{group: ":pleroma", key: "Pleroma.Repo"}) +      refute ConfigDB.get_by_params(%{group: ":postgrex", key: ":json_library"})        assert ConfigDB.from_binary(config1.value) == [key: "value", key2: [Repo]]        assert ConfigDB.from_binary(config2.value) == [key: "value2", key2: ["Activity"]] diff --git a/test/tasks/user_test.exs b/test/tasks/user_test.exs index b45f37263..8df835b56 100644 --- a/test/tasks/user_test.exs +++ b/test/tasks/user_test.exs @@ -140,7 +140,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do      test "user is unsubscribed" do        followed = insert(:user)        user = insert(:user) -      User.follow(user, followed, "accept") +      User.follow(user, followed, :follow_accept)        Mix.Tasks.Pleroma.User.run(["unsubscribe", user.nickname]) diff --git a/test/user_test.exs b/test/user_test.exs index 0479f294d..347c5be72 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -194,7 +194,8 @@ defmodule Pleroma.UserTest do      CommonAPI.follow(pending_follower, locked)      CommonAPI.follow(pending_follower, locked)      CommonAPI.follow(accepted_follower, locked) -    Pleroma.FollowingRelationship.update(accepted_follower, locked, "accept") + +    Pleroma.FollowingRelationship.update(accepted_follower, locked, :follow_accept)      assert [^pending_follower] = User.get_follow_requests(locked)    end @@ -319,7 +320,7 @@ defmodule Pleroma.UserTest do            following_address: "http://localhost:4001/users/fuser2/following"          }) -      {:ok, user} = User.follow(user, followed, "accept") +      {:ok, user} = User.follow(user, followed, :follow_accept)        {:ok, user, _activity} = User.unfollow(user, followed) @@ -332,7 +333,7 @@ defmodule Pleroma.UserTest do        followed = insert(:user)        user = insert(:user) -      {:ok, user} = User.follow(user, followed, "accept") +      {:ok, user} = User.follow(user, followed, :follow_accept)        assert User.following(user) == [user.follower_address, followed.follower_address] @@ -353,7 +354,7 @@ defmodule Pleroma.UserTest do    test "test if a user is following another user" do      followed = insert(:user)      user = insert(:user) -    User.follow(user, followed, "accept") +    User.follow(user, followed, :follow_accept)      assert User.following?(user, followed)      refute User.following?(followed, user) @@ -581,7 +582,7 @@ defmodule Pleroma.UserTest do        {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin") -      assert user.source_data["endpoints"] +      assert user.inbox        refute user.last_refreshed_at == orig_user.last_refreshed_at      end @@ -609,7 +610,7 @@ defmodule Pleroma.UserTest do               ) <> "/followers"    end -  describe "remote user creation changeset" do +  describe "remote user changeset" do      @valid_remote %{        bio: "hello",        name: "Someone", @@ -621,28 +622,28 @@ defmodule Pleroma.UserTest do      setup do: clear_config([:instance, :user_name_length])      test "it confirms validity" do -      cs = User.remote_user_creation(@valid_remote) +      cs = User.remote_user_changeset(@valid_remote)        assert cs.valid?      end      test "it sets the follower_adress" do -      cs = User.remote_user_creation(@valid_remote) +      cs = User.remote_user_changeset(@valid_remote)        # remote users get a fake local follower address        assert cs.changes.follower_address ==                 User.ap_followers(%User{nickname: @valid_remote[:nickname]})      end      test "it enforces the fqn format for nicknames" do -      cs = User.remote_user_creation(%{@valid_remote | nickname: "bla"}) +      cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})        assert Ecto.Changeset.get_field(cs, :local) == false        assert cs.changes.avatar        refute cs.valid?      end      test "it has required fields" do -      [:name, :ap_id] +      [:ap_id]        |> Enum.each(fn field -> -        cs = User.remote_user_creation(Map.delete(@valid_remote, field)) +        cs = User.remote_user_changeset(Map.delete(@valid_remote, field))          refute cs.valid?        end)      end @@ -755,8 +756,8 @@ defmodule Pleroma.UserTest do        ]        {:ok, job} = User.follow_import(user1, identifiers) -      result = ObanHelpers.perform(job) +      assert {:ok, result} = ObanHelpers.perform(job)        assert is_list(result)        assert result == [user2, user3]      end @@ -978,14 +979,26 @@ defmodule Pleroma.UserTest do        ]        {:ok, job} = User.blocks_import(user1, identifiers) -      result = ObanHelpers.perform(job) +      assert {:ok, result} = ObanHelpers.perform(job)        assert is_list(result)        assert result == [user2, user3]      end    end    describe "get_recipients_from_activity" do +    test "works for announces" do +      actor = insert(:user) +      user = insert(:user, local: true) + +      {:ok, activity} = CommonAPI.post(actor, %{"status" => "hello"}) +      {:ok, announce, _} = CommonAPI.repeat(activity.id, user) + +      recipients = User.get_recipients_from_activity(announce) + +      assert user in recipients +    end +      test "get recipients" do        actor = insert(:user)        user = insert(:user, local: true) @@ -1198,58 +1211,6 @@ defmodule Pleroma.UserTest do      assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")    end -  describe "insert or update a user from given data" do -    test "with normal data" do -      user = insert(:user, %{nickname: "nick@name.de"}) -      data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname} - -      assert {:ok, %User{}} = User.insert_or_update_user(data) -    end - -    test "with overly long fields" do -      current_max_length = Pleroma.Config.get([:instance, :account_field_value_length], 255) -      user = insert(:user, nickname: "nickname@supergood.domain") - -      data = %{ -        ap_id: user.ap_id, -        name: user.name, -        nickname: user.nickname, -        fields: [ -          %{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)} -        ] -      } - -      assert {:ok, %User{}} = User.insert_or_update_user(data) -    end - -    test "with an overly long bio" do -      current_max_length = Pleroma.Config.get([:instance, :user_bio_length], 5000) -      user = insert(:user, nickname: "nickname@supergood.domain") - -      data = %{ -        ap_id: user.ap_id, -        name: user.name, -        nickname: user.nickname, -        bio: String.duplicate("h", current_max_length + 1) -      } - -      assert {:ok, %User{}} = User.insert_or_update_user(data) -    end - -    test "with an overly long display name" do -      current_max_length = Pleroma.Config.get([:instance, :user_name_length], 100) -      user = insert(:user, nickname: "nickname@supergood.domain") - -      data = %{ -        ap_id: user.ap_id, -        name: String.duplicate("h", current_max_length + 1), -        nickname: user.nickname -      } - -      assert {:ok, %User{}} = User.insert_or_update_user(data) -    end -  end -    describe "per-user rich-text filtering" do      test "html_filter_policy returns default policies, when rich-text is enabled" do        user = insert(:user) @@ -1404,7 +1365,7 @@ defmodule Pleroma.UserTest do        bio = "A.k.a. @nick@domain.com"        expected_text = -        ~s(A.k.a. <span class="h-card"><a data-user="#{remote_user.id}" class="u-url mention" href="#{ +        ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{            remote_user.ap_id          }" rel="ugc">@<span>nick@domain.com</span></a></span>) diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs index 573853afa..fbacb3993 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -1239,16 +1239,56 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do          filename: "an_image.jpg"        } -      conn = +      object =          conn          |> assign(:user, user)          |> post("/api/ap/upload_media", %{"file" => image, "description" => desc}) +        |> json_response(:created) -      assert object = json_response(conn, :created)        assert object["name"] == desc        assert object["type"] == "Document"        assert object["actor"] == user.ap_id +      assert [%{"href" => object_href, "mediaType" => object_mediatype}] = object["url"] +      assert is_binary(object_href) +      assert object_mediatype == "image/jpeg" + +      activity_request = %{ +        "@context" => "https://www.w3.org/ns/activitystreams", +        "type" => "Create", +        "object" => %{ +          "type" => "Note", +          "content" => "AP C2S test, attachment", +          "attachment" => [object] +        }, +        "to" => "https://www.w3.org/ns/activitystreams#Public", +        "cc" => [] +      } + +      activity_response = +        conn +        |> assign(:user, user) +        |> post("/users/#{user.nickname}/outbox", activity_request) +        |> json_response(:created) + +      assert activity_response["id"] +      assert activity_response["object"] +      assert activity_response["actor"] == user.ap_id + +      assert %Object{data: %{"attachment" => [attachment]}} = +               Object.normalize(activity_response["object"]) + +      assert attachment["type"] == "Document" +      assert attachment["name"] == desc + +      assert [ +               %{ +                 "href" => ^object_href, +                 "type" => "Link", +                 "mediaType" => ^object_mediatype +               } +             ] = attachment["url"] +      # Fails if unauthenticated        conn        |> post("/api/ap/upload_media", %{"file" => image, "description" => desc})        |> json_response(403) diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 17e7b97de..edd7dfb22 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -180,7 +180,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)        assert user.ap_id == user_id        assert user.nickname == "admin@mastodon.example.org" -      assert user.source_data        assert user.ap_enabled        assert user.follower_address == "http://mastodon.example.org/users/admin/followers"      end @@ -995,72 +994,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do      end    end -  describe "like an object" do -    test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do -      Config.put([:instance, :federating], true) -      note_activity = insert(:note_activity) -      assert object_activity = Object.normalize(note_activity) - -      user = insert(:user) - -      {:ok, like_activity, _object} = ActivityPub.like(user, object_activity) -      assert called(Federator.publish(like_activity)) -    end - -    test "returns exist activity if object already liked" do -      note_activity = insert(:note_activity) -      assert object_activity = Object.normalize(note_activity) - -      user = insert(:user) - -      {:ok, like_activity, _object} = ActivityPub.like(user, object_activity) - -      {:ok, like_activity_exist, _object} = ActivityPub.like(user, object_activity) -      assert like_activity == like_activity_exist -    end - -    test "reverts like activity on error" do -      note_activity = insert(:note_activity) -      object = Object.normalize(note_activity) -      user = insert(:user) - -      with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do -        assert {:error, :reverted} = ActivityPub.like(user, object) -      end - -      assert Repo.aggregate(Activity, :count, :id) == 1 -      assert Repo.get(Object, object.id) == object -    end - -    test "adds a like activity to the db" do -      note_activity = insert(:note_activity) -      assert object = Object.normalize(note_activity) - -      user = insert(:user) -      user_two = insert(:user) - -      {:ok, like_activity, object} = ActivityPub.like(user, object) - -      assert like_activity.data["actor"] == user.ap_id -      assert like_activity.data["type"] == "Like" -      assert like_activity.data["object"] == object.data["id"] -      assert like_activity.data["to"] == [User.ap_followers(user), note_activity.data["actor"]] -      assert like_activity.data["context"] == object.data["context"] -      assert object.data["like_count"] == 1 -      assert object.data["likes"] == [user.ap_id] - -      # Just return the original activity if the user already liked it. -      {:ok, same_like_activity, object} = ActivityPub.like(user, object) - -      assert like_activity == same_like_activity -      assert object.data["likes"] == [user.ap_id] -      assert object.data["like_count"] == 1 - -      {:ok, _like_activity, object} = ActivityPub.like(user_two, object) -      assert object.data["like_count"] == 2 -    end -  end -    describe "unliking" do      test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do        Config.put([:instance, :federating], true) @@ -1072,7 +1005,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        {:ok, object} = ActivityPub.unlike(user, object)        refute called(Federator.publish()) -      {:ok, _like_activity, object} = ActivityPub.like(user, object) +      {:ok, _like_activity} = CommonAPI.favorite(user, note_activity.id) +      object = Object.get_by_id(object.id)        assert object.data["like_count"] == 1        {:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object) @@ -1083,10 +1017,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do      test "reverts unliking on error" do        note_activity = insert(:note_activity) -      object = Object.normalize(note_activity)        user = insert(:user) -      {:ok, like_activity, object} = ActivityPub.like(user, object) +      {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id) +      object = Object.normalize(note_activity)        assert object.data["like_count"] == 1        with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do @@ -1107,7 +1041,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        {:ok, object} = ActivityPub.unlike(user, object)        assert object.data["like_count"] == 0 -      {:ok, like_activity, object} = ActivityPub.like(user, object) +      {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id) + +      object = Object.get_by_id(object.id)        assert object.data["like_count"] == 1        {:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object) @@ -1974,4 +1910,497 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do                 ActivityPub.move(old_user, new_user)      end    end + +  test "doesn't retrieve replies activities with exclude_replies" do +    user = insert(:user) + +    {:ok, activity} = CommonAPI.post(user, %{"status" => "yeah"}) + +    {:ok, _reply} = +      CommonAPI.post(user, %{"status" => "yeah", "in_reply_to_status_id" => activity.id}) + +    [result] = ActivityPub.fetch_public_activities(%{"exclude_replies" => "true"}) + +    assert result.id == activity.id + +    assert length(ActivityPub.fetch_public_activities()) == 2 +  end + +  describe "replies filtering with public messages" do +    setup :public_messages + +    test "public timeline", %{users: %{u1: user}} do +      activities_ids = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("local_only", false) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("reply_filtering_user", user) +        |> ActivityPub.fetch_public_activities() +        |> Enum.map(& &1.id) + +      assert length(activities_ids) == 16 +    end + +    test "public timeline with reply_visibility `following`", %{ +      users: %{u1: user}, +      u1: u1, +      u2: u2, +      u3: u3, +      u4: u4, +      activities: activities +    } do +      activities_ids = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("local_only", false) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("reply_visibility", "following") +        |> Map.put("reply_filtering_user", user) +        |> ActivityPub.fetch_public_activities() +        |> Enum.map(& &1.id) + +      assert length(activities_ids) == 14 + +      visible_ids = +        Map.values(u1) ++ Map.values(u2) ++ Map.values(u4) ++ Map.values(activities) ++ [u3[:r1]] + +      assert Enum.all?(visible_ids, &(&1 in activities_ids)) +    end + +    test "public timeline with reply_visibility `self`", %{ +      users: %{u1: user}, +      u1: u1, +      u2: u2, +      u3: u3, +      u4: u4, +      activities: activities +    } do +      activities_ids = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("local_only", false) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("reply_visibility", "self") +        |> Map.put("reply_filtering_user", user) +        |> ActivityPub.fetch_public_activities() +        |> Enum.map(& &1.id) + +      assert length(activities_ids) == 10 +      visible_ids = Map.values(u1) ++ [u2[:r1], u3[:r1], u4[:r1]] ++ Map.values(activities) +      assert Enum.all?(visible_ids, &(&1 in activities_ids)) +    end + +    test "home timeline", %{ +      users: %{u1: user}, +      activities: activities, +      u1: u1, +      u2: u2, +      u3: u3, +      u4: u4 +    } do +      params = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("user", user) +        |> Map.put("reply_filtering_user", user) + +      activities_ids = +        ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) +        |> Enum.map(& &1.id) + +      assert length(activities_ids) == 13 + +      visible_ids = +        Map.values(u1) ++ +          Map.values(u3) ++ +          [ +            activities[:a1], +            activities[:a2], +            activities[:a4], +            u2[:r1], +            u2[:r3], +            u4[:r1], +            u4[:r2] +          ] + +      assert Enum.all?(visible_ids, &(&1 in activities_ids)) +    end + +    test "home timeline with reply_visibility `following`", %{ +      users: %{u1: user}, +      activities: activities, +      u1: u1, +      u2: u2, +      u3: u3, +      u4: u4 +    } do +      params = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("user", user) +        |> Map.put("reply_visibility", "following") +        |> Map.put("reply_filtering_user", user) + +      activities_ids = +        ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) +        |> Enum.map(& &1.id) + +      assert length(activities_ids) == 11 + +      visible_ids = +        Map.values(u1) ++ +          [ +            activities[:a1], +            activities[:a2], +            activities[:a4], +            u2[:r1], +            u2[:r3], +            u3[:r1], +            u4[:r1], +            u4[:r2] +          ] + +      assert Enum.all?(visible_ids, &(&1 in activities_ids)) +    end + +    test "home timeline with reply_visibility `self`", %{ +      users: %{u1: user}, +      activities: activities, +      u1: u1, +      u2: u2, +      u3: u3, +      u4: u4 +    } do +      params = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("user", user) +        |> Map.put("reply_visibility", "self") +        |> Map.put("reply_filtering_user", user) + +      activities_ids = +        ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) +        |> Enum.map(& &1.id) + +      assert length(activities_ids) == 9 + +      visible_ids = +        Map.values(u1) ++ +          [ +            activities[:a1], +            activities[:a2], +            activities[:a4], +            u2[:r1], +            u3[:r1], +            u4[:r1] +          ] + +      assert Enum.all?(visible_ids, &(&1 in activities_ids)) +    end +  end + +  describe "replies filtering with private messages" do +    setup :private_messages + +    test "public timeline", %{users: %{u1: user}} do +      activities_ids = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("local_only", false) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("user", user) +        |> ActivityPub.fetch_public_activities() +        |> Enum.map(& &1.id) + +      assert activities_ids == [] +    end + +    test "public timeline with default reply_visibility `following`", %{users: %{u1: user}} do +      activities_ids = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("local_only", false) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("reply_visibility", "following") +        |> Map.put("reply_filtering_user", user) +        |> Map.put("user", user) +        |> ActivityPub.fetch_public_activities() +        |> Enum.map(& &1.id) + +      assert activities_ids == [] +    end + +    test "public timeline with default reply_visibility `self`", %{users: %{u1: user}} do +      activities_ids = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("local_only", false) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("reply_visibility", "self") +        |> Map.put("reply_filtering_user", user) +        |> Map.put("user", user) +        |> ActivityPub.fetch_public_activities() +        |> Enum.map(& &1.id) + +      assert activities_ids == [] +    end + +    test "home timeline", %{users: %{u1: user}} do +      params = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("user", user) + +      activities_ids = +        ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) +        |> Enum.map(& &1.id) + +      assert length(activities_ids) == 12 +    end + +    test "home timeline with default reply_visibility `following`", %{users: %{u1: user}} do +      params = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("user", user) +        |> Map.put("reply_visibility", "following") +        |> Map.put("reply_filtering_user", user) + +      activities_ids = +        ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) +        |> Enum.map(& &1.id) + +      assert length(activities_ids) == 12 +    end + +    test "home timeline with default reply_visibility `self`", %{ +      users: %{u1: user}, +      activities: activities, +      u1: u1, +      u2: u2, +      u3: u3, +      u4: u4 +    } do +      params = +        %{} +        |> Map.put("type", ["Create", "Announce"]) +        |> Map.put("blocking_user", user) +        |> Map.put("muting_user", user) +        |> Map.put("user", user) +        |> Map.put("reply_visibility", "self") +        |> Map.put("reply_filtering_user", user) + +      activities_ids = +        ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) +        |> Enum.map(& &1.id) + +      assert length(activities_ids) == 10 + +      visible_ids = +        Map.values(u1) ++ Map.values(u4) ++ [u2[:r1], u3[:r1]] ++ Map.values(activities) + +      assert Enum.all?(visible_ids, &(&1 in activities_ids)) +    end +  end + +  defp public_messages(_) do +    [u1, u2, u3, u4] = insert_list(4, :user) +    {:ok, u1} = User.follow(u1, u2) +    {:ok, u2} = User.follow(u2, u1) +    {:ok, u1} = User.follow(u1, u4) +    {:ok, u4} = User.follow(u4, u1) + +    {:ok, u2} = User.follow(u2, u3) +    {:ok, u3} = User.follow(u3, u2) + +    {:ok, a1} = CommonAPI.post(u1, %{"status" => "Status"}) + +    {:ok, r1_1} = +      CommonAPI.post(u2, %{ +        "status" => "@#{u1.nickname} reply from u2 to u1", +        "in_reply_to_status_id" => a1.id +      }) + +    {:ok, r1_2} = +      CommonAPI.post(u3, %{ +        "status" => "@#{u1.nickname} reply from u3 to u1", +        "in_reply_to_status_id" => a1.id +      }) + +    {:ok, r1_3} = +      CommonAPI.post(u4, %{ +        "status" => "@#{u1.nickname} reply from u4 to u1", +        "in_reply_to_status_id" => a1.id +      }) + +    {:ok, a2} = CommonAPI.post(u2, %{"status" => "Status"}) + +    {:ok, r2_1} = +      CommonAPI.post(u1, %{ +        "status" => "@#{u2.nickname} reply from u1 to u2", +        "in_reply_to_status_id" => a2.id +      }) + +    {:ok, r2_2} = +      CommonAPI.post(u3, %{ +        "status" => "@#{u2.nickname} reply from u3 to u2", +        "in_reply_to_status_id" => a2.id +      }) + +    {:ok, r2_3} = +      CommonAPI.post(u4, %{ +        "status" => "@#{u2.nickname} reply from u4 to u2", +        "in_reply_to_status_id" => a2.id +      }) + +    {:ok, a3} = CommonAPI.post(u3, %{"status" => "Status"}) + +    {:ok, r3_1} = +      CommonAPI.post(u1, %{ +        "status" => "@#{u3.nickname} reply from u1 to u3", +        "in_reply_to_status_id" => a3.id +      }) + +    {:ok, r3_2} = +      CommonAPI.post(u2, %{ +        "status" => "@#{u3.nickname} reply from u2 to u3", +        "in_reply_to_status_id" => a3.id +      }) + +    {:ok, r3_3} = +      CommonAPI.post(u4, %{ +        "status" => "@#{u3.nickname} reply from u4 to u3", +        "in_reply_to_status_id" => a3.id +      }) + +    {:ok, a4} = CommonAPI.post(u4, %{"status" => "Status"}) + +    {:ok, r4_1} = +      CommonAPI.post(u1, %{ +        "status" => "@#{u4.nickname} reply from u1 to u4", +        "in_reply_to_status_id" => a4.id +      }) + +    {:ok, r4_2} = +      CommonAPI.post(u2, %{ +        "status" => "@#{u4.nickname} reply from u2 to u4", +        "in_reply_to_status_id" => a4.id +      }) + +    {:ok, r4_3} = +      CommonAPI.post(u3, %{ +        "status" => "@#{u4.nickname} reply from u3 to u4", +        "in_reply_to_status_id" => a4.id +      }) + +    {:ok, +     users: %{u1: u1, u2: u2, u3: u3, u4: u4}, +     activities: %{a1: a1.id, a2: a2.id, a3: a3.id, a4: a4.id}, +     u1: %{r1: r1_1.id, r2: r1_2.id, r3: r1_3.id}, +     u2: %{r1: r2_1.id, r2: r2_2.id, r3: r2_3.id}, +     u3: %{r1: r3_1.id, r2: r3_2.id, r3: r3_3.id}, +     u4: %{r1: r4_1.id, r2: r4_2.id, r3: r4_3.id}} +  end + +  defp private_messages(_) do +    [u1, u2, u3, u4] = insert_list(4, :user) +    {:ok, u1} = User.follow(u1, u2) +    {:ok, u2} = User.follow(u2, u1) +    {:ok, u1} = User.follow(u1, u3) +    {:ok, u3} = User.follow(u3, u1) +    {:ok, u1} = User.follow(u1, u4) +    {:ok, u4} = User.follow(u4, u1) + +    {:ok, u2} = User.follow(u2, u3) +    {:ok, u3} = User.follow(u3, u2) + +    {:ok, a1} = CommonAPI.post(u1, %{"status" => "Status", "visibility" => "private"}) + +    {:ok, r1_1} = +      CommonAPI.post(u2, %{ +        "status" => "@#{u1.nickname} reply from u2 to u1", +        "in_reply_to_status_id" => a1.id, +        "visibility" => "private" +      }) + +    {:ok, r1_2} = +      CommonAPI.post(u3, %{ +        "status" => "@#{u1.nickname} reply from u3 to u1", +        "in_reply_to_status_id" => a1.id, +        "visibility" => "private" +      }) + +    {:ok, r1_3} = +      CommonAPI.post(u4, %{ +        "status" => "@#{u1.nickname} reply from u4 to u1", +        "in_reply_to_status_id" => a1.id, +        "visibility" => "private" +      }) + +    {:ok, a2} = CommonAPI.post(u2, %{"status" => "Status", "visibility" => "private"}) + +    {:ok, r2_1} = +      CommonAPI.post(u1, %{ +        "status" => "@#{u2.nickname} reply from u1 to u2", +        "in_reply_to_status_id" => a2.id, +        "visibility" => "private" +      }) + +    {:ok, r2_2} = +      CommonAPI.post(u3, %{ +        "status" => "@#{u2.nickname} reply from u3 to u2", +        "in_reply_to_status_id" => a2.id, +        "visibility" => "private" +      }) + +    {:ok, a3} = CommonAPI.post(u3, %{"status" => "Status", "visibility" => "private"}) + +    {:ok, r3_1} = +      CommonAPI.post(u1, %{ +        "status" => "@#{u3.nickname} reply from u1 to u3", +        "in_reply_to_status_id" => a3.id, +        "visibility" => "private" +      }) + +    {:ok, r3_2} = +      CommonAPI.post(u2, %{ +        "status" => "@#{u3.nickname} reply from u2 to u3", +        "in_reply_to_status_id" => a3.id, +        "visibility" => "private" +      }) + +    {:ok, a4} = CommonAPI.post(u4, %{"status" => "Status", "visibility" => "private"}) + +    {:ok, r4_1} = +      CommonAPI.post(u1, %{ +        "status" => "@#{u4.nickname} reply from u1 to u4", +        "in_reply_to_status_id" => a4.id, +        "visibility" => "private" +      }) + +    {:ok, +     users: %{u1: u1, u2: u2, u3: u3, u4: u4}, +     activities: %{a1: a1.id, a2: a2.id, a3: a3.id, a4: a4.id}, +     u1: %{r1: r1_1.id, r2: r1_2.id, r3: r1_3.id}, +     u2: %{r1: r2_1.id, r2: r2_2.id}, +     u3: %{r1: r3_1.id, r2: r3_2.id}, +     u4: %{r1: r4_1.id}} +  end  end diff --git a/test/web/activity_pub/mrf/object_age_policy_test.exs b/test/web/activity_pub/mrf/object_age_policy_test.exs index 7ee195eeb..b0fb753bd 100644 --- a/test/web/activity_pub/mrf/object_age_policy_test.exs +++ b/test/web/activity_pub/mrf/object_age_policy_test.exs @@ -20,26 +20,38 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do      :ok    end +  defp get_old_message do +    File.read!("test/fixtures/mastodon-post-activity.json") +    |> Poison.decode!() +  end + +  defp get_new_message do +    old_message = get_old_message() + +    new_object = +      old_message +      |> Map.get("object") +      |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601()) + +    old_message +    |> Map.put("object", new_object) +  end +    describe "with reject action" do      test "it rejects an old post" do        Config.put([:mrf_object_age, :actions], [:reject]) -      data = -        File.read!("test/fixtures/mastodon-post-activity.json") -        |> Poison.decode!() +      data = get_old_message() -      {:reject, _} = ObjectAgePolicy.filter(data) +      assert match?({:reject, _}, ObjectAgePolicy.filter(data))      end      test "it allows a new post" do        Config.put([:mrf_object_age, :actions], [:reject]) -      data = -        File.read!("test/fixtures/mastodon-post-activity.json") -        |> Poison.decode!() -        |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601()) +      data = get_new_message() -      {:ok, _} = ObjectAgePolicy.filter(data) +      assert match?({:ok, _}, ObjectAgePolicy.filter(data))      end    end @@ -47,9 +59,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do      test "it delists an old post" do        Config.put([:mrf_object_age, :actions], [:delist]) -      data = -        File.read!("test/fixtures/mastodon-post-activity.json") -        |> Poison.decode!() +      data = get_old_message()        {:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"]) @@ -61,14 +71,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do      test "it allows a new post" do        Config.put([:mrf_object_age, :actions], [:delist]) -      data = -        File.read!("test/fixtures/mastodon-post-activity.json") -        |> Poison.decode!() -        |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601()) +      data = get_new_message()        {:ok, _user} = User.get_or_fetch_by_ap_id(data["actor"]) -      {:ok, ^data} = ObjectAgePolicy.filter(data) +      assert match?({:ok, ^data}, ObjectAgePolicy.filter(data))      end    end @@ -76,9 +83,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do      test "it strips followers collections from an old post" do        Config.put([:mrf_object_age, :actions], [:strip_followers]) -      data = -        File.read!("test/fixtures/mastodon-post-activity.json") -        |> Poison.decode!() +      data = get_old_message()        {:ok, user} = User.get_or_fetch_by_ap_id(data["actor"]) @@ -91,14 +96,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do      test "it allows a new post" do        Config.put([:mrf_object_age, :actions], [:strip_followers]) -      data = -        File.read!("test/fixtures/mastodon-post-activity.json") -        |> Poison.decode!() -        |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601()) +      data = get_new_message()        {:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"]) -      {:ok, ^data} = ObjectAgePolicy.filter(data) +      assert match?({:ok, ^data}, ObjectAgePolicy.filter(data))      end    end  end diff --git a/test/web/activity_pub/mrf/simple_policy_test.exs b/test/web/activity_pub/mrf/simple_policy_test.exs index 91c24c2d9..b7b9bc6a2 100644 --- a/test/web/activity_pub/mrf/simple_policy_test.exs +++ b/test/web/activity_pub/mrf/simple_policy_test.exs @@ -17,7 +17,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do              reject: [],              accept: [],              avatar_removal: [], -            banner_removal: [] +            banner_removal: [], +            reject_deletes: []            )    describe "when :media_removal" do @@ -382,6 +383,66 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do      end    end +  describe "when :reject_deletes is empty" do +    setup do: Config.put([:mrf_simple, :reject_deletes], []) + +    test "it accepts deletions even from rejected servers" do +      Config.put([:mrf_simple, :reject], ["remote.instance"]) + +      deletion_message = build_remote_deletion_message() + +      assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message} +    end + +    test "it accepts deletions even from non-whitelisted servers" do +      Config.put([:mrf_simple, :accept], ["non.matching.remote"]) + +      deletion_message = build_remote_deletion_message() + +      assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message} +    end +  end + +  describe "when :reject_deletes is not empty but it doesn't have a matching host" do +    setup do: Config.put([:mrf_simple, :reject_deletes], ["non.matching.remote"]) + +    test "it accepts deletions even from rejected servers" do +      Config.put([:mrf_simple, :reject], ["remote.instance"]) + +      deletion_message = build_remote_deletion_message() + +      assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message} +    end + +    test "it accepts deletions even from non-whitelisted servers" do +      Config.put([:mrf_simple, :accept], ["non.matching.remote"]) + +      deletion_message = build_remote_deletion_message() + +      assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message} +    end +  end + +  describe "when :reject_deletes has a matching host" do +    setup do: Config.put([:mrf_simple, :reject_deletes], ["remote.instance"]) + +    test "it rejects the deletion" do +      deletion_message = build_remote_deletion_message() + +      assert SimplePolicy.filter(deletion_message) == {:reject, nil} +    end +  end + +  describe "when :reject_deletes match with wildcard domain" do +    setup do: Config.put([:mrf_simple, :reject_deletes], ["*.remote.instance"]) + +    test "it rejects the deletion" do +      deletion_message = build_remote_deletion_message() + +      assert SimplePolicy.filter(deletion_message) == {:reject, nil} +    end +  end +    defp build_local_message do      %{        "actor" => "#{Pleroma.Web.base_url()}/users/alice", @@ -408,4 +469,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        "type" => "Person"      }    end + +  defp build_remote_deletion_message do +    %{ +      "type" => "Delete", +      "actor" => "https://remote.instance/users/bob" +    } +  end  end diff --git a/test/web/activity_pub/publisher_test.exs b/test/web/activity_pub/publisher_test.exs index 801da03c1..c2bc38d52 100644 --- a/test/web/activity_pub/publisher_test.exs +++ b/test/web/activity_pub/publisher_test.exs @@ -48,10 +48,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do    describe "determine_inbox/2" do      test "it returns sharedInbox for messages involving as:Public in to" do -      user = -        insert(:user, %{ -          source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}} -        }) +      user = insert(:user, %{shared_inbox: "http://example.com/inbox"})        activity = %Activity{          data: %{"to" => [@as_public], "cc" => [user.follower_address]} @@ -61,10 +58,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do      end      test "it returns sharedInbox for messages involving as:Public in cc" do -      user = -        insert(:user, %{ -          source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}} -        }) +      user = insert(:user, %{shared_inbox: "http://example.com/inbox"})        activity = %Activity{          data: %{"cc" => [@as_public], "to" => [user.follower_address]} @@ -74,11 +68,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do      end      test "it returns sharedInbox for messages involving multiple recipients in to" do -      user = -        insert(:user, %{ -          source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}} -        }) - +      user = insert(:user, %{shared_inbox: "http://example.com/inbox"})        user_two = insert(:user)        user_three = insert(:user) @@ -90,11 +80,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do      end      test "it returns sharedInbox for messages involving multiple recipients in cc" do -      user = -        insert(:user, %{ -          source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}} -        }) - +      user = insert(:user, %{shared_inbox: "http://example.com/inbox"})        user_two = insert(:user)        user_three = insert(:user) @@ -107,12 +93,10 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do      test "it returns sharedInbox for messages involving multiple recipients in total" do        user = -        insert(:user, -          source_data: %{ -            "inbox" => "http://example.com/personal-inbox", -            "endpoints" => %{"sharedInbox" => "http://example.com/inbox"} -          } -        ) +        insert(:user, %{ +          shared_inbox: "http://example.com/inbox", +          inbox: "http://example.com/personal-inbox" +        })        user_two = insert(:user) @@ -125,12 +109,10 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do      test "it returns inbox for messages involving single recipients in total" do        user = -        insert(:user, -          source_data: %{ -            "inbox" => "http://example.com/personal-inbox", -            "endpoints" => %{"sharedInbox" => "http://example.com/inbox"} -          } -        ) +        insert(:user, %{ +          shared_inbox: "http://example.com/inbox", +          inbox: "http://example.com/personal-inbox" +        })        activity = %Activity{          data: %{"to" => [user.ap_id], "cc" => []} @@ -258,11 +240,11 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do                     [:passthrough],                     [] do        follower = -        insert(:user, +        insert(:user, %{            local: false, -          source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"}, +          inbox: "https://domain.com/users/nick1/inbox",            ap_enabled: true -        ) +        })        actor = insert(:user, follower_address: follower.ap_id)        user = insert(:user) @@ -295,14 +277,14 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do        fetcher =          insert(:user,            local: false, -          source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"}, +          inbox: "https://domain.com/users/nick1/inbox",            ap_enabled: true          )        another_fetcher =          insert(:user,            local: false, -          source_data: %{"inbox" => "https://domain2.com/users/nick1/inbox"}, +          inbox: "https://domain2.com/users/nick1/inbox",            ap_enabled: true          ) diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index b67bd14b3..0b6b55156 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -5,7 +5,9 @@  defmodule Pleroma.Web.ActivityPub.SideEffectsTest do    use Pleroma.DataCase +  alias Pleroma.Notification    alias Pleroma.Object +  alias Pleroma.Repo    alias Pleroma.Web.ActivityPub.ActivityPub    alias Pleroma.Web.ActivityPub.Builder    alias Pleroma.Web.ActivityPub.SideEffects @@ -15,13 +17,14 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do    describe "like objects" do      setup do +      poster = insert(:user)        user = insert(:user) -      {:ok, post} = CommonAPI.post(user, %{"status" => "hey"}) +      {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})        {:ok, like_data, _meta} = Builder.like(user, post.object)        {:ok, like, _meta} = ActivityPub.persist(like_data, local: true) -      %{like: like, user: user} +      %{like: like, user: user, poster: poster}      end      test "add the like to the original object", %{like: like, user: user} do @@ -30,5 +33,10 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do        assert object.data["like_count"] == 1        assert user.ap_id in object.data["likes"]      end + +    test "creates a notification", %{like: like, poster: poster} do +      {:ok, like, _} = SideEffects.handle(like) +      assert Repo.get_by(Notification, user_id: poster.id, activity_id: like.id) +    end    end  end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 6dfd823f7..6057e360a 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -746,7 +746,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        user = User.get_cached_by_ap_id(activity.actor) -      assert User.fields(user) == [ +      assert user.fields == [                 %{"name" => "foo", "value" => "bar"},                 %{"name" => "foo1", "value" => "bar1"}               ] @@ -767,7 +767,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        user = User.get_cached_by_ap_id(user.ap_id) -      assert User.fields(user) == [ +      assert user.fields == [                 %{"name" => "foo", "value" => "updated"},                 %{"name" => "foo1", "value" => "updated"}               ] @@ -785,7 +785,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        user = User.get_cached_by_ap_id(user.ap_id) -      assert User.fields(user) == [ +      assert user.fields == [                 %{"name" => "foo", "value" => "updated"},                 %{"name" => "foo1", "value" => "updated"}               ] @@ -796,7 +796,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        user = User.get_cached_by_ap_id(user.ap_id) -      assert User.fields(user) == [] +      assert user.fields == []      end      test "it works for incoming update activities which lock the account" do @@ -1230,19 +1230,13 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        attachment = %{          "type" => "Link",          "mediaType" => "video/mp4", -        "href" => -          "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", -        "mimeType" => "video/mp4", -        "size" => 5_015_880,          "url" => [            %{              "href" =>                "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", -            "mediaType" => "video/mp4", -            "type" => "Link" +            "mediaType" => "video/mp4"            } -        ], -        "width" => 480 +        ]        }        assert object.data["url"] == @@ -1624,7 +1618,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do          })        user_two = insert(:user) -      Pleroma.FollowingRelationship.follow(user_two, user, "accept") +      Pleroma.FollowingRelationship.follow(user_two, user, :follow_accept)        {:ok, activity} = CommonAPI.post(user, %{"status" => "test"})        {:ok, unrelated_activity} = CommonAPI.post(user_two, %{"status" => "test"}) @@ -2063,11 +2057,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do                   %{                     "mediaType" => "video/mp4",                     "url" => [ -                     %{ -                       "href" => "https://peertube.moe/stat-480.mp4", -                       "mediaType" => "video/mp4", -                       "type" => "Link" -                     } +                     %{"href" => "https://peertube.moe/stat-480.mp4", "mediaType" => "video/mp4"}                     ]                   }                 ] @@ -2085,23 +2075,13 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do                   %{                     "mediaType" => "video/mp4",                     "url" => [ -                     %{ -                       "href" => "https://pe.er/stat-480.mp4", -                       "mediaType" => "video/mp4", -                       "type" => "Link" -                     } +                     %{"href" => "https://pe.er/stat-480.mp4", "mediaType" => "video/mp4"}                     ]                   },                   %{ -                   "href" => "https://pe.er/stat-480.mp4",                     "mediaType" => "video/mp4", -                   "mimeType" => "video/mp4",                     "url" => [ -                     %{ -                       "href" => "https://pe.er/stat-480.mp4", -                       "mediaType" => "video/mp4", -                       "type" => "Link" -                     } +                     %{"href" => "https://pe.er/stat-480.mp4", "mediaType" => "video/mp4"}                     ]                   }                 ] @@ -2182,4 +2162,18 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do                 Transmogrifier.set_replies(object.data)["replies"]      end    end + +  test "take_emoji_tags/1" do +    user = insert(:user, %{emoji: %{"firefox" => "https://example.org/firefox.png"}}) + +    assert Transmogrifier.take_emoji_tags(user) == [ +             %{ +               "icon" => %{"type" => "Image", "url" => "https://example.org/firefox.png"}, +               "id" => "https://example.org/firefox.png", +               "name" => ":firefox:", +               "type" => "Emoji", +               "updated" => "1970-01-01T00:00:00Z" +             } +           ] +  end  end diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs index e913a5148..b0bfed917 100644 --- a/test/web/activity_pub/utils_test.exs +++ b/test/web/activity_pub/utils_test.exs @@ -224,8 +224,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do        object = Object.normalize(activity)        {:ok, [vote], object} = CommonAPI.vote(other_user, object, [0]) -      vote_object = Object.normalize(vote) -      {:ok, _activity, _object} = ActivityPub.like(user, vote_object) +      {:ok, _activity} = CommonAPI.favorite(user, activity.id)        [fetched_vote] = Utils.get_existing_votes(other_user.ap_id, object)        assert fetched_vote.id == vote.id      end @@ -346,7 +345,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do        user = insert(:user)        refute Utils.get_existing_like(user.ap_id, object) -      {:ok, like_activity, _object} = ActivityPub.like(user, object) +      {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)        assert ^like_activity = Utils.get_existing_like(user.ap_id, object)      end diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs index ecb2dc386..8d00893a5 100644 --- a/test/web/activity_pub/views/user_view_test.exs +++ b/test/web/activity_pub/views/user_view_test.exs @@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do      {:ok, user} =        insert(:user) -      |> User.upgrade_changeset(%{fields: fields}) +      |> User.update_changeset(%{fields: fields})        |> User.update_and_set_cache()      assert %{ @@ -38,7 +38,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do    end    test "Renders with emoji tags" do -    user = insert(:user, emoji: [%{"bib" => "/test"}]) +    user = insert(:user, emoji: %{"bib" => "/test"})      assert %{               "tag" => [ diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index fe8a086d8..f80dbf8dd 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -625,6 +625,39 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, :forbidden)      end + +    test "email with +", %{conn: conn, admin: admin} do +      recipient_email = "foo+bar@baz.com" + +      conn +      |> put_req_header("content-type", "application/json;charset=utf-8") +      |> post("/api/pleroma/admin/users/email_invite", %{email: recipient_email}) +      |> json_response(:no_content) + +      token_record = +        Pleroma.UserInviteToken +        |> Repo.all() +        |> List.last() + +      assert token_record +      refute token_record.used + +      notify_email = Config.get([:instance, :notify_email]) +      instance_name = Config.get([:instance, :name]) + +      email = +        Pleroma.Emails.UserEmail.user_invitation_email( +          admin, +          token_record, +          recipient_email +        ) + +      Swoosh.TestAssertions.assert_email_sent( +        from: {instance_name, notify_email}, +        to: recipient_email, +        html_body: email.html_body +      ) +    end    end    describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do @@ -637,7 +670,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD") -      assert json_response(conn, :internal_server_error) +      assert json_response(conn, :bad_request) == +               "To send invites you need to set the `invites_enabled` option to true."      end      test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do @@ -646,7 +680,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD") -      assert json_response(conn, :internal_server_error) +      assert json_response(conn, :bad_request) == +               "To send invites you need to set the `registrations_open` option to false."      end    end @@ -2075,7 +2110,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          |> get("/api/pleroma/admin/config")          |> json_response(200) -      refute Map.has_key?(configs, "need_reboot") +      assert configs["need_reboot"] == false      end      test "update setting which need reboot, don't change reboot flag until reboot", %{conn: conn} do @@ -2131,7 +2166,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          |> get("/api/pleroma/admin/config")          |> json_response(200) -      refute Map.has_key?(configs, "need_reboot") +      assert configs["need_reboot"] == false      end      test "saving config with nested merge", %{conn: conn} do @@ -2238,13 +2273,17 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do            value: :erlang.term_to_binary([])          ) +      Pleroma.Config.TransferTask.load_and_update_env([], false) + +      assert Application.get_env(:logger, :backends) == [] +        conn =          post(conn, "/api/pleroma/admin/config", %{            configs: [              %{                group: config.group,                key: config.key, -              value: [":console", %{"tuple" => ["ExSyslogger", ":ex_syslogger"]}] +              value: [":console"]              }            ]          }) @@ -2255,8 +2294,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "group" => ":logger",                     "key" => ":backends",                     "value" => [ -                     ":console", -                     %{"tuple" => ["ExSyslogger", ":ex_syslogger"]} +                     ":console"                     ],                     "db" => [":backends"]                   } @@ -2264,14 +2302,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do               }        assert Application.get_env(:logger, :backends) == [ -               :console, -               {ExSyslogger, :ex_syslogger} +               :console               ] - -      capture_log(fn -> -        require Logger -        Logger.warn("Ooops...") -      end) =~ "Ooops..."      end      test "saving full setting if value is not keyword", %{conn: conn} do @@ -2829,6 +2861,20 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end    end +  test "need_reboot flag", %{conn: conn} do +    assert conn +           |> get("/api/pleroma/admin/need_reboot") +           |> json_response(200) == %{"need_reboot" => false} + +    Restarter.Pleroma.need_reboot() + +    assert conn +           |> get("/api/pleroma/admin/need_reboot") +           |> json_response(200) == %{"need_reboot" => true} + +    on_exit(fn -> Restarter.Pleroma.refresh() end) +  end +    describe "GET /api/pleroma/admin/statuses" do      test "returns all public and unlisted statuses", %{conn: conn, admin: admin} do        blocked = insert(:user) @@ -3471,6 +3517,191 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 response["status_visibility"]      end    end + +  describe "POST /api/pleroma/admin/oauth_app" do +    test "errors", %{conn: conn} do +      response = conn |> post("/api/pleroma/admin/oauth_app", %{}) |> json_response(200) + +      assert response == %{"name" => "can't be blank", "redirect_uris" => "can't be blank"} +    end + +    test "success", %{conn: conn} do +      base_url = Pleroma.Web.base_url() +      app_name = "Trusted app" + +      response = +        conn +        |> post("/api/pleroma/admin/oauth_app", %{ +          name: app_name, +          redirect_uris: base_url +        }) +        |> json_response(200) + +      assert %{ +               "client_id" => _, +               "client_secret" => _, +               "name" => ^app_name, +               "redirect_uri" => ^base_url, +               "trusted" => false +             } = response +    end + +    test "with trusted", %{conn: conn} do +      base_url = Pleroma.Web.base_url() +      app_name = "Trusted app" + +      response = +        conn +        |> post("/api/pleroma/admin/oauth_app", %{ +          name: app_name, +          redirect_uris: base_url, +          trusted: true +        }) +        |> json_response(200) + +      assert %{ +               "client_id" => _, +               "client_secret" => _, +               "name" => ^app_name, +               "redirect_uri" => ^base_url, +               "trusted" => true +             } = response +    end +  end + +  describe "GET /api/pleroma/admin/oauth_app" do +    setup do +      app = insert(:oauth_app) +      {:ok, app: app} +    end + +    test "list", %{conn: conn} do +      response = +        conn +        |> get("/api/pleroma/admin/oauth_app") +        |> json_response(200) + +      assert %{"apps" => apps, "count" => count, "page_size" => _} = response + +      assert length(apps) == count +    end + +    test "with page size", %{conn: conn} do +      insert(:oauth_app) +      page_size = 1 + +      response = +        conn +        |> get("/api/pleroma/admin/oauth_app", %{page_size: to_string(page_size)}) +        |> json_response(200) + +      assert %{"apps" => apps, "count" => _, "page_size" => ^page_size} = response + +      assert length(apps) == page_size +    end + +    test "search by client name", %{conn: conn, app: app} do +      response = +        conn +        |> get("/api/pleroma/admin/oauth_app", %{name: app.client_name}) +        |> json_response(200) + +      assert %{"apps" => [returned], "count" => _, "page_size" => _} = response + +      assert returned["client_id"] == app.client_id +      assert returned["name"] == app.client_name +    end + +    test "search by client id", %{conn: conn, app: app} do +      response = +        conn +        |> get("/api/pleroma/admin/oauth_app", %{client_id: app.client_id}) +        |> json_response(200) + +      assert %{"apps" => [returned], "count" => _, "page_size" => _} = response + +      assert returned["client_id"] == app.client_id +      assert returned["name"] == app.client_name +    end + +    test "only trusted", %{conn: conn} do +      app = insert(:oauth_app, trusted: true) + +      response = +        conn +        |> get("/api/pleroma/admin/oauth_app", %{trusted: true}) +        |> json_response(200) + +      assert %{"apps" => [returned], "count" => _, "page_size" => _} = response + +      assert returned["client_id"] == app.client_id +      assert returned["name"] == app.client_name +    end +  end + +  describe "DELETE /api/pleroma/admin/oauth_app/:id" do +    test "with id", %{conn: conn} do +      app = insert(:oauth_app) + +      response = +        conn +        |> delete("/api/pleroma/admin/oauth_app/" <> to_string(app.id)) +        |> json_response(:no_content) + +      assert response == "" +    end + +    test "with non existance id", %{conn: conn} do +      response = +        conn +        |> delete("/api/pleroma/admin/oauth_app/0") +        |> json_response(:bad_request) + +      assert response == "" +    end +  end + +  describe "PATCH /api/pleroma/admin/oauth_app/:id" do +    test "with id", %{conn: conn} do +      app = insert(:oauth_app) + +      name = "another name" +      url = "https://example.com" +      scopes = ["admin"] +      id = app.id +      website = "http://website.com" + +      response = +        conn +        |> patch("/api/pleroma/admin/oauth_app/" <> to_string(app.id), %{ +          name: name, +          trusted: true, +          redirect_uris: url, +          scopes: scopes, +          website: website +        }) +        |> json_response(200) + +      assert %{ +               "client_id" => _, +               "client_secret" => _, +               "id" => ^id, +               "name" => ^name, +               "redirect_uri" => ^url, +               "trusted" => true, +               "website" => ^website +             } = response +    end + +    test "without id", %{conn: conn} do +      response = +        conn +        |> patch("/api/pleroma/admin/oauth_app/0") +        |> json_response(:bad_request) + +      assert response == "" +    end +  end  end  # Needed for testing diff --git a/test/web/api_spec/schema_examples_test.exs b/test/web/api_spec/schema_examples_test.exs new file mode 100644 index 000000000..88b6f07cb --- /dev/null +++ b/test/web/api_spec/schema_examples_test.exs @@ -0,0 +1,43 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ApiSpec.SchemaExamplesTest do +  use ExUnit.Case, async: true +  import Pleroma.Tests.ApiSpecHelpers + +  @content_type "application/json" + +  for operation <- api_operations() do +    describe operation.operationId <> " Request Body" do +      if operation.requestBody do +        @media_type operation.requestBody.content[@content_type] +        @schema resolve_schema(@media_type.schema) + +        if @media_type.example do +          test "request body media type example matches schema" do +            assert_schema(@media_type.example, @schema) +          end +        end + +        if @schema.example do +          test "request body schema example matches schema" do +            assert_schema(@schema.example, @schema) +          end +        end +      end +    end + +    for {status, response} <- operation.responses do +      describe "#{operation.operationId} - #{status} Response" do +        @schema resolve_schema(response.content[@content_type].schema) + +        if @schema.example do +          test "example matches schema" do +            assert_schema(@schema.example, @schema) +          end +        end +      end +    end +  end +end diff --git a/test/web/auth/basic_auth_test.exs b/test/web/auth/basic_auth_test.exs new file mode 100644 index 000000000..64f8a6863 --- /dev/null +++ b/test/web/auth/basic_auth_test.exs @@ -0,0 +1,46 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Auth.BasicAuthTest do +  use Pleroma.Web.ConnCase + +  import Pleroma.Factory + +  test "with HTTP Basic Auth used, grants access to OAuth scope-restricted endpoints", %{ +    conn: conn +  } do +    user = insert(:user) +    assert Comeonin.Pbkdf2.checkpw("test", user.password_hash) + +    basic_auth_contents = +      (URI.encode_www_form(user.nickname) <> ":" <> URI.encode_www_form("test")) +      |> Base.encode64() + +    # Succeeds with HTTP Basic Auth +    response = +      conn +      |> put_req_header("authorization", "Basic " <> basic_auth_contents) +      |> get("/api/v1/accounts/verify_credentials") +      |> json_response(200) + +    user_nickname = user.nickname +    assert %{"username" => ^user_nickname} = response + +    # Succeeds with a properly scoped OAuth token +    valid_token = insert(:oauth_token, scopes: ["read:accounts"]) + +    conn +    |> put_req_header("authorization", "Bearer #{valid_token.token}") +    |> get("/api/v1/accounts/verify_credentials") +    |> json_response(200) + +    # Fails with a wrong-scoped OAuth token (proof of restriction) +    invalid_token = insert(:oauth_token, scopes: ["read:something"]) + +    conn +    |> put_req_header("authorization", "Bearer #{invalid_token.token}") +    |> get("/api/v1/accounts/verify_credentials") +    |> json_response(403) +  end +end diff --git a/test/web/auth/oauth_test_controller_test.exs b/test/web/auth/oauth_test_controller_test.exs new file mode 100644 index 000000000..a2f6009ac --- /dev/null +++ b/test/web/auth/oauth_test_controller_test.exs @@ -0,0 +1,49 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Tests.OAuthTestControllerTest do +  use Pleroma.Web.ConnCase + +  import Pleroma.Factory + +  setup %{conn: conn} do +    user = insert(:user) +    conn = assign(conn, :user, user) +    %{conn: conn, user: user} +  end + +  test "missed_oauth", %{conn: conn} do +    res = +      conn +      |> get("/test/authenticated_api/missed_oauth") +      |> json_response(403) + +    assert res == +             %{ +               "error" => +                 "Security violation: OAuth scopes check was neither handled nor explicitly skipped." +             } +  end + +  test "skipped_oauth", %{conn: conn} do +    conn +    |> assign(:token, nil) +    |> get("/test/authenticated_api/skipped_oauth") +    |> json_response(200) +  end + +  test "performed_oauth", %{user: user} do +    %{conn: good_token_conn} = oauth_access(["read"], user: user) + +    good_token_conn +    |> get("/test/authenticated_api/performed_oauth") +    |> json_response(200) + +    %{conn: bad_token_conn} = oauth_access(["follow"], user: user) + +    bad_token_conn +    |> get("/test/authenticated_api/performed_oauth") +    |> json_response(403) +  end +end diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index f46ad0272..1758662b0 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -21,6 +21,60 @@ defmodule Pleroma.Web.CommonAPITest do    setup do: clear_config([:instance, :limit])    setup do: clear_config([:instance, :max_pinned_statuses]) +  test "favoriting race condition" do +    user = insert(:user) +    users_serial = insert_list(10, :user) +    users = insert_list(10, :user) + +    {:ok, activity} = CommonAPI.post(user, %{"status" => "."}) + +    users_serial +    |> Enum.map(fn user -> +      CommonAPI.favorite(user, activity.id) +    end) + +    object = Object.get_by_ap_id(activity.data["object"]) +    assert object.data["like_count"] == 10 + +    users +    |> Enum.map(fn user -> +      Task.async(fn -> +        CommonAPI.favorite(user, activity.id) +      end) +    end) +    |> Enum.map(&Task.await/1) + +    object = Object.get_by_ap_id(activity.data["object"]) +    assert object.data["like_count"] == 20 +  end + +  test "repeating race condition" do +    user = insert(:user) +    users_serial = insert_list(10, :user) +    users = insert_list(10, :user) + +    {:ok, activity} = CommonAPI.post(user, %{"status" => "."}) + +    users_serial +    |> Enum.map(fn user -> +      CommonAPI.repeat(activity.id, user) +    end) + +    object = Object.get_by_ap_id(activity.data["object"]) +    assert object.data["announcement_count"] == 10 + +    users +    |> Enum.map(fn user -> +      Task.async(fn -> +        CommonAPI.repeat(activity.id, user) +      end) +    end) +    |> Enum.map(&Task.await/1) + +    object = Object.get_by_ap_id(activity.data["object"]) +    assert object.data["announcement_count"] == 20 +  end +    test "when replying to a conversation / participation, it will set the correct context id even if no explicit reply_to is given" do      user = insert(:user)      {:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"}) @@ -97,18 +151,6 @@ defmodule Pleroma.Web.CommonAPITest do      assert Object.normalize(activity).data["emoji"]["firefox"]    end -  test "it adds emoji when updating profiles" do -    user = insert(:user, %{name: ":firefox:"}) - -    {:ok, activity} = CommonAPI.update(user) -    user = User.get_cached_by_ap_id(user.ap_id) -    [firefox] = user.source_data["tag"] - -    assert firefox["name"] == ":firefox:" - -    assert Pleroma.Constants.as_public() in activity.recipients -  end -    describe "posting" do      test "it supports explicit addressing" do        user = insert(:user) @@ -268,6 +310,16 @@ defmodule Pleroma.Web.CommonAPITest do        {:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, user)      end +    test "can't repeat a repeat" do +      user = insert(:user) +      other_user = insert(:user) +      {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) + +      {:ok, %Activity{} = announce, _} = CommonAPI.repeat(activity.id, other_user) + +      refute match?({:ok, %Activity{}, _}, CommonAPI.repeat(announce.id, user)) +    end +      test "repeating a status privately" do        user = insert(:user)        other_user = insert(:user) @@ -297,8 +349,8 @@ defmodule Pleroma.Web.CommonAPITest do        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) -      {:ok, %Activity{} = activity, object} = CommonAPI.repeat(activity.id, user) -      {:ok, ^activity, ^object} = CommonAPI.repeat(activity.id, user) +      {:ok, %Activity{} = announce, object} = CommonAPI.repeat(activity.id, user) +      {:ok, ^announce, ^object} = CommonAPI.repeat(activity.id, user)      end      test "favoriting a status twice returns ok, but without the like activity" do @@ -372,7 +424,9 @@ defmodule Pleroma.Web.CommonAPITest do        user = refresh_record(user) -      assert {:ok, ^activity} = CommonAPI.unpin(activity.id, user) +      id = activity.id + +      assert match?({:ok, %{id: ^id}}, CommonAPI.unpin(activity.id, user))        user = refresh_record(user) @@ -565,7 +619,7 @@ defmodule Pleroma.Web.CommonAPITest do        assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =                 CommonAPI.follow(follower, followed) -      assert User.get_follow_state(follower, followed) == "pending" +      assert User.get_follow_state(follower, followed) == :follow_pending        assert {:ok, follower} = CommonAPI.unfollow(follower, followed)        assert User.get_follow_state(follower, followed) == nil @@ -587,7 +641,7 @@ defmodule Pleroma.Web.CommonAPITest do        assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =                 CommonAPI.follow(follower, followed) -      assert User.get_follow_state(follower, followed) == "pending" +      assert User.get_follow_state(follower, followed) == :follow_pending        assert {:ok, follower} = CommonAPI.unfollow(follower, followed)        assert User.get_follow_state(follower, followed) == nil diff --git a/test/web/common_api/common_api_utils_test.exs b/test/web/common_api/common_api_utils_test.exs index d383d1714..18a3b3b87 100644 --- a/test/web/common_api/common_api_utils_test.exs +++ b/test/web/common_api/common_api_utils_test.exs @@ -7,7 +7,6 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do    alias Pleroma.Object    alias Pleroma.Web.CommonAPI    alias Pleroma.Web.CommonAPI.Utils -  alias Pleroma.Web.Endpoint    use Pleroma.DataCase    import ExUnit.CaptureLog @@ -42,28 +41,6 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do      end    end -  test "parses emoji from name and bio" do -    {:ok, user} = UserBuilder.insert(%{name: ":blank:", bio: ":firefox:"}) - -    expected = [ -      %{ -        "type" => "Emoji", -        "icon" => %{"type" => "Image", "url" => "#{Endpoint.url()}/emoji/Firefox.gif"}, -        "name" => ":firefox:" -      }, -      %{ -        "type" => "Emoji", -        "icon" => %{ -          "type" => "Image", -          "url" => "#{Endpoint.url()}/emoji/blank.png" -        }, -        "name" => ":blank:" -      } -    ] - -    assert expected == Utils.emoji_from_profile(user) -  end -    describe "format_input/3" do      test "works for bare text/plain" do        text = "hello world!" @@ -159,11 +136,11 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do        {output, _, _} = Utils.format_input(text, "text/markdown")        assert output == -               ~s(<p><strong>hello world</strong></p><p><em>another <span class="h-card"><a data-user="#{ +               ~s(<p><strong>hello world</strong></p><p><em>another <span class="h-card"><a class="u-url mention" data-user="#{                   user.id -               }" class="u-url mention" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> and <span class="h-card"><a data-user="#{ +               }" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> and <span class="h-card"><a class="u-url mention" data-user="#{                   user.id -               }" class="u-url mention" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> <a href="http://google.com" rel="ugc">google.com</a> paragraph</em></p>) +               }" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> <a href="http://google.com" rel="ugc">google.com</a> paragraph</em></p>)      end    end @@ -358,26 +335,6 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do      end    end -  describe "get_by_id_or_ap_id/1" do -    test "get activity by id" do -      activity = insert(:note_activity) -      %Pleroma.Activity{} = note = Utils.get_by_id_or_ap_id(activity.id) -      assert note.id == activity.id -    end - -    test "get activity by ap_id" do -      activity = insert(:note_activity) -      %Pleroma.Activity{} = note = Utils.get_by_id_or_ap_id(activity.data["object"]) -      assert note.id == activity.id -    end - -    test "get activity by object when type isn't `Create` " do -      activity = insert(:like_activity) -      %Pleroma.Activity{} = like = Utils.get_by_id_or_ap_id(activity.id) -      assert like.data["object"] == activity.data["object"] -    end -  end -    describe "to_master_date/1" do      test "removes microseconds from date (NaiveDateTime)" do        assert Utils.to_masto_date(~N[2015-01-23 23:50:07.123]) == "2015-01-23T23:50:07.000Z" diff --git a/test/web/federator_test.exs b/test/web/federator_test.exs index da844c24c..261518ef0 100644 --- a/test/web/federator_test.exs +++ b/test/web/federator_test.exs @@ -78,7 +78,7 @@ defmodule Pleroma.Web.FederatorTest do          local: false,          nickname: "nick1@domain.com",          ap_id: "https://domain.com/users/nick1", -        source_data: %{"inbox" => inbox1}, +        inbox: inbox1,          ap_enabled: true        }) @@ -86,7 +86,7 @@ defmodule Pleroma.Web.FederatorTest do          local: false,          nickname: "nick2@domain2.com",          ap_id: "https://domain2.com/users/nick2", -        source_data: %{"inbox" => inbox2}, +        inbox: inbox2,          ap_enabled: true        }) @@ -130,6 +130,9 @@ defmodule Pleroma.Web.FederatorTest do        assert {:ok, job} = Federator.incoming_ap_doc(params)        assert {:ok, _activity} = ObanHelpers.perform(job) + +      assert {:ok, job} = Federator.incoming_ap_doc(params) +      assert {:error, :already_present} = ObanHelpers.perform(job)      end      test "rejects incoming AP docs with incorrect origin" do @@ -148,7 +151,7 @@ defmodule Pleroma.Web.FederatorTest do        }        assert {:ok, job} = Federator.incoming_ap_doc(params) -      assert :error = ObanHelpers.perform(job) +      assert {:error, :origin_containment_failed} = ObanHelpers.perform(job)      end      test "it does not crash if MRF rejects the post" do @@ -164,7 +167,7 @@ defmodule Pleroma.Web.FederatorTest do          |> Poison.decode!()        assert {:ok, job} = Federator.incoming_ap_doc(params) -      assert :error = ObanHelpers.perform(job) +      assert {:error, _} = ObanHelpers.perform(job)      end    end  end diff --git a/test/web/feed/tag_controller_test.exs b/test/web/feed/tag_controller_test.exs index e863df86b..d95aac108 100644 --- a/test/web/feed/tag_controller_test.exs +++ b/test/web/feed/tag_controller_test.exs @@ -150,8 +150,8 @@ defmodule Pleroma.Web.Feed.TagControllerTest do      obj2 = Object.normalize(activity2)      assert xpath(xml, ~x"//channel/item/description/text()"sl) == [ -             HtmlEntities.decode(FeedView.activity_content(obj2)), -             HtmlEntities.decode(FeedView.activity_content(obj1)) +             HtmlEntities.decode(FeedView.activity_content(obj2.data)), +             HtmlEntities.decode(FeedView.activity_content(obj1.data))             ]      response = 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 d78fbc5a1..2d256f63c 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 @@ -82,9 +82,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert user_data = json_response(conn, 200)        assert user_data["note"] == -               ~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a data-user="#{ +               ~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a class="u-url mention" data-user="#{                   user2.id -               }" class="u-url mention" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..) +               }" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..)      end      test "updates the user's locking status", %{conn: conn} do diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs index a9fa0ce48..8c428efee 100644 --- a/test/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -681,17 +681,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do      test "following / unfollowing errors", %{user: user, conn: conn} do        # self follow        conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow") -      assert %{"error" => "Record not found"} = json_response(conn_res, 404) +      assert %{"error" => "Can not follow yourself"} = json_response(conn_res, 400)        # self unfollow        user = User.get_cached_by_id(user.id)        conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow") -      assert %{"error" => "Record not found"} = json_response(conn_res, 404) +      assert %{"error" => "Can not unfollow yourself"} = json_response(conn_res, 400)        # self follow via uri        user = User.get_cached_by_id(user.id)        conn_res = post(conn, "/api/v1/follows", %{"uri" => user.nickname}) -      assert %{"error" => "Record not found"} = json_response(conn_res, 404) +      assert %{"error" => "Can not follow yourself"} = json_response(conn_res, 400)        # follow non existing user        conn_res = post(conn, "/api/v1/accounts/doesntexist/follow") @@ -794,7 +794,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do      test "Account registration via Application", %{conn: conn} do        conn = -        post(conn, "/api/v1/apps", %{ +        conn +        |> put_req_header("content-type", "application/json") +        |> post("/api/v1/apps", %{            client_name: "client_name",            redirect_uris: "urn:ietf:wg:oauth:2.0:oob",            scopes: "read, write, follow" @@ -942,6 +944,73 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do        res = post(conn, "/api/v1/accounts", valid_params)        assert json_response(res, 403) == %{"error" => "Invalid credentials"}      end + +    test "registration from trusted app" do +      clear_config([Pleroma.Captcha, :enabled], true) +      app = insert(:oauth_app, trusted: true, scopes: ["read", "write", "follow", "push"]) + +      conn = +        build_conn() +        |> post("/oauth/token", %{ +          "grant_type" => "client_credentials", +          "client_id" => app.client_id, +          "client_secret" => app.client_secret +        }) + +      assert %{"access_token" => token, "token_type" => "Bearer"} = json_response(conn, 200) + +      response = +        build_conn() +        |> Plug.Conn.put_req_header("authorization", "Bearer " <> token) +        |> post("/api/v1/accounts", %{ +          nickname: "nickanme", +          agreement: true, +          email: "email@example.com", +          fullname: "Lain", +          username: "Lain", +          password: "some_password", +          confirm: "some_password" +        }) +        |> json_response(200) + +      assert %{ +               "access_token" => access_token, +               "created_at" => _, +               "scope" => ["read", "write", "follow", "push"], +               "token_type" => "Bearer" +             } = response + +      response = +        build_conn() +        |> Plug.Conn.put_req_header("authorization", "Bearer " <> access_token) +        |> get("/api/v1/accounts/verify_credentials") +        |> json_response(200) + +      assert %{ +               "acct" => "Lain", +               "bot" => false, +               "display_name" => "Lain", +               "follow_requests_count" => 0, +               "followers_count" => 0, +               "following_count" => 0, +               "locked" => false, +               "note" => "", +               "source" => %{ +                 "fields" => [], +                 "note" => "", +                 "pleroma" => %{ +                   "actor_type" => "Person", +                   "discoverable" => false, +                   "no_rich_text" => false, +                   "show_role" => true +                 }, +                 "privacy" => "public", +                 "sensitive" => false +               }, +               "statuses_count" => 0, +               "username" => "Lain" +             } = response +    end    end    describe "create account by app / rate limit" do diff --git a/test/web/mastodon_api/controllers/app_controller_test.exs b/test/web/mastodon_api/controllers/app_controller_test.exs index 77d234d67..a0b8b126c 100644 --- a/test/web/mastodon_api/controllers/app_controller_test.exs +++ b/test/web/mastodon_api/controllers/app_controller_test.exs @@ -16,8 +16,7 @@ defmodule Pleroma.Web.MastodonAPI.AppControllerTest do      conn =        conn -      |> assign(:user, token.user) -      |> assign(:token, token) +      |> put_req_header("authorization", "Bearer #{token.token}")        |> get("/api/v1/apps/verify_credentials")      app = Repo.preload(token, :app).app @@ -28,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.AppControllerTest do        "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)      } -    assert expected == json_response(conn, 200) +    assert expected == json_response_and_validate_schema(conn, 200)    end    test "creates an oauth app", %{conn: conn} do @@ -37,6 +36,7 @@ defmodule Pleroma.Web.MastodonAPI.AppControllerTest do      conn =        conn +      |> put_req_header("content-type", "application/json")        |> assign(:user, user)        |> post("/api/v1/apps", %{          client_name: app_attrs.client_name, @@ -55,6 +55,6 @@ defmodule Pleroma.Web.MastodonAPI.AppControllerTest do        "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)      } -    assert expected == json_response(conn, 200) +    assert expected == json_response_and_validate_schema(conn, 200)    end  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 index 6567a0667..4222556a4 100644 --- a/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs +++ b/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs @@ -4,13 +4,16 @@  defmodule Pleroma.Web.MastodonAPI.CustomEmojiControllerTest do    use Pleroma.Web.ConnCase, async: true +  alias Pleroma.Web.ApiSpec +  import OpenApiSpex.TestAssertions    test "with tags", %{conn: conn} do -    [emoji | _body] = -      conn -      |> get("/api/v1/custom_emojis") -      |> json_response(200) +    assert resp = +             conn +             |> get("/api/v1/custom_emojis") +             |> json_response_and_validate_schema(200) +    assert [emoji | _body] = resp      assert Map.has_key?(emoji, "shortcode")      assert Map.has_key?(emoji, "static_url")      assert Map.has_key?(emoji, "tags") @@ -18,5 +21,6 @@ defmodule Pleroma.Web.MastodonAPI.CustomEmojiControllerTest do      assert Map.has_key?(emoji, "category")      assert Map.has_key?(emoji, "url")      assert Map.has_key?(emoji, "visible_in_picker") +    assert_schema(emoji, "CustomEmoji", ApiSpec.spec())    end  end diff --git a/test/web/mastodon_api/controllers/domain_block_controller_test.exs b/test/web/mastodon_api/controllers/domain_block_controller_test.exs index 8d24b3b88..01a24afcf 100644 --- a/test/web/mastodon_api/controllers/domain_block_controller_test.exs +++ b/test/web/mastodon_api/controllers/domain_block_controller_test.exs @@ -13,15 +13,21 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do      %{user: user, conn: conn} = oauth_access(["write:blocks"])      other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"}) -    ret_conn = post(conn, "/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"}) +    ret_conn = +      conn +      |> put_req_header("content-type", "application/json") +      |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"}) -    assert %{} = json_response(ret_conn, 200) +    assert %{} == json_response_and_validate_schema(ret_conn, 200)      user = User.get_cached_by_ap_id(user.ap_id)      assert User.blocks?(user, other_user) -    ret_conn = delete(conn, "/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"}) +    ret_conn = +      conn +      |> put_req_header("content-type", "application/json") +      |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"}) -    assert %{} = json_response(ret_conn, 200) +    assert %{} == json_response_and_validate_schema(ret_conn, 200)      user = User.get_cached_by_ap_id(user.ap_id)      refute User.blocks?(user, other_user)    end @@ -32,14 +38,10 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do      {:ok, user} = User.block_domain(user, "bad.site")      {:ok, user} = User.block_domain(user, "even.worse.site") -    conn = -      conn -      |> assign(:user, user) -      |> get("/api/v1/domain_blocks") - -    domain_blocks = json_response(conn, 200) - -    assert "bad.site" in domain_blocks -    assert "even.worse.site" in domain_blocks +    assert ["even.worse.site", "bad.site"] == +             conn +             |> assign(:user, user) +             |> get("/api/v1/domain_blocks") +             |> json_response_and_validate_schema(200)    end  end diff --git a/test/web/mastodon_api/controllers/follow_request_controller_test.exs b/test/web/mastodon_api/controllers/follow_request_controller_test.exs index dd848821a..d8dbe4800 100644 --- a/test/web/mastodon_api/controllers/follow_request_controller_test.exs +++ b/test/web/mastodon_api/controllers/follow_request_controller_test.exs @@ -21,7 +21,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do        other_user = insert(:user)        {:ok, _activity} = ActivityPub.follow(other_user, user) -      {:ok, other_user} = User.follow(other_user, user, "pending") +      {:ok, other_user} = User.follow(other_user, user, :follow_pending)        assert User.following?(other_user, user) == false @@ -35,7 +35,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do        other_user = insert(:user)        {:ok, _activity} = ActivityPub.follow(other_user, user) -      {:ok, other_user} = User.follow(other_user, user, "pending") +      {:ok, other_user} = User.follow(other_user, user, :follow_pending)        user = User.get_cached_by_id(user.id)        other_user = User.get_cached_by_id(other_user.id) diff --git a/test/web/mastodon_api/controllers/notification_controller_test.exs b/test/web/mastodon_api/controllers/notification_controller_test.exs index 344eabb4a..8c815b415 100644 --- a/test/web/mastodon_api/controllers/notification_controller_test.exs +++ b/test/web/mastodon_api/controllers/notification_controller_test.exs @@ -12,6 +12,26 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do    import Pleroma.Factory +  test "does NOT render account/pleroma/relationship if this is disabled by default" do +    clear_config([:extensions, :output_relationships_in_statuses_by_default], false) + +    %{user: user, conn: conn} = oauth_access(["read:notifications"]) +    other_user = insert(:user) + +    {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) +    {:ok, [_notification]} = Notification.create_notifications(activity) + +    response = +      conn +      |> assign(:user, user) +      |> get("/api/v1/notifications") +      |> json_response(200) + +    assert Enum.all?(response, fn n -> +             get_in(n, ["account", "pleroma", "relationship"]) == %{} +           end) +  end +    test "list of notifications" do      %{user: user, conn: conn} = oauth_access(["read:notifications"])      other_user = insert(:user) @@ -26,7 +46,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do        |> get("/api/v1/notifications")      expected_response = -      "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{ +      "hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{          user.ap_id        }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>" @@ -45,7 +65,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do      conn = get(conn, "/api/v1/notifications/#{notification.id}")      expected_response = -      "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{ +      "hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{          user.ap_id        }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>" @@ -53,7 +73,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do      assert response == expected_response    end -  test "dismissing a single notification" do +  test "dismissing a single notification (deprecated endpoint)" do      %{user: user, conn: conn} = oauth_access(["write:notifications"])      other_user = insert(:user) @@ -69,6 +89,22 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do      assert %{} = json_response(conn, 200)    end +  test "dismissing a single notification" do +    %{user: user, conn: conn} = oauth_access(["write:notifications"]) +    other_user = insert(:user) + +    {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) + +    {:ok, [notification]} = Notification.create_notifications(activity) + +    conn = +      conn +      |> assign(:user, user) +      |> post("/api/v1/notifications/#{notification.id}/dismiss") + +    assert %{} = json_response(conn, 200) +  end +    test "clearing all notifications" do      %{user: user, conn: conn} = oauth_access(["write:notifications", "read:notifications"])      other_user = insert(:user) diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index cd9ca4973..85068edd0 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -302,6 +302,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do        assert [] == Repo.all(Activity)      end +    test "ignores nil values", %{conn: conn} do +      conn = +        post(conn, "/api/v1/statuses", %{ +          "status" => "not scheduled", +          "scheduled_at" => nil +        }) + +      assert result = json_response(conn, 200) +      assert Activity.get_by_id(result["id"]) +    end +      test "creates a scheduled activity with a media attachment", %{user: user, conn: conn} do        scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond) @@ -1047,6 +1058,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do    end    test "bookmarks" do +    bookmarks_uri = "/api/v1/bookmarks?with_relationships=true" +      %{conn: conn} = oauth_access(["write:bookmarks", "read:bookmarks"])      author = insert(:user) @@ -1068,7 +1081,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      assert json_response(response2, 200)["bookmarked"] == true -    bookmarks = get(conn, "/api/v1/bookmarks") +    bookmarks = get(conn, bookmarks_uri)      assert [json_response(response2, 200), json_response(response1, 200)] ==               json_response(bookmarks, 200) @@ -1077,7 +1090,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      assert json_response(response1, 200)["bookmarked"] == false -    bookmarks = get(conn, "/api/v1/bookmarks") +    bookmarks = get(conn, bookmarks_uri)      assert [json_response(response2, 200)] == json_response(bookmarks, 200)    end diff --git a/test/web/mastodon_api/controllers/subscription_controller_test.exs b/test/web/mastodon_api/controllers/subscription_controller_test.exs index 987158a74..5682498c0 100644 --- a/test/web/mastodon_api/controllers/subscription_controller_test.exs +++ b/test/web/mastodon_api/controllers/subscription_controller_test.exs @@ -35,7 +35,10 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do      quote do        vapid_details = Application.get_env(:web_push_encryption, :vapid_details, [])        Application.put_env(:web_push_encryption, :vapid_details, []) -      assert "Something went wrong" == unquote(yield) + +      assert %{"error" => "Web push subscription is disabled on this Pleroma instance"} == +               unquote(yield) +        Application.put_env(:web_push_encryption, :vapid_details, vapid_details)      end    end @@ -45,7 +48,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do        assert_error_when_disable_push do          conn          |> post("/api/v1/push/subscription", %{}) -        |> json_response(500) +        |> json_response(403)        end      end @@ -74,7 +77,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do        assert_error_when_disable_push do          conn          |> get("/api/v1/push/subscription", %{}) -        |> json_response(500) +        |> json_response(403)        end      end @@ -127,7 +130,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do        assert_error_when_disable_push do          conn          |> put("/api/v1/push/subscription", %{data: %{"alerts" => %{"mention" => false}}}) -        |> json_response(500) +        |> json_response(403)        end      end @@ -155,7 +158,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do        assert_error_when_disable_push do          conn          |> delete("/api/v1/push/subscription", %{}) -        |> json_response(500) +        |> json_response(403)        end      end diff --git a/test/web/mastodon_api/controllers/suggestion_controller_test.exs b/test/web/mastodon_api/controllers/suggestion_controller_test.exs index c697a39f8..8d0e70db8 100644 --- a/test/web/mastodon_api/controllers/suggestion_controller_test.exs +++ b/test/web/mastodon_api/controllers/suggestion_controller_test.exs @@ -7,34 +7,8 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do    alias Pleroma.Config -  import Pleroma.Factory -  import Tesla.Mock -    setup do: oauth_access(["read"]) -  setup %{user: user} do -    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) - -    [other_user: other_user] -  end -    test "returns empty result", %{conn: conn} do      res =        conn diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs index 97b1c3e66..06efdc901 100644 --- a/test/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs @@ -20,7 +20,30 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do    describe "home" do      setup do: oauth_access(["read:statuses"]) +    test "does NOT render account/pleroma/relationship if this is disabled by default", %{ +      user: user, +      conn: conn +    } do +      clear_config([:extensions, :output_relationships_in_statuses_by_default], false) + +      other_user = insert(:user) + +      {:ok, _} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) + +      response = +        conn +        |> assign(:user, user) +        |> get("/api/v1/timelines/home") +        |> json_response(200) + +      assert Enum.all?(response, fn n -> +               get_in(n, ["account", "pleroma", "relationship"]) == %{} +             end) +    end +      test "the home timeline", %{user: user, conn: conn} do +      uri = "/api/v1/timelines/home?with_relationships=true" +        following = insert(:user, nickname: "followed")        third_user = insert(:user, nickname: "repeated") @@ -28,13 +51,13 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do        {:ok, activity} = CommonAPI.post(third_user, %{"status" => "repeated post"})        {:ok, _, _} = CommonAPI.repeat(activity.id, following) -      ret_conn = get(conn, "/api/v1/timelines/home") +      ret_conn = get(conn, uri)        assert Enum.empty?(json_response(ret_conn, :ok))        {:ok, _user} = User.follow(user, following) -      ret_conn = get(conn, "/api/v1/timelines/home") +      ret_conn = get(conn, uri)        assert [                 %{ @@ -59,7 +82,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do        {:ok, _user} = User.follow(third_user, user) -      ret_conn = get(conn, "/api/v1/timelines/home") +      ret_conn = get(conn, uri)        assert [                 %{ diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index 4435f69ff..85fa4f6a2 100644 --- a/test/web/mastodon_api/views/account_view_test.exs +++ b/test/web/mastodon_api/views/account_view_test.exs @@ -19,16 +19,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do    end    test "Represent a user account" do -    source_data = %{ -      "tag" => [ -        %{ -          "type" => "Emoji", -          "icon" => %{"url" => "/file.png"}, -          "name" => ":karjalanpiirakka:" -        } -      ] -    } -      background_image = %{        "url" => [%{"href" => "https://example.com/images/asuka_hospital.png"}]      } @@ -37,13 +27,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        insert(:user, %{          follower_count: 3,          note_count: 5, -        source_data: source_data,          background: background_image,          nickname: "shp@shitposter.club",          name: ":karjalanpiirakka: shp",          bio:            "<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f", -        inserted_at: ~N[2017-08-15 15:47:06.597036] +        inserted_at: ~N[2017-08-15 15:47:06.597036], +        emoji: %{"karjalanpiirakka" => "/file.png"}        })      expected = %{ @@ -117,7 +107,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        insert(:user, %{          follower_count: 3,          note_count: 5, -        source_data: %{},          actor_type: "Service",          nickname: "shp@shitposter.club",          inserted_at: ~N[2017-08-15 15:47:06.597036] @@ -311,7 +300,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        insert(:user, %{          follower_count: 0,          note_count: 5, -        source_data: %{},          actor_type: "Service",          nickname: "shp@shitposter.club",          inserted_at: ~N[2017-08-15 15:47:06.597036] diff --git a/test/web/mastodon_api/views/poll_view_test.exs b/test/web/mastodon_api/views/poll_view_test.exs index 6211fa888..63b204387 100644 --- a/test/web/mastodon_api/views/poll_view_test.exs +++ b/test/web/mastodon_api/views/poll_view_test.exs @@ -43,7 +43,8 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do          %{title: "why are you even asking?", votes_count: 0}        ],        voted: false, -      votes_count: 0 +      votes_count: 0, +      voters_count: nil      }      result = PollView.render("show.json", %{object: object}) @@ -69,9 +70,20 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do          }        }) +    voter = insert(:user) +      object = Object.normalize(activity) -    assert %{multiple: true} = PollView.render("show.json", %{object: object}) +    {:ok, _votes, object} = CommonAPI.vote(voter, object, [0, 1]) + +    assert match?( +             %{ +               multiple: true, +               voters_count: 1, +               votes_count: 2 +             }, +             PollView.render("show.json", %{object: object}) +           )    end    test "detects emoji" do diff --git a/test/web/mastodon_api/views/push_subscription_view_test.exs b/test/web/mastodon_api/views/subscription_view_test.exs index 10c6082a5..981524c0e 100644 --- a/test/web/mastodon_api/views/push_subscription_view_test.exs +++ b/test/web/mastodon_api/views/subscription_view_test.exs @@ -2,10 +2,10 @@  # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only -defmodule Pleroma.Web.MastodonAPI.PushSubscriptionViewTest do +defmodule Pleroma.Web.MastodonAPI.SubscriptionViewTest do    use Pleroma.DataCase    import Pleroma.Factory -  alias Pleroma.Web.MastodonAPI.PushSubscriptionView, as: View +  alias Pleroma.Web.MastodonAPI.SubscriptionView, as: View    alias Pleroma.Web.Push    test "Represent a subscription" do @@ -18,6 +18,6 @@ defmodule Pleroma.Web.MastodonAPI.PushSubscriptionViewTest do        server_key: Keyword.get(Push.vapid_config(), :public_key)      } -    assert expected == View.render("push_subscription.json", %{subscription: subscription}) +    assert expected == View.render("show.json", %{subscription: subscription})    end  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 32250f06f..61a1689b9 100644 --- a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs +++ b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs @@ -169,6 +169,23 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      id_one = activity.id      id_two = activity_two.id      assert [%{"id" => ^id_one}, %{"id" => ^id_two}] = result + +    {:ok, %{id: id_three}} = +      CommonAPI.post(other_user, %{ +        "status" => "Bye!", +        "in_reply_to_status_id" => activity.id, +        "in_reply_to_conversation_id" => participation.id +      }) + +    assert [%{"id" => ^id_two}, %{"id" => ^id_three}] = +             conn +             |> get("/api/v1/pleroma/conversations/#{participation.id}/statuses?limit=2") +             |> json_response(:ok) + +    assert [%{"id" => ^id_three}] = +             conn +             |> get("/api/v1/pleroma/conversations/#{participation.id}/statuses?min_id=#{id_two}") +             |> json_response(:ok)    end    test "PATCH /api/v1/pleroma/conversations/:id" do @@ -203,7 +220,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do    test "POST /api/v1/pleroma/conversations/read" do      user = insert(:user) -    %{user: other_user, conn: conn} = oauth_access(["write:notifications"]) +    %{user: other_user, conn: conn} = oauth_access(["write:conversations"])      {:ok, _activity} =        CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}", "visibility" => "direct"}) diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs index 9121d90e7..b2664bf28 100644 --- a/test/web/push/impl_test.exs +++ b/test/web/push/impl_test.exs @@ -63,12 +63,12 @@ defmodule Pleroma.Web.Push.ImplTest do          activity: activity        ) -    assert Impl.perform(notif) == [:ok, :ok] +    assert Impl.perform(notif) == {:ok, [:ok, :ok]}    end    @tag capture_log: true    test "returns error if notif does not match " do -    assert Impl.perform(%{}) == :error +    assert Impl.perform(%{}) == {:error, :unknown_type}    end    test "successful message sending" do diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs index b3fe22920..8b8d8af6c 100644 --- a/test/web/streamer/streamer_test.exs +++ b/test/web/streamer/streamer_test.exs @@ -28,6 +28,42 @@ defmodule Pleroma.Web.StreamerTest do        {:ok, %{user: user, notify: notify}}      end +    test "it streams the user's post in the 'user' stream", %{user: user} do +      task = +        Task.async(fn -> +          assert_receive {:text, _}, @streamer_timeout +        end) + +      Streamer.add_socket( +        "user", +        %{transport_pid: task.pid, assigns: %{user: user}} +      ) + +      {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"}) + +      Streamer.stream("user", activity) +      Task.await(task) +    end + +    test "it streams boosts of the user in the 'user' stream", %{user: user} do +      task = +        Task.async(fn -> +          assert_receive {:text, _}, @streamer_timeout +        end) + +      Streamer.add_socket( +        "user", +        %{transport_pid: task.pid, assigns: %{user: user}} +      ) + +      other_user = insert(:user) +      {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"}) +      {:ok, announce, _} = CommonAPI.repeat(activity.id, user) + +      Streamer.stream("user", announce) +      Task.await(task) +    end +      test "it sends notify to in the 'user' stream", %{user: user, notify: notify} do        task =          Task.async(fn -> @@ -209,7 +245,7 @@ defmodule Pleroma.Web.StreamerTest do        Pleroma.Config.put([:instance, :skip_thread_containment], false)        author = insert(:user)        user = insert(:user) -      User.follow(user, author, "accept") +      User.follow(user, author, :follow_accept)        activity =          insert(:note_activity, @@ -232,7 +268,7 @@ defmodule Pleroma.Web.StreamerTest do        Pleroma.Config.put([:instance, :skip_thread_containment], true)        author = insert(:user)        user = insert(:user) -      User.follow(user, author, "accept") +      User.follow(user, author, :follow_accept)        activity =          insert(:note_activity, @@ -255,7 +291,7 @@ defmodule Pleroma.Web.StreamerTest do        Pleroma.Config.put([:instance, :skip_thread_containment], false)        author = insert(:user)        user = insert(:user, skip_thread_containment: true) -      User.follow(user, author, "accept") +      User.follow(user, author, :follow_accept)        activity =          insert(:note_activity, diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs index 92f9aa0f5..f6e13b661 100644 --- a/test/web/twitter_api/twitter_api_test.exs +++ b/test/web/twitter_api/twitter_api_test.exs @@ -109,7 +109,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do      {:ok, user2} = TwitterAPI.register_user(data2)      expected_text = -      ~s(<span class="h-card"><a data-user="#{user1.id}" class="u-url mention" href="#{ +      ~s(<span class="h-card"><a class="u-url mention" data-user="#{user1.id}" href="#{          user1.ap_id        }" rel="ugc">@<span>john</span></a></span> test) diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs index 30e54bebd..b701239a0 100644 --- a/test/web/twitter_api/util_controller_test.exs +++ b/test/web/twitter_api/util_controller_test.exs @@ -95,6 +95,30 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do          end        end      end + +    test "it imports follows with different nickname variations", %{conn: conn} do +      [user2, user3, user4, user5, user6] = insert_list(5, :user) + +      identifiers = +        [ +          user2.ap_id, +          user3.nickname, +          "  ", +          "@" <> user4.nickname, +          user5.nickname <> "@localhost", +          "@" <> user6.nickname <> "@localhost" +        ] +        |> Enum.join("\n") + +      response = +        conn +        |> post("/api/pleroma/follow_import", %{"list" => identifiers}) +        |> json_response(:ok) + +      assert response == "job started" +      assert [{:ok, job_result}] = ObanHelpers.perform_all() +      assert job_result == [user2, user3, user4, user5, user6] +    end    end    describe "POST /api/pleroma/blocks_import" do @@ -136,6 +160,29 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do                 )        end      end + +    test "it imports blocks with different nickname variations", %{conn: conn} do +      [user2, user3, user4, user5, user6] = insert_list(5, :user) + +      identifiers = +        [ +          user2.ap_id, +          user3.nickname, +          "@" <> user4.nickname, +          user5.nickname <> "@localhost", +          "@" <> user6.nickname <> "@localhost" +        ] +        |> Enum.join(" ") + +      response = +        conn +        |> post("/api/pleroma/blocks_import", %{"list" => identifiers}) +        |> json_response(:ok) + +      assert response == "job started" +      assert [{:ok, job_result}] = ObanHelpers.perform_all() +      assert job_result == [user2, user3, user4, user5, user6] +    end    end    describe "PUT /api/pleroma/notification_settings" do  | 
