diff options
Diffstat (limited to 'test')
89 files changed, 3300 insertions, 920 deletions
diff --git a/test/activity/ir/topics_test.exs b/test/activity/ir/topics_test.exs index 44aec1e19..14a6e6b71 100644 --- a/test/activity/ir/topics_test.exs +++ b/test/activity/ir/topics_test.exs @@ -83,7 +83,7 @@ defmodule Pleroma.Activity.Ir.TopicsTest do        assert Enum.member?(topics, "hashtag:bar")      end -    test "only converts strinngs to hash tags", %{ +    test "only converts strings to hash tags", %{        activity: %{object: %{data: data} = object} = activity      } do        tagged_data = Map.put(data, "tag", [2]) diff --git a/test/config/config_db_test.exs b/test/config/config_db_test.exs index ac3dde681..6b0e7b4b6 100644 --- a/test/config/config_db_test.exs +++ b/test/config/config_db_test.exs @@ -478,14 +478,6 @@ defmodule Pleroma.ConfigDBTest do        assert ConfigDB.from_binary(binary) == [key: "value"]      end -    test "keyword with partial_chain key" do -      binary = -        ConfigDB.transform([%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]}]) - -      assert binary == :erlang.term_to_binary(partial_chain: &:hackney_connect.partial_chain/1) -      assert ConfigDB.from_binary(binary) == [partial_chain: &:hackney_connect.partial_chain/1] -    end -      test "keyword" do        binary =          ConfigDB.transform([ diff --git a/test/config/transfer_task_test.exs b/test/config/transfer_task_test.exs index 0265a6156..00db0b686 100644 --- a/test/config/transfer_task_test.exs +++ b/test/config/transfer_task_test.exs @@ -16,6 +16,7 @@ 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) +    initial = Application.get_env(:logger, :level)      ConfigDB.create(%{        group: ":pleroma", @@ -35,16 +36,20 @@ defmodule Pleroma.Config.TransferTaskTest do        value: [:test_value1, :test_value2]      }) +    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      on_exit(fn ->        Application.delete_env(:pleroma, :test_key)        Application.delete_env(:idna, :test_key)        Application.delete_env(:quack, :test_key) +      Application.put_env(:logger, :level, initial)      end)    end @@ -78,8 +83,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 +104,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 +112,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 +127,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 +139,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 +151,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/emoji/packs/blank.png.zip b/test/fixtures/emoji/packs/blank.png.zip Binary files differnew file mode 100644 index 000000000..651daf127 --- /dev/null +++ b/test/fixtures/emoji/packs/blank.png.zip diff --git a/test/fixtures/emoji/packs/default-manifest.json b/test/fixtures/emoji/packs/default-manifest.json new file mode 100644 index 000000000..c8433808d --- /dev/null +++ b/test/fixtures/emoji/packs/default-manifest.json @@ -0,0 +1,10 @@ +{ +  "finmoji": { +    "license": "CC BY-NC-ND 4.0", +    "homepage": "https://finland.fi/emoji/", +    "description": "Finland is the first country in the world to publish its own set of country themed emojis. The Finland emoji collection contains 56 tongue-in-cheek emotions, which were created to explain some hard-to-describe Finnish emotions, Finnish words and customs.", +    "src": "https://finland.fi/wp-content/uploads/2017/06/finland-emojis.zip", +    "src_sha256": "384025A1AC6314473863A11AC7AB38A12C01B851A3F82359B89B4D4211D3291D", +    "files": "finmoji.json" +  } +}
\ No newline at end of file diff --git a/test/fixtures/emoji/packs/finmoji.json b/test/fixtures/emoji/packs/finmoji.json new file mode 100644 index 000000000..279770998 --- /dev/null +++ b/test/fixtures/emoji/packs/finmoji.json @@ -0,0 +1,3 @@ +{ +  "blank": "blank.png" +}
\ No newline at end of file diff --git a/test/fixtures/emoji/packs/manifest.json b/test/fixtures/emoji/packs/manifest.json new file mode 100644 index 000000000..2d51a459b --- /dev/null +++ b/test/fixtures/emoji/packs/manifest.json @@ -0,0 +1,10 @@ +{ +  "blobs.gg": { +    "src_sha256": "3a12f3a181678d5b3584a62095411b0d60a335118135910d879920f8ade5a57f", +    "src": "https://git.pleroma.social/pleroma/emoji-index/raw/master/packs/blobs_gg.zip", +    "license": "Apache 2.0", +    "homepage": "https://blobs.gg", +    "files": "blobs_gg.json", +    "description": "Blob Emoji from blobs.gg repacked as apng" +  } +}
\ No newline at end of file diff --git a/test/fixtures/tesla_mock/funkwhale_audio.json b/test/fixtures/tesla_mock/funkwhale_audio.json new file mode 100644 index 000000000..15736b1f8 --- /dev/null +++ b/test/fixtures/tesla_mock/funkwhale_audio.json @@ -0,0 +1,44 @@ +{ +  "id": "https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871", +  "type": "Audio", +  "name": "Compositions - Test Audio for Pleroma", +  "attributedTo": "https://channels.tests.funkwhale.audio/federation/actors/compositions", +  "published": "2020-03-11T10:01:52.714918+00:00", +  "to": "https://www.w3.org/ns/activitystreams#Public", +  "url": [ +    { +      "type": "Link", +      "mimeType": "audio/ogg", +      "href": "https://channels.tests.funkwhale.audio/api/v1/listen/3901e5d8-0445-49d5-9711-e096cf32e515/?upload=42342395-0208-4fee-a38d-259a6dae0871&download=false" +    }, +    { +      "type": "Link", +      "mimeType": "text/html", +      "href": "https://channels.tests.funkwhale.audio/library/tracks/74" +    } +  ], +  "content": "<p>This is a test Audio for Pleroma.</p>", +  "mediaType": "text/html", +  "tag": [ +    { +      "type": "Hashtag", +      "name": "#funkwhale" +    }, +    { +      "type": "Hashtag", +      "name": "#test" +    }, +    { +      "type": "Hashtag", +      "name": "#tests" +    } +  ], +  "summary": "#funkwhale #test #tests", +  "@context": [ +    "https://www.w3.org/ns/activitystreams", +    "https://w3id.org/security/v1", +    { +      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers" +    } +  ] +} diff --git a/test/fixtures/tesla_mock/funkwhale_channel.json b/test/fixtures/tesla_mock/funkwhale_channel.json new file mode 100644 index 000000000..cf9ee8151 --- /dev/null +++ b/test/fixtures/tesla_mock/funkwhale_channel.json @@ -0,0 +1,44 @@ +{ +  "id": "https://channels.tests.funkwhale.audio/federation/actors/compositions", +  "outbox": "https://channels.tests.funkwhale.audio/federation/actors/compositions/outbox", +  "inbox": "https://channels.tests.funkwhale.audio/federation/actors/compositions/inbox", +  "preferredUsername": "compositions", +  "type": "Person", +  "name": "Compositions", +  "followers": "https://channels.tests.funkwhale.audio/federation/actors/compositions/followers", +  "following": "https://channels.tests.funkwhale.audio/federation/actors/compositions/following", +  "manuallyApprovesFollowers": false, +  "url": [ +    { +      "type": "Link", +      "href": "https://channels.tests.funkwhale.audio/channels/compositions", +      "mediaType": "text/html" +    }, +    { +      "type": "Link", +      "href": "https://channels.tests.funkwhale.audio/api/v1/channels/compositions/rss", +      "mediaType": "application/rss+xml" +    } +  ], +  "icon": { +    "type": "Image", +    "url": "https://channels.tests.funkwhale.audio/media/attachments/75/b4/f1/nosmile.jpeg", +    "mediaType": "image/jpeg" +  }, +  "summary": "<p>I'm testing federation with the fediverse :)</p>", +  "@context": [ +    "https://www.w3.org/ns/activitystreams", +    "https://w3id.org/security/v1", +    { +      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers" +    } +  ], +  "publicKey": { +    "owner": "https://channels.tests.funkwhale.audio/federation/actors/compositions", +    "publicKeyPem": "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAv25u57oZfVLV3KltS+HcsdSx9Op4MmzIes1J8Wu8s0KbdXf2zEwS\nsVqyHgs/XCbnzsR3FqyJTo46D2BVnvZcuU5srNcR2I2HMaqQ0oVdnATE4K6KdcgV\nN+98pMWo56B8LTgE1VpvqbsrXLi9jCTzjrkebVMOP+ZVu+64v1qdgddseblYMnBZ\nct0s7ONbHnqrWlTGf5wES1uIZTVdn5r4MduZG+Uenfi1opBS0lUUxfWdW9r0oF2b\nyneZUyaUCbEroeKbqsweXCWVgnMarUOsgqC42KM4cf95lySSwTSaUtZYIbTw7s9W\n2jveU/rVg8BYZu5JK5obgBoxtlUeUoSswwIDAQAB\n-----END RSA PUBLIC KEY-----\n", +    "id": "https://channels.tests.funkwhale.audio/federation/actors/compositions#main-key" +  }, +  "endpoints": { +    "sharedInbox": "https://channels.tests.funkwhale.audio/federation/shared/inbox" +  } +} diff --git a/test/fixtures/users_mock/localhost.json b/test/fixtures/users_mock/localhost.json new file mode 100644 index 000000000..a49935db1 --- /dev/null +++ b/test/fixtures/users_mock/localhost.json @@ -0,0 +1,41 @@ +{ +  "@context": [ +    "https://www.w3.org/ns/activitystreams", +    "http://localhost:4001/schemas/litepub-0.1.jsonld", +    { +      "@language": "und" +    } +  ], +  "attachment": [], +  "endpoints": { +    "oauthAuthorizationEndpoint": "http://localhost:4001/oauth/authorize", +    "oauthRegistrationEndpoint": "http://localhost:4001/api/v1/apps", +    "oauthTokenEndpoint": "http://localhost:4001/oauth/token", +    "sharedInbox": "http://localhost:4001/inbox" +  }, +  "followers": "http://localhost:4001/users/{{nickname}}/followers", +  "following": "http://localhost:4001/users/{{nickname}}/following", +  "icon": { +    "type": "Image", +    "url": "http://localhost:4001/media/4e914f5b84e4a259a3f6c2d2edc9ab642f2ab05f3e3d9c52c81fc2d984b3d51e.jpg" +  }, +  "id": "http://localhost:4001/users/{{nickname}}", +  "image": { +    "type": "Image", +    "url": "http://localhost:4001/media/f739efddefeee49c6e67e947c4811fdc911785c16ae43da4c3684051fbf8da6a.jpg?name=f739efddefeee49c6e67e947c4811fdc911785c16ae43da4c3684051fbf8da6a.jpg" +  }, +  "inbox": "http://localhost:4001/users/{{nickname}}/inbox", +  "manuallyApprovesFollowers": false, +  "name": "{{nickname}}", +  "outbox": "http://localhost:4001/users/{{nickname}}/outbox", +  "preferredUsername": "{{nickname}}", +  "publicKey": { +    "id": "http://localhost:4001/users/{{nickname}}#main-key", +    "owner": "http://localhost:4001/users/{{nickname}}", +    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5DLtwGXNZElJyxFGfcVc\nXANhaMadj/iYYQwZjOJTV9QsbtiNBeIK54PJrYuU0/0YIdrvS1iqheX5IwXRhcwa\nhm3ZyLz7XeN9st7FBni4BmZMBtMpxAuYuu5p/jbWy13qAiYOhPreCx0wrWgm/lBD\n9mkgaxIxPooBE0S4ZWEJIDIV1Vft3AWcRUyWW1vIBK0uZzs6GYshbQZB952S0yo4\nFzI1hABGHncH8UvuFauh4EZ8tY7/X5I0pGRnDOcRN1dAht5w5yTA+6r5kebiFQjP\nIzN/eCO/a9Flrj9YGW7HDNtjSOH0A31PLRGlJtJO3yK57dnf5ppyCZGfL4emShQo\ncQIDAQAB\n-----END PUBLIC KEY-----\n\n" +  }, +  "summary": "your friendly neighborhood pleroma developer<br>I like cute things and distributed systems, and really hate delete and redrafts", +  "tag": [], +  "type": "Person", +  "url": "http://localhost:4001/users/{{nickname}}" +}
\ No newline at end of file diff --git a/test/fixtures/warnings/otp_version/21.1 b/test/fixtures/warnings/otp_version/21.1 new file mode 100644 index 000000000..90cd64c4f --- /dev/null +++ b/test/fixtures/warnings/otp_version/21.1 @@ -0,0 +1 @@ +21.1
\ No newline at end of file diff --git a/test/fixtures/warnings/otp_version/22.1 b/test/fixtures/warnings/otp_version/22.1 new file mode 100644 index 000000000..d9b314368 --- /dev/null +++ b/test/fixtures/warnings/otp_version/22.1 @@ -0,0 +1 @@ +22.1
\ No newline at end of file diff --git a/test/fixtures/warnings/otp_version/22.4 b/test/fixtures/warnings/otp_version/22.4 new file mode 100644 index 000000000..1da8ccd28 --- /dev/null +++ b/test/fixtures/warnings/otp_version/22.4 @@ -0,0 +1 @@ +22.4
\ No newline at end of file diff --git a/test/fixtures/warnings/otp_version/23.0 b/test/fixtures/warnings/otp_version/23.0 new file mode 100644 index 000000000..4266d8634 --- /dev/null +++ b/test/fixtures/warnings/otp_version/23.0 @@ -0,0 +1 @@ +23.0
\ No newline at end of file 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/http/adapter_helper/gun_test.exs b/test/http/adapter_helper/gun_test.exs new file mode 100644 index 000000000..2e961826e --- /dev/null +++ b/test/http/adapter_helper/gun_test.exs @@ -0,0 +1,258 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.HTTP.AdapterHelper.GunTest do +  use ExUnit.Case, async: true +  use Pleroma.Tests.Helpers + +  import Mox + +  alias Pleroma.Config +  alias Pleroma.Gun.Conn +  alias Pleroma.HTTP.AdapterHelper.Gun +  alias Pleroma.Pool.Connections + +  setup :verify_on_exit! + +  defp gun_mock(_) do +    gun_mock() +    :ok +  end + +  defp gun_mock do +    Pleroma.GunMock +    |> stub(:open, fn _, _, _ -> Task.start_link(fn -> Process.sleep(1000) end) end) +    |> stub(:await_up, fn _, _ -> {:ok, :http} end) +    |> stub(:set_owner, fn _, _ -> :ok end) +  end + +  describe "options/1" do +    setup do: clear_config([:http, :adapter], a: 1, b: 2) + +    test "https url with default port" do +      uri = URI.parse("https://example.com") + +      opts = Gun.options([receive_conn: false], uri) +      assert opts[:certificates_verification] +      assert opts[:tls_opts][:log_level] == :warning +    end + +    test "https ipv4 with default port" do +      uri = URI.parse("https://127.0.0.1") + +      opts = Gun.options([receive_conn: false], uri) +      assert opts[:certificates_verification] +      assert opts[:tls_opts][:log_level] == :warning +    end + +    test "https ipv6 with default port" do +      uri = URI.parse("https://[2a03:2880:f10c:83:face:b00c:0:25de]") + +      opts = Gun.options([receive_conn: false], uri) +      assert opts[:certificates_verification] +      assert opts[:tls_opts][:log_level] == :warning +    end + +    test "https url with non standart port" do +      uri = URI.parse("https://example.com:115") + +      opts = Gun.options([receive_conn: false], uri) + +      assert opts[:certificates_verification] +    end + +    test "get conn on next request" do +      gun_mock() +      level = Application.get_env(:logger, :level) +      Logger.configure(level: :debug) +      on_exit(fn -> Logger.configure(level: level) end) +      uri = URI.parse("http://some-domain2.com") + +      opts = Gun.options(uri) + +      assert opts[:conn] == nil +      assert opts[:close_conn] == nil + +      Process.sleep(50) +      opts = Gun.options(uri) + +      assert is_pid(opts[:conn]) +      assert opts[:close_conn] == false +    end + +    test "merges with defaul http adapter config" do +      defaults = Gun.options([receive_conn: false], URI.parse("https://example.com")) +      assert Keyword.has_key?(defaults, :a) +      assert Keyword.has_key?(defaults, :b) +    end + +    test "default ssl adapter opts with connection" do +      gun_mock() +      uri = URI.parse("https://some-domain.com") + +      :ok = Conn.open(uri, :gun_connections) + +      opts = Gun.options(uri) + +      assert opts[:certificates_verification] +      refute opts[:tls_opts] == [] + +      assert opts[:close_conn] == false +      assert is_pid(opts[:conn]) +    end + +    test "parses string proxy host & port" do +      proxy = Config.get([:http, :proxy_url]) +      Config.put([:http, :proxy_url], "localhost:8123") +      on_exit(fn -> Config.put([:http, :proxy_url], proxy) end) + +      uri = URI.parse("https://some-domain.com") +      opts = Gun.options([receive_conn: false], uri) +      assert opts[:proxy] == {'localhost', 8123} +    end + +    test "parses tuple proxy scheme host and port" do +      proxy = Config.get([:http, :proxy_url]) +      Config.put([:http, :proxy_url], {:socks, 'localhost', 1234}) +      on_exit(fn -> Config.put([:http, :proxy_url], proxy) end) + +      uri = URI.parse("https://some-domain.com") +      opts = Gun.options([receive_conn: false], uri) +      assert opts[:proxy] == {:socks, 'localhost', 1234} +    end + +    test "passed opts have more weight than defaults" do +      proxy = Config.get([:http, :proxy_url]) +      Config.put([:http, :proxy_url], {:socks5, 'localhost', 1234}) +      on_exit(fn -> Config.put([:http, :proxy_url], proxy) end) +      uri = URI.parse("https://some-domain.com") +      opts = Gun.options([receive_conn: false, proxy: {'example.com', 4321}], uri) + +      assert opts[:proxy] == {'example.com', 4321} +    end +  end + +  describe "options/1 with receive_conn parameter" do +    setup :gun_mock + +    test "receive conn by default" do +      uri = URI.parse("http://another-domain.com") +      :ok = Conn.open(uri, :gun_connections) + +      received_opts = Gun.options(uri) +      assert received_opts[:close_conn] == false +      assert is_pid(received_opts[:conn]) +    end + +    test "don't receive conn if receive_conn is false" do +      uri = URI.parse("http://another-domain.com") +      :ok = Conn.open(uri, :gun_connections) + +      opts = [receive_conn: false] +      received_opts = Gun.options(opts, uri) +      assert received_opts[:close_conn] == nil +      assert received_opts[:conn] == nil +    end +  end + +  describe "after_request/1" do +    setup :gun_mock + +    test "body_as not chunks" do +      uri = URI.parse("http://some-domain.com") +      :ok = Conn.open(uri, :gun_connections) +      opts = Gun.options(uri) +      :ok = Gun.after_request(opts) +      conn = opts[:conn] + +      assert %Connections{ +               conns: %{ +                 "http:some-domain.com:80" => %Pleroma.Gun.Conn{ +                   conn: ^conn, +                   conn_state: :idle, +                   used_by: [] +                 } +               } +             } = Connections.get_state(:gun_connections) +    end + +    test "body_as chunks" do +      uri = URI.parse("http://some-domain.com") +      :ok = Conn.open(uri, :gun_connections) +      opts = Gun.options([body_as: :chunks], uri) +      :ok = Gun.after_request(opts) +      conn = opts[:conn] +      self = self() + +      assert %Connections{ +               conns: %{ +                 "http:some-domain.com:80" => %Pleroma.Gun.Conn{ +                   conn: ^conn, +                   conn_state: :active, +                   used_by: [{^self, _}] +                 } +               } +             } = Connections.get_state(:gun_connections) +    end + +    test "with no connection" do +      uri = URI.parse("http://uniq-domain.com") + +      :ok = Conn.open(uri, :gun_connections) + +      opts = Gun.options([body_as: :chunks], uri) +      conn = opts[:conn] +      opts = Keyword.delete(opts, :conn) +      self = self() + +      :ok = Gun.after_request(opts) + +      assert %Connections{ +               conns: %{ +                 "http:uniq-domain.com:80" => %Pleroma.Gun.Conn{ +                   conn: ^conn, +                   conn_state: :active, +                   used_by: [{^self, _}] +                 } +               } +             } = Connections.get_state(:gun_connections) +    end + +    test "with ipv4" do +      uri = URI.parse("http://127.0.0.1") +      :ok = Conn.open(uri, :gun_connections) +      opts = Gun.options(uri) +      :ok = Gun.after_request(opts) +      conn = opts[:conn] + +      assert %Connections{ +               conns: %{ +                 "http:127.0.0.1:80" => %Pleroma.Gun.Conn{ +                   conn: ^conn, +                   conn_state: :idle, +                   used_by: [] +                 } +               } +             } = Connections.get_state(:gun_connections) +    end + +    test "with ipv6" do +      uri = URI.parse("http://[2a03:2880:f10c:83:face:b00c:0:25de]") +      :ok = Conn.open(uri, :gun_connections) +      opts = Gun.options(uri) +      :ok = Gun.after_request(opts) +      conn = opts[:conn] + +      assert %Connections{ +               conns: %{ +                 "http:2a03:2880:f10c:83:face:b00c:0:25de:80" => %Pleroma.Gun.Conn{ +                   conn: ^conn, +                   conn_state: :idle, +                   used_by: [] +                 } +               } +             } = Connections.get_state(:gun_connections) +    end +  end +end diff --git a/test/http/adapter_helper/hackney_test.exs b/test/http/adapter_helper/hackney_test.exs new file mode 100644 index 000000000..3f7e708e0 --- /dev/null +++ b/test/http/adapter_helper/hackney_test.exs @@ -0,0 +1,47 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.HTTP.AdapterHelper.HackneyTest do +  use ExUnit.Case, async: true +  use Pleroma.Tests.Helpers + +  alias Pleroma.HTTP.AdapterHelper.Hackney + +  setup_all do +    uri = URI.parse("http://domain.com") +    {:ok, uri: uri} +  end + +  describe "options/2" do +    setup do: clear_config([:http, :adapter], a: 1, b: 2) + +    test "add proxy and opts from config", %{uri: uri} do +      opts = Hackney.options([proxy: "localhost:8123"], uri) + +      assert opts[:a] == 1 +      assert opts[:b] == 2 +      assert opts[:proxy] == "localhost:8123" +    end + +    test "respect connection opts and no proxy", %{uri: uri} do +      opts = Hackney.options([a: 2, b: 1], uri) + +      assert opts[:a] == 2 +      assert opts[:b] == 1 +      refute Keyword.has_key?(opts, :proxy) +    end + +    test "add opts for https" do +      uri = URI.parse("https://domain.com") + +      opts = Hackney.options(uri) + +      assert opts[:ssl_options] == [ +               partial_chain: &:hackney_connect.partial_chain/1, +               versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"], +               server_name_indication: 'domain.com' +             ] +    end +  end +end diff --git a/test/http/adapter_helper_test.exs b/test/http/adapter_helper_test.exs new file mode 100644 index 000000000..24d501ad5 --- /dev/null +++ b/test/http/adapter_helper_test.exs @@ -0,0 +1,28 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.HTTP.AdapterHelperTest do +  use ExUnit.Case, async: true + +  alias Pleroma.HTTP.AdapterHelper + +  describe "format_proxy/1" do +    test "with nil" do +      assert AdapterHelper.format_proxy(nil) == nil +    end + +    test "with string" do +      assert AdapterHelper.format_proxy("127.0.0.1:8123") == {{127, 0, 0, 1}, 8123} +    end + +    test "localhost with port" do +      assert AdapterHelper.format_proxy("localhost:8123") == {'localhost', 8123} +    end + +    test "tuple" do +      assert AdapterHelper.format_proxy({:socks4, :localhost, 9050}) == +               {:socks4, 'localhost', 9050} +    end +  end +end diff --git a/test/http/connection_test.exs b/test/http/connection_test.exs new file mode 100644 index 000000000..5cc78ad5b --- /dev/null +++ b/test/http/connection_test.exs @@ -0,0 +1,135 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.HTTP.ConnectionTest do +  use ExUnit.Case, async: true +  use Pleroma.Tests.Helpers + +  import ExUnit.CaptureLog + +  alias Pleroma.Config +  alias Pleroma.HTTP.Connection + +  describe "parse_host/1" do +    test "as atom to charlist" do +      assert Connection.parse_host(:localhost) == 'localhost' +    end + +    test "as string to charlist" do +      assert Connection.parse_host("localhost.com") == 'localhost.com' +    end + +    test "as string ip to tuple" do +      assert Connection.parse_host("127.0.0.1") == {127, 0, 0, 1} +    end +  end + +  describe "parse_proxy/1" do +    test "ip with port" do +      assert Connection.parse_proxy("127.0.0.1:8123") == {:ok, {127, 0, 0, 1}, 8123} +    end + +    test "host with port" do +      assert Connection.parse_proxy("localhost:8123") == {:ok, 'localhost', 8123} +    end + +    test "as tuple" do +      assert Connection.parse_proxy({:socks4, :localhost, 9050}) == +               {:ok, :socks4, 'localhost', 9050} +    end + +    test "as tuple with string host" do +      assert Connection.parse_proxy({:socks5, "localhost", 9050}) == +               {:ok, :socks5, 'localhost', 9050} +    end +  end + +  describe "parse_proxy/1 errors" do +    test "ip without port" do +      capture_log(fn -> +        assert Connection.parse_proxy("127.0.0.1") == {:error, :invalid_proxy} +      end) =~ "parsing proxy fail \"127.0.0.1\"" +    end + +    test "host without port" do +      capture_log(fn -> +        assert Connection.parse_proxy("localhost") == {:error, :invalid_proxy} +      end) =~ "parsing proxy fail \"localhost\"" +    end + +    test "host with bad port" do +      capture_log(fn -> +        assert Connection.parse_proxy("localhost:port") == {:error, :invalid_proxy_port} +      end) =~ "parsing port in proxy fail \"localhost:port\"" +    end + +    test "ip with bad port" do +      capture_log(fn -> +        assert Connection.parse_proxy("127.0.0.1:15.9") == {:error, :invalid_proxy_port} +      end) =~ "parsing port in proxy fail \"127.0.0.1:15.9\"" +    end + +    test "as tuple without port" do +      capture_log(fn -> +        assert Connection.parse_proxy({:socks5, :localhost}) == {:error, :invalid_proxy} +      end) =~ "parsing proxy fail {:socks5, :localhost}" +    end + +    test "with nil" do +      assert Connection.parse_proxy(nil) == nil +    end +  end + +  describe "options/3" do +    setup do: clear_config([:http, :proxy_url]) + +    test "without proxy_url in config" do +      Config.delete([:http, :proxy_url]) + +      opts = Connection.options(%URI{}) +      refute Keyword.has_key?(opts, :proxy) +    end + +    test "parses string proxy host & port" do +      Config.put([:http, :proxy_url], "localhost:8123") + +      opts = Connection.options(%URI{}) +      assert opts[:proxy] == {'localhost', 8123} +    end + +    test "parses tuple proxy scheme host and port" do +      Config.put([:http, :proxy_url], {:socks, 'localhost', 1234}) + +      opts = Connection.options(%URI{}) +      assert opts[:proxy] == {:socks, 'localhost', 1234} +    end + +    test "passed opts have more weight than defaults" do +      Config.put([:http, :proxy_url], {:socks5, 'localhost', 1234}) + +      opts = Connection.options(%URI{}, proxy: {'example.com', 4321}) + +      assert opts[:proxy] == {'example.com', 4321} +    end +  end + +  describe "format_host/1" do +    test "with domain" do +      assert Connection.format_host("example.com") == 'example.com' +    end + +    test "with idna domain" do +      assert Connection.format_host("ですexample.com") == 'xn--example-183fne.com' +    end + +    test "with ipv4" do +      assert Connection.format_host("127.0.0.1") == '127.0.0.1' +    end + +    test "with ipv6" do +      assert Connection.format_host("2a03:2880:f10c:83:face:b00c:0:25de") == +               '2a03:2880:f10c:83:face:b00c:0:25de' +    end +  end +end diff --git a/test/http/request_builder_test.exs b/test/http/request_builder_test.exs index bf3a15ebe..f11528c3f 100644 --- a/test/http/request_builder_test.exs +++ b/test/http/request_builder_test.exs @@ -5,6 +5,8 @@  defmodule Pleroma.HTTP.RequestBuilderTest do    use ExUnit.Case, async: true    use Pleroma.Tests.Helpers +  alias Pleroma.Config +  alias Pleroma.HTTP.Request    alias Pleroma.HTTP.RequestBuilder    describe "headers/2" do @@ -12,48 +14,31 @@ defmodule Pleroma.HTTP.RequestBuilderTest do      setup do: clear_config([:http, :user_agent])      test "don't send pleroma user agent" do -      assert RequestBuilder.headers(%{}, []) == %{headers: []} +      assert RequestBuilder.headers(%Request{}, []) == %Request{headers: []}      end      test "send pleroma user agent" do -      Pleroma.Config.put([:http, :send_user_agent], true) -      Pleroma.Config.put([:http, :user_agent], :default) +      Config.put([:http, :send_user_agent], true) +      Config.put([:http, :user_agent], :default) -      assert RequestBuilder.headers(%{}, []) == %{ -               headers: [{"User-Agent", Pleroma.Application.user_agent()}] +      assert RequestBuilder.headers(%Request{}, []) == %Request{ +               headers: [{"user-agent", Pleroma.Application.user_agent()}]               }      end      test "send custom user agent" do -      Pleroma.Config.put([:http, :send_user_agent], true) -      Pleroma.Config.put([:http, :user_agent], "totally-not-pleroma") +      Config.put([:http, :send_user_agent], true) +      Config.put([:http, :user_agent], "totally-not-pleroma") -      assert RequestBuilder.headers(%{}, []) == %{ -               headers: [{"User-Agent", "totally-not-pleroma"}] +      assert RequestBuilder.headers(%Request{}, []) == %Request{ +               headers: [{"user-agent", "totally-not-pleroma"}]               }      end    end -  describe "add_optional_params/3" do -    test "don't add if keyword is empty" do -      assert RequestBuilder.add_optional_params(%{}, %{}, []) == %{} -    end - -    test "add query parameter" do -      assert RequestBuilder.add_optional_params( -               %{}, -               %{query: :query, body: :body, another: :val}, -               [ -                 {:query, "param1=val1¶m2=val2"}, -                 {:body, "some body"} -               ] -             ) == %{query: "param1=val1¶m2=val2", body: "some body"} -    end -  end -    describe "add_param/4" do      test "add file parameter" do -      %{ +      %Request{          body: %Tesla.Multipart{            boundary: _,            content_type_params: [], @@ -70,7 +55,7 @@ defmodule Pleroma.HTTP.RequestBuilderTest do              }            ]          } -      } = RequestBuilder.add_param(%{}, :file, "filename.png", "some-path/filename.png") +      } = RequestBuilder.add_param(%Request{}, :file, "filename.png", "some-path/filename.png")      end      test "add key to body" do @@ -82,7 +67,7 @@ defmodule Pleroma.HTTP.RequestBuilderTest do              %Tesla.Multipart.Part{                body: "\"someval\"",                dispositions: [name: "somekey"], -              headers: ["Content-Type": "application/json"] +              headers: [{"content-type", "application/json"}]              }            ]          } diff --git a/test/http_test.exs b/test/http_test.exs index 3edb0de36..618485b55 100644 --- a/test/http_test.exs +++ b/test/http_test.exs @@ -3,8 +3,10 @@  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.HTTPTest do -  use Pleroma.DataCase +  use ExUnit.Case, async: true +  use Pleroma.Tests.Helpers    import Tesla.Mock +  alias Pleroma.HTTP    setup do      mock(fn @@ -27,7 +29,7 @@ defmodule Pleroma.HTTPTest do    describe "get/1" do      test "returns successfully result" do -      assert Pleroma.HTTP.get("http://example.com/hello") == { +      assert HTTP.get("http://example.com/hello") == {                 :ok,                 %Tesla.Env{status: 200, body: "hello"}               } @@ -36,7 +38,7 @@ defmodule Pleroma.HTTPTest do    describe "get/2 (with headers)" do      test "returns successfully result for json content-type" do -      assert Pleroma.HTTP.get("http://example.com/hello", [{"content-type", "application/json"}]) == +      assert HTTP.get("http://example.com/hello", [{"content-type", "application/json"}]) ==                 {                   :ok,                   %Tesla.Env{ @@ -50,7 +52,7 @@ defmodule Pleroma.HTTPTest do    describe "post/2" do      test "returns successfully result" do -      assert Pleroma.HTTP.post("http://example.com/world", "") == { +      assert HTTP.post("http://example.com/world", "") == {                 :ok,                 %Tesla.Env{status: 200, body: "world"}               } diff --git a/test/notification_test.exs b/test/notification_test.exs index d240ede94..837a9dacd 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -6,12 +6,14 @@ defmodule Pleroma.NotificationTest do    use Pleroma.DataCase    import Pleroma.Factory +  import Mock    alias Pleroma.Notification    alias Pleroma.Tests.ObanHelpers    alias Pleroma.User    alias Pleroma.Web.ActivityPub.Transmogrifier    alias Pleroma.Web.CommonAPI +  alias Pleroma.Web.Push    alias Pleroma.Web.Streamer    describe "create_notifications" do @@ -80,6 +82,80 @@ defmodule Pleroma.NotificationTest do      end    end +  describe "CommonApi.post/2 notification-related functionality" do +    test_with_mock "creates but does NOT send notification to blocker user", +                   Push, +                   [:passthrough], +                   [] do +      user = insert(:user) +      blocker = insert(:user) +      {:ok, _user_relationship} = User.block(blocker, user) + +      {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{blocker.nickname}!"}) + +      blocker_id = blocker.id +      assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification) +      refute called(Push.send(:_)) +    end + +    test_with_mock "creates but does NOT send notification to notification-muter user", +                   Push, +                   [:passthrough], +                   [] do +      user = insert(:user) +      muter = insert(:user) +      {:ok, _user_relationships} = User.mute(muter, user) + +      {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{muter.nickname}!"}) + +      muter_id = muter.id +      assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification) +      refute called(Push.send(:_)) +    end + +    test_with_mock "creates but does NOT send notification to thread-muter user", +                   Push, +                   [:passthrough], +                   [] do +      user = insert(:user) +      thread_muter = insert(:user) + +      {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{thread_muter.nickname}!"}) + +      {:ok, _} = CommonAPI.add_mute(thread_muter, activity) + +      {:ok, _same_context_activity} = +        CommonAPI.post(user, %{ +          "status" => "hey-hey-hey @#{thread_muter.nickname}!", +          "in_reply_to_status_id" => activity.id +        }) + +      [pre_mute_notification, post_mute_notification] = +        Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id)) + +      pre_mute_notification_id = pre_mute_notification.id +      post_mute_notification_id = post_mute_notification.id + +      assert called( +               Push.send( +                 :meck.is(fn +                   %Notification{id: ^pre_mute_notification_id} -> true +                   _ -> false +                 end) +               ) +             ) + +      refute called( +               Push.send( +                 :meck.is(fn +                   %Notification{id: ^post_mute_notification_id} -> true +                   _ -> false +                 end) +               ) +             ) +    end +  end +    describe "create_notification" do      @tag needs_streamer: true      test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do @@ -382,7 +458,7 @@ defmodule Pleroma.NotificationTest do      end    end -  describe "notification target determination" do +  describe "notification target determination / get_notified_from_activity/2" do      test "it sends notifications to addressed users in new messages" do        user = insert(:user)        other_user = insert(:user) @@ -392,7 +468,9 @@ defmodule Pleroma.NotificationTest do            "status" => "hey @#{other_user.nickname}!"          }) -      assert other_user in Notification.get_notified_from_activity(activity) +      {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity) + +      assert other_user in enabled_receivers      end      test "it sends notifications to mentioned users in new messages" do @@ -420,7 +498,9 @@ defmodule Pleroma.NotificationTest do        {:ok, activity} = Transmogrifier.handle_incoming(create_activity) -      assert other_user in Notification.get_notified_from_activity(activity) +      {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity) + +      assert other_user in enabled_receivers      end      test "it does not send notifications to users who are only cc in new messages" do @@ -442,7 +522,9 @@ defmodule Pleroma.NotificationTest do        {:ok, activity} = Transmogrifier.handle_incoming(create_activity) -      assert other_user not in Notification.get_notified_from_activity(activity) +      {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity) + +      assert other_user not in enabled_receivers      end      test "it does not send notification to mentioned users in likes" do @@ -455,9 +537,12 @@ defmodule Pleroma.NotificationTest do            "status" => "hey @#{other_user.nickname}!"          }) -      {:ok, activity_two, _} = CommonAPI.favorite(activity_one.id, third_user) +      {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id) -      assert other_user not in Notification.get_notified_from_activity(activity_two) +      {enabled_receivers, _disabled_receivers} = +        Notification.get_notified_from_activity(activity_two) + +      assert other_user not in enabled_receivers      end      test "it does not send notification to mentioned users in announces" do @@ -472,7 +557,57 @@ defmodule Pleroma.NotificationTest do        {:ok, activity_two, _} = CommonAPI.repeat(activity_one.id, third_user) -      assert other_user not in Notification.get_notified_from_activity(activity_two) +      {enabled_receivers, _disabled_receivers} = +        Notification.get_notified_from_activity(activity_two) + +      assert other_user not in enabled_receivers +    end + +    test "it returns blocking recipient in disabled recipients list" do +      user = insert(:user) +      other_user = insert(:user) +      {:ok, _user_relationship} = User.block(other_user, user) + +      {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"}) + +      {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity) + +      assert [] == enabled_receivers +      assert [other_user] == disabled_receivers +    end + +    test "it returns notification-muting recipient in disabled recipients list" do +      user = insert(:user) +      other_user = insert(:user) +      {:ok, _user_relationships} = User.mute(other_user, user) + +      {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"}) + +      {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity) + +      assert [] == enabled_receivers +      assert [other_user] == disabled_receivers +    end + +    test "it returns thread-muting recipient in disabled recipients list" do +      user = insert(:user) +      other_user = insert(:user) + +      {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"}) + +      {:ok, _} = CommonAPI.add_mute(other_user, activity) + +      {:ok, same_context_activity} = +        CommonAPI.post(user, %{ +          "status" => "hey-hey-hey @#{other_user.nickname}!", +          "in_reply_to_status_id" => activity.id +        }) + +      {enabled_receivers, disabled_receivers} = +        Notification.get_notified_from_activity(same_context_activity) + +      assert [other_user] == disabled_receivers +      refute other_user in enabled_receivers      end    end @@ -485,7 +620,7 @@ defmodule Pleroma.NotificationTest do        assert Enum.empty?(Notification.for_user(user)) -      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user) +      {:ok, _} = CommonAPI.favorite(other_user, activity.id)        assert length(Notification.for_user(user)) == 1 @@ -502,7 +637,7 @@ defmodule Pleroma.NotificationTest do        assert Enum.empty?(Notification.for_user(user)) -      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user) +      {:ok, _} = CommonAPI.favorite(other_user, activity.id)        assert length(Notification.for_user(user)) == 1 @@ -557,7 +692,7 @@ defmodule Pleroma.NotificationTest do        assert Enum.empty?(Notification.for_user(user)) -      {:error, _} = CommonAPI.favorite(activity.id, other_user) +      {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)        assert Enum.empty?(Notification.for_user(user))      end @@ -649,12 +784,20 @@ defmodule Pleroma.NotificationTest do          "object" => remote_user.ap_id        } +      remote_user_url = remote_user.ap_id + +      Tesla.Mock.mock(fn +        %{method: :get, url: ^remote_user_url} -> +          %Tesla.Env{status: 404, body: ""} +      end) +        {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)        ObanHelpers.perform_all()        assert Enum.empty?(Notification.for_user(local_user))      end +    @tag capture_log: true      test "move activity generates a notification" do        %{ap_id: old_ap_id} = old_user = insert(:user)        %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id]) @@ -664,6 +807,18 @@ defmodule Pleroma.NotificationTest do        User.follow(follower, old_user)        User.follow(other_follower, old_user) +      old_user_url = old_user.ap_id + +      body = +        File.read!("test/fixtures/users_mock/localhost.json") +        |> String.replace("{{nickname}}", old_user.nickname) +        |> Jason.encode!() + +      Tesla.Mock.mock(fn +        %{method: :get, url: ^old_user_url} -> +          %Tesla.Env{status: 200, body: body} +      end) +        Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)        ObanHelpers.perform_all() @@ -716,7 +871,7 @@ defmodule Pleroma.NotificationTest do        assert Notification.for_user(user) == []      end -    test "it doesn't return notificatitons for blocked domain" do +    test "it doesn't return notifications for blocked domain" do        user = insert(:user)        blocked = insert(:user, ap_id: "http://some-domain.com")        {:ok, user} = User.block_domain(user, "some-domain.com") diff --git a/test/object_test.exs b/test/object_test.exs index fe583decd..198d3b1cf 100644 --- a/test/object_test.exs +++ b/test/object_test.exs @@ -380,7 +380,8 @@ defmodule Pleroma.ObjectTest do        user = insert(:user)        activity = Activity.get_create_by_object_ap_id(object.data["id"]) -      {:ok, _activity, object} = CommonAPI.favorite(activity.id, user) +      {:ok, activity} = CommonAPI.favorite(user, activity.id) +      object = Object.get_by_ap_id(activity.data["object"])        assert object.data["like_count"] == 1 diff --git a/test/otp_version_test.exs b/test/otp_version_test.exs new file mode 100644 index 000000000..7d2538ec8 --- /dev/null +++ b/test/otp_version_test.exs @@ -0,0 +1,42 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.OTPVersionTest do +  use ExUnit.Case, async: true + +  alias Pleroma.OTPVersion + +  describe "check/1" do +    test "22.4" do +      assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/22.4"]) == +               "22.4" +    end + +    test "22.1" do +      assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/22.1"]) == +               "22.1" +    end + +    test "21.1" do +      assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/21.1"]) == +               "21.1" +    end + +    test "23.0" do +      assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/23.0"]) == +               "23.0" +    end + +    test "with non existance file" do +      assert OTPVersion.get_version_from_files([ +               "test/fixtures/warnings/otp_version/non-exising", +               "test/fixtures/warnings/otp_version/22.4" +             ]) == "22.4" +    end + +    test "empty paths" do +      assert OTPVersion.get_version_from_files([]) == nil +    end +  end +end diff --git a/test/plugs/oauth_scopes_plug_test.exs b/test/plugs/oauth_scopes_plug_test.exs index e79ecf263..abab7abb0 100644 --- a/test/plugs/oauth_scopes_plug_test.exs +++ b/test/plugs/oauth_scopes_plug_test.exs @@ -7,6 +7,7 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do    alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug    alias Pleroma.Plugs.OAuthScopesPlug +  alias Pleroma.Plugs.PlugHelper    alias Pleroma.Repo    import Mock @@ -16,6 +17,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 +        |> PlugHelper.append_to_skipped_plugs(OAuthScopesPlug) +        |> 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/pool/connections_test.exs b/test/pool/connections_test.exs new file mode 100644 index 000000000..aeda54875 --- /dev/null +++ b/test/pool/connections_test.exs @@ -0,0 +1,760 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Pool.ConnectionsTest do +  use ExUnit.Case, async: true +  use Pleroma.Tests.Helpers + +  import ExUnit.CaptureLog +  import Mox + +  alias Pleroma.Gun.Conn +  alias Pleroma.GunMock +  alias Pleroma.Pool.Connections + +  setup :verify_on_exit! + +  setup_all do +    name = :test_connections +    {:ok, pid} = Connections.start_link({name, [checkin_timeout: 150]}) +    {:ok, _} = Registry.start_link(keys: :unique, name: Pleroma.GunMock) + +    on_exit(fn -> +      if Process.alive?(pid), do: GenServer.stop(name) +    end) + +    {:ok, name: name} +  end + +  defp open_mock(num \\ 1) do +    GunMock +    |> expect(:open, num, &start_and_register(&1, &2, &3)) +    |> expect(:await_up, num, fn _, _ -> {:ok, :http} end) +    |> expect(:set_owner, num, fn _, _ -> :ok end) +  end + +  defp connect_mock(mock) do +    mock +    |> expect(:connect, &connect(&1, &2)) +    |> expect(:await, &await(&1, &2)) +  end + +  defp info_mock(mock), do: expect(mock, :info, &info(&1)) + +  defp start_and_register('gun-not-up.com', _, _), do: {:error, :timeout} + +  defp start_and_register(host, port, _) do +    {:ok, pid} = Task.start_link(fn -> Process.sleep(1000) end) + +    scheme = +      case port do +        443 -> "https" +        _ -> "http" +      end + +    Registry.register(GunMock, pid, %{ +      origin_scheme: scheme, +      origin_host: host, +      origin_port: port +    }) + +    {:ok, pid} +  end + +  defp info(pid) do +    [{_, info}] = Registry.lookup(GunMock, pid) +    info +  end + +  defp connect(pid, _) do +    ref = make_ref() +    Registry.register(GunMock, ref, pid) +    ref +  end + +  defp await(pid, ref) do +    [{_, ^pid}] = Registry.lookup(GunMock, ref) +    {:response, :fin, 200, []} +  end + +  defp now, do: :os.system_time(:second) + +  describe "alive?/2" do +    test "is alive", %{name: name} do +      assert Connections.alive?(name) +    end + +    test "returns false if not started" do +      refute Connections.alive?(:some_random_name) +    end +  end + +  test "opens connection and reuse it on next request", %{name: name} do +    open_mock() +    url = "http://some-domain.com" +    key = "http:some-domain.com:80" +    refute Connections.checkin(url, name) +    :ok = Conn.open(url, name) + +    conn = Connections.checkin(url, name) +    assert is_pid(conn) +    assert Process.alive?(conn) + +    self = self() + +    %Connections{ +      conns: %{ +        ^key => %Conn{ +          conn: ^conn, +          gun_state: :up, +          used_by: [{^self, _}], +          conn_state: :active +        } +      } +    } = Connections.get_state(name) + +    reused_conn = Connections.checkin(url, name) + +    assert conn == reused_conn + +    %Connections{ +      conns: %{ +        ^key => %Conn{ +          conn: ^conn, +          gun_state: :up, +          used_by: [{^self, _}, {^self, _}], +          conn_state: :active +        } +      } +    } = Connections.get_state(name) + +    :ok = Connections.checkout(conn, self, name) + +    %Connections{ +      conns: %{ +        ^key => %Conn{ +          conn: ^conn, +          gun_state: :up, +          used_by: [{^self, _}], +          conn_state: :active +        } +      } +    } = Connections.get_state(name) + +    :ok = Connections.checkout(conn, self, name) + +    %Connections{ +      conns: %{ +        ^key => %Conn{ +          conn: ^conn, +          gun_state: :up, +          used_by: [], +          conn_state: :idle +        } +      } +    } = Connections.get_state(name) +  end + +  test "reuse connection for idna domains", %{name: name} do +    open_mock() +    url = "http://ですsome-domain.com" +    refute Connections.checkin(url, name) + +    :ok = Conn.open(url, name) + +    conn = Connections.checkin(url, name) +    assert is_pid(conn) +    assert Process.alive?(conn) + +    self = self() + +    %Connections{ +      conns: %{ +        "http:ですsome-domain.com:80" => %Conn{ +          conn: ^conn, +          gun_state: :up, +          used_by: [{^self, _}], +          conn_state: :active +        } +      } +    } = Connections.get_state(name) + +    reused_conn = Connections.checkin(url, name) + +    assert conn == reused_conn +  end + +  test "reuse for ipv4", %{name: name} do +    open_mock() +    url = "http://127.0.0.1" + +    refute Connections.checkin(url, name) + +    :ok = Conn.open(url, name) + +    conn = Connections.checkin(url, name) +    assert is_pid(conn) +    assert Process.alive?(conn) + +    self = self() + +    %Connections{ +      conns: %{ +        "http:127.0.0.1:80" => %Conn{ +          conn: ^conn, +          gun_state: :up, +          used_by: [{^self, _}], +          conn_state: :active +        } +      } +    } = Connections.get_state(name) + +    reused_conn = Connections.checkin(url, name) + +    assert conn == reused_conn + +    :ok = Connections.checkout(conn, self, name) +    :ok = Connections.checkout(reused_conn, self, name) + +    %Connections{ +      conns: %{ +        "http:127.0.0.1:80" => %Conn{ +          conn: ^conn, +          gun_state: :up, +          used_by: [], +          conn_state: :idle +        } +      } +    } = Connections.get_state(name) +  end + +  test "reuse for ipv6", %{name: name} do +    open_mock() +    url = "http://[2a03:2880:f10c:83:face:b00c:0:25de]" + +    refute Connections.checkin(url, name) + +    :ok = Conn.open(url, name) + +    conn = Connections.checkin(url, name) +    assert is_pid(conn) +    assert Process.alive?(conn) + +    self = self() + +    %Connections{ +      conns: %{ +        "http:2a03:2880:f10c:83:face:b00c:0:25de:80" => %Conn{ +          conn: ^conn, +          gun_state: :up, +          used_by: [{^self, _}], +          conn_state: :active +        } +      } +    } = Connections.get_state(name) + +    reused_conn = Connections.checkin(url, name) + +    assert conn == reused_conn +  end + +  test "up and down ipv4", %{name: name} do +    open_mock() +    |> info_mock() +    |> allow(self(), name) + +    self = self() +    url = "http://127.0.0.1" +    :ok = Conn.open(url, name) +    conn = Connections.checkin(url, name) +    send(name, {:gun_down, conn, nil, nil, nil}) +    send(name, {:gun_up, conn, nil}) + +    %Connections{ +      conns: %{ +        "http:127.0.0.1:80" => %Conn{ +          conn: ^conn, +          gun_state: :up, +          used_by: [{^self, _}], +          conn_state: :active +        } +      } +    } = Connections.get_state(name) +  end + +  test "up and down ipv6", %{name: name} do +    self = self() + +    open_mock() +    |> info_mock() +    |> allow(self, name) + +    url = "http://[2a03:2880:f10c:83:face:b00c:0:25de]" +    :ok = Conn.open(url, name) +    conn = Connections.checkin(url, name) +    send(name, {:gun_down, conn, nil, nil, nil}) +    send(name, {:gun_up, conn, nil}) + +    %Connections{ +      conns: %{ +        "http:2a03:2880:f10c:83:face:b00c:0:25de:80" => %Conn{ +          conn: ^conn, +          gun_state: :up, +          used_by: [{^self, _}], +          conn_state: :active +        } +      } +    } = Connections.get_state(name) +  end + +  test "reuses connection based on protocol", %{name: name} do +    open_mock(2) +    http_url = "http://some-domain.com" +    http_key = "http:some-domain.com:80" +    https_url = "https://some-domain.com" +    https_key = "https:some-domain.com:443" + +    refute Connections.checkin(http_url, name) +    :ok = Conn.open(http_url, name) +    conn = Connections.checkin(http_url, name) +    assert is_pid(conn) +    assert Process.alive?(conn) + +    refute Connections.checkin(https_url, name) +    :ok = Conn.open(https_url, name) +    https_conn = Connections.checkin(https_url, name) + +    refute conn == https_conn + +    reused_https = Connections.checkin(https_url, name) + +    refute conn == reused_https + +    assert reused_https == https_conn + +    %Connections{ +      conns: %{ +        ^http_key => %Conn{ +          conn: ^conn, +          gun_state: :up +        }, +        ^https_key => %Conn{ +          conn: ^https_conn, +          gun_state: :up +        } +      } +    } = Connections.get_state(name) +  end + +  test "connection can't get up", %{name: name} do +    expect(GunMock, :open, &start_and_register(&1, &2, &3)) +    url = "http://gun-not-up.com" + +    assert capture_log(fn -> +             refute Conn.open(url, name) +             refute Connections.checkin(url, name) +           end) =~ +             "Opening connection to http://gun-not-up.com failed with error {:error, :timeout}" +  end + +  test "process gun_down message and then gun_up", %{name: name} do +    self = self() + +    open_mock() +    |> info_mock() +    |> allow(self, name) + +    url = "http://gun-down-and-up.com" +    key = "http:gun-down-and-up.com:80" +    :ok = Conn.open(url, name) +    conn = Connections.checkin(url, name) + +    assert is_pid(conn) +    assert Process.alive?(conn) + +    %Connections{ +      conns: %{ +        ^key => %Conn{ +          conn: ^conn, +          gun_state: :up, +          used_by: [{^self, _}] +        } +      } +    } = Connections.get_state(name) + +    send(name, {:gun_down, conn, :http, nil, nil}) + +    %Connections{ +      conns: %{ +        ^key => %Conn{ +          conn: ^conn, +          gun_state: :down, +          used_by: [{^self, _}] +        } +      } +    } = Connections.get_state(name) + +    send(name, {:gun_up, conn, :http}) + +    conn2 = Connections.checkin(url, name) +    assert conn == conn2 + +    assert is_pid(conn2) +    assert Process.alive?(conn2) + +    %Connections{ +      conns: %{ +        ^key => %Conn{ +          conn: _, +          gun_state: :up, +          used_by: [{^self, _}, {^self, _}] +        } +      } +    } = Connections.get_state(name) +  end + +  test "async processes get same conn for same domain", %{name: name} do +    open_mock() +    url = "http://some-domain.com" +    :ok = Conn.open(url, name) + +    tasks = +      for _ <- 1..5 do +        Task.async(fn -> +          Connections.checkin(url, name) +        end) +      end + +    tasks_with_results = Task.yield_many(tasks) + +    results = +      Enum.map(tasks_with_results, fn {task, res} -> +        res || Task.shutdown(task, :brutal_kill) +      end) + +    conns = for {:ok, value} <- results, do: value + +    %Connections{ +      conns: %{ +        "http:some-domain.com:80" => %Conn{ +          conn: conn, +          gun_state: :up +        } +      } +    } = Connections.get_state(name) + +    assert Enum.all?(conns, fn res -> res == conn end) +  end + +  test "remove frequently used and idle", %{name: name} do +    open_mock(3) +    self = self() +    http_url = "http://some-domain.com" +    https_url = "https://some-domain.com" +    :ok = Conn.open(https_url, name) +    :ok = Conn.open(http_url, name) + +    conn1 = Connections.checkin(https_url, name) + +    [conn2 | _conns] = +      for _ <- 1..4 do +        Connections.checkin(http_url, name) +      end + +    http_key = "http:some-domain.com:80" + +    %Connections{ +      conns: %{ +        ^http_key => %Conn{ +          conn: ^conn2, +          gun_state: :up, +          conn_state: :active, +          used_by: [{^self, _}, {^self, _}, {^self, _}, {^self, _}] +        }, +        "https:some-domain.com:443" => %Conn{ +          conn: ^conn1, +          gun_state: :up, +          conn_state: :active, +          used_by: [{^self, _}] +        } +      } +    } = Connections.get_state(name) + +    :ok = Connections.checkout(conn1, self, name) + +    another_url = "http://another-domain.com" +    :ok = Conn.open(another_url, name) +    conn = Connections.checkin(another_url, name) + +    %Connections{ +      conns: %{ +        "http:another-domain.com:80" => %Conn{ +          conn: ^conn, +          gun_state: :up +        }, +        ^http_key => %Conn{ +          conn: _, +          gun_state: :up +        } +      } +    } = Connections.get_state(name) +  end + +  describe "with proxy" do +    test "as ip", %{name: name} do +      open_mock() +      |> connect_mock() + +      url = "http://proxy-string.com" +      key = "http:proxy-string.com:80" +      :ok = Conn.open(url, name, proxy: {{127, 0, 0, 1}, 8123}) + +      conn = Connections.checkin(url, name) + +      %Connections{ +        conns: %{ +          ^key => %Conn{ +            conn: ^conn, +            gun_state: :up +          } +        } +      } = Connections.get_state(name) + +      reused_conn = Connections.checkin(url, name) + +      assert reused_conn == conn +    end + +    test "as host", %{name: name} do +      open_mock() +      |> connect_mock() + +      url = "http://proxy-tuple-atom.com" +      :ok = Conn.open(url, name, proxy: {'localhost', 9050}) +      conn = Connections.checkin(url, name) + +      %Connections{ +        conns: %{ +          "http:proxy-tuple-atom.com:80" => %Conn{ +            conn: ^conn, +            gun_state: :up +          } +        } +      } = Connections.get_state(name) + +      reused_conn = Connections.checkin(url, name) + +      assert reused_conn == conn +    end + +    test "as ip and ssl", %{name: name} do +      open_mock() +      |> connect_mock() + +      url = "https://proxy-string.com" + +      :ok = Conn.open(url, name, proxy: {{127, 0, 0, 1}, 8123}) +      conn = Connections.checkin(url, name) + +      %Connections{ +        conns: %{ +          "https:proxy-string.com:443" => %Conn{ +            conn: ^conn, +            gun_state: :up +          } +        } +      } = Connections.get_state(name) + +      reused_conn = Connections.checkin(url, name) + +      assert reused_conn == conn +    end + +    test "as host and ssl", %{name: name} do +      open_mock() +      |> connect_mock() + +      url = "https://proxy-tuple-atom.com" +      :ok = Conn.open(url, name, proxy: {'localhost', 9050}) +      conn = Connections.checkin(url, name) + +      %Connections{ +        conns: %{ +          "https:proxy-tuple-atom.com:443" => %Conn{ +            conn: ^conn, +            gun_state: :up +          } +        } +      } = Connections.get_state(name) + +      reused_conn = Connections.checkin(url, name) + +      assert reused_conn == conn +    end + +    test "with socks type", %{name: name} do +      open_mock() + +      url = "http://proxy-socks.com" + +      :ok = Conn.open(url, name, proxy: {:socks5, 'localhost', 1234}) + +      conn = Connections.checkin(url, name) + +      %Connections{ +        conns: %{ +          "http:proxy-socks.com:80" => %Conn{ +            conn: ^conn, +            gun_state: :up +          } +        } +      } = Connections.get_state(name) + +      reused_conn = Connections.checkin(url, name) + +      assert reused_conn == conn +    end + +    test "with socks4 type and ssl", %{name: name} do +      open_mock() +      url = "https://proxy-socks.com" + +      :ok = Conn.open(url, name, proxy: {:socks4, 'localhost', 1234}) + +      conn = Connections.checkin(url, name) + +      %Connections{ +        conns: %{ +          "https:proxy-socks.com:443" => %Conn{ +            conn: ^conn, +            gun_state: :up +          } +        } +      } = Connections.get_state(name) + +      reused_conn = Connections.checkin(url, name) + +      assert reused_conn == conn +    end +  end + +  describe "crf/3" do +    setup do +      crf = Connections.crf(1, 10, 1) +      {:ok, crf: crf} +    end + +    test "more used will have crf higher", %{crf: crf} do +      # used 3 times +      crf1 = Connections.crf(1, 10, crf) +      crf1 = Connections.crf(1, 10, crf1) + +      # used 2 times +      crf2 = Connections.crf(1, 10, crf) + +      assert crf1 > crf2 +    end + +    test "recently used will have crf higher on equal references", %{crf: crf} do +      # used 3 sec ago +      crf1 = Connections.crf(3, 10, crf) + +      # used 4 sec ago +      crf2 = Connections.crf(4, 10, crf) + +      assert crf1 > crf2 +    end + +    test "equal crf on equal reference and time", %{crf: crf} do +      # used 2 times +      crf1 = Connections.crf(1, 10, crf) + +      # used 2 times +      crf2 = Connections.crf(1, 10, crf) + +      assert crf1 == crf2 +    end + +    test "recently used will have higher crf", %{crf: crf} do +      crf1 = Connections.crf(2, 10, crf) +      crf1 = Connections.crf(1, 10, crf1) + +      crf2 = Connections.crf(3, 10, crf) +      crf2 = Connections.crf(4, 10, crf2) +      assert crf1 > crf2 +    end +  end + +  describe "get_unused_conns/1" do +    test "crf is equalent, sorting by reference", %{name: name} do +      Connections.add_conn(name, "1", %Conn{ +        conn_state: :idle, +        last_reference: now() - 1 +      }) + +      Connections.add_conn(name, "2", %Conn{ +        conn_state: :idle, +        last_reference: now() +      }) + +      assert [{"1", _unused_conn} | _others] = Connections.get_unused_conns(name) +    end + +    test "reference is equalent, sorting by crf", %{name: name} do +      Connections.add_conn(name, "1", %Conn{ +        conn_state: :idle, +        crf: 1.999 +      }) + +      Connections.add_conn(name, "2", %Conn{ +        conn_state: :idle, +        crf: 2 +      }) + +      assert [{"1", _unused_conn} | _others] = Connections.get_unused_conns(name) +    end + +    test "higher crf and lower reference", %{name: name} do +      Connections.add_conn(name, "1", %Conn{ +        conn_state: :idle, +        crf: 3, +        last_reference: now() - 1 +      }) + +      Connections.add_conn(name, "2", %Conn{ +        conn_state: :idle, +        crf: 2, +        last_reference: now() +      }) + +      assert [{"2", _unused_conn} | _others] = Connections.get_unused_conns(name) +    end + +    test "lower crf and lower reference", %{name: name} do +      Connections.add_conn(name, "1", %Conn{ +        conn_state: :idle, +        crf: 1.99, +        last_reference: now() - 1 +      }) + +      Connections.add_conn(name, "2", %Conn{ +        conn_state: :idle, +        crf: 2, +        last_reference: now() +      }) + +      assert [{"1", _unused_conn} | _others] = Connections.get_unused_conns(name) +    end +  end + +  test "count/1" do +    name = :test_count +    {:ok, _} = Connections.start_link({name, [checkin_timeout: 150]}) +    assert Connections.count(name) == 0 +    Connections.add_conn(name, "1", %Conn{conn: self()}) +    assert Connections.count(name) == 1 +    Connections.remove_conn(name, "1") +    assert Connections.count(name) == 0 +  end +end diff --git a/test/reverse_proxy_test.exs b/test/reverse_proxy/reverse_proxy_test.exs index 87c6aca4e..c677066b3 100644 --- a/test/reverse_proxy_test.exs +++ b/test/reverse_proxy/reverse_proxy_test.exs @@ -4,13 +4,16 @@  defmodule Pleroma.ReverseProxyTest do    use Pleroma.Web.ConnCase, async: true +    import ExUnit.CaptureLog    import Mox +    alias Pleroma.ReverseProxy    alias Pleroma.ReverseProxy.ClientMock +  alias Plug.Conn    setup_all do -    {:ok, _} = Registry.start_link(keys: :unique, name: Pleroma.ReverseProxy.ClientMock) +    {:ok, _} = Registry.start_link(keys: :unique, name: ClientMock)      :ok    end @@ -21,7 +24,7 @@ defmodule Pleroma.ReverseProxyTest do      ClientMock      |> expect(:request, fn :get, url, _, _, _ -> -      Registry.register(Pleroma.ReverseProxy.ClientMock, url, 0) +      Registry.register(ClientMock, url, 0)        {:ok, 200,         [ @@ -29,14 +32,14 @@ defmodule Pleroma.ReverseProxyTest do           {"content-length", byte_size(json) |> to_string()}         ], %{url: url}}      end) -    |> expect(:stream_body, invokes, fn %{url: url} -> -      case Registry.lookup(Pleroma.ReverseProxy.ClientMock, url) do +    |> expect(:stream_body, invokes, fn %{url: url} = client -> +      case Registry.lookup(ClientMock, url) do          [{_, 0}] -> -          Registry.update_value(Pleroma.ReverseProxy.ClientMock, url, &(&1 + 1)) -          {:ok, json} +          Registry.update_value(ClientMock, url, &(&1 + 1)) +          {:ok, json, client}          [{_, 1}] -> -          Registry.unregister(Pleroma.ReverseProxy.ClientMock, url) +          Registry.unregister(ClientMock, url)            :done        end      end) @@ -78,7 +81,39 @@ defmodule Pleroma.ReverseProxyTest do      assert conn.halted    end -  describe "max_body " do +  defp stream_mock(invokes, with_close? \\ false) do +    ClientMock +    |> expect(:request, fn :get, "/stream-bytes/" <> length, _, _, _ -> +      Registry.register(ClientMock, "/stream-bytes/" <> length, 0) + +      {:ok, 200, [{"content-type", "application/octet-stream"}], +       %{url: "/stream-bytes/" <> length}} +    end) +    |> expect(:stream_body, invokes, fn %{url: "/stream-bytes/" <> length} = client -> +      max = String.to_integer(length) + +      case Registry.lookup(ClientMock, "/stream-bytes/" <> length) do +        [{_, current}] when current < max -> +          Registry.update_value( +            ClientMock, +            "/stream-bytes/" <> length, +            &(&1 + 10) +          ) + +          {:ok, "0123456789", client} + +        [{_, ^max}] -> +          Registry.unregister(ClientMock, "/stream-bytes/" <> length) +          :done +      end +    end) + +    if with_close? do +      expect(ClientMock, :close, fn _ -> :ok end) +    end +  end + +  describe "max_body" do      test "length returns error if content-length more than option", %{conn: conn} do        user_agent_mock("hackney/1.15.1", 0) @@ -94,38 +129,6 @@ defmodule Pleroma.ReverseProxyTest do               end) == ""      end -    defp stream_mock(invokes, with_close? \\ false) do -      ClientMock -      |> expect(:request, fn :get, "/stream-bytes/" <> length, _, _, _ -> -        Registry.register(Pleroma.ReverseProxy.ClientMock, "/stream-bytes/" <> length, 0) - -        {:ok, 200, [{"content-type", "application/octet-stream"}], -         %{url: "/stream-bytes/" <> length}} -      end) -      |> expect(:stream_body, invokes, fn %{url: "/stream-bytes/" <> length} -> -        max = String.to_integer(length) - -        case Registry.lookup(Pleroma.ReverseProxy.ClientMock, "/stream-bytes/" <> length) do -          [{_, current}] when current < max -> -            Registry.update_value( -              Pleroma.ReverseProxy.ClientMock, -              "/stream-bytes/" <> length, -              &(&1 + 10) -            ) - -            {:ok, "0123456789"} - -          [{_, ^max}] -> -            Registry.unregister(Pleroma.ReverseProxy.ClientMock, "/stream-bytes/" <> length) -            :done -        end -      end) - -      if with_close? do -        expect(ClientMock, :close, fn _ -> :ok end) -      end -    end -      test "max_body_length returns error if streaming body more than that option", %{conn: conn} do        stream_mock(3, true) @@ -214,24 +217,24 @@ defmodule Pleroma.ReverseProxyTest do      conn = ReverseProxy.call(conn, "/stream-bytes/200")      assert conn.state == :chunked      assert byte_size(conn.resp_body) == 200 -    assert Plug.Conn.get_resp_header(conn, "content-type") == ["application/octet-stream"] +    assert Conn.get_resp_header(conn, "content-type") == ["application/octet-stream"]    end    defp headers_mock(_) do      ClientMock      |> expect(:request, fn :get, "/headers", headers, _, _ -> -      Registry.register(Pleroma.ReverseProxy.ClientMock, "/headers", 0) +      Registry.register(ClientMock, "/headers", 0)        {:ok, 200, [{"content-type", "application/json"}], %{url: "/headers", headers: headers}}      end) -    |> expect(:stream_body, 2, fn %{url: url, headers: headers} -> -      case Registry.lookup(Pleroma.ReverseProxy.ClientMock, url) do +    |> expect(:stream_body, 2, fn %{url: url, headers: headers} = client -> +      case Registry.lookup(ClientMock, url) do          [{_, 0}] -> -          Registry.update_value(Pleroma.ReverseProxy.ClientMock, url, &(&1 + 1)) +          Registry.update_value(ClientMock, url, &(&1 + 1))            headers = for {k, v} <- headers, into: %{}, do: {String.capitalize(k), v} -          {:ok, Jason.encode!(%{headers: headers})} +          {:ok, Jason.encode!(%{headers: headers}), client}          [{_, 1}] -> -          Registry.unregister(Pleroma.ReverseProxy.ClientMock, url) +          Registry.unregister(ClientMock, url)            :done        end      end) @@ -244,7 +247,7 @@ defmodule Pleroma.ReverseProxyTest do      test "header passes", %{conn: conn} do        conn = -        Plug.Conn.put_req_header( +        Conn.put_req_header(            conn,            "accept",            "text/html" @@ -257,7 +260,7 @@ defmodule Pleroma.ReverseProxyTest do      test "header is filtered", %{conn: conn} do        conn = -        Plug.Conn.put_req_header( +        Conn.put_req_header(            conn,            "accept-language",            "en-US" @@ -290,18 +293,18 @@ defmodule Pleroma.ReverseProxyTest do    defp disposition_headers_mock(headers) do      ClientMock      |> expect(:request, fn :get, "/disposition", _, _, _ -> -      Registry.register(Pleroma.ReverseProxy.ClientMock, "/disposition", 0) +      Registry.register(ClientMock, "/disposition", 0)        {:ok, 200, headers, %{url: "/disposition"}}      end) -    |> expect(:stream_body, 2, fn %{url: "/disposition"} -> -      case Registry.lookup(Pleroma.ReverseProxy.ClientMock, "/disposition") do +    |> expect(:stream_body, 2, fn %{url: "/disposition"} = client -> +      case Registry.lookup(ClientMock, "/disposition") do          [{_, 0}] -> -          Registry.update_value(Pleroma.ReverseProxy.ClientMock, "/disposition", &(&1 + 1)) -          {:ok, ""} +          Registry.update_value(ClientMock, "/disposition", &(&1 + 1)) +          {:ok, "", client}          [{_, 1}] -> -          Registry.unregister(Pleroma.ReverseProxy.ClientMock, "/disposition") +          Registry.unregister(ClientMock, "/disposition")            :done        end      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/stat_test.exs index 33b77e7e7..bccc1c8d0 100644 --- a/test/stat_test.exs +++ b/test/stat_test.exs @@ -60,7 +60,7 @@ defmodule Pleroma.StateTest do        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})        _ = CommonAPI.follow(user, other_user) -      CommonAPI.favorite(activity.id, other_user) +      CommonAPI.favorite(other_user, activity.id)        CommonAPI.repeat(activity.id, other_user)        assert %{direct: 0, private: 0, public: 1, unlisted: 0} = diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index e72638814..20cb2b3d1 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -107,7 +107,7 @@ defmodule HttpRequestMock do          "https://osada.macgirvin.com/.well-known/webfinger?resource=acct:mike@osada.macgirvin.com",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -120,7 +120,7 @@ defmodule HttpRequestMock do          "https://social.heldscal.la/.well-known/webfinger?resource=https://social.heldscal.la/user/29191",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -141,7 +141,7 @@ defmodule HttpRequestMock do          "https://pawoo.net/.well-known/webfinger?resource=acct:https://pawoo.net/users/pekorino",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -167,7 +167,7 @@ defmodule HttpRequestMock do          "https://social.stopwatchingus-heidelberg.de/.well-known/webfinger?resource=acct:https://social.stopwatchingus-heidelberg.de/user/18330",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -188,7 +188,7 @@ defmodule HttpRequestMock do          "https://mamot.fr/.well-known/webfinger?resource=acct:https://mamot.fr/users/Skruyb",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -201,7 +201,7 @@ defmodule HttpRequestMock do          "https://social.heldscal.la/.well-known/webfinger?resource=nonexistant@social.heldscal.la",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -214,7 +214,7 @@ defmodule HttpRequestMock do          "https://squeet.me/xrd/?uri=lain@squeet.me",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -227,7 +227,7 @@ defmodule HttpRequestMock do          "https://mst3k.interlinked.me/users/luciferMysticus",          _,          _, -        Accept: "application/activity+json" +        [{"accept", "application/activity+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -248,7 +248,7 @@ defmodule HttpRequestMock do          "https://hubzilla.example.org/channel/kaniini",          _,          _, -        Accept: "application/activity+json" +        [{"accept", "application/activity+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -257,7 +257,7 @@ defmodule HttpRequestMock do       }}    end -  def get("https://niu.moe/users/rye", _, _, Accept: "application/activity+json") do +  def get("https://niu.moe/users/rye", _, _, [{"accept", "application/activity+json"}]) do      {:ok,       %Tesla.Env{         status: 200, @@ -265,7 +265,7 @@ defmodule HttpRequestMock do       }}    end -  def get("https://n1u.moe/users/rye", _, _, Accept: "application/activity+json") do +  def get("https://n1u.moe/users/rye", _, _, [{"accept", "application/activity+json"}]) do      {:ok,       %Tesla.Env{         status: 200, @@ -284,7 +284,7 @@ defmodule HttpRequestMock do       }}    end -  def get("https://puckipedia.com/", _, _, Accept: "application/activity+json") do +  def get("https://puckipedia.com/", _, _, [{"accept", "application/activity+json"}]) do      {:ok,       %Tesla.Env{         status: 200, @@ -308,9 +308,9 @@ defmodule HttpRequestMock do       }}    end -  def get("https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39", _, _, -        Accept: "application/activity+json" -      ) do +  def get("https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39", _, _, [ +        {"accept", "application/activity+json"} +      ]) do      {:ok,       %Tesla.Env{         status: 200, @@ -318,7 +318,7 @@ defmodule HttpRequestMock do       }}    end -  def get("https://mobilizon.org/@tcit", _, _, Accept: "application/activity+json") do +  def get("https://mobilizon.org/@tcit", _, _, [{"accept", "application/activity+json"}]) do      {:ok,       %Tesla.Env{         status: 200, @@ -358,7 +358,7 @@ defmodule HttpRequestMock do       }}    end -  def get("http://mastodon.example.org/users/admin", _, _, Accept: "application/activity+json") do +  def get("http://mastodon.example.org/users/admin", _, _, _) do      {:ok,       %Tesla.Env{         status: 200, @@ -366,7 +366,9 @@ defmodule HttpRequestMock do       }}    end -  def get("http://mastodon.example.org/users/relay", _, _, Accept: "application/activity+json") do +  def get("http://mastodon.example.org/users/relay", _, _, [ +        {"accept", "application/activity+json"} +      ]) do      {:ok,       %Tesla.Env{         status: 200, @@ -374,7 +376,9 @@ defmodule HttpRequestMock do       }}    end -  def get("http://mastodon.example.org/users/gargron", _, _, Accept: "application/activity+json") do +  def get("http://mastodon.example.org/users/gargron", _, _, [ +        {"accept", "application/activity+json"} +      ]) do      {:error, :nxdomain}    end @@ -557,7 +561,7 @@ defmodule HttpRequestMock do          "http://mastodon.example.org/@admin/99541947525187367",          _,          _, -        Accept: "application/activity+json" +        _        ) do      {:ok,       %Tesla.Env{ @@ -582,7 +586,7 @@ defmodule HttpRequestMock do       }}    end -  def get("https://mstdn.io/users/mayuutann", _, _, Accept: "application/activity+json") do +  def get("https://mstdn.io/users/mayuutann", _, _, [{"accept", "application/activity+json"}]) do      {:ok,       %Tesla.Env{         status: 200, @@ -594,7 +598,7 @@ defmodule HttpRequestMock do          "https://mstdn.io/users/mayuutann/statuses/99568293732299394",          _,          _, -        Accept: "application/activity+json" +        [{"accept", "application/activity+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -614,7 +618,7 @@ defmodule HttpRequestMock do       }}    end -  def get(url, _, _, Accept: "application/xrd+xml,application/jrd+json") +  def get(url, _, _, [{"accept", "application/xrd+xml,application/jrd+json"}])        when url in [               "https://pleroma.soykaf.com/.well-known/webfinger?resource=acct:https://pleroma.soykaf.com/users/lain",               "https://pleroma.soykaf.com/.well-known/webfinger?resource=https://pleroma.soykaf.com/users/lain" @@ -641,7 +645,7 @@ defmodule HttpRequestMock do          "https://shitposter.club/.well-known/webfinger?resource=https://shitposter.club/user/1",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -685,7 +689,7 @@ defmodule HttpRequestMock do          "https://shitposter.club/.well-known/webfinger?resource=https://shitposter.club/user/5381",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -738,7 +742,7 @@ defmodule HttpRequestMock do          "https://social.sakamoto.gq/.well-known/webfinger?resource=https://social.sakamoto.gq/users/eal",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -751,7 +755,7 @@ defmodule HttpRequestMock do          "https://social.sakamoto.gq/objects/0ccc1a2c-66b0-4305-b23a-7f7f2b040056",          _,          _, -        Accept: "application/atom+xml" +        [{"accept", "application/atom+xml"}]        ) do      {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/sakamoto.atom")}}    end @@ -768,7 +772,7 @@ defmodule HttpRequestMock do          "https://mastodon.social/.well-known/webfinger?resource=https://mastodon.social/users/lambadalambda",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -790,7 +794,7 @@ defmodule HttpRequestMock do          "http://gs.example.org/.well-known/webfinger?resource=http://gs.example.org:4040/index.php/user/1",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -804,7 +808,7 @@ defmodule HttpRequestMock do          "http://gs.example.org:4040/index.php/user/1",          _,          _, -        Accept: "application/activity+json" +        [{"accept", "application/activity+json"}]        ) do      {:ok, %Tesla.Env{status: 406, body: ""}}    end @@ -840,7 +844,7 @@ defmodule HttpRequestMock do          "https://squeet.me/xrd?uri=lain@squeet.me",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -853,7 +857,7 @@ defmodule HttpRequestMock do          "https://social.heldscal.la/.well-known/webfinger?resource=shp@social.heldscal.la",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -866,7 +870,7 @@ defmodule HttpRequestMock do          "https://social.heldscal.la/.well-known/webfinger?resource=invalid_content@social.heldscal.la",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok, %Tesla.Env{status: 200, body: ""}}    end @@ -883,7 +887,7 @@ defmodule HttpRequestMock do          "http://framatube.org/main/xrd?uri=framasoft@framatube.org",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -905,7 +909,7 @@ defmodule HttpRequestMock do          "http://gnusocial.de/main/xrd?uri=winterdienst@gnusocial.de",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -942,7 +946,7 @@ defmodule HttpRequestMock do          "https://gerzilla.de/xrd/?uri=kaniini@gerzilla.de",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -1005,7 +1009,7 @@ defmodule HttpRequestMock do       %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/osada-user-indio.json")}}    end -  def get("https://social.heldscal.la/user/23211", _, _, Accept: "application/activity+json") do +  def get("https://social.heldscal.la/user/23211", _, _, [{"accept", "application/activity+json"}]) do      {:ok, Tesla.Mock.json(%{"id" => "https://social.heldscal.la/user/23211"}, status: 200)}    end @@ -1138,7 +1142,7 @@ defmodule HttpRequestMock do          "https://zetsubou.xn--q9jyb4c/.well-known/webfinger?resource=lain@zetsubou.xn--q9jyb4c",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -1151,7 +1155,7 @@ defmodule HttpRequestMock do          "https://zetsubou.xn--q9jyb4c/.well-known/webfinger?resource=https://zetsubou.xn--q9jyb4c/users/lain",          _,          _, -        Accept: "application/xrd+xml,application/jrd+json" +        [{"accept", "application/xrd+xml,application/jrd+json"}]        ) do      {:ok,       %Tesla.Env{ @@ -1173,7 +1177,9 @@ defmodule HttpRequestMock do       }}    end -  def get("https://info.pleroma.site/activity.json", _, _, Accept: "application/activity+json") do +  def get("https://info.pleroma.site/activity.json", _, _, [ +        {"accept", "application/activity+json"} +      ]) do      {:ok,       %Tesla.Env{         status: 200, @@ -1185,7 +1191,9 @@ defmodule HttpRequestMock do      {:ok, %Tesla.Env{status: 404, body: ""}}    end -  def get("https://info.pleroma.site/activity2.json", _, _, Accept: "application/activity+json") do +  def get("https://info.pleroma.site/activity2.json", _, _, [ +        {"accept", "application/activity+json"} +      ]) do      {:ok,       %Tesla.Env{         status: 200, @@ -1197,7 +1205,9 @@ defmodule HttpRequestMock do      {:ok, %Tesla.Env{status: 404, body: ""}}    end -  def get("https://info.pleroma.site/activity3.json", _, _, Accept: "application/activity+json") do +  def get("https://info.pleroma.site/activity3.json", _, _, [ +        {"accept", "application/activity+json"} +      ]) do      {:ok,       %Tesla.Env{         status: 200, @@ -1273,6 +1283,21 @@ defmodule HttpRequestMock do      {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/rin.json")}}    end +  def get( +        "https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871", +        _, +        _, +        _ +      ) do +    {:ok, +     %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/funkwhale_audio.json")}} +  end + +  def get("https://channels.tests.funkwhale.audio/federation/actors/compositions", _, _, _) do +    {:ok, +     %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/funkwhale_channel.json")}} +  end +    def get("http://example.com/rel_me/error", _, _, _) do      {:ok, %Tesla.Env{status: 404, body: ""}}    end diff --git a/test/tasks/database_test.exs b/test/tasks/database_test.exs index ed1c31d9c..7b05993d3 100644 --- a/test/tasks/database_test.exs +++ b/test/tasks/database_test.exs @@ -102,7 +102,7 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do        {:ok, %{id: id, object: object}} = CommonAPI.post(user, %{"status" => "test"})        {:ok, %{object: object2}} = CommonAPI.post(user, %{"status" => "test test"}) -      CommonAPI.favorite(id, user2) +      CommonAPI.favorite(user2, id)        likes = %{          "first" => diff --git a/test/tasks/emoji_test.exs b/test/tasks/emoji_test.exs new file mode 100644 index 000000000..f5de3ef0e --- /dev/null +++ b/test/tasks/emoji_test.exs @@ -0,0 +1,226 @@ +defmodule Mix.Tasks.Pleroma.EmojiTest do +  use ExUnit.Case, async: true + +  import ExUnit.CaptureIO +  import Tesla.Mock + +  alias Mix.Tasks.Pleroma.Emoji + +  describe "ls-packs" do +    test "with default manifest as url" do +      mock(fn +        %{ +          method: :get, +          url: "https://git.pleroma.social/pleroma/emoji-index/raw/master/index.json" +        } -> +          %Tesla.Env{ +            status: 200, +            body: File.read!("test/fixtures/emoji/packs/default-manifest.json") +          } +      end) + +      capture_io(fn -> Emoji.run(["ls-packs"]) end) =~ +        "https://finland.fi/wp-content/uploads/2017/06/finland-emojis.zip" +    end + +    test "with passed manifest as file" do +      capture_io(fn -> +        Emoji.run(["ls-packs", "-m", "test/fixtures/emoji/packs/manifest.json"]) +      end) =~ "https://git.pleroma.social/pleroma/emoji-index/raw/master/packs/blobs_gg.zip" +    end +  end + +  describe "get-packs" do +    test "download pack from default manifest" do +      mock(fn +        %{ +          method: :get, +          url: "https://git.pleroma.social/pleroma/emoji-index/raw/master/index.json" +        } -> +          %Tesla.Env{ +            status: 200, +            body: File.read!("test/fixtures/emoji/packs/default-manifest.json") +          } + +        %{ +          method: :get, +          url: "https://finland.fi/wp-content/uploads/2017/06/finland-emojis.zip" +        } -> +          %Tesla.Env{ +            status: 200, +            body: File.read!("test/fixtures/emoji/packs/blank.png.zip") +          } + +        %{ +          method: :get, +          url: "https://git.pleroma.social/pleroma/emoji-index/raw/master/finmoji.json" +        } -> +          %Tesla.Env{ +            status: 200, +            body: File.read!("test/fixtures/emoji/packs/finmoji.json") +          } +      end) + +      assert capture_io(fn -> Emoji.run(["get-packs", "finmoji"]) end) =~ "Writing pack.json for" + +      emoji_path = +        Path.join( +          Pleroma.Config.get!([:instance, :static_dir]), +          "emoji" +        ) + +      assert File.exists?(Path.join([emoji_path, "finmoji", "pack.json"])) +      on_exit(fn -> File.rm_rf!("test/instance_static/emoji/finmoji") end) +    end + +    test "pack not found" do +      mock(fn +        %{ +          method: :get, +          url: "https://git.pleroma.social/pleroma/emoji-index/raw/master/index.json" +        } -> +          %Tesla.Env{ +            status: 200, +            body: File.read!("test/fixtures/emoji/packs/default-manifest.json") +          } +      end) + +      assert capture_io(fn -> Emoji.run(["get-packs", "not_found"]) end) =~ +               "No pack named \"not_found\" found" +    end + +    test "raise on bad sha256" do +      mock(fn +        %{ +          method: :get, +          url: "https://git.pleroma.social/pleroma/emoji-index/raw/master/packs/blobs_gg.zip" +        } -> +          %Tesla.Env{ +            status: 200, +            body: File.read!("test/fixtures/emoji/packs/blank.png.zip") +          } +      end) + +      assert_raise RuntimeError, ~r/^Bad SHA256 for blobs.gg/, fn -> +        capture_io(fn -> +          Emoji.run(["get-packs", "blobs.gg", "-m", "test/fixtures/emoji/packs/manifest.json"]) +        end) +      end +    end +  end + +  describe "gen-pack" do +    setup do +      url = "https://finland.fi/wp-content/uploads/2017/06/finland-emojis.zip" + +      mock(fn %{ +                method: :get, +                url: ^url +              } -> +        %Tesla.Env{status: 200, body: File.read!("test/fixtures/emoji/packs/blank.png.zip")} +      end) + +      {:ok, url: url} +    end + +    test "with default extensions", %{url: url} do +      name = "pack1" +      pack_json = "#{name}.json" +      files_json = "#{name}_file.json" +      refute File.exists?(pack_json) +      refute File.exists?(files_json) + +      captured = +        capture_io(fn -> +          Emoji.run([ +            "gen-pack", +            url, +            "--name", +            name, +            "--license", +            "license", +            "--homepage", +            "homepage", +            "--description", +            "description", +            "--files", +            files_json, +            "--extensions", +            ".png .gif" +          ]) +        end) + +      assert captured =~ "#{pack_json} has been created with the pack1 pack" +      assert captured =~ "Using .png .gif extensions" + +      assert File.exists?(pack_json) +      assert File.exists?(files_json) + +      on_exit(fn -> +        File.rm!(pack_json) +        File.rm!(files_json) +      end) +    end + +    test "with custom extensions and update existing files", %{url: url} do +      name = "pack2" +      pack_json = "#{name}.json" +      files_json = "#{name}_file.json" +      refute File.exists?(pack_json) +      refute File.exists?(files_json) + +      captured = +        capture_io(fn -> +          Emoji.run([ +            "gen-pack", +            url, +            "--name", +            name, +            "--license", +            "license", +            "--homepage", +            "homepage", +            "--description", +            "description", +            "--files", +            files_json, +            "--extensions", +            " .png   .gif    .jpeg " +          ]) +        end) + +      assert captured =~ "#{pack_json} has been created with the pack2 pack" +      assert captured =~ "Using .png .gif .jpeg extensions" + +      assert File.exists?(pack_json) +      assert File.exists?(files_json) + +      captured = +        capture_io(fn -> +          Emoji.run([ +            "gen-pack", +            url, +            "--name", +            name, +            "--license", +            "license", +            "--homepage", +            "homepage", +            "--description", +            "description", +            "--files", +            files_json, +            "--extensions", +            " .png   .gif    .jpeg " +          ]) +        end) + +      assert captured =~ "#{pack_json} has been updated with the pack2 pack" + +      on_exit(fn -> +        File.rm!(pack_json) +        File.rm!(files_json) +      end) +    end +  end +end 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/test_helper.exs b/test/test_helper.exs index 6b91d2b46..ee880e226 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -6,7 +6,10 @@ os_exclude = if :os.type() == {:unix, :darwin}, do: [skip_on_mac: true], else: [  ExUnit.start(exclude: [:federated | os_exclude])  Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, :manual) +  Mox.defmock(Pleroma.ReverseProxy.ClientMock, for: Pleroma.ReverseProxy.Client) +Mox.defmock(Pleroma.GunMock, for: Pleroma.Gun) +  {:ok, _} = Application.ensure_all_started(:ex_machina)  ExUnit.after_suite(fn _results -> diff --git a/test/user_invite_token_test.exs b/test/user_invite_token_test.exs index 4f70ef337..63f18f13c 100644 --- a/test/user_invite_token_test.exs +++ b/test/user_invite_token_test.exs @@ -4,7 +4,6 @@  defmodule Pleroma.UserInviteTokenTest do    use ExUnit.Case, async: true -  use Pleroma.DataCase    alias Pleroma.UserInviteToken    describe "valid_invite?/1 one time invites" do @@ -64,7 +63,6 @@ defmodule Pleroma.UserInviteTokenTest do      test "expires yesterday returns false", %{invite: invite} do        invite = %{invite | expires_at: Date.add(Date.utc_today(), -1)} -      invite = Repo.insert!(invite)        refute UserInviteToken.valid_invite?(invite)      end    end @@ -82,7 +80,6 @@ defmodule Pleroma.UserInviteTokenTest do      test "overdue date and less uses returns false", %{invite: invite} do        invite = %{invite | expires_at: Date.add(Date.utc_today(), -1)} -      invite = Repo.insert!(invite)        refute UserInviteToken.valid_invite?(invite)      end @@ -93,7 +90,6 @@ defmodule Pleroma.UserInviteTokenTest do      test "overdue date with more uses returns false", %{invite: invite} do        invite = %{invite | expires_at: Date.add(Date.utc_today(), -1), uses: 5} -      invite = Repo.insert!(invite)        refute UserInviteToken.valid_invite?(invite)      end    end diff --git a/test/user_test.exs b/test/user_test.exs index 119a36ec1..65e118d6d 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -86,7 +86,7 @@ defmodule Pleroma.UserTest do        {:ok, user: insert(:user)}      end -    test "outgoing_relations_ap_ids/1", %{user: user} do +    test "outgoing_relationships_ap_ids/1", %{user: user} do        rel_types = [:block, :mute, :notification_mute, :reblog_mute, :inverse_subscription]        ap_ids_by_rel = @@ -124,10 +124,10 @@ defmodule Pleroma.UserTest do        assert ap_ids_by_rel[:inverse_subscription] ==                 Enum.sort(Enum.map(User.subscriber_users(user), & &1.ap_id)) -      outgoing_relations_ap_ids = User.outgoing_relations_ap_ids(user, rel_types) +      outgoing_relationships_ap_ids = User.outgoing_relationships_ap_ids(user, rel_types)        assert ap_ids_by_rel == -               Enum.into(outgoing_relations_ap_ids, %{}, fn {k, v} -> {k, Enum.sort(v)} end) +               Enum.into(outgoing_relationships_ap_ids, %{}, fn {k, v} -> {k, Enum.sort(v)} end)      end    end @@ -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 @@ -1141,8 +1142,8 @@ defmodule Pleroma.UserTest do        object_two = insert(:note, user: follower)        activity_two = insert(:note_activity, user: follower, note: object_two) -      {:ok, like, _} = CommonAPI.favorite(activity_two.id, user) -      {:ok, like_two, _} = CommonAPI.favorite(activity.id, follower) +      {:ok, like} = CommonAPI.favorite(user, activity_two.id) +      {:ok, like_two} = CommonAPI.favorite(follower, activity.id)        {:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user)        {:ok, job} = User.delete(user) @@ -1198,58 +1199,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 +1353,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 a43dd34f0..6410df49b 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 @@ -1425,6 +1424,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert Repo.get(Object, object.id).data["type"] == "Tombstone"      end +    test "it doesn't fail when an activity was already deleted" do +      {:ok, delete} = insert(:note_activity) |> Object.normalize() |> ActivityPub.delete() + +      assert {:ok, ^delete} = delete |> Object.normalize() |> ActivityPub.delete() +    end +      test "decrements user note count only for public activities" do        user = insert(:user, note_count: 10) @@ -1894,14 +1899,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        {:ok, a4} = CommonAPI.post(user2, %{"status" => "Agent Smith "})        {:ok, a5} = CommonAPI.post(user1, %{"status" => "Red or Blue "}) -      {:ok, _, _} = CommonAPI.favorite(a4.id, user) -      {:ok, _, _} = CommonAPI.favorite(a3.id, other_user) -      {:ok, _, _} = CommonAPI.favorite(a3.id, user) -      {:ok, _, _} = CommonAPI.favorite(a5.id, other_user) -      {:ok, _, _} = CommonAPI.favorite(a5.id, user) -      {:ok, _, _} = CommonAPI.favorite(a4.id, other_user) -      {:ok, _, _} = CommonAPI.favorite(a1.id, user) -      {:ok, _, _} = CommonAPI.favorite(a1.id, other_user) +      {:ok, _} = CommonAPI.favorite(user, a4.id) +      {:ok, _} = CommonAPI.favorite(other_user, a3.id) +      {:ok, _} = CommonAPI.favorite(user, a3.id) +      {:ok, _} = CommonAPI.favorite(other_user, a5.id) +      {:ok, _} = CommonAPI.favorite(user, a5.id) +      {:ok, _} = CommonAPI.favorite(other_user, a4.id) +      {:ok, _} = CommonAPI.favorite(user, a1.id) +      {:ok, _} = CommonAPI.favorite(other_user, a1.id)        result = ActivityPub.fetch_favourites(user)        assert Enum.map(result, & &1.id) == [a1.id, a5.id, a3.id, a4.id] diff --git a/test/web/activity_pub/mrf/anti_followbot_policy_test.exs b/test/web/activity_pub/mrf/anti_followbot_policy_test.exs index 37a7bfcf7..fca0de7c6 100644 --- a/test/web/activity_pub/mrf/anti_followbot_policy_test.exs +++ b/test/web/activity_pub/mrf/anti_followbot_policy_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do diff --git a/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs b/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs index b524fdd23..1a13699be 100644 --- a/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs +++ b/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do @@ -110,6 +110,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do    end    describe "with unknown actors" do +    setup do +      Tesla.Mock.mock(fn +        %{method: :get, url: "http://invalid.actor"} -> +          %Tesla.Env{status: 500, body: ""} +      end) + +      :ok +    end +      test "it rejects posts without links" do        message =          @linkless_message diff --git a/test/web/activity_pub/mrf/ensure_re_prepended_test.exs b/test/web/activity_pub/mrf/ensure_re_prepended_test.exs index dbc8b9e80..38ddec5bb 100644 --- a/test/web/activity_pub/mrf/ensure_re_prepended_test.exs +++ b/test/web/activity_pub/mrf/ensure_re_prepended_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do diff --git a/test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs b/test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs index 63ed71129..64ea61dd4 100644 --- a/test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs +++ b/test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicyTest do diff --git a/test/web/activity_pub/mrf/normalize_markup_test.exs b/test/web/activity_pub/mrf/normalize_markup_test.exs index 0207be56b..9b39c45bd 100644 --- a/test/web/activity_pub/mrf/normalize_markup_test.exs +++ b/test/web/activity_pub/mrf/normalize_markup_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkupTest do 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 0fbc5f57a..7ee195eeb 100644 --- a/test/web/activity_pub/mrf/object_age_policy_test.exs +++ b/test/web/activity_pub/mrf/object_age_policy_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do diff --git a/test/web/activity_pub/mrf/reject_non_public_test.exs b/test/web/activity_pub/mrf/reject_non_public_test.exs index abfd32df8..f36299b86 100644 --- a/test/web/activity_pub/mrf/reject_non_public_test.exs +++ b/test/web/activity_pub/mrf/reject_non_public_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do diff --git a/test/web/activity_pub/mrf/simple_policy_test.exs b/test/web/activity_pub/mrf/simple_policy_test.exs index 5aebbc675..91c24c2d9 100644 --- a/test/web/activity_pub/mrf/simple_policy_test.exs +++ b/test/web/activity_pub/mrf/simple_policy_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs new file mode 100644 index 000000000..3c5c3696e --- /dev/null +++ b/test/web/activity_pub/object_validator_test.exs @@ -0,0 +1,83 @@ +defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator +  alias Pleroma.Web.ActivityPub.Utils +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "likes" do +    setup do +      user = insert(:user) +      {:ok, post_activity} = CommonAPI.post(user, %{"status" => "uguu"}) + +      valid_like = %{ +        "to" => [user.ap_id], +        "cc" => [], +        "type" => "Like", +        "id" => Utils.generate_activity_id(), +        "object" => post_activity.data["object"], +        "actor" => user.ap_id, +        "context" => "a context" +      } + +      %{valid_like: valid_like, user: user, post_activity: post_activity} +    end + +    test "returns ok when called in the ObjectValidator", %{valid_like: valid_like} do +      {:ok, object, _meta} = ObjectValidator.validate(valid_like, []) + +      assert "id" in Map.keys(object) +    end + +    test "is valid for a valid object", %{valid_like: valid_like} do +      assert LikeValidator.cast_and_validate(valid_like).valid? +    end + +    test "it errors when the actor is missing or not known", %{valid_like: valid_like} do +      without_actor = Map.delete(valid_like, "actor") + +      refute LikeValidator.cast_and_validate(without_actor).valid? + +      with_invalid_actor = Map.put(valid_like, "actor", "invalidactor") + +      refute LikeValidator.cast_and_validate(with_invalid_actor).valid? +    end + +    test "it errors when the object is missing or not known", %{valid_like: valid_like} do +      without_object = Map.delete(valid_like, "object") + +      refute LikeValidator.cast_and_validate(without_object).valid? + +      with_invalid_object = Map.put(valid_like, "object", "invalidobject") + +      refute LikeValidator.cast_and_validate(with_invalid_object).valid? +    end + +    test "it errors when the actor has already like the object", %{ +      valid_like: valid_like, +      user: user, +      post_activity: post_activity +    } do +      _like = CommonAPI.favorite(user, post_activity.id) + +      refute LikeValidator.cast_and_validate(valid_like).valid? +    end + +    test "it works when actor or object are wrapped in maps", %{valid_like: valid_like} do +      wrapped_like = +        valid_like +        |> Map.put("actor", %{"id" => valid_like["actor"]}) +        |> Map.put("object", %{"id" => valid_like["object"]}) + +      validated = LikeValidator.cast_and_validate(wrapped_like) + +      assert validated.valid? + +      assert {:actor, valid_like["actor"]} in validated.changes +      assert {:object, valid_like["object"]} in validated.changes +    end +  end +end diff --git a/test/web/activity_pub/object_validators/note_validator_test.exs b/test/web/activity_pub/object_validators/note_validator_test.exs new file mode 100644 index 000000000..30c481ffb --- /dev/null +++ b/test/web/activity_pub/object_validators/note_validator_test.exs @@ -0,0 +1,35 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidatorTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator +  alias Pleroma.Web.ActivityPub.Utils + +  import Pleroma.Factory + +  describe "Notes" do +    setup do +      user = insert(:user) + +      note = %{ +        "id" => Utils.generate_activity_id(), +        "type" => "Note", +        "actor" => user.ap_id, +        "to" => [user.follower_address], +        "cc" => [], +        "content" => "Hellow this is content.", +        "context" => "xxx", +        "summary" => "a post" +      } + +      %{user: user, note: note} +    end + +    test "a basic note validates", %{note: note} do +      %{valid?: true} = NoteValidator.cast_and_validate(note) +    end +  end +end diff --git a/test/web/activity_pub/object_validators/types/date_time_test.exs b/test/web/activity_pub/object_validators/types/date_time_test.exs new file mode 100644 index 000000000..3e17a9497 --- /dev/null +++ b/test/web/activity_pub/object_validators/types/date_time_test.exs @@ -0,0 +1,32 @@ +defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTimeTest do +  alias Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTime +  use Pleroma.DataCase + +  test "it validates an xsd:Datetime" do +    valid_strings = [ +      "2004-04-12T13:20:00", +      "2004-04-12T13:20:15.5", +      "2004-04-12T13:20:00-05:00", +      "2004-04-12T13:20:00Z" +    ] + +    invalid_strings = [ +      "2004-04-12T13:00", +      "2004-04-1213:20:00", +      "99-04-12T13:00", +      "2004-04-12" +    ] + +    assert {:ok, "2004-04-01T12:00:00Z"} == DateTime.cast("2004-04-01T12:00:00Z") + +    Enum.each(valid_strings, fn date_time -> +      result = DateTime.cast(date_time) +      assert {:ok, _} = result +    end) + +    Enum.each(invalid_strings, fn date_time -> +      result = DateTime.cast(date_time) +      assert :error == result +    end) +  end +end diff --git a/test/web/activity_pub/object_validators/types/object_id_test.exs b/test/web/activity_pub/object_validators/types/object_id_test.exs new file mode 100644 index 000000000..834213182 --- /dev/null +++ b/test/web/activity_pub/object_validators/types/object_id_test.exs @@ -0,0 +1,37 @@ +defmodule Pleroma.Web.ObjectValidators.Types.ObjectIDTest do +  alias Pleroma.Web.ActivityPub.ObjectValidators.Types.ObjectID +  use Pleroma.DataCase + +  @uris [ +    "http://lain.com/users/lain", +    "http://lain.com", +    "https://lain.com/object/1" +  ] + +  @non_uris [ +    "https://", +    "rin", +    1, +    :x, +    %{"1" => 2} +  ] + +  test "it accepts http uris" do +    Enum.each(@uris, fn uri -> +      assert {:ok, uri} == ObjectID.cast(uri) +    end) +  end + +  test "it accepts an object with a nested uri id" do +    Enum.each(@uris, fn uri -> +      assert {:ok, uri} == ObjectID.cast(%{"id" => uri}) +    end) +  end + +  test "it rejects non-uri strings" do +    Enum.each(@non_uris, fn non_uri -> +      assert :error == ObjectID.cast(non_uri) +      assert :error == ObjectID.cast(%{"id" => non_uri}) +    end) +  end +end diff --git a/test/web/activity_pub/pipeline_test.exs b/test/web/activity_pub/pipeline_test.exs new file mode 100644 index 000000000..f3c437498 --- /dev/null +++ b/test/web/activity_pub/pipeline_test.exs @@ -0,0 +1,87 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.PipelineTest do +  use Pleroma.DataCase + +  import Mock +  import Pleroma.Factory + +  describe "common_pipeline/2" do +    test "it goes through validation, filtering, persisting, side effects and federation for local activities" do +      activity = insert(:note_activity) +      meta = [local: true] + +      with_mocks([ +        {Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]}, +        { +          Pleroma.Web.ActivityPub.MRF, +          [], +          [filter: fn o -> {:ok, o} end] +        }, +        { +          Pleroma.Web.ActivityPub.ActivityPub, +          [], +          [persist: fn o, m -> {:ok, o, m} end] +        }, +        { +          Pleroma.Web.ActivityPub.SideEffects, +          [], +          [handle: fn o, m -> {:ok, o, m} end] +        }, +        { +          Pleroma.Web.Federator, +          [], +          [publish: fn _o -> :ok end] +        } +      ]) do +        assert {:ok, ^activity, ^meta} = +                 Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta) + +        assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta)) +        assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity)) +        assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta)) +        assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta)) +        assert_called(Pleroma.Web.Federator.publish(activity)) +      end +    end + +    test "it goes through validation, filtering, persisting, side effects without federation for remote activities" do +      activity = insert(:note_activity) +      meta = [local: false] + +      with_mocks([ +        {Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]}, +        { +          Pleroma.Web.ActivityPub.MRF, +          [], +          [filter: fn o -> {:ok, o} end] +        }, +        { +          Pleroma.Web.ActivityPub.ActivityPub, +          [], +          [persist: fn o, m -> {:ok, o, m} end] +        }, +        { +          Pleroma.Web.ActivityPub.SideEffects, +          [], +          [handle: fn o, m -> {:ok, o, m} end] +        }, +        { +          Pleroma.Web.Federator, +          [], +          [] +        } +      ]) do +        assert {:ok, ^activity, ^meta} = +                 Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta) + +        assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta)) +        assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity)) +        assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta)) +        assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta)) +      end +    end +  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/relay_test.exs b/test/web/activity_pub/relay_test.exs index 040625e4d..9e16e39c4 100644 --- a/test/web/activity_pub/relay_test.exs +++ b/test/web/activity_pub/relay_test.exs @@ -89,6 +89,11 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do            }          ) +      Tesla.Mock.mock(fn +        %{method: :get, url: "http://mastodon.example.org/eee/99541947525187367"} -> +          %Tesla.Env{status: 500, body: ""} +      end) +        assert capture_log(fn ->                 assert Relay.publish(activity) == {:error, nil}               end) =~ "[error] error: nil" diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs new file mode 100644 index 000000000..b67bd14b3 --- /dev/null +++ b/test/web/activity_pub/side_effects_test.exs @@ -0,0 +1,34 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.SideEffectsTest do +  use Pleroma.DataCase + +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.ActivityPub +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.SideEffects +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "like objects" do +    setup do +      user = insert(:user) +      {:ok, post} = CommonAPI.post(user, %{"status" => "hey"}) + +      {:ok, like_data, _meta} = Builder.like(user, post.object) +      {:ok, like, _meta} = ActivityPub.persist(like_data, local: true) + +      %{like: like, user: user} +    end + +    test "add the like to the original object", %{like: like, user: user} do +      {:ok, like, _} = SideEffects.handle(like) +      object = Object.get_by_ap_id(like.data["object"]) +      assert object.data["like_count"] == 1 +      assert user.ap_id in object.data["likes"] +    end +  end +end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index b2cabbd30..6057e360a 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -334,7 +334,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do          |> Poison.decode!()          |> Map.put("object", activity.data["object"]) -      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) +      {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data) + +      refute Enum.empty?(activity.recipients)        assert data["actor"] == "http://mastodon.example.org/users/admin"        assert data["type"] == "Like" @@ -744,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"}               ] @@ -765,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"}               ] @@ -783,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"}               ] @@ -794,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 @@ -1228,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"] == @@ -1622,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"}) @@ -2061,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"}                     ]                   }                 ] @@ -2083,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"}                     ]                   }                 ] @@ -2180,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/views/object_view_test.exs b/test/web/activity_pub/views/object_view_test.exs index de5ffc5b3..6c006206b 100644 --- a/test/web/activity_pub/views/object_view_test.exs +++ b/test/web/activity_pub/views/object_view_test.exs @@ -59,7 +59,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do      object = Object.normalize(note)      user = insert(:user) -    {:ok, like_activity, _} = CommonAPI.favorite(note.id, user) +    {:ok, like_activity} = CommonAPI.favorite(user, note.id)      result = ObjectView.render("object.json", %{object: like_activity}) 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 d77e8d1d2..f80dbf8dd 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -21,7 +21,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    alias Pleroma.UserInviteToken    alias Pleroma.Web.ActivityPub.Relay    alias Pleroma.Web.CommonAPI -  alias Pleroma.Web.MastodonAPI.StatusView    alias Pleroma.Web.MediaProxy    setup_all do @@ -626,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 @@ -638,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 @@ -647,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 @@ -1586,208 +1620,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end    end -  describe "GET /api/pleroma/admin/grouped_reports" do -    setup do -      [reporter, target_user] = insert_pair(:user) - -      date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!() -      date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!() -      date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!() - -      first_status = -        insert(:note_activity, user: target_user, data_attrs: %{"published" => date1}) - -      second_status = -        insert(:note_activity, user: target_user, data_attrs: %{"published" => date2}) - -      third_status = -        insert(:note_activity, user: target_user, data_attrs: %{"published" => date3}) - -      {:ok, first_report} = -        CommonAPI.report(reporter, %{ -          "account_id" => target_user.id, -          "status_ids" => [first_status.id, second_status.id, third_status.id] -        }) - -      {:ok, second_report} = -        CommonAPI.report(reporter, %{ -          "account_id" => target_user.id, -          "status_ids" => [first_status.id, second_status.id] -        }) - -      {:ok, third_report} = -        CommonAPI.report(reporter, %{ -          "account_id" => target_user.id, -          "status_ids" => [first_status.id] -        }) - -      %{ -        first_status: Activity.get_by_ap_id_with_object(first_status.data["id"]), -        second_status: Activity.get_by_ap_id_with_object(second_status.data["id"]), -        third_status: Activity.get_by_ap_id_with_object(third_status.data["id"]), -        first_report: first_report, -        first_status_reports: [first_report, second_report, third_report], -        second_status_reports: [first_report, second_report], -        third_status_reports: [first_report], -        target_user: target_user, -        reporter: reporter -      } -    end - -    test "returns reports grouped by status", %{ -      conn: conn, -      first_status: first_status, -      second_status: second_status, -      third_status: third_status, -      first_status_reports: first_status_reports, -      second_status_reports: second_status_reports, -      third_status_reports: third_status_reports, -      target_user: target_user, -      reporter: reporter -    } do -      response = -        conn -        |> get("/api/pleroma/admin/grouped_reports") -        |> json_response(:ok) - -      assert length(response["reports"]) == 3 - -      first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id)) - -      second_group = Enum.find(response["reports"], &(&1["status"]["id"] == second_status.id)) - -      third_group = Enum.find(response["reports"], &(&1["status"]["id"] == third_status.id)) - -      assert length(first_group["reports"]) == 3 -      assert length(second_group["reports"]) == 2 -      assert length(third_group["reports"]) == 1 - -      assert first_group["date"] == -               Enum.max_by(first_status_reports, fn act -> -                 NaiveDateTime.from_iso8601!(act.data["published"]) -               end).data["published"] - -      assert first_group["status"] == -               Map.put( -                 stringify_keys(StatusView.render("show.json", %{activity: first_status})), -                 "deleted", -                 false -               ) - -      assert(first_group["account"]["id"] == target_user.id) - -      assert length(first_group["actors"]) == 1 -      assert hd(first_group["actors"])["id"] == reporter.id - -      assert Enum.map(first_group["reports"], & &1["id"]) -- -               Enum.map(first_status_reports, & &1.id) == [] - -      assert second_group["date"] == -               Enum.max_by(second_status_reports, fn act -> -                 NaiveDateTime.from_iso8601!(act.data["published"]) -               end).data["published"] - -      assert second_group["status"] == -               Map.put( -                 stringify_keys(StatusView.render("show.json", %{activity: second_status})), -                 "deleted", -                 false -               ) - -      assert second_group["account"]["id"] == target_user.id - -      assert length(second_group["actors"]) == 1 -      assert hd(second_group["actors"])["id"] == reporter.id - -      assert Enum.map(second_group["reports"], & &1["id"]) -- -               Enum.map(second_status_reports, & &1.id) == [] - -      assert third_group["date"] == -               Enum.max_by(third_status_reports, fn act -> -                 NaiveDateTime.from_iso8601!(act.data["published"]) -               end).data["published"] - -      assert third_group["status"] == -               Map.put( -                 stringify_keys(StatusView.render("show.json", %{activity: third_status})), -                 "deleted", -                 false -               ) - -      assert third_group["account"]["id"] == target_user.id - -      assert length(third_group["actors"]) == 1 -      assert hd(third_group["actors"])["id"] == reporter.id - -      assert Enum.map(third_group["reports"], & &1["id"]) -- -               Enum.map(third_status_reports, & &1.id) == [] -    end - -    test "reopened report renders status data", %{ -      conn: conn, -      first_report: first_report, -      first_status: first_status -    } do -      {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved") - -      response = -        conn -        |> get("/api/pleroma/admin/grouped_reports") -        |> json_response(:ok) - -      first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id)) - -      assert first_group["status"] == -               Map.put( -                 stringify_keys(StatusView.render("show.json", %{activity: first_status})), -                 "deleted", -                 false -               ) -    end - -    test "reopened report does not render status data if status has been deleted", %{ -      conn: conn, -      first_report: first_report, -      first_status: first_status, -      target_user: target_user -    } do -      {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved") -      {:ok, _} = CommonAPI.delete(first_status.id, target_user) - -      refute Activity.get_by_ap_id(first_status.id) - -      response = -        conn -        |> get("/api/pleroma/admin/grouped_reports") -        |> json_response(:ok) - -      assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["status"][ -               "deleted" -             ] == true - -      assert length(Enum.filter(response["reports"], &(&1["status"]["deleted"] == false))) == 2 -    end - -    test "account not empty if status was deleted", %{ -      conn: conn, -      first_report: first_report, -      first_status: first_status, -      target_user: target_user -    } do -      {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved") -      {:ok, _} = CommonAPI.delete(first_status.id, target_user) - -      refute Activity.get_by_ap_id(first_status.id) - -      response = -        conn -        |> get("/api/pleroma/admin/grouped_reports") -        |> json_response(:ok) - -      assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["account"] -    end -  end -    describe "PUT /api/pleroma/admin/statuses/:id" do      setup do        activity = insert(:note_activity) @@ -2278,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 @@ -2334,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 @@ -2441,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"]              }            ]          }) @@ -2458,8 +2294,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "group" => ":logger",                     "key" => ":backends",                     "value" => [ -                     ":console", -                     %{"tuple" => ["ExSyslogger", ":ex_syslogger"]} +                     ":console"                     ],                     "db" => [":backends"]                   } @@ -2467,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 @@ -2572,9 +2401,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end      test "common config example", %{conn: conn} do -      adapter = Application.get_env(:tesla, :adapter) -      on_exit(fn -> Application.put_env(:tesla, :adapter, adapter) end) -        conn =          post(conn, "/api/pleroma/admin/config", %{            configs: [ @@ -2587,23 +2413,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                  %{"tuple" => [":seconds_valid", 60]},                  %{"tuple" => [":path", ""]},                  %{"tuple" => [":key1", nil]}, -                %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},                  %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},                  %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},                  %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},                  %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]},                  %{"tuple" => [":name", "Pleroma"]}                ] -            }, -            %{ -              "group" => ":tesla", -              "key" => ":adapter", -              "value" => "Tesla.Adapter.Httpc"              }            ]          }) -      assert Application.get_env(:tesla, :adapter) == Tesla.Adapter.Httpc        assert Config.get([Pleroma.Captcha.NotReal, :name]) == "Pleroma"        assert json_response(conn, 200) == %{ @@ -2617,7 +2436,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                       %{"tuple" => [":seconds_valid", 60]},                       %{"tuple" => [":path", ""]},                       %{"tuple" => [":key1", nil]}, -                     %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},                       %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},                       %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},                       %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]}, @@ -2630,19 +2448,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                       ":seconds_valid",                       ":path",                       ":key1", -                     ":partial_chain",                       ":regex1",                       ":regex2",                       ":regex3",                       ":regex4",                       ":name"                     ] -                 }, -                 %{ -                   "group" => ":tesla", -                   "key" => ":adapter", -                   "value" => "Tesla.Adapter.Httpc", -                   "db" => [":adapter"]                   }                 ]               } @@ -3050,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) @@ -3374,6 +3199,75 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end    end +  describe "GET /users/:nickname/credentials" do +    test "gets the user credentials", %{conn: conn} do +      user = insert(:user) +      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials") + +      response = assert json_response(conn, 200) +      assert response["email"] == user.email +    end + +    test "returns 403 if requested by a non-admin" do +      user = insert(:user) + +      conn = +        build_conn() +        |> assign(:user, user) +        |> get("/api/pleroma/admin/users/#{user.nickname}/credentials") + +      assert json_response(conn, :forbidden) +    end +  end + +  describe "PATCH /users/:nickname/credentials" do +    test "changes password and email", %{conn: conn, admin: admin} do +      user = insert(:user) +      assert user.password_reset_pending == false + +      conn = +        patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{ +          "password" => "new_password", +          "email" => "new_email@example.com", +          "name" => "new_name" +        }) + +      assert json_response(conn, 200) == %{"status" => "success"} + +      ObanHelpers.perform_all() + +      updated_user = User.get_by_id(user.id) + +      assert updated_user.email == "new_email@example.com" +      assert updated_user.name == "new_name" +      assert updated_user.password_hash != user.password_hash +      assert updated_user.password_reset_pending == true + +      [log_entry2, log_entry1] = ModerationLog |> Repo.all() |> Enum.sort() + +      assert ModerationLog.get_log_entry_message(log_entry1) == +               "@#{admin.nickname} updated users: @#{user.nickname}" + +      assert ModerationLog.get_log_entry_message(log_entry2) == +               "@#{admin.nickname} forced password reset for users: @#{user.nickname}" +    end + +    test "returns 403 if requested by a non-admin" do +      user = insert(:user) + +      conn = +        build_conn() +        |> assign(:user, user) +        |> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{ +          "password" => "new_password", +          "email" => "new_email@example.com", +          "name" => "new_name" +        }) + +      assert json_response(conn, :forbidden) +    end +  end +    describe "PATCH /users/:nickname/force_password_reset" do      test "sets password_reset_pending to true", %{conn: conn} do        user = insert(:user) diff --git a/test/web/api_spec/app_operation_test.exs b/test/web/api_spec/app_operation_test.exs new file mode 100644 index 000000000..5b96abb44 --- /dev/null +++ b/test/web/api_spec/app_operation_test.exs @@ -0,0 +1,45 @@ +# 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.AppOperationTest do +  use Pleroma.Web.ConnCase, async: true + +  alias Pleroma.Web.ApiSpec +  alias Pleroma.Web.ApiSpec.Schemas.AppCreateRequest +  alias Pleroma.Web.ApiSpec.Schemas.AppCreateResponse + +  import OpenApiSpex.TestAssertions +  import Pleroma.Factory + +  test "AppCreateRequest example matches schema" do +    api_spec = ApiSpec.spec() +    schema = AppCreateRequest.schema() +    assert_schema(schema.example, "AppCreateRequest", api_spec) +  end + +  test "AppCreateResponse example matches schema" do +    api_spec = ApiSpec.spec() +    schema = AppCreateResponse.schema() +    assert_schema(schema.example, "AppCreateResponse", api_spec) +  end + +  test "AppController produces a AppCreateResponse", %{conn: conn} do +    api_spec = ApiSpec.spec() +    app_attrs = build(:oauth_app) + +    json = +      conn +      |> put_req_header("content-type", "application/json") +      |> post( +        "/api/v1/apps", +        Jason.encode!(%{ +          client_name: app_attrs.client_name, +          redirect_uris: app_attrs.redirect_uris +        }) +      ) +      |> json_response(200) + +    assert_schema(json, "AppCreateResponse", api_spec) +  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 0da0bd2e2..e130736ec 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -97,18 +97,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) @@ -284,9 +272,12 @@ defmodule Pleroma.Web.CommonAPITest do        user = insert(:user)        other_user = insert(:user) -      {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) +      {:ok, post_activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) -      {:ok, %Activity{}, _} = CommonAPI.favorite(activity.id, user) +      {:ok, %Activity{data: data}} = CommonAPI.favorite(user, post_activity.id) +      assert data["type"] == "Like" +      assert data["actor"] == user.ap_id +      assert data["object"] == post_activity.data["object"]      end      test "retweeting a status twice returns the status" do @@ -298,13 +289,13 @@ defmodule Pleroma.Web.CommonAPITest do        {:ok, ^activity, ^object} = CommonAPI.repeat(activity.id, user)      end -    test "favoriting a status twice returns the status" do +    test "favoriting a status twice returns ok, but without the like activity" do        user = insert(:user)        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) -      {:ok, %Activity{} = activity, object} = CommonAPI.favorite(activity.id, user) -      {:ok, ^activity, ^object} = CommonAPI.favorite(activity.id, user) +      {:ok, %Activity{}} = CommonAPI.favorite(user, activity.id) +      assert {:ok, :already_liked} = CommonAPI.favorite(user, activity.id)      end    end @@ -562,7 +553,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 @@ -584,7 +575,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 45fc94522..b21445fe9 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 @@ -472,6 +449,13 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do        activity = insert(:note_activity, user: user, note: object)        Pleroma.Repo.delete(object) +      obj_url = activity.data["object"] + +      Tesla.Mock.mock(fn +        %{method: :get, url: ^obj_url} -> +          %Tesla.Env{status: 404, body: ""} +      end) +        assert Utils.maybe_notify_mentioned_recipients(["test-test"], activity) == [                 "test-test"               ] diff --git a/test/web/federator_test.exs b/test/web/federator_test.exs index da844c24c..59e53bb03 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        }) 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 43538cb17..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 @@ -76,15 +76,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        conn =          patch(conn, "/api/v1/accounts/update_credentials", %{ -          "note" => "I drink #cofe with @#{user2.nickname}" +          "note" => "I drink #cofe with @#{user2.nickname}\n\nsuya.."          })        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>) +               }" 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 @@ -118,6 +118,18 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert user_data["pleroma"]["hide_followers"] == true      end +    test "updates the user's discoverable status", %{conn: conn} do +      assert %{"source" => %{"pleroma" => %{"discoverable" => true}}} = +               conn +               |> patch("/api/v1/accounts/update_credentials", %{discoverable: "true"}) +               |> json_response(:ok) + +      assert %{"source" => %{"pleroma" => %{"discoverable" => false}}} = +               conn +               |> patch("/api/v1/accounts/update_credentials", %{discoverable: "false"}) +               |> json_response(:ok) +    end +      test "updates the user's hide_followers_count and hide_follows_count", %{conn: conn} do        conn =          patch(conn, "/api/v1/accounts/update_credentials", %{ @@ -261,7 +273,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do      test "update fields", %{conn: conn} do        fields = [          %{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "<script>bar</script>"}, -        %{"name" => "link", "value" => "cofe.io"} +        %{"name" => "link.io", "value" => "cofe.io"}        ]        account_data = @@ -271,7 +283,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert account_data["fields"] == [                 %{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"}, -               %{"name" => "link", "value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)} +               %{ +                 "name" => "link.io", +                 "value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>) +               }               ]        assert account_data["source"]["fields"] == [ @@ -279,14 +294,16 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do                   "name" => "<a href=\"http://google.com\">foo</a>",                   "value" => "<script>bar</script>"                 }, -               %{"name" => "link", "value" => "cofe.io"} +               %{"name" => "link.io", "value" => "cofe.io"}               ] +    end +    test "update fields via x-www-form-urlencoded", %{conn: conn} do        fields =          [            "fields_attributes[1][name]=link", -          "fields_attributes[1][value]=cofe.io", -          "fields_attributes[0][name]=<a href=\"http://google.com\">foo</a>", +          "fields_attributes[1][value]=http://cofe.io", +          "fields_attributes[0][name]=foo",            "fields_attributes[0][value]=bar"          ]          |> Enum.join("&") @@ -298,32 +315,49 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do          |> json_response(200)        assert account["fields"] == [ -               %{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"}, -               %{"name" => "link", "value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)} +               %{"name" => "foo", "value" => "bar"}, +               %{ +                 "name" => "link", +                 "value" => ~S(<a href="http://cofe.io" rel="ugc">http://cofe.io</a>) +               }               ]        assert account["source"]["fields"] == [ -               %{ -                 "name" => "<a href=\"http://google.com\">foo</a>", -                 "value" => "bar" -               }, -               %{"name" => "link", "value" => "cofe.io"} +               %{"name" => "foo", "value" => "bar"}, +               %{"name" => "link", "value" => "http://cofe.io"} +             ] +    end + +    test "update fields with empty name", %{conn: conn} do +      fields = [ +        %{"name" => "foo", "value" => ""}, +        %{"name" => "", "value" => "bar"} +      ] + +      account = +        conn +        |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields}) +        |> json_response(200) + +      assert account["fields"] == [ +               %{"name" => "foo", "value" => ""}               ] +    end +    test "update fields when invalid request", %{conn: conn} do        name_limit = Pleroma.Config.get([:instance, :account_field_name_length])        value_limit = Pleroma.Config.get([:instance, :account_field_value_length]) +      long_name = Enum.map(0..name_limit, fn _ -> "x" end) |> Enum.join()        long_value = Enum.map(0..value_limit, fn _ -> "x" end) |> Enum.join() -      fields = [%{"name" => "<b>foo<b>", "value" => long_value}] +      fields = [%{"name" => "foo", "value" => long_value}]        assert %{"error" => "Invalid request"} ==                 conn                 |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})                 |> json_response(403) -      long_name = Enum.map(0..name_limit, fn _ -> "x" end) |> Enum.join() -        fields = [%{"name" => long_name, "value" => "bar"}]        assert %{"error" => "Invalid request"} == @@ -334,7 +368,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        Pleroma.Config.put([:instance, :max_account_fields], 1)        fields = [ -        %{"name" => "<b>foo<b>", "value" => "<i>bar</i>"}, +        %{"name" => "foo", "value" => "bar"},          %{"name" => "link", "value" => "cofe.io"}        ] @@ -342,20 +376,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do                 conn                 |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})                 |> json_response(403) - -      fields = [ -        %{"name" => "foo", "value" => ""}, -        %{"name" => "", "value" => "bar"} -      ] - -      account = -        conn -        |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields}) -        |> json_response(200) - -      assert account["fields"] == [ -               %{"name" => "foo", "value" => ""} -             ]      end    end  end diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs index f770232df..61c2697b2 100644 --- a/test/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -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" diff --git a/test/web/mastodon_api/controllers/app_controller_test.exs b/test/web/mastodon_api/controllers/app_controller_test.exs index 77d234d67..e7b11d14e 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 @@ -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, 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..d66190c90 100644 --- a/test/web/mastodon_api/controllers/domain_block_controller_test.exs +++ b/test/web/mastodon_api/controllers/domain_block_controller_test.exs @@ -6,20 +6,29 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do    use Pleroma.Web.ConnCase    alias Pleroma.User +  alias Pleroma.Web.ApiSpec +  alias Pleroma.Web.ApiSpec.Schemas.DomainBlocksResponse    import Pleroma.Factory +  import OpenApiSpex.TestAssertions    test "blocking / unblocking a domain" 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)      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)      user = User.get_cached_by_ap_id(user.ap_id) @@ -41,5 +50,12 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do      assert "bad.site" in domain_blocks      assert "even.worse.site" in domain_blocks +    assert_schema(domain_blocks, "DomainBlocksResponse", ApiSpec.spec()) +  end + +  test "DomainBlocksResponse example matches schema" do +    api_spec = ApiSpec.spec() +    schema = DomainBlocksResponse.schema() +    assert_schema(schema.example, "DomainBlocksResponse", api_spec)    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 7a0011646..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) @@ -194,10 +230,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do        {:ok, private_activity} =          CommonAPI.post(other_user, %{"status" => ".", "visibility" => "private"}) -      {:ok, _, _} = CommonAPI.favorite(public_activity.id, user) -      {:ok, _, _} = CommonAPI.favorite(direct_activity.id, user) -      {:ok, _, _} = CommonAPI.favorite(unlisted_activity.id, user) -      {:ok, _, _} = CommonAPI.favorite(private_activity.id, user) +      {:ok, _} = CommonAPI.favorite(user, public_activity.id) +      {:ok, _} = CommonAPI.favorite(user, direct_activity.id) +      {:ok, _} = CommonAPI.favorite(user, unlisted_activity.id) +      {:ok, _} = CommonAPI.favorite(user, private_activity.id)        activity_ids =          conn @@ -274,7 +310,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do      {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})      {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"}) -    {:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, other_user) +    {:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)      {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)      {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user) @@ -310,7 +346,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do      {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})      {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"}) -    {:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, other_user) +    {:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)      {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)      {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user) @@ -452,11 +488,24 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do      assert length(json_response(conn, 200)) == 1    end +  @tag capture_log: true    test "see move notifications" do      old_user = insert(:user)      new_user = insert(:user, also_known_as: [old_user.ap_id])      %{user: follower, conn: conn} = oauth_access(["read:notifications"]) +    old_user_url = old_user.ap_id + +    body = +      File.read!("test/fixtures/users_mock/localhost.json") +      |> String.replace("{{nickname}}", old_user.nickname) +      |> Jason.encode!() + +    Tesla.Mock.mock(fn +      %{method: :get, url: ^old_user_url} -> +        %Tesla.Env{status: 200, body: body} +    end) +      User.follow(follower, old_user)      Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)      Pleroma.Tests.ObanHelpers.perform_all() diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index d59974d50..162f7b1b2 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -775,7 +775,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do        user1 = insert(:user)        user2 = insert(:user)        user3 = insert(:user) -      CommonAPI.favorite(activity.id, user2) +      {:ok, _} = CommonAPI.favorite(user2, activity.id)        {:ok, _bookmark} = Pleroma.Bookmark.create(user2.id, activity.id)        {:ok, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1)        {:ok, _, _object} = CommonAPI.repeat(activity.id, user2) @@ -850,11 +850,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do        activity = insert(:note_activity)        post(conn, "/api/v1/statuses/#{activity.id}/favourite") -      assert post(conn, "/api/v1/statuses/#{activity.id}/favourite") |> json_response(200) + +      assert post(conn, "/api/v1/statuses/#{activity.id}/favourite") +             |> json_response(200)      end      test "returns 404 error for a wrong id", %{conn: conn} do -      conn = post(conn, "/api/v1/statuses/1/favourite") +      conn = +        conn +        |> post("/api/v1/statuses/1/favourite")        assert json_response(conn, 404) == %{"error" => "Record not found"}      end @@ -866,7 +870,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      test "unfavorites a status and returns it", %{user: user, conn: conn} do        activity = insert(:note_activity) -      {:ok, _, _} = CommonAPI.favorite(activity.id, user) +      {:ok, _} = CommonAPI.favorite(user, activity.id)        conn = post(conn, "/api/v1/statuses/#{activity.id}/unfavourite") @@ -1043,6 +1047,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) @@ -1064,7 +1070,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) @@ -1073,7 +1079,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 @@ -1176,7 +1182,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      test "returns users who have favorited the status", %{conn: conn, activity: activity} do        other_user = insert(:user) -      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user) +      {:ok, _} = CommonAPI.favorite(other_user, activity.id)        response =          conn @@ -1207,7 +1213,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do        other_user = insert(:user)        {:ok, _user_relationship} = User.block(user, other_user) -      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user) +      {:ok, _} = CommonAPI.favorite(other_user, activity.id)        response =          conn @@ -1219,7 +1225,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      test "does not fail on an unauthenticated request", %{activity: activity} do        other_user = insert(:user) -      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user) +      {:ok, _} = CommonAPI.favorite(other_user, activity.id)        response =          build_conn() @@ -1239,7 +1245,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do            "visibility" => "direct"          }) -      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user) +      {:ok, _} = CommonAPI.favorite(other_user, activity.id)        favourited_by_url = "/api/v1/statuses/#{activity.id}/favourited_by" @@ -1399,7 +1405,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})      {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"}) -    {:ok, _, _} = CommonAPI.favorite(activity.id, user) +    {:ok, _} = CommonAPI.favorite(user, activity.id)      first_conn = get(conn, "/api/v1/favourites") @@ -1416,7 +1422,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do            "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."        }) -    {:ok, _, _} = CommonAPI.favorite(second_activity.id, user) +    {:ok, _} = CommonAPI.favorite(user, second_activity.id)      last_like = status["id"] 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 6fedb4223..06efdc901 100644 --- a/test/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs @@ -20,20 +20,91 @@ 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 -      following = insert(:user) +      uri = "/api/v1/timelines/home?with_relationships=true" -      {:ok, _activity} = CommonAPI.post(following, %{"status" => "test"}) +      following = insert(:user, nickname: "followed") +      third_user = insert(:user, nickname: "repeated") + +      {:ok, _activity} = CommonAPI.post(following, %{"status" => "post"}) +      {: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) -      conn = get(conn, "/api/v1/timelines/home") - -      assert [%{"content" => "test"}] = json_response(conn, :ok) +      ret_conn = get(conn, uri) + +      assert [ +               %{ +                 "reblog" => %{ +                   "content" => "repeated post", +                   "account" => %{ +                     "pleroma" => %{ +                       "relationship" => %{"following" => false, "followed_by" => false} +                     } +                   } +                 }, +                 "account" => %{"pleroma" => %{"relationship" => %{"following" => true}}} +               }, +               %{ +                 "content" => "post", +                 "account" => %{ +                   "acct" => "followed", +                   "pleroma" => %{"relationship" => %{"following" => true}} +                 } +               } +             ] = json_response(ret_conn, :ok) + +      {:ok, _user} = User.follow(third_user, user) + +      ret_conn = get(conn, uri) + +      assert [ +               %{ +                 "reblog" => %{ +                   "content" => "repeated post", +                   "account" => %{ +                     "acct" => "repeated", +                     "pleroma" => %{ +                       "relationship" => %{"following" => false, "followed_by" => true} +                     } +                   } +                 }, +                 "account" => %{"pleroma" => %{"relationship" => %{"following" => true}}} +               }, +               %{ +                 "content" => "post", +                 "account" => %{ +                   "acct" => "followed", +                   "pleroma" => %{"relationship" => %{"following" => true}} +                 } +               } +             ] = json_response(ret_conn, :ok)      end      test "the home timeline when the direct messages are excluded", %{user: user, conn: conn} do diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index d60ed7b64..85fa4f6a2 100644 --- a/test/web/mastodon_api/views/account_view_test.exs +++ b/test/web/mastodon_api/views/account_view_test.exs @@ -4,22 +4,21 @@  defmodule Pleroma.Web.MastodonAPI.AccountViewTest do    use Pleroma.DataCase -  import Pleroma.Factory +    alias Pleroma.User +  alias Pleroma.UserRelationship    alias Pleroma.Web.CommonAPI    alias Pleroma.Web.MastodonAPI.AccountView -  test "Represent a user account" do -    source_data = %{ -      "tag" => [ -        %{ -          "type" => "Emoji", -          "icon" => %{"url" => "/file.png"}, -          "name" => ":karjalanpiirakka:" -        } -      ] -    } +  import Pleroma.Factory +  import Tesla.Mock +  setup do +    mock(fn env -> apply(HttpRequestMock, :request, [env]) end) +    :ok +  end + +  test "Represent a user account" do      background_image = %{        "url" => [%{"href" => "https://example.com/images/asuka_hospital.png"}]      } @@ -28,12 +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>", -        inserted_at: ~N[2017-08-15 15:47:06.597036] +        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], +        emoji: %{"karjalanpiirakka" => "/file.png"}        })      expected = %{ @@ -46,7 +46,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        followers_count: 3,        following_count: 0,        statuses_count: 5, -      note: "<span>valid html</span>", +      note: "<span>valid html</span>. a<br/>b<br/>c<br/>d<br/>f",        url: user.ap_id,        avatar: "http://localhost:4001/images/avi.png",        avatar_static: "http://localhost:4001/images/avi.png", @@ -63,7 +63,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        fields: [],        bot: false,        source: %{ -        note: "valid html", +        note: "valid html. a\nb\nc\nd\nf",          sensitive: false,          pleroma: %{            actor_type: "Person", @@ -107,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] @@ -160,6 +159,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do      assert expected == AccountView.render("show.json", %{user: user})    end +  test "Represent a Funkwhale channel" do +    {:ok, user} = +      User.get_or_fetch_by_ap_id( +        "https://channels.tests.funkwhale.audio/federation/actors/compositions" +      ) + +    assert represented = AccountView.render("show.json", %{user: user}) +    assert represented.acct == "compositions@channels.tests.funkwhale.audio" +    assert represented.url == "https://channels.tests.funkwhale.audio/channels/compositions" +  end +    test "Represent a deactivated user for an admin" do      admin = insert(:user, is_admin: true)      deactivated_user = insert(:user, deactivated: true) @@ -181,6 +191,32 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do    end    describe "relationship" do +    defp test_relationship_rendering(user, other_user, expected_result) do +      opts = %{user: user, target: other_user, relationships: nil} +      assert expected_result == AccountView.render("relationship.json", opts) + +      relationships_opt = UserRelationship.view_relationships_option(user, [other_user]) +      opts = Map.put(opts, :relationships, relationships_opt) +      assert expected_result == AccountView.render("relationship.json", opts) + +      assert [expected_result] == +               AccountView.render("relationships.json", %{user: user, targets: [other_user]}) +    end + +    @blank_response %{ +      following: false, +      followed_by: false, +      blocking: false, +      blocked_by: false, +      muting: false, +      muting_notifications: false, +      subscribing: false, +      requested: false, +      domain_blocking: false, +      showing_reblogs: true, +      endorsed: false +    } +      test "represent a relationship for the following and followed user" do        user = insert(:user)        other_user = insert(:user) @@ -191,23 +227,21 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        {:ok, _user_relationships} = User.mute(user, other_user, true)        {:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, other_user) -      expected = %{ -        id: to_string(other_user.id), -        following: true, -        followed_by: true, -        blocking: false, -        blocked_by: false, -        muting: true, -        muting_notifications: true, -        subscribing: true, -        requested: false, -        domain_blocking: false, -        showing_reblogs: false, -        endorsed: false -      } - -      assert expected == -               AccountView.render("relationship.json", %{user: user, target: other_user}) +      expected = +        Map.merge( +          @blank_response, +          %{ +            following: true, +            followed_by: true, +            muting: true, +            muting_notifications: true, +            subscribing: true, +            showing_reblogs: false, +            id: to_string(other_user.id) +          } +        ) + +      test_relationship_rendering(user, other_user, expected)      end      test "represent a relationship for the blocking and blocked user" do @@ -219,23 +253,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        {:ok, _user_relationship} = User.block(user, other_user)        {:ok, _user_relationship} = User.block(other_user, user) -      expected = %{ -        id: to_string(other_user.id), -        following: false, -        followed_by: false, -        blocking: true, -        blocked_by: true, -        muting: false, -        muting_notifications: false, -        subscribing: false, -        requested: false, -        domain_blocking: false, -        showing_reblogs: true, -        endorsed: false -      } +      expected = +        Map.merge( +          @blank_response, +          %{following: false, blocking: true, blocked_by: true, id: to_string(other_user.id)} +        ) -      assert expected == -               AccountView.render("relationship.json", %{user: user, target: other_user}) +      test_relationship_rendering(user, other_user, expected)      end      test "represent a relationship for the user blocking a domain" do @@ -244,8 +268,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        {:ok, user} = User.block_domain(user, "bad.site") -      assert %{domain_blocking: true, blocking: false} = -               AccountView.render("relationship.json", %{user: user, target: other_user}) +      expected = +        Map.merge( +          @blank_response, +          %{domain_blocking: true, blocking: false, id: to_string(other_user.id)} +        ) + +      test_relationship_rendering(user, other_user, expected)      end      test "represent a relationship for the user with a pending follow request" do @@ -256,23 +285,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        user = User.get_cached_by_id(user.id)        other_user = User.get_cached_by_id(other_user.id) -      expected = %{ -        id: to_string(other_user.id), -        following: false, -        followed_by: false, -        blocking: false, -        blocked_by: false, -        muting: false, -        muting_notifications: false, -        subscribing: false, -        requested: true, -        domain_blocking: false, -        showing_reblogs: true, -        endorsed: false -      } +      expected = +        Map.merge( +          @blank_response, +          %{requested: true, following: false, id: to_string(other_user.id)} +        ) -      assert expected == -               AccountView.render("relationship.json", %{user: user, target: other_user}) +      test_relationship_rendering(user, other_user, expected)      end    end @@ -281,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/notification_view_test.exs b/test/web/mastodon_api/views/notification_view_test.exs index d04c3022f..c3ec9dfec 100644 --- a/test/web/mastodon_api/views/notification_view_test.exs +++ b/test/web/mastodon_api/views/notification_view_test.exs @@ -16,6 +16,21 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do    alias Pleroma.Web.MastodonAPI.StatusView    import Pleroma.Factory +  defp test_notifications_rendering(notifications, user, expected_result) do +    result = NotificationView.render("index.json", %{notifications: notifications, for: user}) + +    assert expected_result == result + +    result = +      NotificationView.render("index.json", %{ +        notifications: notifications, +        for: user, +        relationships: nil +      }) + +    assert expected_result == result +  end +    test "Mention notification" do      user = insert(:user)      mentioned_user = insert(:user) @@ -32,17 +47,14 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do        created_at: Utils.to_masto_date(notification.inserted_at)      } -    result = -      NotificationView.render("index.json", %{notifications: [notification], for: mentioned_user}) - -    assert [expected] == result +    test_notifications_rendering([notification], mentioned_user, [expected])    end    test "Favourite notification" do      user = insert(:user)      another_user = insert(:user)      {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"}) -    {:ok, favorite_activity, _object} = CommonAPI.favorite(create_activity.id, another_user) +    {:ok, favorite_activity} = CommonAPI.favorite(another_user, create_activity.id)      {:ok, [notification]} = Notification.create_notifications(favorite_activity)      create_activity = Activity.get_by_id(create_activity.id) @@ -55,9 +67,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do        created_at: Utils.to_masto_date(notification.inserted_at)      } -    result = NotificationView.render("index.json", %{notifications: [notification], for: user}) - -    assert [expected] == result +    test_notifications_rendering([notification], user, [expected])    end    test "Reblog notification" do @@ -77,9 +87,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do        created_at: Utils.to_masto_date(notification.inserted_at)      } -    result = NotificationView.render("index.json", %{notifications: [notification], for: user}) - -    assert [expected] == result +    test_notifications_rendering([notification], user, [expected])    end    test "Follow notification" do @@ -96,23 +104,32 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do        created_at: Utils.to_masto_date(notification.inserted_at)      } -    result = -      NotificationView.render("index.json", %{notifications: [notification], for: followed}) - -    assert [expected] == result +    test_notifications_rendering([notification], followed, [expected])      User.perform(:delete, follower)      notification = Notification |> Repo.one() |> Repo.preload(:activity) -    assert [] == -             NotificationView.render("index.json", %{notifications: [notification], for: followed}) +    test_notifications_rendering([notification], followed, [])    end +  @tag capture_log: true    test "Move notification" do      old_user = insert(:user)      new_user = insert(:user, also_known_as: [old_user.ap_id])      follower = insert(:user) +    old_user_url = old_user.ap_id + +    body = +      File.read!("test/fixtures/users_mock/localhost.json") +      |> String.replace("{{nickname}}", old_user.nickname) +      |> Jason.encode!() + +    Tesla.Mock.mock(fn +      %{method: :get, url: ^old_user_url} -> +        %Tesla.Env{status: 200, body: body} +    end) +      User.follow(follower, old_user)      Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)      Pleroma.Tests.ObanHelpers.perform_all() @@ -131,8 +148,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do        created_at: Utils.to_masto_date(notification.inserted_at)      } -    assert [expected] == -             NotificationView.render("index.json", %{notifications: [notification], for: follower}) +    test_notifications_rendering([notification], follower, [expected])    end    test "EmojiReact notification" do @@ -158,7 +174,6 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do        created_at: Utils.to_masto_date(notification.inserted_at)      } -    assert expected == -             NotificationView.render("show.json", %{notification: notification, for: user}) +    test_notifications_rendering([notification], user, [expected])    end  end diff --git a/test/web/mastodon_api/views/status_view_test.exs b/test/web/mastodon_api/views/status_view_test.exs index 191895c6f..6791c2fb0 100644 --- a/test/web/mastodon_api/views/status_view_test.exs +++ b/test/web/mastodon_api/views/status_view_test.exs @@ -12,10 +12,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do    alias Pleroma.Object    alias Pleroma.Repo    alias Pleroma.User +  alias Pleroma.UserRelationship    alias Pleroma.Web.CommonAPI    alias Pleroma.Web.CommonAPI.Utils    alias Pleroma.Web.MastodonAPI.AccountView    alias Pleroma.Web.MastodonAPI.StatusView +    import Pleroma.Factory    import Tesla.Mock @@ -92,6 +94,23 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do      Repo.delete(user)      Cachex.clear(:user_cache) +    finger_url = +      "https://localhost/.well-known/webfinger?resource=acct:#{user.nickname}@localhost" + +    Tesla.Mock.mock_global(fn +      %{method: :get, url: "http://localhost/.well-known/host-meta"} -> +        %Tesla.Env{status: 404, body: ""} + +      %{method: :get, url: "https://localhost/.well-known/host-meta"} -> +        %Tesla.Env{status: 404, body: ""} + +      %{ +        method: :get, +        url: ^finger_url +      } -> +        %Tesla.Env{status: 404, body: ""} +    end) +      %{account: ms_user} = StatusView.render("show.json", activity: activity)      assert ms_user.acct == "erroruser@example.com" @@ -212,12 +231,21 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do      {:ok, _user_relationships} = User.mute(user, other_user)      {:ok, activity} = CommonAPI.post(other_user, %{"status" => "test"}) -    status = StatusView.render("show.json", %{activity: activity}) +    relationships_opt = UserRelationship.view_relationships_option(user, [other_user]) + +    opts = %{activity: activity} +    status = StatusView.render("show.json", opts)      assert status.muted == false -    status = StatusView.render("show.json", %{activity: activity, for: user}) +    status = StatusView.render("show.json", Map.put(opts, :relationships, relationships_opt)) +    assert status.muted == false + +    for_opts = %{activity: activity, for: user} +    status = StatusView.render("show.json", for_opts) +    assert status.muted == true +    status = StatusView.render("show.json", Map.put(for_opts, :relationships, relationships_opt))      assert status.muted == true    end @@ -420,6 +448,22 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do      assert length(represented[:media_attachments]) == 1    end +  test "funkwhale audio" do +    user = insert(:user) + +    {:ok, object} = +      Pleroma.Object.Fetcher.fetch_object_from_id( +        "https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871" +      ) + +    %Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"]) + +    represented = StatusView.render("show.json", %{for: user, activity: activity}) + +    assert represented[:id] == to_string(activity.id) +    assert length(represented[:media_attachments]) == 1 +  end +    test "a Mobilizon event" do      user = insert(:user) diff --git a/test/web/metadata/metadata_test.exs b/test/web/metadata/metadata_test.exs new file mode 100644 index 000000000..3f8b29e58 --- /dev/null +++ b/test/web/metadata/metadata_test.exs @@ -0,0 +1,25 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MetadataTest do +  use Pleroma.DataCase, async: true + +  import Pleroma.Factory + +  describe "restrict indexing remote users" do +    test "for remote user" do +      user = insert(:user, local: false) + +      assert Pleroma.Web.Metadata.build_tags(%{user: user}) =~ +               "<meta content=\"noindex, noarchive\" name=\"robots\">" +    end + +    test "for local user" do +      user = insert(:user) + +      refute Pleroma.Web.Metadata.build_tags(%{user: user}) =~ +               "<meta content=\"noindex, noarchive\" name=\"robots\">" +    end +  end +end diff --git a/test/web/metadata/restrict_indexing_test.exs b/test/web/metadata/restrict_indexing_test.exs new file mode 100644 index 000000000..aad0bac42 --- /dev/null +++ b/test/web/metadata/restrict_indexing_test.exs @@ -0,0 +1,21 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Metadata.Providers.RestrictIndexingTest do +  use ExUnit.Case, async: true + +  describe "build_tags/1" do +    test "for remote user" do +      assert Pleroma.Web.Metadata.Providers.RestrictIndexing.build_tags(%{ +               user: %Pleroma.User{local: false} +             }) == [{:meta, [name: "robots", content: "noindex, noarchive"], []}] +    end + +    test "for local user" do +      assert Pleroma.Web.Metadata.Providers.RestrictIndexing.build_tags(%{ +               user: %Pleroma.User{local: true} +             }) == [] +    end +  end +end diff --git a/test/web/node_info_test.exs b/test/web/node_info_test.exs index 43f322606..9bcc07b37 100644 --- a/test/web/node_info_test.exs +++ b/test/web/node_info_test.exs @@ -7,6 +7,8 @@ defmodule Pleroma.Web.NodeInfoTest do    import Pleroma.Factory +  alias Pleroma.Config +    setup do: clear_config([:mrf_simple])    setup do: clear_config(:instance) @@ -47,7 +49,7 @@ defmodule Pleroma.Web.NodeInfoTest do      assert result = json_response(conn, 200) -    assert Pleroma.Config.get([Pleroma.User, :restricted_nicknames]) == +    assert Config.get([Pleroma.User, :restricted_nicknames]) ==               result["metadata"]["restrictedNicknames"]    end @@ -65,10 +67,10 @@ defmodule Pleroma.Web.NodeInfoTest do    end    test "returns fieldsLimits field", %{conn: conn} do -    Pleroma.Config.put([:instance, :max_account_fields], 10) -    Pleroma.Config.put([:instance, :max_remote_account_fields], 15) -    Pleroma.Config.put([:instance, :account_field_name_length], 255) -    Pleroma.Config.put([:instance, :account_field_value_length], 2048) +    Config.put([:instance, :max_account_fields], 10) +    Config.put([:instance, :max_remote_account_fields], 15) +    Config.put([:instance, :account_field_name_length], 255) +    Config.put([:instance, :account_field_value_length], 2048)      response =        conn @@ -82,8 +84,8 @@ defmodule Pleroma.Web.NodeInfoTest do    end    test "it returns the safe_dm_mentions feature if enabled", %{conn: conn} do -    option = Pleroma.Config.get([:instance, :safe_dm_mentions]) -    Pleroma.Config.put([:instance, :safe_dm_mentions], true) +    option = Config.get([:instance, :safe_dm_mentions]) +    Config.put([:instance, :safe_dm_mentions], true)      response =        conn @@ -92,7 +94,7 @@ defmodule Pleroma.Web.NodeInfoTest do      assert "safe_dm_mentions" in response["metadata"]["features"] -    Pleroma.Config.put([:instance, :safe_dm_mentions], false) +    Config.put([:instance, :safe_dm_mentions], false)      response =        conn @@ -101,14 +103,14 @@ defmodule Pleroma.Web.NodeInfoTest do      refute "safe_dm_mentions" in response["metadata"]["features"] -    Pleroma.Config.put([:instance, :safe_dm_mentions], option) +    Config.put([:instance, :safe_dm_mentions], option)    end    describe "`metadata/federation/enabled`" do      setup do: clear_config([:instance, :federating])      test "it shows if federation is enabled/disabled", %{conn: conn} do -      Pleroma.Config.put([:instance, :federating], true) +      Config.put([:instance, :federating], true)        response =          conn @@ -117,7 +119,7 @@ defmodule Pleroma.Web.NodeInfoTest do        assert response["metadata"]["federation"]["enabled"] == true -      Pleroma.Config.put([:instance, :federating], false) +      Config.put([:instance, :federating], false)        response =          conn @@ -128,15 +130,39 @@ defmodule Pleroma.Web.NodeInfoTest do      end    end +  test "it shows default features flags", %{conn: conn} do +    response = +      conn +      |> get("/nodeinfo/2.1.json") +      |> json_response(:ok) + +    default_features = [ +      "pleroma_api", +      "mastodon_api", +      "mastodon_api_streaming", +      "polls", +      "pleroma_explicit_addressing", +      "shareable_emoji_packs", +      "multifetch", +      "pleroma_emoji_reactions", +      "pleroma:api/v1/notifications:include_types_filter" +    ] + +    assert MapSet.subset?( +             MapSet.new(default_features), +             MapSet.new(response["metadata"]["features"]) +           ) +  end +    test "it shows MRF transparency data if enabled", %{conn: conn} do -    config = Pleroma.Config.get([:instance, :rewrite_policy]) -    Pleroma.Config.put([:instance, :rewrite_policy], [Pleroma.Web.ActivityPub.MRF.SimplePolicy]) +    config = Config.get([:instance, :rewrite_policy]) +    Config.put([:instance, :rewrite_policy], [Pleroma.Web.ActivityPub.MRF.SimplePolicy]) -    option = Pleroma.Config.get([:instance, :mrf_transparency]) -    Pleroma.Config.put([:instance, :mrf_transparency], true) +    option = Config.get([:instance, :mrf_transparency]) +    Config.put([:instance, :mrf_transparency], true)      simple_config = %{"reject" => ["example.com"]} -    Pleroma.Config.put(:mrf_simple, simple_config) +    Config.put(:mrf_simple, simple_config)      response =        conn @@ -145,25 +171,25 @@ defmodule Pleroma.Web.NodeInfoTest do      assert response["metadata"]["federation"]["mrf_simple"] == simple_config -    Pleroma.Config.put([:instance, :rewrite_policy], config) -    Pleroma.Config.put([:instance, :mrf_transparency], option) -    Pleroma.Config.put(:mrf_simple, %{}) +    Config.put([:instance, :rewrite_policy], config) +    Config.put([:instance, :mrf_transparency], option) +    Config.put(:mrf_simple, %{})    end    test "it performs exclusions from MRF transparency data if configured", %{conn: conn} do -    config = Pleroma.Config.get([:instance, :rewrite_policy]) -    Pleroma.Config.put([:instance, :rewrite_policy], [Pleroma.Web.ActivityPub.MRF.SimplePolicy]) +    config = Config.get([:instance, :rewrite_policy]) +    Config.put([:instance, :rewrite_policy], [Pleroma.Web.ActivityPub.MRF.SimplePolicy]) -    option = Pleroma.Config.get([:instance, :mrf_transparency]) -    Pleroma.Config.put([:instance, :mrf_transparency], true) +    option = Config.get([:instance, :mrf_transparency]) +    Config.put([:instance, :mrf_transparency], true) -    exclusions = Pleroma.Config.get([:instance, :mrf_transparency_exclusions]) -    Pleroma.Config.put([:instance, :mrf_transparency_exclusions], ["other.site"]) +    exclusions = Config.get([:instance, :mrf_transparency_exclusions]) +    Config.put([:instance, :mrf_transparency_exclusions], ["other.site"])      simple_config = %{"reject" => ["example.com", "other.site"]}      expected_config = %{"reject" => ["example.com"]} -    Pleroma.Config.put(:mrf_simple, simple_config) +    Config.put(:mrf_simple, simple_config)      response =        conn @@ -173,9 +199,9 @@ defmodule Pleroma.Web.NodeInfoTest do      assert response["metadata"]["federation"]["mrf_simple"] == expected_config      assert response["metadata"]["federation"]["exclusions"] == true -    Pleroma.Config.put([:instance, :rewrite_policy], config) -    Pleroma.Config.put([:instance, :mrf_transparency], option) -    Pleroma.Config.put([:instance, :mrf_transparency_exclusions], exclusions) -    Pleroma.Config.put(:mrf_simple, %{}) +    Config.put([:instance, :rewrite_policy], config) +    Config.put([:instance, :mrf_transparency], option) +    Config.put([:instance, :mrf_transparency_exclusions], exclusions) +    Config.put(:mrf_simple, %{})    end  end diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs index 0b0972b17..f2f98d768 100644 --- a/test/web/oauth/oauth_controller_test.exs +++ b/test/web/oauth/oauth_controller_test.exs @@ -575,7 +575,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do        # In case scope param is missing, expecting _all_ app-supported scopes to be granted        for user <- [non_admin, admin],            {requested_scopes, expected_scopes} <- -            %{scopes_subset => scopes_subset, nil => app_scopes} do +            %{scopes_subset => scopes_subset, nil: app_scopes} do          conn =            post(              build_conn(), diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs index 6787b414b..bb349cb19 100644 --- a/test/web/ostatus/ostatus_controller_test.exs +++ b/test/web/ostatus/ostatus_controller_test.exs @@ -136,7 +136,7 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do        user = insert(:user) -      {:ok, like_activity, _} = CommonAPI.favorite(note_activity.id, user) +      {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)        assert like_activity.data["type"] == "Like" diff --git a/test/web/pleroma_api/controllers/account_controller_test.exs b/test/web/pleroma_api/controllers/account_controller_test.exs index 2aa87ac30..ae5334015 100644 --- a/test/web/pleroma_api/controllers/account_controller_test.exs +++ b/test/web/pleroma_api/controllers/account_controller_test.exs @@ -138,7 +138,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        user: user      } do        [activity | _] = insert_pair(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id)        response =          conn @@ -155,7 +155,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        user: user      } do        activity = insert(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id)        build_conn()        |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") @@ -172,7 +172,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do            "visibility" => "direct"          }) -      CommonAPI.favorite(direct.id, user) +      CommonAPI.favorite(user, direct.id)        for u <- [user, current_user] do          response = @@ -202,7 +202,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do            "visibility" => "direct"          }) -      CommonAPI.favorite(direct.id, user) +      CommonAPI.favorite(user, direct.id)        response =          conn @@ -219,7 +219,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        activities = insert_list(10, :note_activity)        Enum.each(activities, fn activity -> -        CommonAPI.favorite(activity.id, user) +        CommonAPI.favorite(user, activity.id)        end)        third_activity = Enum.at(activities, 2) @@ -245,7 +245,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        7        |> insert_list(:note_activity)        |> Enum.each(fn activity -> -        CommonAPI.favorite(activity.id, user) +        CommonAPI.favorite(user, activity.id)        end)        response = @@ -277,7 +277,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do      test "returns 403 error when user has hidden own favorites", %{conn: conn} do        user = insert(:user, hide_favorites: true)        activity = insert(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id)        conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites") @@ -287,7 +287,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do      test "hides favorites for new users by default", %{conn: conn} do        user = insert(:user)        activity = insert(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id)        assert user.hide_favorites        conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites") 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 089d55577..9121d90e7 100644 --- a/test/web/push/impl_test.exs +++ b/test/web/push/impl_test.exs @@ -134,7 +134,7 @@ defmodule Pleroma.Web.Push.ImplTest do      user = insert(:user, nickname: "Bob")      other_user = insert(:user)      {:ok, _, _, activity} = CommonAPI.follow(user, other_user) -    object = Object.normalize(activity) +    object = Object.normalize(activity, false)      assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has followed you" @@ -170,7 +170,7 @@ defmodule Pleroma.Web.Push.ImplTest do            "<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."        }) -    {:ok, activity, _} = CommonAPI.favorite(activity.id, user) +    {:ok, activity} = CommonAPI.favorite(user, activity.id)      object = Object.normalize(activity)      assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has favorited your post" diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs index a5d6e8ecf..eb082b79f 100644 --- a/test/web/streamer/streamer_test.exs +++ b/test/web/streamer/streamer_test.exs @@ -64,9 +64,6 @@ defmodule Pleroma.Web.StreamerTest do        blocked = insert(:user)        {:ok, _user_relationship} = User.block(user, blocked) -      {:ok, activity} = CommonAPI.post(user, %{"status" => ":("}) -      {:ok, notif, _} = CommonAPI.favorite(activity.id, blocked) -        task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)        Streamer.add_socket( @@ -74,6 +71,9 @@ defmodule Pleroma.Web.StreamerTest do          %{transport_pid: task.pid, assigns: %{user: user}}        ) +      {:ok, activity} = CommonAPI.post(user, %{"status" => ":("}) +      {:ok, notif} = CommonAPI.favorite(blocked, activity.id) +        Streamer.stream("user:notification", notif)        Task.await(task)      end @@ -83,10 +83,6 @@ defmodule Pleroma.Web.StreamerTest do      } do        user2 = insert(:user) -      {:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"}) -      {:ok, activity} = CommonAPI.add_mute(user, activity) -      {:ok, notif, _} = CommonAPI.favorite(activity.id, user2) -        task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)        Streamer.add_socket( @@ -94,6 +90,10 @@ defmodule Pleroma.Web.StreamerTest do          %{transport_pid: task.pid, assigns: %{user: user}}        ) +      {:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"}) +      {:ok, activity} = CommonAPI.add_mute(user, activity) +      {:ok, notif} = CommonAPI.favorite(user2, activity.id) +        Streamer.stream("user:notification", notif)        Task.await(task)      end @@ -103,10 +103,6 @@ defmodule Pleroma.Web.StreamerTest do      } do        user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"}) -      {:ok, user} = User.block_domain(user, "hecking-lewd-place.com") -      {:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"}) -      {:ok, notif, _} = CommonAPI.favorite(activity.id, user2) -        task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)        Streamer.add_socket( @@ -114,6 +110,10 @@ defmodule Pleroma.Web.StreamerTest do          %{transport_pid: task.pid, assigns: %{user: user}}        ) +      {:ok, user} = User.block_domain(user, "hecking-lewd-place.com") +      {:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"}) +      {:ok, notif} = CommonAPI.favorite(user2, activity.id) +        Streamer.stream("user:notification", notif)        Task.await(task)      end @@ -121,6 +121,18 @@ defmodule Pleroma.Web.StreamerTest do      test "it sends follow activities to the 'user:notification' stream", %{        user: user      } do +      user_url = user.ap_id + +      body = +        File.read!("test/fixtures/users_mock/localhost.json") +        |> String.replace("{{nickname}}", user.nickname) +        |> Jason.encode!() + +      Tesla.Mock.mock_global(fn +        %{method: :get, url: ^user_url} -> +          %Tesla.Env{status: 200, body: body} +      end) +        user2 = insert(:user)        task = Task.async(fn -> assert_receive {:text, _}, @streamer_timeout end) @@ -197,7 +209,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, @@ -220,7 +232,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, @@ -243,7 +255,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, @@ -464,7 +476,7 @@ defmodule Pleroma.Web.StreamerTest do      CommonAPI.hide_reblogs(user1, user2)      {:ok, create_activity} = CommonAPI.post(user3, %{"status" => "I'm kawen"}) -    {:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, user2) +    {:ok, favorite_activity} = CommonAPI.favorite(user2, create_activity.id)      task =        Task.async(fn -> 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)  | 
