aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/emoji/formatter_test.exs7
-rw-r--r--test/emoji_test.exs8
-rw-r--r--test/fixtures/emoji-reaction.json30
-rw-r--r--test/fixtures/misskey-like.json14
-rw-r--r--test/html_test.exs44
-rw-r--r--test/object/containment_test.exs24
-rw-r--r--test/object_test.exs16
-rw-r--r--test/plugs/cache_control_test.exs2
-rw-r--r--test/plugs/rate_limiter_test.exs257
-rw-r--r--test/support/http_request_mock.ex28
-rw-r--r--test/user_search_test.exs7
-rw-r--r--test/user_test.exs65
-rw-r--r--test/web/activity_pub/activity_pub_test.exs237
-rw-r--r--test/web/activity_pub/mrf/normalize_markup_test.exs10
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs141
-rw-r--r--test/web/activity_pub/utils_test.exs11
-rw-r--r--test/web/admin_api/admin_api_controller_test.exs33
-rw-r--r--test/web/common_api/common_api_test.exs47
-rw-r--r--test/web/feed/feed_controller_test.exs30
-rw-r--r--test/web/mastodon_api/controllers/conversation_controller_test.exs53
-rw-r--r--test/web/mastodon_api/views/conversation_view_test.exs1
-rw-r--r--test/web/mastodon_api/views/status_view_test.exs34
-rw-r--r--test/web/node_info_test.exs24
-rw-r--r--test/web/oauth/oauth_controller_test.exs23
-rw-r--r--test/web/pleroma_api/controllers/pleroma_api_controller_test.exs60
-rw-r--r--test/web/rel_me_test.exs4
-rw-r--r--test/web/static_fe/static_fe_controller_test.exs210
-rw-r--r--test/web/streamer/streamer_test.exs30
28 files changed, 1202 insertions, 248 deletions
diff --git a/test/emoji/formatter_test.exs b/test/emoji/formatter_test.exs
index 6d25fc453..fda80d470 100644
--- a/test/emoji/formatter_test.exs
+++ b/test/emoji/formatter_test.exs
@@ -12,7 +12,7 @@ defmodule Pleroma.Emoji.FormatterTest do
text = "I love :firefox:"
expected_result =
- "I love <img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"/emoji/Firefox.gif\" />"
+ "I love <img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"/emoji/Firefox.gif\"/>"
assert Formatter.emojify(text) == expected_result
end
@@ -28,10 +28,7 @@ defmodule Pleroma.Emoji.FormatterTest do
}
|> Pleroma.Emoji.build()
- expected_result =
- "I love <img class=\"emoji\" alt=\"\" title=\"\" src=\"https://placehold.it/1x1\" />"
-
- assert Formatter.emojify(text, [{custom_emoji.code, custom_emoji}]) == expected_result
+ refute Formatter.emojify(text, [{custom_emoji.code, custom_emoji}]) =~ text
end
end
diff --git a/test/emoji_test.exs b/test/emoji_test.exs
index 1fdbd0fdf..7bdf2b6fa 100644
--- a/test/emoji_test.exs
+++ b/test/emoji_test.exs
@@ -6,6 +6,14 @@ defmodule Pleroma.EmojiTest do
use ExUnit.Case, async: true
alias Pleroma.Emoji
+ describe "is_unicode_emoji?/1" do
+ test "tells if a string is an unicode emoji" do
+ refute Emoji.is_unicode_emoji?("X")
+ assert Emoji.is_unicode_emoji?("☂")
+ assert Emoji.is_unicode_emoji?("🥺")
+ end
+ end
+
describe "get_all/0" do
setup do
emoji_list = Emoji.get_all()
diff --git a/test/fixtures/emoji-reaction.json b/test/fixtures/emoji-reaction.json
new file mode 100644
index 000000000..3812e43ad
--- /dev/null
+++ b/test/fixtures/emoji-reaction.json
@@ -0,0 +1,30 @@
+{
+ "type": "EmojiReaction",
+ "signature": {
+ "type": "RsaSignature2017",
+ "signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==",
+ "creator": "http://mastodon.example.org/users/admin#main-key",
+ "created": "2018-02-17T18:57:49Z"
+ },
+ "object": "http://localtesting.pleroma.lol/objects/eb92579d-3417-42a8-8652-2492c2d4f454",
+ "content": "👌",
+ "nickname": "lain",
+ "id": "http://mastodon.example.org/users/admin#reactions/2",
+ "actor": "http://mastodon.example.org/users/admin",
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ {
+ "toot": "http://joinmastodon.org/ns#",
+ "sensitive": "as:sensitive",
+ "ostatus": "http://ostatus.org#",
+ "movedTo": "as:movedTo",
+ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
+ "conversation": "ostatus:conversation",
+ "atomUri": "ostatus:atomUri",
+ "Hashtag": "as:Hashtag",
+ "Emoji": "toot:Emoji"
+ }
+ ]
+}
diff --git a/test/fixtures/misskey-like.json b/test/fixtures/misskey-like.json
new file mode 100644
index 000000000..84d56f473
--- /dev/null
+++ b/test/fixtures/misskey-like.json
@@ -0,0 +1,14 @@
+{
+ "@context" : [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ {"Hashtag" : "as:Hashtag"}
+ ],
+ "_misskey_reaction" : "pudding",
+ "actor": "http://mastodon.example.org/users/admin",
+ "cc" : ["https://testing.pleroma.lol/users/lain"],
+ "id" : "https://misskey.xyz/75149198-2f45-46e4-930a-8b0538297075",
+ "nickname" : "lain",
+ "object" : "https://testing.pleroma.lol/objects/c331bbf7-2eb9-4801-a709-2a6103492a5a",
+ "type" : "Like"
+}
diff --git a/test/html_test.exs b/test/html_test.exs
index 306ad3b3b..f0869534c 100644
--- a/test/html_test.exs
+++ b/test/html_test.exs
@@ -21,31 +21,31 @@ defmodule Pleroma.HTMLTest do
"""
@html_onerror_sample """
- <img src="http://example.com/image.jpg" onerror="alert('hacked')">
+ <img src="http://example.com/image.jpg" onerror="alert('hacked')">
"""
@html_span_class_sample """
- <span class="animate-spin">hi</span>
+ <span class="animate-spin">hi</span>
"""
@html_span_microformats_sample """
- <span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
+ <span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
"""
@html_span_invalid_microformats_sample """
- <span class="h-card"><a class="u-url mention animate-spin">@<span>foo</span></a></span>
+ <span class="h-card"><a class="u-url mention animate-spin">@<span>foo</span></a></span>
"""
describe "StripTags scrubber" do
test "works as expected" do
expected = """
- this is in bold
+ this is in bold
this is a paragraph
this is a linebreak
- this is a link with allowed "rel" attribute: example.com
- this is a link with not allowed "rel" attribute: example.com
+ this is a link with allowed &quot;rel&quot; attribute: example.com
+ this is a link with not allowed &quot;rel&quot; attribute: example.com
this is an image:
- alert('hacked')
+ alert(&#39;hacked&#39;)
"""
assert expected == HTML.strip_tags(@html_sample)
@@ -61,13 +61,13 @@ defmodule Pleroma.HTMLTest do
describe "TwitterText scrubber" do
test "normalizes HTML as expected" do
expected = """
- this is in bold
+ this is in bold
<p>this is a paragraph</p>
- this is a linebreak<br />
- this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
- this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
- this is an image: <img src="http://example.com/image.jpg" /><br />
- alert('hacked')
+ this is a linebreak<br/>
+ this is a link with allowed &quot;rel&quot; attribute: <a href="http://example.com/" rel="tag">example.com</a>
+ this is a link with not allowed &quot;rel&quot; attribute: <a href="http://example.com/">example.com</a>
+ this is an image: <img src="http://example.com/image.jpg"/><br/>
+ alert(&#39;hacked&#39;)
"""
assert expected == HTML.filter_tags(@html_sample, Pleroma.HTML.Scrubber.TwitterText)
@@ -75,7 +75,7 @@ defmodule Pleroma.HTMLTest do
test "does not allow attribute-based XSS" do
expected = """
- <img src="http://example.com/image.jpg" />
+ <img src="http://example.com/image.jpg"/>
"""
assert expected == HTML.filter_tags(@html_onerror_sample, Pleroma.HTML.Scrubber.TwitterText)
@@ -115,13 +115,13 @@ defmodule Pleroma.HTMLTest do
describe "default scrubber" do
test "normalizes HTML as expected" do
expected = """
- <b>this is in bold</b>
+ <b>this is in bold</b>
<p>this is a paragraph</p>
- this is a linebreak<br />
- this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
- this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
- this is an image: <img src="http://example.com/image.jpg" /><br />
- alert('hacked')
+ this is a linebreak<br/>
+ this is a link with allowed &quot;rel&quot; attribute: <a href="http://example.com/" rel="tag">example.com</a>
+ this is a link with not allowed &quot;rel&quot; attribute: <a href="http://example.com/">example.com</a>
+ this is an image: <img src="http://example.com/image.jpg"/><br/>
+ alert(&#39;hacked&#39;)
"""
assert expected == HTML.filter_tags(@html_sample, Pleroma.HTML.Scrubber.Default)
@@ -129,7 +129,7 @@ defmodule Pleroma.HTMLTest do
test "does not allow attribute-based XSS" do
expected = """
- <img src="http://example.com/image.jpg" />
+ <img src="http://example.com/image.jpg"/>
"""
assert expected == HTML.filter_tags(@html_onerror_sample, Pleroma.HTML.Scrubber.Default)
diff --git a/test/object/containment_test.exs b/test/object/containment_test.exs
index 0dc2728b9..7636803a6 100644
--- a/test/object/containment_test.exs
+++ b/test/object/containment_test.exs
@@ -17,6 +17,16 @@ defmodule Pleroma.Object.ContainmentTest do
end
describe "general origin containment" do
+ test "works for completely actorless posts" do
+ assert :error ==
+ Containment.contain_origin("https://glaceon.social/users/monorail", %{
+ "deleted" => "2019-10-30T05:48:50.249606Z",
+ "formerType" => "Note",
+ "id" => "https://glaceon.social/users/monorail/statuses/103049757364029187",
+ "type" => "Tombstone"
+ })
+ end
+
test "contain_origin_from_id() catches obvious spoofing attempts" do
data = %{
"id" => "http://example.com/~alyssa/activities/1234.json"
@@ -67,6 +77,20 @@ defmodule Pleroma.Object.ContainmentTest do
end) =~
"[error] Could not decode user at fetch https://n1u.moe/users/rye"
end
+
+ test "contain_origin_from_id() gracefully handles cases where no ID is present" do
+ data = %{
+ "type" => "Create",
+ "object" => %{
+ "id" => "http://example.net/~alyssa/activities/1234",
+ "attributedTo" => "http://example.org/~alyssa"
+ },
+ "actor" => "http://example.com/~bob"
+ }
+
+ :error =
+ Containment.contain_origin_from_id("http://example.net/~alyssa/activities/1234", data)
+ end
end
describe "containment of children" do
diff --git a/test/object_test.exs b/test/object_test.exs
index dd228c32f..9247a6d84 100644
--- a/test/object_test.exs
+++ b/test/object_test.exs
@@ -124,6 +124,8 @@ defmodule Pleroma.ObjectTest do
%Object{} =
object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
+ Object.set_cache(object)
+
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
@@ -133,6 +135,8 @@ defmodule Pleroma.ObjectTest do
})
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
+ object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
+ assert updated_object == object_in_cache
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
end
@@ -141,6 +145,8 @@ defmodule Pleroma.ObjectTest do
%Object{} =
object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
+ Object.set_cache(object)
+
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
@@ -148,6 +154,8 @@ defmodule Pleroma.ObjectTest do
mock_modified.(%Tesla.Env{status: 404, body: ""})
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
+ object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
+ assert updated_object == object_in_cache
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
end) =~
@@ -160,6 +168,8 @@ defmodule Pleroma.ObjectTest do
%Object{} =
object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
+ Object.set_cache(object)
+
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
@@ -169,6 +179,8 @@ defmodule Pleroma.ObjectTest do
})
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100)
+ object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
+ assert updated_object == object_in_cache
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
end
@@ -177,6 +189,8 @@ defmodule Pleroma.ObjectTest do
%Object{} =
object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
+ Object.set_cache(object)
+
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
@@ -192,6 +206,8 @@ defmodule Pleroma.ObjectTest do
})
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
+ object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
+ assert updated_object == object_in_cache
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
diff --git a/test/plugs/cache_control_test.exs b/test/plugs/cache_control_test.exs
index 69ce6cc7d..be78b3e1e 100644
--- a/test/plugs/cache_control_test.exs
+++ b/test/plugs/cache_control_test.exs
@@ -9,7 +9,7 @@ defmodule Pleroma.Web.CacheControlTest do
test "Verify Cache-Control header on static assets", %{conn: conn} do
conn = get(conn, "/index.html")
- assert Conn.get_resp_header(conn, "cache-control") == ["public, no-cache"]
+ assert Conn.get_resp_header(conn, "cache-control") == ["public max-age=86400 must-revalidate"]
end
test "Verify Cache-Control header on the API", %{conn: conn} do
diff --git a/test/plugs/rate_limiter_test.exs b/test/plugs/rate_limiter_test.exs
index 395095079..49f63c424 100644
--- a/test/plugs/rate_limiter_test.exs
+++ b/test/plugs/rate_limiter_test.exs
@@ -12,163 +12,196 @@ defmodule Pleroma.Plugs.RateLimiterTest do
# Note: each example must work with separate buckets in order to prevent concurrency issues
- test "init/1" do
- limiter_name = :test_init
- Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
+ describe "config" do
+ test "config is required for plug to work" do
+ limiter_name = :test_init
+ Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
- assert {limiter_name, {1, 1}, []} == RateLimiter.init(limiter_name)
- assert nil == RateLimiter.init(:foo)
- end
+ assert %{limits: {1, 1}, name: :test_init, opts: [name: :test_init]} ==
+ RateLimiter.init(name: limiter_name)
- test "ip/1" do
- assert "127.0.0.1" == RateLimiter.ip(%{remote_ip: {127, 0, 0, 1}})
- end
+ assert nil == RateLimiter.init(name: :foo)
+ end
- test "it restricts by opts" do
- limiter_name = :test_opts
- scale = 1000
- limit = 5
+ test "it restricts based on config values" do
+ limiter_name = :test_opts
+ scale = 80
+ limit = 5
- Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
+ Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
- opts = RateLimiter.init(limiter_name)
- conn = conn(:get, "/")
- bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}"
+ opts = RateLimiter.init(name: limiter_name)
+ conn = conn(:get, "/")
- conn = RateLimiter.call(conn, opts)
- assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ for i <- 1..5 do
+ conn = RateLimiter.call(conn, opts)
+ assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
+ Process.sleep(10)
+ end
- conn = RateLimiter.call(conn, opts)
- assert {2, 3, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ conn = RateLimiter.call(conn, opts)
+ assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
+ assert conn.halted
- conn = RateLimiter.call(conn, opts)
- assert {3, 2, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ Process.sleep(50)
- conn = RateLimiter.call(conn, opts)
- assert {4, 1, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ conn = conn(:get, "/")
- conn = RateLimiter.call(conn, opts)
- assert {5, 0, to_reset, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ conn = RateLimiter.call(conn, opts)
+ assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
- conn = RateLimiter.call(conn, opts)
+ refute conn.status == Plug.Conn.Status.code(:too_many_requests)
+ refute conn.resp_body
+ refute conn.halted
+ end
+ end
- assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
- assert conn.halted
+ describe "options" do
+ test "`bucket_name` option overrides default bucket name" do
+ limiter_name = :test_bucket_name
- Process.sleep(to_reset)
+ Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
- conn = conn(:get, "/")
+ base_bucket_name = "#{limiter_name}:group1"
+ opts = RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name)
- conn = RateLimiter.call(conn, opts)
- assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ conn = conn(:get, "/")
- refute conn.status == Plug.Conn.Status.code(:too_many_requests)
- refute conn.resp_body
- refute conn.halted
- end
+ RateLimiter.call(conn, opts)
+ assert {1, 4} = RateLimiter.inspect_bucket(conn, base_bucket_name, opts)
+ assert {:err, :not_found} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
+ end
- test "`bucket_name` option overrides default bucket name" do
- limiter_name = :test_bucket_name
- scale = 1000
- limit = 5
+ test "`params` option allows different queries to be tracked independently" do
+ limiter_name = :test_params
+ Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
- Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
- base_bucket_name = "#{limiter_name}:group1"
- opts = RateLimiter.init({limiter_name, bucket_name: base_bucket_name})
+ opts = RateLimiter.init(name: limiter_name, params: ["id"])
- conn = conn(:get, "/")
- default_bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}"
- customized_bucket_name = "#{base_bucket_name}:#{RateLimiter.ip(conn)}"
+ conn = conn(:get, "/?id=1")
+ conn = Plug.Conn.fetch_query_params(conn)
+ conn_2 = conn(:get, "/?id=2")
- RateLimiter.call(conn, opts)
- assert {1, 4, _, _, _} = ExRated.inspect_bucket(customized_bucket_name, scale, limit)
- assert {0, 5, _, _, _} = ExRated.inspect_bucket(default_bucket_name, scale, limit)
- end
-
- test "`params` option appends specified params' values to bucket name" do
- limiter_name = :test_params
- scale = 1000
- limit = 5
+ RateLimiter.call(conn, opts)
+ assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
+ assert {0, 5} = RateLimiter.inspect_bucket(conn_2, limiter_name, opts)
+ end
- Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
- opts = RateLimiter.init({limiter_name, params: ["id"]})
- id = "1"
+ test "it supports combination of options modifying bucket name" do
+ limiter_name = :test_options_combo
+ Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
- conn = conn(:get, "/?id=#{id}")
- conn = Plug.Conn.fetch_query_params(conn)
+ base_bucket_name = "#{limiter_name}:group1"
+ opts = RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name, params: ["id"])
+ id = "100"
- default_bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}"
- parametrized_bucket_name = "#{limiter_name}:#{id}:#{RateLimiter.ip(conn)}"
+ conn = conn(:get, "/?id=#{id}")
+ conn = Plug.Conn.fetch_query_params(conn)
+ conn_2 = conn(:get, "/?id=#{101}")
- RateLimiter.call(conn, opts)
- assert {1, 4, _, _, _} = ExRated.inspect_bucket(parametrized_bucket_name, scale, limit)
- assert {0, 5, _, _, _} = ExRated.inspect_bucket(default_bucket_name, scale, limit)
+ RateLimiter.call(conn, opts)
+ assert {1, 4} = RateLimiter.inspect_bucket(conn, base_bucket_name, opts)
+ assert {0, 5} = RateLimiter.inspect_bucket(conn_2, base_bucket_name, opts)
+ end
end
- test "it supports combination of options modifying bucket name" do
- limiter_name = :test_options_combo
- scale = 1000
- limit = 5
+ describe "unauthenticated users" do
+ test "are restricted based on remote IP" do
+ limiter_name = :test_unauthenticated
+ Pleroma.Config.put([:rate_limit, limiter_name], [{1000, 5}, {1, 10}])
+
+ opts = RateLimiter.init(name: limiter_name)
- Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
- base_bucket_name = "#{limiter_name}:group1"
- opts = RateLimiter.init({limiter_name, bucket_name: base_bucket_name, params: ["id"]})
- id = "100"
+ conn = %{conn(:get, "/") | remote_ip: {127, 0, 0, 2}}
+ conn_2 = %{conn(:get, "/") | remote_ip: {127, 0, 0, 3}}
- conn = conn(:get, "/?id=#{id}")
- conn = Plug.Conn.fetch_query_params(conn)
+ for i <- 1..5 do
+ conn = RateLimiter.call(conn, opts)
+ assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
+ refute conn.halted
+ end
- default_bucket_name = "#{limiter_name}:#{RateLimiter.ip(conn)}"
- parametrized_bucket_name = "#{base_bucket_name}:#{id}:#{RateLimiter.ip(conn)}"
+ conn = RateLimiter.call(conn, opts)
- RateLimiter.call(conn, opts)
- assert {1, 4, _, _, _} = ExRated.inspect_bucket(parametrized_bucket_name, scale, limit)
- assert {0, 5, _, _, _} = ExRated.inspect_bucket(default_bucket_name, scale, limit)
+ assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
+ assert conn.halted
+
+ conn_2 = RateLimiter.call(conn_2, opts)
+ assert {1, 4} = RateLimiter.inspect_bucket(conn_2, limiter_name, opts)
+
+ refute conn_2.status == Plug.Conn.Status.code(:too_many_requests)
+ refute conn_2.resp_body
+ refute conn_2.halted
+ end
end
- test "optional limits for authenticated users" do
- limiter_name = :test_authenticated
- Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo)
+ describe "authenticated users" do
+ setup do
+ Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo)
+
+ :ok
+ end
+
+ test "can have limits seperate from unauthenticated connections" do
+ limiter_name = :test_authenticated
+
+ scale = 1000
+ limit = 5
+ Pleroma.Config.put([:rate_limit, limiter_name], [{1, 10}, {scale, limit}])
+
+ opts = RateLimiter.init(name: limiter_name)
- scale = 1000
- limit = 5
- Pleroma.Config.put([:rate_limit, limiter_name], [{1, 10}, {scale, limit}])
+ user = insert(:user)
+ conn = conn(:get, "/") |> assign(:user, user)
- opts = RateLimiter.init(limiter_name)
+ for i <- 1..5 do
+ conn = RateLimiter.call(conn, opts)
+ assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
+ refute conn.halted
+ end
- user = insert(:user)
- conn = conn(:get, "/") |> assign(:user, user)
- bucket_name = "#{limiter_name}:#{user.id}"
+ conn = RateLimiter.call(conn, opts)
- conn = RateLimiter.call(conn, opts)
- assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
+ assert conn.halted
- conn = RateLimiter.call(conn, opts)
- assert {2, 3, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ Process.sleep(1550)
- conn = RateLimiter.call(conn, opts)
- assert {3, 2, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ conn = conn(:get, "/") |> assign(:user, user)
+ conn = RateLimiter.call(conn, opts)
+ assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
- conn = RateLimiter.call(conn, opts)
- assert {4, 1, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ refute conn.status == Plug.Conn.Status.code(:too_many_requests)
+ refute conn.resp_body
+ refute conn.halted
+ end
- conn = RateLimiter.call(conn, opts)
- assert {5, 0, to_reset, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ test "diffrerent users are counted independently" do
+ limiter_name = :test_authenticated
+ Pleroma.Config.put([:rate_limit, limiter_name], [{1, 10}, {1000, 5}])
- conn = RateLimiter.call(conn, opts)
+ opts = RateLimiter.init(name: limiter_name)
- assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
- assert conn.halted
+ user = insert(:user)
+ conn = conn(:get, "/") |> assign(:user, user)
- Process.sleep(to_reset)
+ user_2 = insert(:user)
+ conn_2 = conn(:get, "/") |> assign(:user, user_2)
- conn = conn(:get, "/") |> assign(:user, user)
+ for i <- 1..5 do
+ conn = RateLimiter.call(conn, opts)
+ assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
+ end
- conn = RateLimiter.call(conn, opts)
- assert {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, scale, limit)
+ conn = RateLimiter.call(conn, opts)
+ assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
+ assert conn.halted
- refute conn.status == Plug.Conn.Status.code(:too_many_requests)
- refute conn.resp_body
- refute conn.halted
+ conn_2 = RateLimiter.call(conn_2, opts)
+ assert {1, 4} = RateLimiter.inspect_bucket(conn_2, limiter_name, opts)
+ refute conn_2.status == Plug.Conn.Status.code(:too_many_requests)
+ refute conn_2.resp_body
+ refute conn_2.halted
+ end
end
end
diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex
index eba22c40b..965335e96 100644
--- a/test/support/http_request_mock.ex
+++ b/test/support/http_request_mock.ex
@@ -1183,6 +1183,30 @@ defmodule HttpRequestMock do
}}
end
+ def get("https://10.111.10.1/notice/9kCP7V", _, _, _) do
+ {:ok, %Tesla.Env{status: 200, body: ""}}
+ end
+
+ def get("https://172.16.32.40/notice/9kCP7V", _, _, _) do
+ {:ok, %Tesla.Env{status: 200, body: ""}}
+ end
+
+ def get("https://192.168.10.40/notice/9kCP7V", _, _, _) do
+ {:ok, %Tesla.Env{status: 200, body: ""}}
+ end
+
+ def get("https://www.patreon.com/posts/mastodon-2-9-and-28121681", _, _, _) do
+ {:ok, %Tesla.Env{status: 200, body: ""}}
+ end
+
+ def get("http://mastodon.example.org/@admin/99541947525187367", _, _, _) do
+ {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/mastodon-post-activity.json")}}
+ end
+
+ def get("https://info.pleroma.site/activity4.json", _, _, _) do
+ {:ok, %Tesla.Env{status: 500, body: "Error occurred"}}
+ end
+
def get("http://example.com/rel_me/anchor", _, _, _) do
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rel_me_anchor.html")}}
end
@@ -1215,6 +1239,10 @@ defmodule HttpRequestMock do
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/rin.json")}}
end
+ def get("http://example.com/rel_me/error", _, _, _) do
+ {:ok, %Tesla.Env{status: 404, body: ""}}
+ end
+
def get(url, query, body, headers) do
{:error,
"Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{
diff --git a/test/user_search_test.exs b/test/user_search_test.exs
index 78a02d536..721af1e5b 100644
--- a/test/user_search_test.exs
+++ b/test/user_search_test.exs
@@ -51,13 +51,6 @@ defmodule Pleroma.UserSearchTest do
end)
end
- test "finds users, preferring nickname matches over name matches" do
- u1 = insert(:user, %{name: "lain", nickname: "nick1"})
- u2 = insert(:user, %{nickname: "lain", name: "nick1"})
-
- assert [u2.id, u1.id] == Enum.map(User.search("lain"), & &1.id)
- end
-
test "finds users, considering density of matched tokens" do
u1 = insert(:user, %{name: "Bar Bar plus Word Word"})
u2 = insert(:user, %{name: "Word Word Bar Bar Bar"})
diff --git a/test/user_test.exs b/test/user_test.exs
index 188295a86..6b1b24ce5 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -878,27 +878,50 @@ defmodule Pleroma.UserTest do
end
end
- test "get recipients from activity" do
- actor = insert(:user)
- user = insert(:user, local: true)
- user_two = insert(:user, local: false)
- addressed = insert(:user, local: true)
- addressed_remote = insert(:user, local: false)
-
- {:ok, activity} =
- CommonAPI.post(actor, %{
- "status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
- })
-
- assert Enum.map([actor, addressed], & &1.ap_id) --
- Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
-
- {:ok, user} = User.follow(user, actor)
- {:ok, _user_two} = User.follow(user_two, actor)
- recipients = User.get_recipients_from_activity(activity)
- assert length(recipients) == 3
- assert user in recipients
- assert addressed in recipients
+ describe "get_recipients_from_activity" do
+ test "get recipients" do
+ actor = insert(:user)
+ user = insert(:user, local: true)
+ user_two = insert(:user, local: false)
+ addressed = insert(:user, local: true)
+ addressed_remote = insert(:user, local: false)
+
+ {:ok, activity} =
+ CommonAPI.post(actor, %{
+ "status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
+ })
+
+ assert Enum.map([actor, addressed], & &1.ap_id) --
+ Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
+
+ {:ok, user} = User.follow(user, actor)
+ {:ok, _user_two} = User.follow(user_two, actor)
+ recipients = User.get_recipients_from_activity(activity)
+ assert length(recipients) == 3
+ assert user in recipients
+ assert addressed in recipients
+ end
+
+ test "has following" do
+ actor = insert(:user)
+ user = insert(:user)
+ user_two = insert(:user)
+ addressed = insert(:user, local: true)
+
+ {:ok, activity} =
+ CommonAPI.post(actor, %{
+ "status" => "hey @#{addressed.nickname}"
+ })
+
+ assert Enum.map([actor, addressed], & &1.ap_id) --
+ Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
+
+ {:ok, _actor} = User.follow(actor, user)
+ {:ok, _actor} = User.follow(actor, user_two)
+ recipients = User.get_recipients_from_activity(activity)
+ assert length(recipients) == 2
+ assert addressed in recipients
+ end
end
describe ".deactivate" do
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
index bbae3fcf1..71aab92c3 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -13,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Utils
+ alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
@@ -736,56 +737,54 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
test "retrieves a maximum of 20 activities" do
- activities = ActivityBuilder.insert_list(30)
- last_expected = List.last(activities)
+ ActivityBuilder.insert_list(10)
+ expected_activities = ActivityBuilder.insert_list(20)
activities = ActivityPub.fetch_public_activities()
- last = List.last(activities)
+ assert collect_ids(activities) == collect_ids(expected_activities)
assert length(activities) == 20
- assert last == last_expected
end
test "retrieves ids starting from a since_id" do
activities = ActivityBuilder.insert_list(30)
- later_activities = ActivityBuilder.insert_list(10)
+ expected_activities = ActivityBuilder.insert_list(10)
since_id = List.last(activities).id
- last_expected = List.last(later_activities)
activities = ActivityPub.fetch_public_activities(%{"since_id" => since_id})
- last = List.last(activities)
+ assert collect_ids(activities) == collect_ids(expected_activities)
assert length(activities) == 10
- assert last == last_expected
end
test "retrieves ids up to max_id" do
- _first_activities = ActivityBuilder.insert_list(10)
- activities = ActivityBuilder.insert_list(20)
- later_activities = ActivityBuilder.insert_list(10)
- max_id = List.first(later_activities).id
- last_expected = List.last(activities)
+ ActivityBuilder.insert_list(10)
+ expected_activities = ActivityBuilder.insert_list(20)
+
+ %{id: max_id} =
+ 10
+ |> ActivityBuilder.insert_list()
+ |> List.first()
activities = ActivityPub.fetch_public_activities(%{"max_id" => max_id})
- last = List.last(activities)
assert length(activities) == 20
- assert last == last_expected
+ assert collect_ids(activities) == collect_ids(expected_activities)
end
test "paginates via offset/limit" do
- _first_activities = ActivityBuilder.insert_list(10)
- activities = ActivityBuilder.insert_list(10)
- _later_activities = ActivityBuilder.insert_list(10)
- first_expected = List.first(activities)
+ _first_part_activities = ActivityBuilder.insert_list(10)
+ second_part_activities = ActivityBuilder.insert_list(10)
+
+ later_activities = ActivityBuilder.insert_list(10)
activities =
ActivityPub.fetch_public_activities(%{"page" => "2", "page_size" => "20"}, :offset)
- first = List.first(activities)
-
assert length(activities) == 20
- assert first == first_expected
+
+ assert collect_ids(activities) ==
+ collect_ids(second_part_activities) ++ collect_ids(later_activities)
end
test "doesn't return reblogs for users for whom reblogs have been muted" do
@@ -816,6 +815,78 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
+ describe "react to an object" do
+ test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
+ Pleroma.Config.put([:instance, :federating], true)
+ user = insert(:user)
+ reactor = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
+ assert object = Object.normalize(activity)
+
+ {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
+
+ assert called(Pleroma.Web.Federator.publish(reaction_activity))
+ end
+
+ test "adds an emoji reaction activity to the db" do
+ user = insert(:user)
+ reactor = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
+ assert object = Object.normalize(activity)
+
+ {:ok, reaction_activity, object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
+
+ assert reaction_activity
+
+ assert reaction_activity.data["actor"] == reactor.ap_id
+ assert reaction_activity.data["type"] == "EmojiReaction"
+ assert reaction_activity.data["content"] == "🔥"
+ assert reaction_activity.data["object"] == object.data["id"]
+ assert reaction_activity.data["to"] == [User.ap_followers(reactor), activity.data["actor"]]
+ assert reaction_activity.data["context"] == object.data["context"]
+ assert object.data["reaction_count"] == 1
+ assert object.data["reactions"]["🔥"] == [reactor.ap_id]
+ end
+ end
+
+ describe "unreacting to an object" do
+ test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
+ Pleroma.Config.put([:instance, :federating], true)
+ user = insert(:user)
+ reactor = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
+ assert object = Object.normalize(activity)
+
+ {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
+
+ assert called(Pleroma.Web.Federator.publish(reaction_activity))
+
+ {:ok, unreaction_activity, _object} =
+ ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
+
+ assert called(Pleroma.Web.Federator.publish(unreaction_activity))
+ end
+
+ test "adds an undo activity to the db" do
+ user = insert(:user)
+ reactor = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
+ assert object = Object.normalize(activity)
+
+ {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
+
+ {:ok, unreaction_activity, _object} =
+ ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
+
+ assert unreaction_activity.actor == reactor.ap_id
+ assert unreaction_activity.data["object"] == reaction_activity.data["id"]
+
+ object = Object.get_by_ap_id(object.data["id"])
+ assert object.data["reaction_count"] == 0
+ assert object.data["reactions"] == %{}
+ end
+ end
+
describe "like an object" do
test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
Pleroma.Config.put([:instance, :federating], true)
@@ -1284,35 +1355,99 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert 3 = length(activities)
end
- test "it can create a Flag activity" do
- reporter = insert(:user)
- target_account = insert(:user)
- {:ok, activity} = CommonAPI.post(target_account, %{"status" => "foobar"})
- context = Utils.generate_context_id()
- content = "foobar"
-
- reporter_ap_id = reporter.ap_id
- target_ap_id = target_account.ap_id
- activity_ap_id = activity.data["id"]
-
- assert {:ok, activity} =
- ActivityPub.flag(%{
- actor: reporter,
- context: context,
- account: target_account,
- statuses: [activity],
- content: content
- })
-
- assert %Activity{
- actor: ^reporter_ap_id,
- data: %{
- "type" => "Flag",
- "content" => ^content,
- "context" => ^context,
- "object" => [^target_ap_id, ^activity_ap_id]
- }
- } = activity
+ describe "flag/1" do
+ setup do
+ reporter = insert(:user)
+ target_account = insert(:user)
+ content = "foobar"
+ {:ok, activity} = CommonAPI.post(target_account, %{"status" => content})
+ context = Utils.generate_context_id()
+
+ reporter_ap_id = reporter.ap_id
+ target_ap_id = target_account.ap_id
+ activity_ap_id = activity.data["id"]
+
+ activity_with_object = Activity.get_by_ap_id_with_object(activity_ap_id)
+
+ {:ok,
+ %{
+ reporter: reporter,
+ context: context,
+ target_account: target_account,
+ reported_activity: activity,
+ content: content,
+ activity_ap_id: activity_ap_id,
+ activity_with_object: activity_with_object,
+ reporter_ap_id: reporter_ap_id,
+ target_ap_id: target_ap_id
+ }}
+ end
+
+ test "it can create a Flag activity",
+ %{
+ reporter: reporter,
+ context: context,
+ target_account: target_account,
+ reported_activity: reported_activity,
+ content: content,
+ activity_ap_id: activity_ap_id,
+ activity_with_object: activity_with_object,
+ reporter_ap_id: reporter_ap_id,
+ target_ap_id: target_ap_id
+ } do
+ assert {:ok, activity} =
+ ActivityPub.flag(%{
+ actor: reporter,
+ context: context,
+ account: target_account,
+ statuses: [reported_activity],
+ content: content
+ })
+
+ note_obj = %{
+ "type" => "Note",
+ "id" => activity_ap_id,
+ "content" => content,
+ "published" => activity_with_object.object.data["published"],
+ "actor" => AccountView.render("show.json", %{user: target_account})
+ }
+
+ assert %Activity{
+ actor: ^reporter_ap_id,
+ data: %{
+ "type" => "Flag",
+ "content" => ^content,
+ "context" => ^context,
+ "object" => [^target_ap_id, ^note_obj]
+ }
+ } = activity
+ end
+
+ test_with_mock "strips status data from Flag, before federating it",
+ %{
+ reporter: reporter,
+ context: context,
+ target_account: target_account,
+ reported_activity: reported_activity,
+ content: content
+ },
+ Utils,
+ [:passthrough],
+ [] do
+ {:ok, activity} =
+ ActivityPub.flag(%{
+ actor: reporter,
+ context: context,
+ account: target_account,
+ statuses: [reported_activity],
+ content: content
+ })
+
+ new_data =
+ put_in(activity.data, ["object"], [target_account.ap_id, reported_activity.data["id"]])
+
+ assert_called(Utils.maybe_federate(%{activity | data: new_data}))
+ end
end
test "fetch_activities/2 returns activities addressed to a list " do
diff --git a/test/web/activity_pub/mrf/normalize_markup_test.exs b/test/web/activity_pub/mrf/normalize_markup_test.exs
index 3916a1f35..0207be56b 100644
--- a/test/web/activity_pub/mrf/normalize_markup_test.exs
+++ b/test/web/activity_pub/mrf/normalize_markup_test.exs
@@ -20,11 +20,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkupTest do
expected = """
<b>this is in bold</b>
<p>this is a paragraph</p>
- this is a linebreak<br />
- this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
- this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
- this is an image: <img src="http://example.com/image.jpg" /><br />
- alert('hacked')
+ this is a linebreak<br/>
+ this is a link with allowed &quot;rel&quot; attribute: <a href="http://example.com/" rel="tag">example.com</a>
+ this is a link with not allowed &quot;rel&quot; attribute: <a href="http://example.com/">example.com</a>
+ this is an image: <img src="http://example.com/image.jpg"/><br/>
+ alert(&#39;hacked&#39;)
"""
message = %{"type" => "Create", "object" => %{"content" => @html_sample}}
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index 76e7ad8ea..517a9621a 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -11,6 +11,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Transmogrifier
+ alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.CommonAPI
import Mock
@@ -338,6 +339,80 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert data["object"] == activity.data["object"]
end
+ test "it works for incoming misskey likes, turning them into EmojiReactions" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+
+ data =
+ File.read!("test/fixtures/misskey-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == data["actor"]
+ assert data["type"] == "EmojiReaction"
+ assert data["id"] == data["id"]
+ assert data["object"] == activity.data["object"]
+ assert data["content"] == "🍮"
+ end
+
+ test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReactions" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+
+ data =
+ File.read!("test/fixtures/misskey-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+ |> Map.put("_misskey_reaction", "⭐")
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == data["actor"]
+ assert data["type"] == "EmojiReaction"
+ assert data["id"] == data["id"]
+ assert data["object"] == activity.data["object"]
+ assert data["content"] == "⭐"
+ end
+
+ test "it works for incoming emoji reactions" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+
+ data =
+ File.read!("test/fixtures/emoji-reaction.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+ assert data["type"] == "EmojiReaction"
+ assert data["id"] == "http://mastodon.example.org/users/admin#reactions/2"
+ assert data["object"] == activity.data["object"]
+ assert data["content"] == "👌"
+ end
+
+ test "it works for incoming emoji reaction undos" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+ {:ok, reaction_activity, _object} = CommonAPI.react_with_emoji(activity.id, user, "👌")
+
+ data =
+ File.read!("test/fixtures/mastodon-undo-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", reaction_activity.data["id"])
+ |> Map.put("actor", user.ap_id)
+
+ {:ok, activity} = Transmogrifier.handle_incoming(data)
+
+ assert activity.actor == user.ap_id
+ assert activity.data["id"] == data["id"]
+ assert activity.data["type"] == "Undo"
+ end
+
test "it returns an error for incoming unlikes wihout a like activity" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
@@ -552,6 +627,20 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
refute Map.has_key?(object.data, "likes")
end
+ test "it strips internal reactions" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
+ {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, user, "📢")
+
+ %{object: object} = Activity.get_by_id_with_object(activity.id)
+ assert Map.has_key?(object.data, "reactions")
+ assert Map.has_key?(object.data, "reaction_count")
+
+ object_data = Transmogrifier.strip_internal_fields(object.data)
+ refute Map.has_key?(object_data, "reactions")
+ refute Map.has_key?(object_data, "reaction_count")
+ end
+
test "it works for incoming update activities" do
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
@@ -777,7 +866,10 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|> Poison.decode!()
|> Map.put("actor", ap_id)
- assert :error == Transmogrifier.handle_incoming(data)
+ assert capture_log(fn ->
+ assert :error == Transmogrifier.handle_incoming(data)
+ end) =~ "Object containment failed"
+
assert User.get_cached_by_ap_id(ap_id)
end
@@ -835,6 +927,25 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
end
+ test "it works for incoming follows to locked account" do
+ pending_follower = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
+ user = insert(:user, locked: true)
+
+ data =
+ File.read!("test/fixtures/mastodon-follow-activity.json")
+ |> Poison.decode!()
+ |> Map.put("object", user.ap_id)
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["type"] == "Follow"
+ assert data["object"] == user.ap_id
+ assert data["state"] == "pending"
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+
+ assert [^pending_follower] = User.get_follow_requests(user)
+ end
+
test "it works for incoming blocks" do
user = insert(:user)
@@ -1121,10 +1232,18 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
object = Object.normalize(activity)
+ note_obj = %{
+ "type" => "Note",
+ "id" => activity.data["id"],
+ "content" => "test post",
+ "published" => object.data["published"],
+ "actor" => AccountView.render("show.json", %{user: user})
+ }
+
message = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"cc" => [user.ap_id],
- "object" => [user.ap_id, object.data["id"]],
+ "object" => [user.ap_id, activity.data["id"]],
"type" => "Flag",
"content" => "blocked AND reported!!!",
"actor" => other_user.ap_id
@@ -1132,7 +1251,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
- assert activity.data["object"] == [user.ap_id, object.data["id"]]
+ assert activity.data["object"] == [user.ap_id, note_obj]
assert activity.data["content"] == "blocked AND reported!!!"
assert activity.data["actor"] == other_user.ap_id
assert activity.data["cc"] == [user.ap_id]
@@ -1464,7 +1583,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"type" => "Announce"
}
- :error = Transmogrifier.handle_incoming(data)
+ assert capture_log(fn ->
+ :error = Transmogrifier.handle_incoming(data)
+ end) =~ "Object containment failed"
end
test "it rejects activities which reference objects that have an incorrect attribution (variant 1)" do
@@ -1477,7 +1598,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"type" => "Announce"
}
- :error = Transmogrifier.handle_incoming(data)
+ assert capture_log(fn ->
+ :error = Transmogrifier.handle_incoming(data)
+ end) =~ "Object containment failed"
end
test "it rejects activities which reference objects that have an incorrect attribution (variant 2)" do
@@ -1490,7 +1613,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"type" => "Announce"
}
- :error = Transmogrifier.handle_incoming(data)
+ assert capture_log(fn ->
+ :error = Transmogrifier.handle_incoming(data)
+ end) =~ "Object containment failed"
end
end
@@ -1793,7 +1918,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
describe "get_obj_helper/2" do
test "returns nil when cannot normalize object" do
- refute Transmogrifier.get_obj_helper("test-obj-id")
+ assert capture_log(fn ->
+ refute Transmogrifier.get_obj_helper("test-obj-id")
+ end) =~ "Unsupported URI scheme"
end
test "returns {:ok, %Object{}} for success case" do
diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs
index c1b000fac..586eb1d2f 100644
--- a/test/web/activity_pub/utils_test.exs
+++ b/test/web/activity_pub/utils_test.exs
@@ -10,6 +10,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Utils
+ alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
@@ -581,11 +582,19 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
%{}
)
+ note_obj = %{
+ "type" => "Note",
+ "id" => activity_ap_id,
+ "content" => content,
+ "published" => activity.object.data["published"],
+ "actor" => AccountView.render("show.json", %{user: target_account})
+ }
+
assert %{
"type" => "Flag",
"content" => ^content,
"context" => ^context,
- "object" => [^target_ap_id, ^activity_ap_id],
+ "object" => [^target_ap_id, ^note_obj],
"state" => "open"
} = res
end
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs
index 22c989892..bc9235309 100644
--- a/test/web/admin_api/admin_api_controller_test.exs
+++ b/test/web/admin_api/admin_api_controller_test.exs
@@ -13,6 +13,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
alias Pleroma.Tests.ObanHelpers
alias Pleroma.User
alias Pleroma.UserInviteToken
+ alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MediaProxy
import Pleroma.Factory
@@ -1044,6 +1045,32 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
]
}
end
+
+ test "it omits relay user", %{admin: admin} do
+ assert %User{} = Relay.get_actor()
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> get("/api/pleroma/admin/users")
+
+ assert json_response(conn, 200) == %{
+ "count" => 1,
+ "page_size" => 50,
+ "users" => [
+ %{
+ "deactivated" => admin.deactivated,
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "roles" => %{"admin" => true, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(admin.name || admin.nickname)
+ }
+ ]
+ }
+ end
end
test "PATCH /api/pleroma/admin/users/activate" do
@@ -2242,6 +2269,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
Pleroma.Config.put([:instance, :dynamic_configuration], true)
end
+ clear_config([:feed, :post_title]) do
+ Pleroma.Config.put([:feed, :post_title], %{max_length: 100, omission: "…"})
+ end
+
test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
@@ -2538,7 +2569,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
conn =
build_conn()
|> assign(:user, admin)
- |> patch("/api/pleroma/admin/users/#{user.nickname}/force_password_reset")
+ |> patch("/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
assert json_response(conn, 204) == ""
diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs
index 1d2f20617..09a3e8dcf 100644
--- a/test/web/common_api/common_api_test.exs
+++ b/test/web/common_api/common_api_test.exs
@@ -10,6 +10,7 @@ defmodule Pleroma.Web.CommonAPITest do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Visibility
+ alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
@@ -140,7 +141,7 @@ defmodule Pleroma.Web.CommonAPITest do
object = Object.normalize(activity)
- assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
+ assert object.data["content"] == "<p><b>2hu</b></p>alert(&#39;xss&#39;)"
end
test "it filters out obviously bad tags when accepting a post as Markdown" do
@@ -156,7 +157,7 @@ defmodule Pleroma.Web.CommonAPITest do
object = Object.normalize(activity)
- assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
+ assert object.data["content"] == "<p><b>2hu</b></p>alert(&#39;xss&#39;)"
end
test "it does not allow replies to direct messages that are not direct messages themselves" do
@@ -226,6 +227,33 @@ defmodule Pleroma.Web.CommonAPITest do
end
describe "reactions" do
+ test "reacting to a status with an emoji" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+
+ {:ok, reaction, _} = CommonAPI.react_with_emoji(activity.id, user, "👍")
+
+ assert reaction.data["actor"] == user.ap_id
+ assert reaction.data["content"] == "👍"
+
+ # TODO: test error case.
+ end
+
+ test "unreacting to a status with an emoji" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+ {:ok, reaction, _} = CommonAPI.react_with_emoji(activity.id, user, "👍")
+
+ {:ok, unreaction, _} = CommonAPI.unreact_with_emoji(activity.id, user, "👍")
+
+ assert unreaction.data["type"] == "Undo"
+ assert unreaction.data["object"] == reaction.data["id"]
+ end
+
test "repeating a status" do
user = insert(:user)
other_user = insert(:user)
@@ -385,6 +413,14 @@ defmodule Pleroma.Web.CommonAPITest do
"status_ids" => [activity.id]
}
+ note_obj = %{
+ "type" => "Note",
+ "id" => activity_ap_id,
+ "content" => "foobar",
+ "published" => activity.object.data["published"],
+ "actor" => AccountView.render("show.json", %{user: target_user})
+ }
+
assert {:ok, flag_activity} = CommonAPI.report(reporter, report_data)
assert %Activity{
@@ -392,7 +428,7 @@ defmodule Pleroma.Web.CommonAPITest do
data: %{
"type" => "Flag",
"content" => ^comment,
- "object" => [^target_ap_id, ^activity_ap_id],
+ "object" => [^target_ap_id, ^note_obj],
"state" => "open"
}
} = flag_activity
@@ -412,6 +448,11 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
assert report.data["state"] == "resolved"
+
+ [reported_user, activity_id] = report.data["object"]
+
+ assert reported_user == target_user.ap_id
+ assert activity_id == activity.data["id"]
end
test "does not update report state when state is unsupported" do
diff --git a/test/web/feed/feed_controller_test.exs b/test/web/feed/feed_controller_test.exs
index 1f44eae20..6f61acf43 100644
--- a/test/web/feed/feed_controller_test.exs
+++ b/test/web/feed/feed_controller_test.exs
@@ -6,16 +6,25 @@ defmodule Pleroma.Web.Feed.FeedControllerTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
+ import SweetXml
alias Pleroma.Object
alias Pleroma.User
+ clear_config([:feed])
+
test "gets a feed", %{conn: conn} do
+ Pleroma.Config.put(
+ [:feed, :post_title],
+ %{max_length: 10, omission: "..."}
+ )
+
activity = insert(:note_activity)
note =
insert(:note,
data: %{
+ "content" => "This is :moominmamma: note ",
"attachment" => [
%{
"url" => [%{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}]
@@ -26,15 +35,30 @@ defmodule Pleroma.Web.Feed.FeedControllerTest do
)
note_activity = insert(:note_activity, note: note)
- object = Object.normalize(note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
- conn =
+ note2 =
+ insert(:note,
+ user: user,
+ data: %{"content" => "42 This is :moominmamma: note ", "inReplyTo" => activity.data["id"]}
+ )
+
+ _note_activity2 = insert(:note_activity, note: note2)
+ object = Object.normalize(note_activity)
+
+ resp =
conn
|> put_req_header("content-type", "application/atom+xml")
|> get("/users/#{user.nickname}/feed.atom")
+ |> response(200)
+
+ activity_titles =
+ resp
+ |> SweetXml.parse()
+ |> SweetXml.xpath(~x"//entry/title/text()"l)
- assert response(conn, 200) =~ object.data["content"]
+ assert activity_titles == ['42 This...', 'This is...']
+ assert resp =~ object.data["content"]
end
test "returns 404 for a missing feed", %{conn: conn} do
diff --git a/test/web/mastodon_api/controllers/conversation_controller_test.exs b/test/web/mastodon_api/controllers/conversation_controller_test.exs
index 542af4944..2a1223b18 100644
--- a/test/web/mastodon_api/controllers/conversation_controller_test.exs
+++ b/test/web/mastodon_api/controllers/conversation_controller_test.exs
@@ -59,6 +59,59 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0
end
+ test "filters conversations by recipients", %{conn: conn} do
+ user_one = insert(:user)
+ user_two = insert(:user)
+ user_three = insert(:user)
+
+ {:ok, direct1} =
+ CommonAPI.post(user_one, %{
+ "status" => "Hi @#{user_two.nickname}!",
+ "visibility" => "direct"
+ })
+
+ {:ok, _direct2} =
+ CommonAPI.post(user_one, %{
+ "status" => "Hi @#{user_three.nickname}!",
+ "visibility" => "direct"
+ })
+
+ {:ok, direct3} =
+ CommonAPI.post(user_one, %{
+ "status" => "Hi @#{user_two.nickname}, @#{user_three.nickname}!",
+ "visibility" => "direct"
+ })
+
+ {:ok, _direct4} =
+ CommonAPI.post(user_two, %{
+ "status" => "Hi @#{user_three.nickname}!",
+ "visibility" => "direct"
+ })
+
+ {:ok, direct5} =
+ CommonAPI.post(user_two, %{
+ "status" => "Hi @#{user_one.nickname}!",
+ "visibility" => "direct"
+ })
+
+ [conversation1, conversation2] =
+ conn
+ |> assign(:user, user_one)
+ |> get("/api/v1/conversations", %{"recipients" => [user_two.id]})
+ |> json_response(200)
+
+ assert conversation1["last_status"]["id"] == direct5.id
+ assert conversation2["last_status"]["id"] == direct1.id
+
+ [conversation1] =
+ conn
+ |> assign(:user, user_one)
+ |> get("/api/v1/conversations", %{"recipients" => [user_two.id, user_three.id]})
+ |> json_response(200)
+
+ assert conversation1["last_status"]["id"] == direct3.id
+ end
+
test "updates the last_status on reply", %{conn: conn} do
user_one = insert(:user)
user_two = insert(:user)
diff --git a/test/web/mastodon_api/views/conversation_view_test.exs b/test/web/mastodon_api/views/conversation_view_test.exs
index a2a880705..6ed22597d 100644
--- a/test/web/mastodon_api/views/conversation_view_test.exs
+++ b/test/web/mastodon_api/views/conversation_view_test.exs
@@ -30,5 +30,6 @@ defmodule Pleroma.Web.MastodonAPI.ConversationViewTest do
assert [account] = conversation.accounts
assert account.id == other_user.id
+ assert conversation.last_status.pleroma.direct_conversation_id == participation.id
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 c200ad8fe..d46ecc646 100644
--- a/test/web/mastodon_api/views/status_view_test.exs
+++ b/test/web/mastodon_api/views/status_view_test.exs
@@ -7,6 +7,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
alias Pleroma.Activity
alias Pleroma.Bookmark
+ alias Pleroma.Conversation.Participation
+ alias Pleroma.HTML
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
@@ -22,10 +24,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
:ok
end
- test "returns the direct conversation id when given the `with_conversation_id` option" do
+ test "loads and returns the direct conversation id when given the `with_direct_conversation_id` option" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
+ [participation] = Participation.for_user(user)
status =
StatusView.render("show.json",
@@ -34,7 +37,26 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
for: user
)
- assert status[:pleroma][:direct_conversation_id]
+ assert status[:pleroma][:direct_conversation_id] == participation.id
+
+ status = StatusView.render("show.json", activity: activity, for: user)
+ assert status[:pleroma][:direct_conversation_id] == nil
+ end
+
+ test "returns the direct conversation id when given the `direct_conversation_id` option" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
+ [participation] = Participation.for_user(user)
+
+ status =
+ StatusView.render("show.json",
+ activity: activity,
+ direct_conversation_id: participation.id,
+ for: user
+ )
+
+ assert status[:pleroma][:direct_conversation_id] == participation.id
end
test "returns a temporary ap_id based user for activities missing db users" do
@@ -107,7 +129,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
in_reply_to_account_id: nil,
card: nil,
reblog: nil,
- content: HtmlSanitizeEx.basic_html(object_data["content"]),
+ content: HTML.filter_tags(object_data["content"]),
created_at: created_at,
reblogs_count: 0,
replies_count: 0,
@@ -119,7 +141,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
pinned: false,
sensitive: false,
poll: nil,
- spoiler_text: HtmlSanitizeEx.basic_html(object_data["summary"]),
+ spoiler_text: HTML.filter_tags(object_data["summary"]),
visibility: "public",
media_attachments: [],
mentions: [],
@@ -146,8 +168,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
local: true,
conversation_id: convo_id,
in_reply_to_account_acct: nil,
- content: %{"text/plain" => HtmlSanitizeEx.strip_tags(object_data["content"])},
- spoiler_text: %{"text/plain" => HtmlSanitizeEx.strip_tags(object_data["summary"])},
+ content: %{"text/plain" => HTML.strip_tags(object_data["content"])},
+ spoiler_text: %{"text/plain" => HTML.strip_tags(object_data["summary"])},
expires_at: nil,
direct_conversation_id: nil,
thread_muted: false
diff --git a/test/web/node_info_test.exs b/test/web/node_info_test.exs
index a3281b25b..6cc876602 100644
--- a/test/web/node_info_test.exs
+++ b/test/web/node_info_test.exs
@@ -84,6 +84,30 @@ defmodule Pleroma.Web.NodeInfoTest do
Pleroma.Config.put([:instance, :safe_dm_mentions], option)
end
+ test "it shows if federation is enabled/disabled", %{conn: conn} do
+ original = Pleroma.Config.get([:instance, :federating])
+
+ Pleroma.Config.put([:instance, :federating], true)
+
+ response =
+ conn
+ |> get("/nodeinfo/2.1.json")
+ |> json_response(:ok)
+
+ assert response["metadata"]["federation"]["enabled"] == true
+
+ Pleroma.Config.put([:instance, :federating], false)
+
+ response =
+ conn
+ |> get("/nodeinfo/2.1.json")
+ |> json_response(:ok)
+
+ assert response["metadata"]["federation"]["enabled"] == false
+
+ Pleroma.Config.put([:instance, :federating], original)
+ 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])
diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs
index ad8d79083..beb995cd8 100644
--- a/test/web/oauth/oauth_controller_test.exs
+++ b/test/web/oauth/oauth_controller_test.exs
@@ -469,6 +469,29 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
assert html_response(conn, 200) =~ ~s(type="submit")
end
+ test "renders authentication page if user is already authenticated but user request with another client",
+ %{
+ app: app,
+ conn: conn
+ } do
+ token = insert(:oauth_token, app_id: app.id)
+
+ conn =
+ conn
+ |> put_session(:oauth_token, token.token)
+ |> get(
+ "/oauth/authorize",
+ %{
+ "response_type" => "code",
+ "client_id" => "another_client_id",
+ "redirect_uri" => OAuthController.default_redirect_uri(app),
+ "scope" => "read"
+ }
+ )
+
+ assert html_response(conn, 200) =~ ~s(type="submit")
+ end
+
test "with existing authentication and non-OOB `redirect_uri`, redirects to app with `token` and `state` params",
%{
app: app,
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 0c83edb56..b1b59beed 100644
--- a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
+++ b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
@@ -7,12 +7,72 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do
alias Pleroma.Conversation.Participation
alias Pleroma.Notification
+ alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
+ test "POST /api/v1/pleroma/statuses/:id/react_with_emoji", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
+
+ result =
+ conn
+ |> assign(:user, other_user)
+ |> post("/api/v1/pleroma/statuses/#{activity.id}/react_with_emoji", %{"emoji" => "☕"})
+
+ assert %{"id" => id} = json_response(result, 200)
+ assert to_string(activity.id) == id
+ end
+
+ test "POST /api/v1/pleroma/statuses/:id/unreact_with_emoji", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
+ {:ok, activity, _object} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
+
+ result =
+ conn
+ |> assign(:user, other_user)
+ |> post("/api/v1/pleroma/statuses/#{activity.id}/unreact_with_emoji", %{"emoji" => "☕"})
+
+ assert %{"id" => id} = json_response(result, 200)
+ assert to_string(activity.id) == id
+
+ object = Object.normalize(activity)
+
+ assert object.data["reaction_count"] == 0
+ end
+
+ test "GET /api/v1/pleroma/statuses/:id/emoji_reactions_by", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/statuses/#{activity.id}/emoji_reactions_by")
+ |> json_response(200)
+
+ assert result == %{}
+
+ {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/statuses/#{activity.id}/emoji_reactions_by")
+ |> json_response(200)
+
+ [represented_user] = result["🎅"]
+ assert represented_user["id"] == other_user.id
+ end
+
test "/api/v1/pleroma/conversations/:id", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)
diff --git a/test/web/rel_me_test.exs b/test/web/rel_me_test.exs
index 2251fed16..77b5d5dc6 100644
--- a/test/web/rel_me_test.exs
+++ b/test/web/rel_me_test.exs
@@ -14,7 +14,9 @@ defmodule Pleroma.Web.RelMeTest do
hrefs = ["https://social.example.org/users/lain"]
assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/null") == {:ok, []}
- assert {:error, _} = Pleroma.Web.RelMe.parse("http://example.com/rel_me/error")
+
+ assert {:ok, %Tesla.Env{status: 404}} =
+ Pleroma.Web.RelMe.parse("http://example.com/rel_me/error")
assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/link") == {:ok, hrefs}
assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/anchor") == {:ok, hrefs}
diff --git a/test/web/static_fe/static_fe_controller_test.exs b/test/web/static_fe/static_fe_controller_test.exs
new file mode 100644
index 000000000..2ce8f9fa3
--- /dev/null
+++ b/test/web/static_fe/static_fe_controller_test.exs
@@ -0,0 +1,210 @@
+defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
+ use Pleroma.Web.ConnCase
+ alias Pleroma.Activity
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ clear_config_all([:static_fe, :enabled]) do
+ Pleroma.Config.put([:static_fe, :enabled], true)
+ end
+
+ describe "user profile page" do
+ test "just the profile as HTML", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/users/#{user.nickname}")
+
+ assert html_response(conn, 200) =~ user.nickname
+ end
+
+ test "renders json unless there's an html accept header", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> get("/users/#{user.nickname}")
+
+ assert json_response(conn, 200)
+ end
+
+ test "404 when user not found", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/users/limpopo")
+
+ assert html_response(conn, 404) =~ "not found"
+ end
+
+ test "profile does not include private messages", %{conn: conn} do
+ user = insert(:user)
+ CommonAPI.post(user, %{"status" => "public"})
+ CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/users/#{user.nickname}")
+
+ html = html_response(conn, 200)
+
+ assert html =~ ">public<"
+ refute html =~ ">private<"
+ end
+
+ test "pagination", %{conn: conn} do
+ user = insert(:user)
+ Enum.map(1..30, fn i -> CommonAPI.post(user, %{"status" => "test#{i}"}) end)
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/users/#{user.nickname}")
+
+ html = html_response(conn, 200)
+
+ assert html =~ ">test30<"
+ assert html =~ ">test11<"
+ refute html =~ ">test10<"
+ refute html =~ ">test1<"
+ end
+
+ test "pagination, page 2", %{conn: conn} do
+ user = insert(:user)
+ activities = Enum.map(1..30, fn i -> CommonAPI.post(user, %{"status" => "test#{i}"}) end)
+ {:ok, a11} = Enum.at(activities, 11)
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/users/#{user.nickname}?max_id=#{a11.id}")
+
+ html = html_response(conn, 200)
+
+ assert html =~ ">test1<"
+ assert html =~ ">test10<"
+ refute html =~ ">test20<"
+ refute html =~ ">test29<"
+ end
+ end
+
+ describe "notice rendering" do
+ test "single notice page", %{conn: conn} do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "testing a thing!"})
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/notice/#{activity.id}")
+
+ html = html_response(conn, 200)
+ assert html =~ "<header>"
+ assert html =~ user.nickname
+ assert html =~ "testing a thing!"
+ end
+
+ test "shows the whole thread", %{conn: conn} do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "space: the final frontier"})
+
+ CommonAPI.post(user, %{
+ "status" => "these are the voyages or something",
+ "in_reply_to_status_id" => activity.id
+ })
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/notice/#{activity.id}")
+
+ html = html_response(conn, 200)
+ assert html =~ "the final frontier"
+ assert html =~ "voyages"
+ end
+
+ test "redirect by AP object ID", %{conn: conn} do
+ user = insert(:user)
+
+ {:ok, %Activity{data: %{"object" => object_url}}} =
+ CommonAPI.post(user, %{"status" => "beam me up"})
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get(URI.parse(object_url).path)
+
+ assert html_response(conn, 302) =~ "redirected"
+ end
+
+ test "redirect by activity ID", %{conn: conn} do
+ user = insert(:user)
+
+ {:ok, %Activity{data: %{"id" => id}}} =
+ CommonAPI.post(user, %{"status" => "I'm a doctor, not a devops!"})
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get(URI.parse(id).path)
+
+ assert html_response(conn, 302) =~ "redirected"
+ end
+
+ test "404 when notice not found", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/notice/88c9c317")
+
+ assert html_response(conn, 404) =~ "not found"
+ end
+
+ test "404 for private status", %{conn: conn} do
+ user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{"status" => "don't show me!", "visibility" => "private"})
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/notice/#{activity.id}")
+
+ assert html_response(conn, 404) =~ "not found"
+ end
+
+ test "302 for remote cached status", %{conn: conn} do
+ user = insert(:user)
+
+ message = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "to" => user.follower_address,
+ "cc" => "https://www.w3.org/ns/activitystreams#Public",
+ "type" => "Create",
+ "object" => %{
+ "content" => "blah blah blah",
+ "type" => "Note",
+ "attributedTo" => user.ap_id,
+ "inReplyTo" => nil
+ },
+ "actor" => user.ap_id
+ }
+
+ assert {:ok, activity} = Transmogrifier.handle_incoming(message)
+
+ conn =
+ conn
+ |> put_req_header("accept", "text/html")
+ |> get("/notice/#{activity.id}")
+
+ assert html_response(conn, 302) =~ "redirected"
+ end
+ end
+end
diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs
index cb1015171..80a7541b2 100644
--- a/test/web/streamer/streamer_test.exs
+++ b/test/web/streamer/streamer_test.exs
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.StreamerTest do
import Pleroma.Factory
+ alias Pleroma.Conversation.Participation
alias Pleroma.List
alias Pleroma.User
alias Pleroma.Web.CommonAPI
@@ -110,6 +111,24 @@ defmodule Pleroma.Web.StreamerTest do
Streamer.stream("user:notification", notif)
Task.await(task)
end
+
+ test "it sends follow activities to the 'user:notification' stream", %{
+ user: user
+ } do
+ user2 = insert(:user)
+ task = Task.async(fn -> assert_receive {:text, _}, 4_000 end)
+
+ Streamer.add_socket(
+ "user:notification",
+ %{transport_pid: task.pid, assigns: %{user: user}}
+ )
+
+ {:ok, _follower, _followed, _activity} = CommonAPI.follow(user2, user)
+
+ # We don't directly pipe the notification to the streamer as it's already
+ # generated as a side effect of CommonAPI.follow().
+ Task.await(task)
+ end
end
test "it sends to public" do
@@ -463,7 +482,14 @@ defmodule Pleroma.Web.StreamerTest do
task =
Task.async(fn ->
- assert_receive {:text, _received_event}, 4_000
+ assert_receive {:text, received_event}, 4_000
+
+ assert %{"event" => "conversation", "payload" => received_payload} =
+ Jason.decode!(received_event)
+
+ assert %{"last_status" => last_status} = Jason.decode!(received_payload)
+ [participation] = Participation.for_user(user)
+ assert last_status["pleroma"]["direct_conversation_id"] == participation.id
end)
Streamer.add_socket(
@@ -480,7 +506,7 @@ defmodule Pleroma.Web.StreamerTest do
Task.await(task)
end
- test "it doesn't send conversation update to the 'direct' streamj when the last message in the conversation is deleted" do
+ test "it doesn't send conversation update to the 'direct' stream when the last message in the conversation is deleted" do
user = insert(:user)
another_user = insert(:user)