summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-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/object/containment_test.exs24
-rw-r--r--test/object_test.exs16
-rw-r--r--test/plugs/admin_secret_authentication_plug_test.exs42
-rw-r--r--test/plugs/cache_control_test.exs2
-rw-r--r--test/plugs/rate_limiter_test.exs257
-rw-r--r--test/plugs/user_enabled_plug_test.exs17
-rw-r--r--test/user_test.exs12
-rw-r--r--test/web/activity_pub/activity_pub_test.exs114
-rw-r--r--test/web/activity_pub/mrf/object_age_policy_test.exs105
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs88
-rw-r--r--test/web/activity_pub/utils_test.exs43
-rw-r--r--test/web/admin_api/admin_api_controller_test.exs235
-rw-r--r--test/web/common_api/common_api_test.exs56
-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/controllers/filter_controller_test.exs2
-rw-r--r--test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs2
-rw-r--r--test/web/node_info_test.exs51
-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/static_fe/static_fe_controller_test.exs210
24 files changed, 1323 insertions, 171 deletions
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/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/admin_secret_authentication_plug_test.exs b/test/plugs/admin_secret_authentication_plug_test.exs
index c94a62c10..506b1f609 100644
--- a/test/plugs/admin_secret_authentication_plug_test.exs
+++ b/test/plugs/admin_secret_authentication_plug_test.exs
@@ -22,21 +22,39 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do
assert conn == ret_conn
end
- test "with secret set and given in the 'admin_token' parameter, it assigns an admin user", %{
- conn: conn
- } do
- Pleroma.Config.put(:admin_token, "password123")
+ describe "when secret set it assigns an admin user" do
+ test "with `admin_token` query parameter", %{conn: conn} do
+ Pleroma.Config.put(:admin_token, "password123")
- conn =
- %{conn | params: %{"admin_token" => "wrong_password"}}
- |> AdminSecretAuthenticationPlug.call(%{})
+ conn =
+ %{conn | params: %{"admin_token" => "wrong_password"}}
+ |> AdminSecretAuthenticationPlug.call(%{})
- refute conn.assigns[:user]
+ refute conn.assigns[:user]
- conn =
- %{conn | params: %{"admin_token" => "password123"}}
- |> AdminSecretAuthenticationPlug.call(%{})
+ conn =
+ %{conn | params: %{"admin_token" => "password123"}}
+ |> AdminSecretAuthenticationPlug.call(%{})
+
+ assert conn.assigns[:user].is_admin
+ end
+
+ test "with `x-admin-token` HTTP header", %{conn: conn} do
+ Pleroma.Config.put(:admin_token, "☕️")
+
+ conn =
+ conn
+ |> put_req_header("x-admin-token", "🥛")
+ |> AdminSecretAuthenticationPlug.call(%{})
+
+ refute conn.assigns[:user]
+
+ conn =
+ conn
+ |> put_req_header("x-admin-token", "☕️")
+ |> AdminSecretAuthenticationPlug.call(%{})
- assert conn.assigns[:user].is_admin
+ assert conn.assigns[:user].is_admin
+ end
end
end
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/plugs/user_enabled_plug_test.exs b/test/plugs/user_enabled_plug_test.exs
index 996a7d77b..a4035bf0e 100644
--- a/test/plugs/user_enabled_plug_test.exs
+++ b/test/plugs/user_enabled_plug_test.exs
@@ -16,6 +16,23 @@ defmodule Pleroma.Plugs.UserEnabledPlugTest do
assert ret_conn == conn
end
+ test "with a user that's not confirmed and a config requiring confirmation, it removes that user",
+ %{conn: conn} do
+ old = Pleroma.Config.get([:instance, :account_activation_required])
+ Pleroma.Config.put([:instance, :account_activation_required], true)
+
+ user = insert(:user, confirmation_pending: true)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> UserEnabledPlug.call(%{})
+
+ assert conn.assigns.user == nil
+
+ Pleroma.Config.put([:instance, :account_activation_required], old)
+ end
+
test "with a user that is deactivated, it removes that user", %{conn: conn} do
user = insert(:user, deactivated: true)
diff --git a/test/user_test.exs b/test/user_test.exs
index 485106b75..e6302b525 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -167,9 +167,10 @@ defmodule Pleroma.UserTest do
{:ok, user} = User.follow(user, followed)
user = User.get_cached_by_id(user.id)
-
followed = User.get_cached_by_ap_id(followed.ap_id)
+
assert followed.follower_count == 1
+ assert user.following_count == 1
assert User.ap_followers(followed) in User.following(user)
end
@@ -971,12 +972,14 @@ defmodule Pleroma.UserTest do
user2 = insert(:user)
{:ok, user2} = User.follow(user2, user)
+ assert user2.following_count == 1
assert User.following_count(user2) == 1
{:ok, _user} = User.deactivate(user)
info = User.get_cached_user_info(user2)
+ assert refresh_record(user2).following_count == 0
assert info.following_count == 0
assert User.following_count(user2) == 0
assert [] = User.get_friends(user2)
@@ -1214,6 +1217,13 @@ defmodule Pleroma.UserTest do
refute User.auth_active?(local_user)
assert User.auth_active?(confirmed_user)
assert User.auth_active?(remote_user)
+
+ # also shows unactive for deactivated users
+
+ deactivated_but_confirmed =
+ insert(:user, local: true, confirmation_pending: false, deactivated: true)
+
+ refute User.auth_active?(deactivated_but_confirmed)
end
describe "superuser?/1" do
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
index f29b8cc74..d437ad456 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -734,56 +734,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
@@ -814,6 +812,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)
diff --git a/test/web/activity_pub/mrf/object_age_policy_test.exs b/test/web/activity_pub/mrf/object_age_policy_test.exs
new file mode 100644
index 000000000..643609da4
--- /dev/null
+++ b/test/web/activity_pub/mrf/object_age_policy_test.exs
@@ -0,0 +1,105 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
+ use Pleroma.DataCase
+ alias Pleroma.Config
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy
+ alias Pleroma.Web.ActivityPub.Visibility
+
+ clear_config([:mrf_object_age]) do
+ Config.put(:mrf_object_age,
+ threshold: 172_800,
+ actions: [:delist, :strip_followers]
+ )
+ end
+
+ setup_all do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+ :ok
+ end
+
+ describe "with reject action" do
+ test "it rejects an old post" do
+ Config.put([:mrf_object_age, :actions], [:reject])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+
+ {:reject, _} = ObjectAgePolicy.filter(data)
+ end
+
+ test "it allows a new post" do
+ Config.put([:mrf_object_age, :actions], [:reject])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+ |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+
+ {:ok, _} = ObjectAgePolicy.filter(data)
+ end
+ end
+
+ describe "with delist action" do
+ test "it delists an old post" do
+ Config.put([:mrf_object_age, :actions], [:delist])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+
+ {:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
+
+ {:ok, data} = ObjectAgePolicy.filter(data)
+
+ assert Visibility.get_visibility(%{data: data}) == "unlisted"
+ end
+
+ test "it allows a new post" do
+ Config.put([:mrf_object_age, :actions], [:delist])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+ |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+
+ {:ok, _user} = User.get_or_fetch_by_ap_id(data["actor"])
+
+ {:ok, ^data} = ObjectAgePolicy.filter(data)
+ end
+ end
+
+ describe "with strip_followers action" do
+ test "it strips followers collections from an old post" do
+ Config.put([:mrf_object_age, :actions], [:strip_followers])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+
+ {:ok, user} = User.get_or_fetch_by_ap_id(data["actor"])
+
+ {:ok, data} = ObjectAgePolicy.filter(data)
+
+ refute user.follower_address in data["to"]
+ refute user.follower_address in data["cc"]
+ end
+
+ test "it allows a new post" do
+ Config.put([:mrf_object_age, :actions], [:strip_followers])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+ |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+
+ {:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
+
+ {:ok, ^data} = ObjectAgePolicy.filter(data)
+ end
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index 4645eb39d..0bdd514e9 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -339,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"})
@@ -553,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!()
diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs
index 586eb1d2f..1feb076ba 100644
--- a/test/web/activity_pub/utils_test.exs
+++ b/test/web/activity_pub/utils_test.exs
@@ -636,4 +636,47 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
assert updated_object.data["announcement_count"] == 1
end
end
+
+ describe "get_reports_grouped_by_status/1" do
+ setup do
+ [reporter, target_user] = insert_pair(:user)
+ first_status = insert(:note_activity, user: target_user)
+ second_status = insert(:note_activity, user: target_user)
+
+ CommonAPI.report(reporter, %{
+ "account_id" => target_user.id,
+ "comment" => "I feel offended",
+ "status_ids" => [first_status.id]
+ })
+
+ CommonAPI.report(reporter, %{
+ "account_id" => target_user.id,
+ "comment" => "I feel offended2",
+ "status_ids" => [second_status.id]
+ })
+
+ data = [%{activity: first_status.data["id"]}, %{activity: second_status.data["id"]}]
+
+ {:ok,
+ %{
+ first_status: first_status,
+ second_status: second_status,
+ data: data
+ }}
+ end
+
+ test "works for deprecated reports format", %{
+ first_status: first_status,
+ second_status: second_status,
+ data: data
+ } do
+ groups = Utils.get_reports_grouped_by_status(data).groups
+
+ first_group = Enum.find(groups, &(&1.status.id == first_status.data["id"]))
+ second_group = Enum.find(groups, &(&1.status.id == second_status.data["id"]))
+
+ assert first_group.status.id == first_status.data["id"]
+ assert second_group.status.id == second_status.data["id"]
+ end
+ end
end
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs
index 045c87e95..3a4c4d65c 100644
--- a/test/web/admin_api/admin_api_controller_test.exs
+++ b/test/web/admin_api/admin_api_controller_test.exs
@@ -1312,7 +1312,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
end
end
- describe "PUT /api/pleroma/admin/reports/:id" do
+ describe "PATCH /api/pleroma/admin/reports" do
setup %{conn: conn} do
admin = insert(:user, is_admin: true)
[reporter, target_user] = insert_pair(:user)
@@ -1325,16 +1325,32 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"status_ids" => [activity.id]
})
- %{conn: assign(conn, :user, admin), id: report_id, admin: admin}
+ {:ok, %{id: second_report_id}} =
+ CommonAPI.report(reporter, %{
+ "account_id" => target_user.id,
+ "comment" => "I feel very offended",
+ "status_ids" => [activity.id]
+ })
+
+ %{
+ conn: assign(conn, :user, admin),
+ id: report_id,
+ admin: admin,
+ second_report_id: second_report_id
+ }
end
test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
- response =
- conn
- |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "resolved"})
- |> json_response(:ok)
+ conn
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [
+ %{"state" => "resolved", "id" => id}
+ ]
+ })
+ |> json_response(:no_content)
- assert response["state"] == "resolved"
+ activity = Activity.get_by_id(id)
+ assert activity.data["state"] == "resolved"
log_entry = Repo.one(ModerationLog)
@@ -1343,12 +1359,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
end
test "closes report", %{conn: conn, id: id, admin: admin} do
- response =
- conn
- |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "closed"})
- |> json_response(:ok)
+ conn
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [
+ %{"state" => "closed", "id" => id}
+ ]
+ })
+ |> json_response(:no_content)
- assert response["state"] == "closed"
+ activity = Activity.get_by_id(id)
+ assert activity.data["state"] == "closed"
log_entry = Repo.one(ModerationLog)
@@ -1359,17 +1379,54 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
test "returns 400 when state is unknown", %{conn: conn, id: id} do
conn =
conn
- |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "test"})
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [
+ %{"state" => "test", "id" => id}
+ ]
+ })
- assert json_response(conn, :bad_request) == "Unsupported state"
+ assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"
end
test "returns 404 when report is not exist", %{conn: conn} do
conn =
conn
- |> put("/api/pleroma/admin/reports/test", %{"state" => "closed"})
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [
+ %{"state" => "closed", "id" => "test"}
+ ]
+ })
- assert json_response(conn, :not_found) == "Not found"
+ assert hd(json_response(conn, :bad_request))["error"] == "not_found"
+ end
+
+ test "updates state of multiple reports", %{
+ conn: conn,
+ id: id,
+ admin: admin,
+ second_report_id: second_report_id
+ } do
+ conn
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [
+ %{"state" => "resolved", "id" => id},
+ %{"state" => "closed", "id" => second_report_id}
+ ]
+ })
+ |> json_response(:no_content)
+
+ activity = Activity.get_by_id(id)
+ second_activity = Activity.get_by_id(second_report_id)
+ assert activity.data["state"] == "resolved"
+ assert second_activity.data["state"] == "closed"
+
+ [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(first_log_entry) ==
+ "@#{admin.nickname} updated report ##{id} with 'resolved' state"
+
+ assert ModerationLog.get_log_entry_message(second_log_entry) ==
+ "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
end
end
@@ -1492,7 +1549,145 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
end
end
- #
+ describe "GET /api/pleroma/admin/grouped_reports" do
+ setup %{conn: conn} do
+ admin = insert(:user, is_admin: true)
+ [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]
+ })
+
+ %{
+ conn: assign(conn, :user, admin),
+ 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_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.data["id"]))
+
+ second_group =
+ Enum.find(response["reports"], &(&1["status"]["id"] == second_status.data["id"]))
+
+ third_group =
+ Enum.find(response["reports"], &(&1["status"]["id"] == third_status.data["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"] == %{
+ "id" => first_status.data["id"],
+ "content" => first_status.object.data["content"],
+ "published" => first_status.object.data["published"]
+ }
+
+ 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"] == %{
+ "id" => second_status.data["id"],
+ "content" => second_status.object.data["content"],
+ "published" => second_status.object.data["published"]
+ }
+
+ 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"] == %{
+ "id" => third_status.data["id"],
+ "content" => third_status.object.data["content"],
+ "published" => third_status.object.data["published"]
+ }
+
+ 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
+ end
+
describe "POST /api/pleroma/admin/reports/:id/respond" do
setup %{conn: conn} do
admin = insert(:user, is_admin: true)
@@ -2269,6 +2464,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")
@@ -2565,7 +2764,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 8e6fbd7f0..138488d44 100644
--- a/test/web/common_api/common_api_test.exs
+++ b/test/web/common_api/common_api_test.exs
@@ -227,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)
@@ -441,6 +468,35 @@ defmodule Pleroma.Web.CommonAPITest do
assert CommonAPI.update_report_state(report_id, "test") == {:error, "Unsupported state"}
end
+
+ test "updates state of multiple reports" do
+ [reporter, target_user] = insert_pair(:user)
+ activity = insert(:note_activity, user: target_user)
+
+ {:ok, %Activity{id: first_report_id}} =
+ CommonAPI.report(reporter, %{
+ "account_id" => target_user.id,
+ "comment" => "I feel offended",
+ "status_ids" => [activity.id]
+ })
+
+ {:ok, %Activity{id: second_report_id}} =
+ CommonAPI.report(reporter, %{
+ "account_id" => target_user.id,
+ "comment" => "I feel very offended!",
+ "status_ids" => [activity.id]
+ })
+
+ {:ok, report_ids} =
+ CommonAPI.update_report_state([first_report_id, second_report_id], "resolved")
+
+ first_report = Activity.get_by_id(first_report_id)
+ second_report = Activity.get_by_id(second_report_id)
+
+ assert report_ids -- [first_report_id, second_report_id] == []
+ assert first_report.data["state"] == "resolved"
+ assert second_report.data["state"] == "resolved"
+ end
end
describe "reblog muting" 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/controllers/filter_controller_test.exs b/test/web/mastodon_api/controllers/filter_controller_test.exs
index 5d5b56c8e..550689788 100644
--- a/test/web/mastodon_api/controllers/filter_controller_test.exs
+++ b/test/web/mastodon_api/controllers/filter_controller_test.exs
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
- use Pleroma.Web.ConnCase, async: true
+ use Pleroma.Web.ConnCase
alias Pleroma.Web.MastodonAPI.FilterView
diff --git a/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs b/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs
index 9ad6a4fa7..ae5fee2bc 100644
--- a/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs
+++ b/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do
- use Pleroma.Web.ConnCase, async: true
+ use Pleroma.Web.ConnCase
alias Pleroma.Repo
alias Pleroma.ScheduledActivity
diff --git a/test/web/node_info_test.exs b/test/web/node_info_test.exs
index a3281b25b..9a574a38d 100644
--- a/test/web/node_info_test.exs
+++ b/test/web/node_info_test.exs
@@ -61,6 +61,33 @@ defmodule Pleroma.Web.NodeInfoTest do
assert Pleroma.Application.repository() == result["software"]["repository"]
end
+ test "returns fieldsLimits field", %{conn: conn} do
+ max_account_fields = Pleroma.Config.get([:instance, :max_account_fields])
+ max_remote_account_fields = Pleroma.Config.get([:instance, :max_remote_account_fields])
+ account_field_name_length = Pleroma.Config.get([:instance, :account_field_name_length])
+ account_field_value_length = Pleroma.Config.get([:instance, :account_field_value_length])
+
+ 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)
+
+ response =
+ conn
+ |> get("/nodeinfo/2.1.json")
+ |> json_response(:ok)
+
+ assert response["metadata"]["fieldsLimits"]["maxFields"] == 10
+ assert response["metadata"]["fieldsLimits"]["maxRemoteFields"] == 15
+ assert response["metadata"]["fieldsLimits"]["nameLength"] == 255
+ assert response["metadata"]["fieldsLimits"]["valueLength"] == 2048
+
+ Pleroma.Config.put([:instance, :max_account_fields], max_account_fields)
+ Pleroma.Config.put([:instance, :max_remote_account_fields], max_remote_account_fields)
+ Pleroma.Config.put([:instance, :account_field_name_length], account_field_name_length)
+ Pleroma.Config.put([:instance, :account_field_value_length], account_field_value_length)
+ 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)
@@ -84,6 +111,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/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