aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/fixtures/mastodon-undo-like-compact-object.json29
-rw-r--r--test/list_test.exs4
-rw-r--r--test/notification_test.exs12
-rw-r--r--test/reverse_proxy_test.exs58
-rw-r--r--test/support/factory.ex41
-rw-r--r--test/web/activity_pub/activity_pub_controller_test.exs40
-rw-r--r--test/web/activity_pub/activity_pub_test.exs69
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs68
-rw-r--r--test/web/admin_api/views/report_view_test.exs8
-rw-r--r--test/web/common_api/common_api_test.exs51
-rw-r--r--test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs (renamed from test/web/mastodon_api/controllers/mastodon_api_controller/update_credentials_test.exs)0
-rw-r--r--test/web/mastodon_api/controllers/account_controller_test.exs852
-rw-r--r--test/web/mastodon_api/controllers/app_controller_test.exs60
-rw-r--r--test/web/mastodon_api/controllers/auth_controller_test.exs121
-rw-r--r--test/web/mastodon_api/controllers/conversation_controller_test.exs75
-rw-r--r--test/web/mastodon_api/controllers/domain_block_controller_test.exs2
-rw-r--r--test/web/mastodon_api/controllers/media_controller_test.exs92
-rw-r--r--test/web/mastodon_api/controllers/poll_controller_test.exs184
-rw-r--r--test/web/mastodon_api/controllers/report_controller_test.exs88
-rw-r--r--test/web/mastodon_api/controllers/status_controller_test.exs35
-rw-r--r--test/web/mastodon_api/controllers/suggestion_controller_test.exs92
-rw-r--r--test/web/mastodon_api/mastodon_api_controller_test.exs1896
-rw-r--r--test/web/mastodon_api/mastodon_api_test.exs4
-rw-r--r--test/web/mastodon_api/views/account_view_test.exs99
-rw-r--r--test/web/mastodon_api/views/notification_view_test.exs8
-rw-r--r--test/web/mastodon_api/views/poll_view_test.exs126
-rw-r--r--test/web/mastodon_api/views/status_view_test.exs121
-rw-r--r--test/web/ostatus/ostatus_controller_test.exs6
-rw-r--r--test/web/pleroma_api/controllers/account_controller_test.exs395
-rw-r--r--test/web/pleroma_api/controllers/emoji_api_controller_test.exs (renamed from test/web/pleroma_api/emoji_api_controller_test.exs)4
-rw-r--r--test/web/pleroma_api/controllers/mascot_controller_test.exs77
-rw-r--r--test/web/pleroma_api/controllers/scrobble_controller_test.exs63
-rw-r--r--test/web/pleroma_api/controllers/subscription_notification_controller_test.exs234
-rw-r--r--test/web/twitter_api/twitter_api_test.exs28
34 files changed, 2751 insertions, 2291 deletions
diff --git a/test/fixtures/mastodon-undo-like-compact-object.json b/test/fixtures/mastodon-undo-like-compact-object.json
new file mode 100644
index 000000000..ae66a0d19
--- /dev/null
+++ b/test/fixtures/mastodon-undo-like-compact-object.json
@@ -0,0 +1,29 @@
+{
+ "type": "Undo",
+ "signature": {
+ "type": "RsaSignature2017",
+ "signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==",
+ "creator": "http://mastodon.example.org/users/admin#main-key",
+ "created": "2018-05-19T16:36:58Z"
+ },
+ "object": "http://mastodon.example.org/users/admin#likes/2",
+ "nickname": "lain",
+ "id": "http://mastodon.example.org/users/admin#likes/2/undo",
+ "actor": "http://mastodon.example.org/users/admin",
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ {
+ "toot": "http://joinmastodon.org/ns#",
+ "sensitive": "as:sensitive",
+ "ostatus": "http://ostatus.org#",
+ "movedTo": "as:movedTo",
+ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
+ "conversation": "ostatus:conversation",
+ "atomUri": "ostatus:atomUri",
+ "Hashtag": "as:Hashtag",
+ "Emoji": "toot:Emoji"
+ }
+ ]
+}
diff --git a/test/list_test.exs b/test/list_test.exs
index ba79251da..e7b23915b 100644
--- a/test/list_test.exs
+++ b/test/list_test.exs
@@ -113,10 +113,10 @@ defmodule Pleroma.ListTest do
{:ok, not_owned_list} = Pleroma.List.follow(not_owned_list, member_1)
{:ok, not_owned_list} = Pleroma.List.follow(not_owned_list, member_2)
- lists_1 = Pleroma.List.get_lists_account_belongs(owner, member_1.id)
+ lists_1 = Pleroma.List.get_lists_account_belongs(owner, member_1)
assert owned_list in lists_1
refute not_owned_list in lists_1
- lists_2 = Pleroma.List.get_lists_account_belongs(owner, member_2.id)
+ lists_2 = Pleroma.List.get_lists_account_belongs(owner, member_2)
assert owned_list in lists_2
refute not_owned_list in lists_2
end
diff --git a/test/notification_test.exs b/test/notification_test.exs
index 1dbad34c1..54c0f9877 100644
--- a/test/notification_test.exs
+++ b/test/notification_test.exs
@@ -33,16 +33,16 @@ defmodule Pleroma.NotificationTest do
assert other_notification.activity_id == activity.id
end
- test "it does not create a notification for subscribed users" do
+ test "it creates a notification for subscribed users" do
user = insert(:user)
subscriber = insert(:user)
User.subscribe(subscriber, user)
{:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
- {:ok, notifications} = Notification.create_notifications(status)
+ {:ok, [notification]} = Notification.create_notifications(status)
- assert notifications == []
+ assert notification.user_id == subscriber.id
end
test "does not create a notification for subscribed users if status is a reply" do
@@ -182,16 +182,14 @@ defmodule Pleroma.NotificationTest do
refute Notification.create_notification(activity_dupe, followed_user)
end
- test "it doesn't create notifications for follow+subscribed users" do
+ test "it doesn't create duplicate notifications for follow+subscribed users" do
user = insert(:user)
subscriber = insert(:user)
{:ok, _, _, _} = CommonAPI.follow(subscriber, user)
User.subscribe(subscriber, user)
{:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
- {:ok, notifications} = Notification.create_notifications(status)
-
- assert notifications == []
+ {:ok, [_notif]} = Notification.create_notifications(status)
end
test "it doesn't create subscription notifications if the recipient cannot see the status" do
diff --git a/test/reverse_proxy_test.exs b/test/reverse_proxy_test.exs
index 3a83c4c48..0672f57db 100644
--- a/test/reverse_proxy_test.exs
+++ b/test/reverse_proxy_test.exs
@@ -42,6 +42,18 @@ defmodule Pleroma.ReverseProxyTest do
end)
end
+ describe "reverse proxy" do
+ test "do not track successful request", %{conn: conn} do
+ user_agent_mock("hackney/1.15.1", 2)
+ url = "/success"
+
+ conn = ReverseProxy.call(conn, url)
+
+ assert conn.status == 200
+ assert Cachex.get(:failed_proxy_url_cache, url) == {:ok, nil}
+ end
+ end
+
describe "user-agent" do
test "don't keep", %{conn: conn} do
user_agent_mock("hackney/1.15.1", 2)
@@ -71,9 +83,15 @@ defmodule Pleroma.ReverseProxyTest do
user_agent_mock("hackney/1.15.1", 0)
assert capture_log(fn ->
- ReverseProxy.call(conn, "/user-agent", max_body_length: 4)
+ ReverseProxy.call(conn, "/huge-file", max_body_length: 4)
end) =~
- "[error] Elixir.Pleroma.ReverseProxy: request to \"/user-agent\" failed: :body_too_large"
+ "[error] Elixir.Pleroma.ReverseProxy: request to \"/huge-file\" failed: :body_too_large"
+
+ assert {:ok, true} == Cachex.get(:failed_proxy_url_cache, "/huge-file")
+
+ assert capture_log(fn ->
+ ReverseProxy.call(conn, "/huge-file", max_body_length: 4)
+ end) == ""
end
defp stream_mock(invokes, with_close? \\ false) do
@@ -140,28 +158,54 @@ defmodule Pleroma.ReverseProxyTest do
describe "returns error on" do
test "500", %{conn: conn} do
error_mock(500)
+ url = "/status/500"
- capture_log(fn -> ReverseProxy.call(conn, "/status/500") end) =~
+ capture_log(fn -> ReverseProxy.call(conn, url) end) =~
"[error] Elixir.Pleroma.ReverseProxy: request to /status/500 failed with HTTP status 500"
+
+ assert Cachex.get(:failed_proxy_url_cache, url) == {:ok, true}
+
+ {:ok, ttl} = Cachex.ttl(:failed_proxy_url_cache, url)
+ assert ttl <= 60_000
end
test "400", %{conn: conn} do
error_mock(400)
+ url = "/status/400"
- capture_log(fn -> ReverseProxy.call(conn, "/status/400") end) =~
+ capture_log(fn -> ReverseProxy.call(conn, url) end) =~
"[error] Elixir.Pleroma.ReverseProxy: request to /status/400 failed with HTTP status 400"
+
+ assert Cachex.get(:failed_proxy_url_cache, url) == {:ok, true}
+ assert Cachex.ttl(:failed_proxy_url_cache, url) == {:ok, nil}
+ end
+
+ test "403", %{conn: conn} do
+ error_mock(403)
+ url = "/status/403"
+
+ capture_log(fn ->
+ ReverseProxy.call(conn, url, failed_request_ttl: :timer.seconds(120))
+ end) =~
+ "[error] Elixir.Pleroma.ReverseProxy: request to /status/403 failed with HTTP status 403"
+
+ {:ok, ttl} = Cachex.ttl(:failed_proxy_url_cache, url)
+ assert ttl > 100_000
end
test "204", %{conn: conn} do
- ClientMock
- |> expect(:request, fn :get, "/status/204", _, _, _ -> {:ok, 204, [], %{}} end)
+ url = "/status/204"
+ expect(ClientMock, :request, fn :get, _url, _, _, _ -> {:ok, 204, [], %{}} end)
capture_log(fn ->
- conn = ReverseProxy.call(conn, "/status/204")
+ conn = ReverseProxy.call(conn, url)
assert conn.resp_body == "Request failed: No Content"
assert conn.halted
end) =~
"[error] Elixir.Pleroma.ReverseProxy: request to \"/status/204\" failed with HTTP status 204"
+
+ assert Cachex.get(:failed_proxy_url_cache, url) == {:ok, true}
+ assert Cachex.ttl(:failed_proxy_url_cache, url) == {:ok, nil}
end
end
diff --git a/test/support/factory.ex b/test/support/factory.ex
index 719115003..4f3244025 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -71,6 +71,47 @@ defmodule Pleroma.Factory do
}
end
+ def audio_factory(attrs \\ %{}) do
+ text = sequence(:text, &"lain radio episode #{&1}")
+
+ user = attrs[:user] || insert(:user)
+
+ data = %{
+ "type" => "Audio",
+ "id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
+ "artist" => "lain",
+ "title" => text,
+ "album" => "lain radio",
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
+ "actor" => user.ap_id,
+ "length" => 180_000
+ }
+
+ %Pleroma.Object{
+ data: merge_attributes(data, Map.get(attrs, :data, %{}))
+ }
+ end
+
+ def listen_factory do
+ audio = insert(:audio)
+
+ data = %{
+ "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
+ "type" => "Listen",
+ "actor" => audio.data["actor"],
+ "to" => audio.data["to"],
+ "object" => audio.data,
+ "published" => audio.data["published"]
+ }
+
+ %Pleroma.Activity{
+ data: data,
+ actor: data["actor"],
+ recipients: data["to"]
+ }
+ end
+
def direct_note_factory do
user2 = insert(:user)
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
index ab52044ae..1ffa91b70 100644
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/web/activity_pub/activity_pub_controller_test.exs
@@ -976,4 +976,44 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
assert Delivery.get(object.id, other_user.id)
end
end
+
+ describe "Additionnal ActivityPub C2S endpoints" do
+ test "/api/ap/whoami", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/ap/whoami")
+
+ user = User.get_cached_by_id(user.id)
+
+ assert UserView.render("user.json", %{user: user}) == json_response(conn, 200)
+ end
+
+ clear_config([:media_proxy])
+ clear_config([Pleroma.Upload])
+
+ test "uploadMedia", %{conn: conn} do
+ user = insert(:user)
+
+ desc = "Description of the image"
+
+ image = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/ap/upload_media", %{"file" => image, "description" => desc})
+
+ assert object = json_response(conn, :created)
+ assert object["name"] == desc
+ assert object["type"] == "Document"
+ assert object["actor"] == user.ap_id
+ end
+ end
end
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
index f28fd6871..f29497847 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -257,6 +257,42 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
+ describe "listen activities" do
+ test "does not increase user note count" do
+ user = insert(:user)
+
+ {:ok, activity} =
+ ActivityPub.listen(%{
+ to: ["https://www.w3.org/ns/activitystreams#Public"],
+ actor: user,
+ context: "",
+ object: %{
+ "actor" => user.ap_id,
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "artist" => "lain",
+ "title" => "lain radio episode 1",
+ "length" => 180_000,
+ "type" => "Audio"
+ }
+ })
+
+ assert activity.actor == user.ap_id
+
+ user = User.get_cached_by_id(user.id)
+ assert user.info.note_count == 0
+ end
+
+ test "can be fetched into a timeline" do
+ _listen_activity_1 = insert(:listen)
+ _listen_activity_2 = insert(:listen)
+ _listen_activity_3 = insert(:listen)
+
+ timeline = ActivityPub.fetch_activities([], %{"type" => ["Listen"]})
+
+ assert length(timeline) == 3
+ end
+ end
+
describe "create activities" do
test "removes doubled 'to' recipients" do
user = insert(:user)
@@ -803,6 +839,39 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
+ describe "announcing a private object" do
+ test "adds an announce activity to the db if the audience is not widened" do
+ user = insert(:user)
+ {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+ object = Object.normalize(note_activity)
+
+ {:ok, announce_activity, object} = ActivityPub.announce(user, object, nil, true, false)
+
+ assert announce_activity.data["to"] == [User.ap_followers(user)]
+
+ assert announce_activity.data["object"] == object.data["id"]
+ assert announce_activity.data["actor"] == user.ap_id
+ assert announce_activity.data["context"] == object.data["context"]
+ end
+
+ test "does not add an announce activity to the db if the audience is widened" do
+ user = insert(:user)
+ {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+ object = Object.normalize(note_activity)
+
+ assert {:error, _} = ActivityPub.announce(user, object, nil, true, true)
+ end
+
+ test "does not add an announce activity to the db if the announcer is not the author" do
+ user = insert(:user)
+ announcer = insert(:user)
+ {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+ object = Object.normalize(note_activity)
+
+ assert {:error, _} = ActivityPub.announce(announcer, object, nil, true, false)
+ end
+ end
+
describe "unannouncing an object" do
test "unannouncing a previously announced object" do
note_activity = insert(:note_activity)
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index a35db71dc..6c64be10b 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -177,6 +177,35 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
end)
end
+ test "it works for incoming listens" do
+ data = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [],
+ "type" => "Listen",
+ "id" => "http://mastodon.example.org/users/admin/listens/1234/activity",
+ "actor" => "http://mastodon.example.org/users/admin",
+ "object" => %{
+ "type" => "Audio",
+ "id" => "http://mastodon.example.org/users/admin/listens/1234",
+ "attributedTo" => "http://mastodon.example.org/users/admin",
+ "title" => "lain radio episode 1",
+ "artist" => "lain",
+ "album" => "lain radio",
+ "length" => 180_000
+ }
+ }
+
+ {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+
+ object = Object.normalize(activity)
+
+ assert object.data["title"] == "lain radio episode 1"
+ assert object.data["artist"] == "lain"
+ assert object.data["album"] == "lain radio"
+ assert object.data["length"] == 180_000
+ end
+
test "it rewrites Note votes to Answers and increments vote counters on question activities" do
user = insert(:user)
@@ -349,6 +378,31 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2"
end
+ test "it works for incoming unlikes with an existing like activity and a compact object" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
+
+ like_data =
+ File.read!("test/fixtures/mastodon-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
+
+ data =
+ File.read!("test/fixtures/mastodon-undo-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", like_data["id"])
+ |> Map.put("actor", like_data["actor"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+ assert data["type"] == "Undo"
+ assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
+ assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2"
+ end
+
test "it works for incoming announces" do
data = File.read!("test/fixtures/mastodon-announce.json") |> Poison.decode!()
@@ -1190,6 +1244,20 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert is_nil(modified["bcc"])
end
+
+ test "it can handle Listen activities" do
+ listen_activity = insert(:listen)
+
+ {:ok, modified} = Transmogrifier.prepare_outgoing(listen_activity.data)
+
+ assert modified["type"] == "Listen"
+
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.listen(user, %{"title" => "lain radio episode 1"})
+
+ {:ok, _modified} = Transmogrifier.prepare_outgoing(activity.data)
+ end
end
describe "user upgrade" do
diff --git a/test/web/admin_api/views/report_view_test.exs b/test/web/admin_api/views/report_view_test.exs
index 35b6947a0..475705857 100644
--- a/test/web/admin_api/views/report_view_test.exs
+++ b/test/web/admin_api/views/report_view_test.exs
@@ -21,12 +21,12 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
content: nil,
actor:
Map.merge(
- AccountView.render("account.json", %{user: user}),
+ AccountView.render("show.json", %{user: user}),
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})
),
account:
Map.merge(
- AccountView.render("account.json", %{user: other_user}),
+ AccountView.render("show.json", %{user: other_user}),
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: other_user})
),
statuses: [],
@@ -53,12 +53,12 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
content: nil,
actor:
Map.merge(
- AccountView.render("account.json", %{user: user}),
+ AccountView.render("show.json", %{user: user}),
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})
),
account:
Map.merge(
- AccountView.render("account.json", %{user: other_user}),
+ AccountView.render("show.json", %{user: other_user}),
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: other_user})
),
statuses: [StatusView.render("show.json", %{activity: activity})],
diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs
index f28a66090..2d3c41e82 100644
--- a/test/web/common_api/common_api_test.exs
+++ b/test/web/common_api/common_api_test.exs
@@ -231,6 +231,18 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, user)
end
+ test "repeating a status privately" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+
+ {:ok, %Activity{} = announce_activity, _} =
+ CommonAPI.repeat(activity.id, user, %{"visibility" => "private"})
+
+ assert Visibility.is_private?(announce_activity)
+ end
+
test "favoriting a status" do
user = insert(:user)
other_user = insert(:user)
@@ -510,4 +522,43 @@ defmodule Pleroma.Web.CommonAPITest do
assert {:error, "Already voted"} == CommonAPI.vote(other_user, object, [1])
end
end
+
+ describe "listen/2" do
+ test "returns a valid activity" do
+ user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.listen(user, %{
+ "title" => "lain radio episode 1",
+ "album" => "lain radio",
+ "artist" => "lain",
+ "length" => 180_000
+ })
+
+ object = Object.normalize(activity)
+
+ assert object.data["title"] == "lain radio episode 1"
+
+ assert Visibility.get_visibility(activity) == "public"
+ end
+
+ test "respects visibility=private" do
+ user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.listen(user, %{
+ "title" => "lain radio episode 1",
+ "album" => "lain radio",
+ "artist" => "lain",
+ "length" => 180_000,
+ "visibility" => "private"
+ })
+
+ object = Object.normalize(activity)
+
+ assert object.data["title"] == "lain radio episode 1"
+
+ assert Visibility.get_visibility(activity) == "private"
+ end
+ end
end
diff --git a/test/web/mastodon_api/controllers/mastodon_api_controller/update_credentials_test.exs b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
index 560f55137..560f55137 100644
--- a/test/web/mastodon_api/controllers/mastodon_api_controller/update_credentials_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs
new file mode 100644
index 000000000..8c8017838
--- /dev/null
+++ b/test/web/mastodon_api/controllers/account_controller_test.exs
@@ -0,0 +1,852 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Repo
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.OAuth.Token
+
+ import Pleroma.Factory
+
+ describe "account fetching" do
+ test "works by id" do
+ user = insert(:user)
+
+ conn =
+ build_conn()
+ |> get("/api/v1/accounts/#{user.id}")
+
+ assert %{"id" => id} = json_response(conn, 200)
+ assert id == to_string(user.id)
+
+ conn =
+ build_conn()
+ |> get("/api/v1/accounts/-1")
+
+ assert %{"error" => "Can't find user"} = json_response(conn, 404)
+ end
+
+ test "works by nickname" do
+ user = insert(:user)
+
+ conn =
+ build_conn()
+ |> get("/api/v1/accounts/#{user.nickname}")
+
+ assert %{"id" => id} = json_response(conn, 200)
+ assert id == user.id
+ end
+
+ test "works by nickname for remote users" do
+ limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
+ Pleroma.Config.put([:instance, :limit_to_local_content], false)
+ user = insert(:user, nickname: "user@example.com", local: false)
+
+ conn =
+ build_conn()
+ |> get("/api/v1/accounts/#{user.nickname}")
+
+ Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
+ assert %{"id" => id} = json_response(conn, 200)
+ assert id == user.id
+ end
+
+ test "respects limit_to_local_content == :all for remote user nicknames" do
+ limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
+ Pleroma.Config.put([:instance, :limit_to_local_content], :all)
+
+ user = insert(:user, nickname: "user@example.com", local: false)
+
+ conn =
+ build_conn()
+ |> get("/api/v1/accounts/#{user.nickname}")
+
+ Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
+ assert json_response(conn, 404)
+ end
+
+ test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
+ limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
+ Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
+
+ user = insert(:user, nickname: "user@example.com", local: false)
+ reading_user = insert(:user)
+
+ conn =
+ build_conn()
+ |> get("/api/v1/accounts/#{user.nickname}")
+
+ assert json_response(conn, 404)
+
+ conn =
+ build_conn()
+ |> assign(:user, reading_user)
+ |> get("/api/v1/accounts/#{user.nickname}")
+
+ Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
+ assert %{"id" => id} = json_response(conn, 200)
+ assert id == user.id
+ end
+
+ test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
+ # Need to set an old-style integer ID to reproduce the problem
+ # (these are no longer assigned to new accounts but were preserved
+ # for existing accounts during the migration to flakeIDs)
+ user_one = insert(:user, %{id: 1212})
+ user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
+
+ resp_one =
+ conn
+ |> get("/api/v1/accounts/#{user_one.id}")
+
+ resp_two =
+ conn
+ |> get("/api/v1/accounts/#{user_two.nickname}")
+
+ resp_three =
+ conn
+ |> get("/api/v1/accounts/#{user_two.id}")
+
+ acc_one = json_response(resp_one, 200)
+ acc_two = json_response(resp_two, 200)
+ acc_three = json_response(resp_three, 200)
+ refute acc_one == acc_two
+ assert acc_two == acc_three
+ end
+ end
+
+ describe "user timelines" do
+ test "gets a users statuses", %{conn: conn} do
+ user_one = insert(:user)
+ user_two = insert(:user)
+ user_three = insert(:user)
+
+ {:ok, user_three} = User.follow(user_three, user_one)
+
+ {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
+
+ {:ok, direct_activity} =
+ CommonAPI.post(user_one, %{
+ "status" => "Hi, @#{user_two.nickname}.",
+ "visibility" => "direct"
+ })
+
+ {:ok, private_activity} =
+ CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
+
+ resp =
+ conn
+ |> get("/api/v1/accounts/#{user_one.id}/statuses")
+
+ assert [%{"id" => id}] = json_response(resp, 200)
+ assert id == to_string(activity.id)
+
+ resp =
+ conn
+ |> assign(:user, user_two)
+ |> get("/api/v1/accounts/#{user_one.id}/statuses")
+
+ assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
+ assert id_one == to_string(direct_activity.id)
+ assert id_two == to_string(activity.id)
+
+ resp =
+ conn
+ |> assign(:user, user_three)
+ |> get("/api/v1/accounts/#{user_one.id}/statuses")
+
+ assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
+ assert id_one == to_string(private_activity.id)
+ assert id_two == to_string(activity.id)
+ end
+
+ test "unimplemented pinned statuses feature", %{conn: conn} do
+ note = insert(:note_activity)
+ user = User.get_cached_by_ap_id(note.data["actor"])
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
+
+ assert json_response(conn, 200) == []
+ end
+
+ test "gets an users media", %{conn: conn} do
+ note = insert(:note_activity)
+ user = User.get_cached_by_ap_id(note.data["actor"])
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, %{id: media_id}} = ActivityPub.upload(file, actor: user.ap_id)
+
+ {:ok, image_post} = CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media_id]})
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
+
+ assert [%{"id" => id}] = json_response(conn, 200)
+ assert id == to_string(image_post.id)
+
+ conn =
+ build_conn()
+ |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
+
+ assert [%{"id" => id}] = json_response(conn, 200)
+ assert id == to_string(image_post.id)
+ end
+
+ test "gets a user's statuses without reblogs", %{conn: conn} do
+ user = insert(:user)
+ {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
+ {:ok, _, _} = CommonAPI.repeat(post.id, user)
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
+
+ assert [%{"id" => id}] = json_response(conn, 200)
+ assert id == to_string(post.id)
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
+
+ assert [%{"id" => id}] = json_response(conn, 200)
+ assert id == to_string(post.id)
+ end
+
+ test "filters user's statuses by a hashtag", %{conn: conn} do
+ user = insert(:user)
+ {:ok, post} = CommonAPI.post(user, %{"status" => "#hashtag"})
+ {:ok, _post} = CommonAPI.post(user, %{"status" => "hashtag"})
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/statuses", %{"tagged" => "hashtag"})
+
+ assert [%{"id" => id}] = json_response(conn, 200)
+ assert id == to_string(post.id)
+ end
+ end
+
+ describe "followers" do
+ test "getting followers", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+ {:ok, user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{other_user.id}/followers")
+
+ assert [%{"id" => id}] = json_response(conn, 200)
+ assert id == to_string(user.id)
+ end
+
+ test "getting followers, hide_followers", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user, %{info: %{hide_followers: true}})
+ {:ok, _user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{other_user.id}/followers")
+
+ assert [] == json_response(conn, 200)
+ end
+
+ test "getting followers, hide_followers, same user requesting", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user, %{info: %{hide_followers: true}})
+ {:ok, _user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> assign(:user, other_user)
+ |> get("/api/v1/accounts/#{other_user.id}/followers")
+
+ refute [] == json_response(conn, 200)
+ end
+
+ test "getting followers, pagination", %{conn: conn} do
+ user = insert(:user)
+ follower1 = insert(:user)
+ follower2 = insert(:user)
+ follower3 = insert(:user)
+ {:ok, _} = User.follow(follower1, user)
+ {:ok, _} = User.follow(follower2, user)
+ {:ok, _} = User.follow(follower3, user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+
+ res_conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
+
+ assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
+ assert id3 == follower3.id
+ assert id2 == follower2.id
+
+ res_conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
+
+ assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
+ assert id2 == follower2.id
+ assert id1 == follower1.id
+
+ res_conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
+
+ assert [%{"id" => id2}] = json_response(res_conn, 200)
+ assert id2 == follower2.id
+
+ assert [link_header] = get_resp_header(res_conn, "link")
+ assert link_header =~ ~r/min_id=#{follower2.id}/
+ assert link_header =~ ~r/max_id=#{follower2.id}/
+ end
+ end
+
+ describe "following" do
+ test "getting following", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+ {:ok, user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/following")
+
+ assert [%{"id" => id}] = json_response(conn, 200)
+ assert id == to_string(other_user.id)
+ end
+
+ test "getting following, hide_follows", %{conn: conn} do
+ user = insert(:user, %{info: %{hide_follows: true}})
+ other_user = insert(:user)
+ {:ok, user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/following")
+
+ assert [] == json_response(conn, 200)
+ end
+
+ test "getting following, hide_follows, same user requesting", %{conn: conn} do
+ user = insert(:user, %{info: %{hide_follows: true}})
+ other_user = insert(:user)
+ {:ok, user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/#{user.id}/following")
+
+ refute [] == json_response(conn, 200)
+ end
+
+ test "getting following, pagination", %{conn: conn} do
+ user = insert(:user)
+ following1 = insert(:user)
+ following2 = insert(:user)
+ following3 = insert(:user)
+ {:ok, _} = User.follow(user, following1)
+ {:ok, _} = User.follow(user, following2)
+ {:ok, _} = User.follow(user, following3)
+
+ conn =
+ conn
+ |> assign(:user, user)
+
+ res_conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
+
+ assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
+ assert id3 == following3.id
+ assert id2 == following2.id
+
+ res_conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
+
+ assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
+ assert id2 == following2.id
+ assert id1 == following1.id
+
+ res_conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
+
+ assert [%{"id" => id2}] = json_response(res_conn, 200)
+ assert id2 == following2.id
+
+ assert [link_header] = get_resp_header(res_conn, "link")
+ assert link_header =~ ~r/min_id=#{following2.id}/
+ assert link_header =~ ~r/max_id=#{following2.id}/
+ end
+ end
+
+ describe "follow/unfollow" do
+ test "following / unfollowing a user", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/follow")
+
+ assert %{"id" => _id, "following" => true} = json_response(conn, 200)
+
+ user = User.get_cached_by_id(user.id)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/unfollow")
+
+ assert %{"id" => _id, "following" => false} = json_response(conn, 200)
+
+ user = User.get_cached_by_id(user.id)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> post("/api/v1/follows", %{"uri" => other_user.nickname})
+
+ assert %{"id" => id} = json_response(conn, 200)
+ assert id == to_string(other_user.id)
+ end
+
+ test "following without reblogs" do
+ follower = insert(:user)
+ followed = insert(:user)
+ other_user = insert(:user)
+
+ conn =
+ build_conn()
+ |> assign(:user, follower)
+ |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=false")
+
+ assert %{"showing_reblogs" => false} = json_response(conn, 200)
+
+ {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"})
+ {:ok, reblog, _} = CommonAPI.repeat(activity.id, followed)
+
+ conn =
+ build_conn()
+ |> assign(:user, User.get_cached_by_id(follower.id))
+ |> get("/api/v1/timelines/home")
+
+ assert [] == json_response(conn, 200)
+
+ conn =
+ build_conn()
+ |> assign(:user, follower)
+ |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
+
+ assert %{"showing_reblogs" => true} = json_response(conn, 200)
+
+ conn =
+ build_conn()
+ |> assign(:user, User.get_cached_by_id(follower.id))
+ |> get("/api/v1/timelines/home")
+
+ expected_activity_id = reblog.id
+ assert [%{"id" => ^expected_activity_id}] = json_response(conn, 200)
+ end
+
+ test "following / unfollowing errors" do
+ user = insert(:user)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+
+ # self follow
+ conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
+ assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+
+ # self unfollow
+ user = User.get_cached_by_id(user.id)
+ conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow")
+ assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+
+ # self follow via uri
+ user = User.get_cached_by_id(user.id)
+ conn_res = post(conn, "/api/v1/follows", %{"uri" => user.nickname})
+ assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+
+ # follow non existing user
+ conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
+ assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+
+ # follow non existing user via uri
+ conn_res = post(conn, "/api/v1/follows", %{"uri" => "doesntexist"})
+ assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+
+ # unfollow non existing user
+ conn_res = post(conn, "/api/v1/accounts/doesntexist/unfollow")
+ assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+ end
+ end
+
+ describe "mute/unmute" do
+ test "with notifications", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/mute")
+
+ response = json_response(conn, 200)
+
+ assert %{"id" => _id, "muting" => true, "muting_notifications" => true} = response
+ user = User.get_cached_by_id(user.id)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/unmute")
+
+ response = json_response(conn, 200)
+ assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
+ end
+
+ test "without notifications", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
+
+ response = json_response(conn, 200)
+
+ assert %{"id" => _id, "muting" => true, "muting_notifications" => false} = response
+ user = User.get_cached_by_id(user.id)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/unmute")
+
+ response = json_response(conn, 200)
+ assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
+ end
+ end
+
+ describe "pinned statuses" do
+ setup do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
+
+ [user: user, activity: activity]
+ end
+
+ test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
+ {:ok, _} = CommonAPI.pin(activity.id, user)
+
+ result =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
+ |> json_response(200)
+
+ id_str = to_string(activity.id)
+
+ assert [%{"id" => ^id_str, "pinned" => true}] = result
+ end
+ end
+
+ test "blocking / unblocking a user", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/block")
+
+ assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
+
+ user = User.get_cached_by_id(user.id)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/unblock")
+
+ assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
+ end
+
+ describe "create account by app" do
+ setup do
+ valid_params = %{
+ username: "lain",
+ email: "lain@example.org",
+ password: "PlzDontHackLain",
+ agreement: true
+ }
+
+ [valid_params: valid_params]
+ end
+
+ test "Account registration via Application", %{conn: conn} do
+ conn =
+ conn
+ |> post("/api/v1/apps", %{
+ client_name: "client_name",
+ redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
+ scopes: "read, write, follow"
+ })
+
+ %{
+ "client_id" => client_id,
+ "client_secret" => client_secret,
+ "id" => _,
+ "name" => "client_name",
+ "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
+ "vapid_key" => _,
+ "website" => nil
+ } = json_response(conn, 200)
+
+ conn =
+ conn
+ |> post("/oauth/token", %{
+ grant_type: "client_credentials",
+ client_id: client_id,
+ client_secret: client_secret
+ })
+
+ assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
+ json_response(conn, 200)
+
+ assert token
+ token_from_db = Repo.get_by(Token, token: token)
+ assert token_from_db
+ assert refresh
+ assert scope == "read write follow"
+
+ conn =
+ build_conn()
+ |> put_req_header("authorization", "Bearer " <> token)
+ |> post("/api/v1/accounts", %{
+ username: "lain",
+ email: "lain@example.org",
+ password: "PlzDontHackLain",
+ bio: "Test Bio",
+ agreement: true
+ })
+
+ %{
+ "access_token" => token,
+ "created_at" => _created_at,
+ "scope" => _scope,
+ "token_type" => "Bearer"
+ } = json_response(conn, 200)
+
+ token_from_db = Repo.get_by(Token, token: token)
+ assert token_from_db
+ token_from_db = Repo.preload(token_from_db, :user)
+ assert token_from_db.user
+
+ assert token_from_db.user.info.confirmation_pending
+ end
+
+ test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
+ _user = insert(:user, email: "lain@example.org")
+ app_token = insert(:oauth_token, user: nil)
+
+ conn =
+ conn
+ |> put_req_header("authorization", "Bearer " <> app_token.token)
+
+ res = post(conn, "/api/v1/accounts", valid_params)
+ assert json_response(res, 400) == %{"error" => "{\"email\":[\"has already been taken\"]}"}
+ end
+
+ test "rate limit", %{conn: conn} do
+ app_token = insert(:oauth_token, user: nil)
+
+ conn =
+ put_req_header(conn, "authorization", "Bearer " <> app_token.token)
+ |> Map.put(:remote_ip, {15, 15, 15, 15})
+
+ for i <- 1..5 do
+ conn =
+ conn
+ |> post("/api/v1/accounts", %{
+ username: "#{i}lain",
+ email: "#{i}lain@example.org",
+ password: "PlzDontHackLain",
+ agreement: true
+ })
+
+ %{
+ "access_token" => token,
+ "created_at" => _created_at,
+ "scope" => _scope,
+ "token_type" => "Bearer"
+ } = json_response(conn, 200)
+
+ token_from_db = Repo.get_by(Token, token: token)
+ assert token_from_db
+ token_from_db = Repo.preload(token_from_db, :user)
+ assert token_from_db.user
+
+ assert token_from_db.user.info.confirmation_pending
+ end
+
+ conn =
+ conn
+ |> post("/api/v1/accounts", %{
+ username: "6lain",
+ email: "6lain@example.org",
+ password: "PlzDontHackLain",
+ agreement: true
+ })
+
+ assert json_response(conn, :too_many_requests) == %{"error" => "Throttled"}
+ end
+
+ test "returns bad_request if missing required params", %{
+ conn: conn,
+ valid_params: valid_params
+ } do
+ app_token = insert(:oauth_token, user: nil)
+
+ conn =
+ conn
+ |> put_req_header("authorization", "Bearer " <> app_token.token)
+
+ res = post(conn, "/api/v1/accounts", valid_params)
+ assert json_response(res, 200)
+
+ [{127, 0, 0, 1}, {127, 0, 0, 2}, {127, 0, 0, 3}, {127, 0, 0, 4}]
+ |> Stream.zip(valid_params)
+ |> Enum.each(fn {ip, {attr, _}} ->
+ res =
+ conn
+ |> Map.put(:remote_ip, ip)
+ |> post("/api/v1/accounts", Map.delete(valid_params, attr))
+ |> json_response(400)
+
+ assert res == %{"error" => "Missing parameters"}
+ end)
+ end
+
+ test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
+ conn =
+ conn
+ |> put_req_header("authorization", "Bearer " <> "invalid-token")
+
+ res = post(conn, "/api/v1/accounts", valid_params)
+ assert json_response(res, 403) == %{"error" => "Invalid credentials"}
+ end
+ end
+
+ describe "GET /api/v1/accounts/:id/lists - account_lists" do
+ test "returns lists to which the account belongs", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+ assert {:ok, %Pleroma.List{} = list} = Pleroma.List.create("Test List", user)
+ {:ok, %{following: _following}} = Pleroma.List.follow(list, other_user)
+
+ res =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/#{other_user.id}/lists")
+ |> json_response(200)
+
+ assert res == [%{"id" => to_string(list.id), "title" => "Test List"}]
+ end
+ end
+
+ describe "verify_credentials" do
+ test "verify_credentials", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/verify_credentials")
+
+ response = json_response(conn, 200)
+
+ assert %{"id" => id, "source" => %{"privacy" => "public"}} = response
+ assert response["pleroma"]["chat_token"]
+ assert id == to_string(user.id)
+ end
+
+ test "verify_credentials default scope unlisted", %{conn: conn} do
+ user = insert(:user, %{info: %User.Info{default_scope: "unlisted"}})
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/verify_credentials")
+
+ assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
+ assert id == to_string(user.id)
+ end
+
+ test "locked accounts", %{conn: conn} do
+ user = insert(:user, %{info: %User.Info{default_scope: "private"}})
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/verify_credentials")
+
+ assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
+ assert id == to_string(user.id)
+ end
+ end
+
+ describe "user relationships" do
+ test "returns the relationships for the current user", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+ {:ok, user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]})
+
+ assert [relationship] = json_response(conn, 200)
+
+ assert to_string(other_user.id) == relationship["id"]
+ end
+
+ test "returns an empty list on a bad request", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/relationships", %{})
+
+ assert [] = json_response(conn, 200)
+ end
+ end
+end
diff --git a/test/web/mastodon_api/controllers/app_controller_test.exs b/test/web/mastodon_api/controllers/app_controller_test.exs
new file mode 100644
index 000000000..51788155b
--- /dev/null
+++ b/test/web/mastodon_api/controllers/app_controller_test.exs
@@ -0,0 +1,60 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.AppControllerTest do
+ use Pleroma.Web.ConnCase, async: true
+
+ alias Pleroma.Repo
+ alias Pleroma.Web.OAuth.App
+ alias Pleroma.Web.Push
+
+ import Pleroma.Factory
+
+ test "apps/verify_credentials", %{conn: conn} do
+ token = insert(:oauth_token)
+
+ conn =
+ conn
+ |> assign(:user, token.user)
+ |> assign(:token, token)
+ |> get("/api/v1/apps/verify_credentials")
+
+ app = Repo.preload(token, :app).app
+
+ expected = %{
+ "name" => app.client_name,
+ "website" => app.website,
+ "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
+ }
+
+ assert expected == json_response(conn, 200)
+ end
+
+ test "creates an oauth app", %{conn: conn} do
+ user = insert(:user)
+ app_attrs = build(:oauth_app)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/apps", %{
+ client_name: app_attrs.client_name,
+ redirect_uris: app_attrs.redirect_uris
+ })
+
+ [app] = Repo.all(App)
+
+ expected = %{
+ "name" => app.client_name,
+ "website" => app.website,
+ "client_id" => app.client_id,
+ "client_secret" => app.client_secret,
+ "id" => app.id |> to_string(),
+ "redirect_uri" => app.redirect_uris,
+ "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
+ }
+
+ assert expected == json_response(conn, 200)
+ end
+end
diff --git a/test/web/mastodon_api/controllers/auth_controller_test.exs b/test/web/mastodon_api/controllers/auth_controller_test.exs
new file mode 100644
index 000000000..98b2a82e7
--- /dev/null
+++ b/test/web/mastodon_api/controllers/auth_controller_test.exs
@@ -0,0 +1,121 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.AuthControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Config
+ alias Pleroma.Repo
+ alias Pleroma.Tests.ObanHelpers
+
+ import Pleroma.Factory
+ import Swoosh.TestAssertions
+
+ describe "GET /web/login" do
+ setup %{conn: conn} do
+ session_opts = [
+ store: :cookie,
+ key: "_test",
+ signing_salt: "cooldude"
+ ]
+
+ conn =
+ conn
+ |> Plug.Session.call(Plug.Session.init(session_opts))
+ |> fetch_session()
+
+ test_path = "/web/statuses/test"
+ %{conn: conn, path: test_path}
+ end
+
+ test "redirects to the saved path after log in", %{conn: conn, path: path} do
+ app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
+ auth = insert(:oauth_authorization, app: app)
+
+ conn =
+ conn
+ |> put_session(:return_to, path)
+ |> get("/web/login", %{code: auth.token})
+
+ assert conn.status == 302
+ assert redirected_to(conn) == path
+ end
+
+ test "redirects to the getting-started page when referer is not present", %{conn: conn} do
+ app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
+ auth = insert(:oauth_authorization, app: app)
+
+ conn = get(conn, "/web/login", %{code: auth.token})
+
+ assert conn.status == 302
+ assert redirected_to(conn) == "/web/getting-started"
+ end
+ end
+
+ describe "POST /auth/password, with valid parameters" do
+ setup %{conn: conn} do
+ user = insert(:user)
+ conn = post(conn, "/auth/password?email=#{user.email}")
+ %{conn: conn, user: user}
+ end
+
+ test "it returns 204", %{conn: conn} do
+ assert json_response(conn, :no_content)
+ end
+
+ test "it creates a PasswordResetToken record for user", %{user: user} do
+ token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
+ assert token_record
+ end
+
+ test "it sends an email to user", %{user: user} do
+ ObanHelpers.perform_all()
+ token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
+
+ email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
+ notify_email = Config.get([:instance, :notify_email])
+ instance_name = Config.get([:instance, :name])
+
+ assert_email_sent(
+ from: {instance_name, notify_email},
+ to: {user.name, user.email},
+ html_body: email.html_body
+ )
+ end
+ end
+
+ describe "POST /auth/password, with invalid parameters" do
+ setup do
+ user = insert(:user)
+ {:ok, user: user}
+ end
+
+ test "it returns 404 when user is not found", %{conn: conn, user: user} do
+ conn = post(conn, "/auth/password?email=nonexisting_#{user.email}")
+ assert conn.status == 404
+ assert conn.resp_body == ""
+ end
+
+ test "it returns 400 when user is not local", %{conn: conn, user: user} do
+ {:ok, user} = Repo.update(Ecto.Changeset.change(user, local: false))
+ conn = post(conn, "/auth/password?email=#{user.email}")
+ assert conn.status == 400
+ assert conn.resp_body == ""
+ end
+ end
+
+ describe "DELETE /auth/sign_out" do
+ test "redirect to root page", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> delete("/auth/sign_out")
+
+ assert conn.status == 302
+ assert redirected_to(conn) == "/"
+ end
+ end
+end
diff --git a/test/web/mastodon_api/controllers/conversation_controller_test.exs b/test/web/mastodon_api/controllers/conversation_controller_test.exs
new file mode 100644
index 000000000..7117fc76a
--- /dev/null
+++ b/test/web/mastodon_api/controllers/conversation_controller_test.exs
@@ -0,0 +1,75 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.User
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ test "Conversations", %{conn: conn} do
+ user_one = insert(:user)
+ user_two = insert(:user)
+ user_three = insert(:user)
+
+ {:ok, user_two} = User.follow(user_two, user_one)
+
+ {:ok, direct} =
+ CommonAPI.post(user_one, %{
+ "status" => "Hi @#{user_two.nickname}, @#{user_three.nickname}!",
+ "visibility" => "direct"
+ })
+
+ {:ok, _follower_only} =
+ CommonAPI.post(user_one, %{
+ "status" => "Hi @#{user_two.nickname}!",
+ "visibility" => "private"
+ })
+
+ res_conn =
+ conn
+ |> assign(:user, user_one)
+ |> get("/api/v1/conversations")
+
+ assert response = json_response(res_conn, 200)
+
+ assert [
+ %{
+ "id" => res_id,
+ "accounts" => res_accounts,
+ "last_status" => res_last_status,
+ "unread" => unread
+ }
+ ] = response
+
+ account_ids = Enum.map(res_accounts, & &1["id"])
+ assert length(res_accounts) == 2
+ assert user_two.id in account_ids
+ assert user_three.id in account_ids
+ assert is_binary(res_id)
+ assert unread == true
+ assert res_last_status["id"] == direct.id
+
+ # Apparently undocumented API endpoint
+ res_conn =
+ conn
+ |> assign(:user, user_one)
+ |> post("/api/v1/conversations/#{res_id}/read")
+
+ assert response = json_response(res_conn, 200)
+ assert length(response["accounts"]) == 2
+ assert response["last_status"]["id"] == direct.id
+ assert response["unread"] == false
+
+ # (vanilla) Mastodon frontend behaviour
+ res_conn =
+ conn
+ |> assign(:user, user_one)
+ |> get("/api/v1/statuses/#{res_last_status["id"]}/context")
+
+ assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)
+ end
+end
diff --git a/test/web/mastodon_api/controllers/domain_block_controller_test.exs b/test/web/mastodon_api/controllers/domain_block_controller_test.exs
index 3c3558385..25a279cdc 100644
--- a/test/web/mastodon_api/controllers/domain_block_controller_test.exs
+++ b/test/web/mastodon_api/controllers/domain_block_controller_test.exs
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
- use Pleroma.Web.ConnCase, async: true
+ use Pleroma.Web.ConnCase
alias Pleroma.User
diff --git a/test/web/mastodon_api/controllers/media_controller_test.exs b/test/web/mastodon_api/controllers/media_controller_test.exs
new file mode 100644
index 000000000..06c6a1cb3
--- /dev/null
+++ b/test/web/mastodon_api/controllers/media_controller_test.exs
@@ -0,0 +1,92 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Object
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
+
+ import Pleroma.Factory
+
+ describe "media upload" do
+ setup do
+ user = insert(:user)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+
+ image = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ [conn: conn, image: image]
+ end
+
+ clear_config([:media_proxy])
+ clear_config([Pleroma.Upload])
+
+ test "returns uploaded image", %{conn: conn, image: image} do
+ desc = "Description of the image"
+
+ media =
+ conn
+ |> post("/api/v1/media", %{"file" => image, "description" => desc})
+ |> json_response(:ok)
+
+ assert media["type"] == "image"
+ assert media["description"] == desc
+ assert media["id"]
+
+ object = Object.get_by_id(media["id"])
+ assert object.data["actor"] == User.ap_id(conn.assigns[:user])
+ end
+ end
+
+ describe "PUT /api/v1/media/:id" do
+ setup do
+ actor = insert(:user)
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, %Object{} = object} =
+ ActivityPub.upload(
+ file,
+ actor: User.ap_id(actor),
+ description: "test-m"
+ )
+
+ [actor: actor, object: object]
+ end
+
+ test "updates name of media", %{conn: conn, actor: actor, object: object} do
+ media =
+ conn
+ |> assign(:user, actor)
+ |> put("/api/v1/media/#{object.id}", %{"description" => "test-media"})
+ |> json_response(:ok)
+
+ assert media["description"] == "test-media"
+ assert refresh_record(object).data["name"] == "test-media"
+ end
+
+ test "returns error wheb request is bad", %{conn: conn, actor: actor, object: object} do
+ media =
+ conn
+ |> assign(:user, actor)
+ |> put("/api/v1/media/#{object.id}", %{})
+ |> json_response(400)
+
+ assert media == %{"error" => "bad_request"}
+ end
+ end
+end
diff --git a/test/web/mastodon_api/controllers/poll_controller_test.exs b/test/web/mastodon_api/controllers/poll_controller_test.exs
new file mode 100644
index 000000000..40cf3e879
--- /dev/null
+++ b/test/web/mastodon_api/controllers/poll_controller_test.exs
@@ -0,0 +1,184 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Object
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ describe "GET /api/v1/polls/:id" do
+ test "returns poll entity for object id", %{conn: conn} do
+ user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "Pleroma does",
+ "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20}
+ })
+
+ object = Object.normalize(activity)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/polls/#{object.id}")
+
+ response = json_response(conn, 200)
+ id = to_string(object.id)
+ assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
+ end
+
+ test "does not expose polls for private statuses", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "Pleroma does",
+ "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20},
+ "visibility" => "private"
+ })
+
+ object = Object.normalize(activity)
+
+ conn =
+ conn
+ |> assign(:user, other_user)
+ |> get("/api/v1/polls/#{object.id}")
+
+ assert json_response(conn, 404)
+ end
+ end
+
+ describe "POST /api/v1/polls/:id/votes" do
+ test "votes are added to the poll", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "A very delicious sandwich",
+ "poll" => %{
+ "options" => ["Lettuce", "Grilled Bacon", "Tomato"],
+ "expires_in" => 20,
+ "multiple" => true
+ }
+ })
+
+ object = Object.normalize(activity)
+
+ conn =
+ conn
+ |> assign(:user, other_user)
+ |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
+
+ assert json_response(conn, 200)
+ object = Object.get_by_id(object.id)
+
+ assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
+ total_items == 1
+ end)
+ end
+
+ test "author can't vote", %{conn: conn} do
+ user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "Am I cute?",
+ "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
+ })
+
+ object = Object.normalize(activity)
+
+ assert conn
+ |> assign(:user, user)
+ |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [1]})
+ |> json_response(422) == %{"error" => "Poll's author can't vote"}
+
+ object = Object.get_by_id(object.id)
+
+ refute Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 1
+ end
+
+ test "does not allow multiple choices on a single-choice question", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "The glass is",
+ "poll" => %{"options" => ["half empty", "half full"], "expires_in" => 20}
+ })
+
+ object = Object.normalize(activity)
+
+ assert conn
+ |> assign(:user, other_user)
+ |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1]})
+ |> json_response(422) == %{"error" => "Too many choices"}
+
+ object = Object.get_by_id(object.id)
+
+ refute Enum.any?(object.data["oneOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
+ total_items == 1
+ end)
+ end
+
+ test "does not allow choice index to be greater than options count", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "Am I cute?",
+ "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
+ })
+
+ object = Object.normalize(activity)
+
+ conn =
+ conn
+ |> assign(:user, other_user)
+ |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]})
+
+ assert json_response(conn, 422) == %{"error" => "Invalid indices"}
+ end
+
+ test "returns 404 error when object is not exist", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/polls/1/votes", %{"choices" => [0]})
+
+ assert json_response(conn, 404) == %{"error" => "Record not found"}
+ end
+
+ test "returns 404 when poll is private and not available for user", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "Am I cute?",
+ "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20},
+ "visibility" => "private"
+ })
+
+ object = Object.normalize(activity)
+
+ conn =
+ conn
+ |> assign(:user, other_user)
+ |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]})
+
+ assert json_response(conn, 404) == %{"error" => "Record not found"}
+ end
+ end
+end
diff --git a/test/web/mastodon_api/controllers/report_controller_test.exs b/test/web/mastodon_api/controllers/report_controller_test.exs
new file mode 100644
index 000000000..979ca48f3
--- /dev/null
+++ b/test/web/mastodon_api/controllers/report_controller_test.exs
@@ -0,0 +1,88 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ setup do
+ reporter = insert(:user)
+ target_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
+
+ [reporter: reporter, target_user: target_user, activity: activity]
+ end
+
+ test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
+ assert %{"action_taken" => false, "id" => _} =
+ conn
+ |> assign(:user, reporter)
+ |> post("/api/v1/reports", %{"account_id" => target_user.id})
+ |> json_response(200)
+ end
+
+ test "submit a report with statuses and comment", %{
+ conn: conn,
+ reporter: reporter,
+ target_user: target_user,
+ activity: activity
+ } do
+ assert %{"action_taken" => false, "id" => _} =
+ conn
+ |> assign(:user, reporter)
+ |> post("/api/v1/reports", %{
+ "account_id" => target_user.id,
+ "status_ids" => [activity.id],
+ "comment" => "bad status!",
+ "forward" => "false"
+ })
+ |> json_response(200)
+ end
+
+ test "account_id is required", %{
+ conn: conn,
+ reporter: reporter,
+ activity: activity
+ } do
+ assert %{"error" => "Valid `account_id` required"} =
+ conn
+ |> assign(:user, reporter)
+ |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
+ |> json_response(400)
+ end
+
+ test "comment must be up to the size specified in the config", %{
+ conn: conn,
+ reporter: reporter,
+ target_user: target_user
+ } do
+ max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
+ comment = String.pad_trailing("a", max_size + 1, "a")
+
+ error = %{"error" => "Comment must be up to #{max_size} characters"}
+
+ assert ^error =
+ conn
+ |> assign(:user, reporter)
+ |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
+ |> json_response(400)
+ end
+
+ test "returns error when account is not exist", %{
+ conn: conn,
+ reporter: reporter,
+ activity: activity
+ } do
+ conn =
+ conn
+ |> assign(:user, reporter)
+ |> post("/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"})
+
+ assert json_response(conn, 400) == %{"error" => "Account not found"}
+ end
+end
diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs
index b194feae6..b648ad6ff 100644
--- a/test/web/mastodon_api/controllers/status_controller_test.exs
+++ b/test/web/mastodon_api/controllers/status_controller_test.exs
@@ -547,6 +547,24 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
assert to_string(activity.id) == id
end
+ test "reblogs privately and returns the reblogged status", %{conn: conn} do
+ activity = insert(:note_activity)
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/statuses/#{activity.id}/reblog", %{"visibility" => "private"})
+
+ assert %{
+ "reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1},
+ "reblogged" => true,
+ "visibility" => "private"
+ } = json_response(conn, 200)
+
+ assert to_string(activity.id) == id
+ end
+
test "reblogged status for another user", %{conn: conn} do
activity = insert(:note_activity)
user1 = insert(:user)
@@ -1149,6 +1167,23 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
assert Enum.empty?(response)
end
+ test "does not return users who have reblogged the status privately", %{
+ conn: %{assigns: %{user: user}} = conn,
+ activity: activity
+ } do
+ other_user = insert(:user)
+
+ {:ok, _, _} = CommonAPI.repeat(activity.id, other_user, %{"visibility" => "private"})
+
+ response =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/statuses/#{activity.id}/reblogged_by")
+ |> json_response(:ok)
+
+ assert Enum.empty?(response)
+ end
+
test "does not fail on an unauthenticated request", %{conn: conn, activity: activity} do
other_user = insert(:user)
{:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
diff --git a/test/web/mastodon_api/controllers/suggestion_controller_test.exs b/test/web/mastodon_api/controllers/suggestion_controller_test.exs
new file mode 100644
index 000000000..78620a873
--- /dev/null
+++ b/test/web/mastodon_api/controllers/suggestion_controller_test.exs
@@ -0,0 +1,92 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Config
+
+ import ExUnit.CaptureLog
+ import Pleroma.Factory
+ import Tesla.Mock
+
+ setup do
+ user = insert(:user)
+ other_user = insert(:user)
+ host = Config.get([Pleroma.Web.Endpoint, :url, :host])
+ url500 = "http://test500?#{host}&#{user.nickname}"
+ url200 = "http://test200?#{host}&#{user.nickname}"
+
+ mock(fn
+ %{method: :get, url: ^url500} ->
+ %Tesla.Env{status: 500, body: "bad request"}
+
+ %{method: :get, url: ^url200} ->
+ %Tesla.Env{
+ status: 200,
+ body:
+ ~s([{"acct":"yj455","avatar":"https://social.heldscal.la/avatar/201.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/201.jpeg"}, {"acct":"#{
+ other_user.ap_id
+ }","avatar":"https://social.heldscal.la/avatar/202.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/202.jpeg"}])
+ }
+ end)
+
+ [user: user, other_user: other_user]
+ end
+
+ clear_config(:suggestions)
+
+ test "returns empty result when suggestions disabled", %{conn: conn, user: user} do
+ Config.put([:suggestions, :enabled], false)
+
+ res =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/suggestions")
+ |> json_response(200)
+
+ assert res == []
+ end
+
+ test "returns error", %{conn: conn, user: user} do
+ Config.put([:suggestions, :enabled], true)
+ Config.put([:suggestions, :third_party_engine], "http://test500?{{host}}&{{user}}")
+
+ assert capture_log(fn ->
+ res =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/suggestions")
+ |> json_response(500)
+
+ assert res == "Something went wrong"
+ end) =~ "Could not retrieve suggestions"
+ end
+
+ test "returns suggestions", %{conn: conn, user: user, other_user: other_user} do
+ Config.put([:suggestions, :enabled], true)
+ Config.put([:suggestions, :third_party_engine], "http://test200?{{host}}&{{user}}")
+
+ res =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/suggestions")
+ |> json_response(200)
+
+ assert res == [
+ %{
+ "acct" => "yj455",
+ "avatar" => "https://social.heldscal.la/avatar/201.jpeg",
+ "avatar_static" => "https://social.heldscal.la/avatar/s/201.jpeg",
+ "id" => 0
+ },
+ %{
+ "acct" => other_user.ap_id,
+ "avatar" => "https://social.heldscal.la/avatar/202.jpeg",
+ "avatar_static" => "https://social.heldscal.la/avatar/s/202.jpeg",
+ "id" => other_user.id
+ }
+ ]
+ end
+end
diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs
index b3acb7a22..e642e3c1a 100644
--- a/test/web/mastodon_api/mastodon_api_controller_test.exs
+++ b/test/web/mastodon_api/mastodon_api_controller_test.exs
@@ -8,23 +8,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
alias Ecto.Changeset
alias Pleroma.Config
alias Pleroma.Notification
- alias Pleroma.Object
alias Pleroma.Repo
- alias Pleroma.Tests.ObanHelpers
alias Pleroma.User
- alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.CommonAPI
- alias Pleroma.Web.OAuth.App
- alias Pleroma.Web.OAuth.Token
- alias Pleroma.Web.Push
- import ExUnit.CaptureLog
import Pleroma.Factory
- import Swoosh.TestAssertions
import Tesla.Mock
- @image "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
-
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
@@ -33,941 +23,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
clear_config([:instance, :public])
clear_config([:rich_media, :enabled])
- test "Conversations", %{conn: conn} do
- user_one = insert(:user)
- user_two = insert(:user)
- user_three = insert(:user)
-
- {:ok, user_two} = User.follow(user_two, user_one)
-
- {:ok, direct} =
- CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}, @#{user_three.nickname}!",
- "visibility" => "direct"
- })
-
- {:ok, _follower_only} =
- CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}!",
- "visibility" => "private"
- })
-
- res_conn =
- conn
- |> assign(:user, user_one)
- |> get("/api/v1/conversations")
-
- assert response = json_response(res_conn, 200)
-
- assert [
- %{
- "id" => res_id,
- "accounts" => res_accounts,
- "last_status" => res_last_status,
- "unread" => unread
- }
- ] = response
-
- account_ids = Enum.map(res_accounts, & &1["id"])
- assert length(res_accounts) == 2
- assert user_two.id in account_ids
- assert user_three.id in account_ids
- assert is_binary(res_id)
- assert unread == true
- assert res_last_status["id"] == direct.id
-
- # Apparently undocumented API endpoint
- res_conn =
- conn
- |> assign(:user, user_one)
- |> post("/api/v1/conversations/#{res_id}/read")
-
- assert response = json_response(res_conn, 200)
- assert length(response["accounts"]) == 2
- assert response["last_status"]["id"] == direct.id
- assert response["unread"] == false
-
- # (vanilla) Mastodon frontend behaviour
- res_conn =
- conn
- |> assign(:user, user_one)
- |> get("/api/v1/statuses/#{res_last_status["id"]}/context")
-
- assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)
- end
-
- test "verify_credentials", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/verify_credentials")
-
- response = json_response(conn, 200)
-
- assert %{"id" => id, "source" => %{"privacy" => "public"}} = response
- assert response["pleroma"]["chat_token"]
- assert id == to_string(user.id)
- end
-
- test "verify_credentials default scope unlisted", %{conn: conn} do
- user = insert(:user, %{info: %User.Info{default_scope: "unlisted"}})
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/verify_credentials")
-
- assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
- assert id == to_string(user.id)
- end
-
- test "apps/verify_credentials", %{conn: conn} do
- token = insert(:oauth_token)
-
- conn =
- conn
- |> assign(:user, token.user)
- |> assign(:token, token)
- |> get("/api/v1/apps/verify_credentials")
-
- app = Repo.preload(token, :app).app
-
- expected = %{
- "name" => app.client_name,
- "website" => app.website,
- "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
- }
-
- assert expected == json_response(conn, 200)
- end
-
- test "user avatar can be set", %{conn: conn} do
- user = insert(:user)
- avatar_image = File.read!("test/fixtures/avatar_data_uri")
-
- conn =
- conn
- |> assign(:user, user)
- |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image})
-
- user = refresh_record(user)
-
- assert %{
- "name" => _,
- "type" => _,
- "url" => [
- %{
- "href" => _,
- "mediaType" => _,
- "type" => _
- }
- ]
- } = user.avatar
-
- assert %{"url" => _} = json_response(conn, 200)
- end
-
- test "user avatar can be reset", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""})
-
- user = User.get_cached_by_id(user.id)
-
- assert user.avatar == nil
-
- assert %{"url" => nil} = json_response(conn, 200)
- end
-
- test "can set profile banner", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})
-
- user = refresh_record(user)
- assert user.info.banner["type"] == "Image"
-
- assert %{"url" => _} = json_response(conn, 200)
- end
-
- test "can reset profile banner", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})
-
- user = refresh_record(user)
- assert user.info.banner == %{}
-
- assert %{"url" => nil} = json_response(conn, 200)
- end
-
- test "background image can be set", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image})
-
- user = refresh_record(user)
- assert user.info.background["type"] == "Image"
- assert %{"url" => _} = json_response(conn, 200)
- end
-
- test "background image can be reset", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""})
-
- user = refresh_record(user)
- assert user.info.background == %{}
- assert %{"url" => nil} = json_response(conn, 200)
- end
-
- test "creates an oauth app", %{conn: conn} do
- user = insert(:user)
- app_attrs = build(:oauth_app)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/apps", %{
- client_name: app_attrs.client_name,
- redirect_uris: app_attrs.redirect_uris
- })
-
- [app] = Repo.all(App)
-
- expected = %{
- "name" => app.client_name,
- "website" => app.website,
- "client_id" => app.client_id,
- "client_secret" => app.client_secret,
- "id" => app.id |> to_string(),
- "redirect_uri" => app.redirect_uris,
- "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
- }
-
- assert expected == json_response(conn, 200)
- end
-
- describe "user timelines" do
- test "gets a users statuses", %{conn: conn} do
- user_one = insert(:user)
- user_two = insert(:user)
- user_three = insert(:user)
-
- {:ok, user_three} = User.follow(user_three, user_one)
-
- {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
-
- {:ok, direct_activity} =
- CommonAPI.post(user_one, %{
- "status" => "Hi, @#{user_two.nickname}.",
- "visibility" => "direct"
- })
-
- {:ok, private_activity} =
- CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
-
- resp =
- conn
- |> get("/api/v1/accounts/#{user_one.id}/statuses")
-
- assert [%{"id" => id}] = json_response(resp, 200)
- assert id == to_string(activity.id)
-
- resp =
- conn
- |> assign(:user, user_two)
- |> get("/api/v1/accounts/#{user_one.id}/statuses")
-
- assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
- assert id_one == to_string(direct_activity.id)
- assert id_two == to_string(activity.id)
-
- resp =
- conn
- |> assign(:user, user_three)
- |> get("/api/v1/accounts/#{user_one.id}/statuses")
-
- assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
- assert id_one == to_string(private_activity.id)
- assert id_two == to_string(activity.id)
- end
-
- test "unimplemented pinned statuses feature", %{conn: conn} do
- note = insert(:note_activity)
- user = User.get_cached_by_ap_id(note.data["actor"])
-
- conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
-
- assert json_response(conn, 200) == []
- end
-
- test "gets an users media", %{conn: conn} do
- note = insert(:note_activity)
- user = User.get_cached_by_ap_id(note.data["actor"])
-
- file = %Plug.Upload{
- content_type: "image/jpg",
- path: Path.absname("test/fixtures/image.jpg"),
- filename: "an_image.jpg"
- }
-
- {:ok, %{id: media_id}} = ActivityPub.upload(file, actor: user.ap_id)
-
- {:ok, image_post} = CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media_id]})
-
- conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
-
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(image_post.id)
-
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
-
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(image_post.id)
- end
-
- test "gets a user's statuses without reblogs", %{conn: conn} do
- user = insert(:user)
- {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
- {:ok, _, _} = CommonAPI.repeat(post.id, user)
-
- conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
-
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(post.id)
-
- conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
-
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(post.id)
- end
-
- test "filters user's statuses by a hashtag", %{conn: conn} do
- user = insert(:user)
- {:ok, post} = CommonAPI.post(user, %{"status" => "#hashtag"})
- {:ok, _post} = CommonAPI.post(user, %{"status" => "hashtag"})
-
- conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/statuses", %{"tagged" => "hashtag"})
-
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(post.id)
- end
- end
-
- describe "user relationships" do
- test "returns the relationships for the current user", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
- {:ok, user} = User.follow(user, other_user)
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]})
-
- assert [relationship] = json_response(conn, 200)
-
- assert to_string(other_user.id) == relationship["id"]
- end
-
- test "returns an empty list on a bad request", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/relationships", %{})
-
- assert [] = json_response(conn, 200)
- end
- end
-
- describe "media upload" do
- setup do
- user = insert(:user)
-
- conn =
- build_conn()
- |> assign(:user, user)
-
- image = %Plug.Upload{
- content_type: "image/jpg",
- path: Path.absname("test/fixtures/image.jpg"),
- filename: "an_image.jpg"
- }
-
- [conn: conn, image: image]
- end
-
- clear_config([:media_proxy])
- clear_config([Pleroma.Upload])
-
- test "returns uploaded image", %{conn: conn, image: image} do
- desc = "Description of the image"
-
- media =
- conn
- |> post("/api/v1/media", %{"file" => image, "description" => desc})
- |> json_response(:ok)
-
- assert media["type"] == "image"
- assert media["description"] == desc
- assert media["id"]
-
- object = Repo.get(Object, media["id"])
- assert object.data["actor"] == User.ap_id(conn.assigns[:user])
- end
- end
-
- describe "locked accounts" do
- test "verify_credentials", %{conn: conn} do
- user = insert(:user, %{info: %User.Info{default_scope: "private"}})
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/verify_credentials")
-
- assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
- assert id == to_string(user.id)
- end
- end
-
- describe "account fetching" do
- test "works by id" do
- user = insert(:user)
-
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.id}")
-
- assert %{"id" => id} = json_response(conn, 200)
- assert id == to_string(user.id)
-
- conn =
- build_conn()
- |> get("/api/v1/accounts/-1")
-
- assert %{"error" => "Can't find user"} = json_response(conn, 404)
- end
-
- test "works by nickname" do
- user = insert(:user)
-
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.nickname}")
-
- assert %{"id" => id} = json_response(conn, 200)
- assert id == user.id
- end
-
- test "works by nickname for remote users" do
- limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
- Pleroma.Config.put([:instance, :limit_to_local_content], false)
- user = insert(:user, nickname: "user@example.com", local: false)
-
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.nickname}")
-
- Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
- assert %{"id" => id} = json_response(conn, 200)
- assert id == user.id
- end
-
- test "respects limit_to_local_content == :all for remote user nicknames" do
- limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
- Pleroma.Config.put([:instance, :limit_to_local_content], :all)
-
- user = insert(:user, nickname: "user@example.com", local: false)
-
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.nickname}")
-
- Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
- assert json_response(conn, 404)
- end
-
- test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
- limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
- Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
-
- user = insert(:user, nickname: "user@example.com", local: false)
- reading_user = insert(:user)
-
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.nickname}")
-
- assert json_response(conn, 404)
-
- conn =
- build_conn()
- |> assign(:user, reading_user)
- |> get("/api/v1/accounts/#{user.nickname}")
-
- Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
- assert %{"id" => id} = json_response(conn, 200)
- assert id == user.id
- end
- end
-
- describe "/api/v1/pleroma/mascot" do
- test "mascot upload", %{conn: conn} do
- user = insert(:user)
-
- non_image_file = %Plug.Upload{
- content_type: "audio/mpeg",
- path: Path.absname("test/fixtures/sound.mp3"),
- filename: "sound.mp3"
- }
-
- conn =
- conn
- |> assign(:user, user)
- |> put("/api/v1/pleroma/mascot", %{"file" => non_image_file})
-
- assert json_response(conn, 415)
-
- file = %Plug.Upload{
- content_type: "image/jpg",
- path: Path.absname("test/fixtures/image.jpg"),
- filename: "an_image.jpg"
- }
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> put("/api/v1/pleroma/mascot", %{"file" => file})
-
- assert %{"id" => _, "type" => image} = json_response(conn, 200)
- end
-
- test "mascot retrieving", %{conn: conn} do
- user = insert(:user)
- # When user hasn't set a mascot, we should just get pleroma tan back
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/pleroma/mascot")
-
- assert %{"url" => url} = json_response(conn, 200)
- assert url =~ "pleroma-fox-tan-smol"
-
- # When a user sets their mascot, we should get that back
- file = %Plug.Upload{
- content_type: "image/jpg",
- path: Path.absname("test/fixtures/image.jpg"),
- filename: "an_image.jpg"
- }
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> put("/api/v1/pleroma/mascot", %{"file" => file})
-
- assert json_response(conn, 200)
-
- user = User.get_cached_by_id(user.id)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> get("/api/v1/pleroma/mascot")
-
- assert %{"url" => url, "type" => "image"} = json_response(conn, 200)
- assert url =~ "an_image"
- end
- end
-
- test "getting followers", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
- {:ok, user} = User.follow(user, other_user)
-
- conn =
- conn
- |> get("/api/v1/accounts/#{other_user.id}/followers")
-
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(user.id)
- end
-
- test "getting followers, hide_followers", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user, %{info: %{hide_followers: true}})
- {:ok, _user} = User.follow(user, other_user)
-
- conn =
- conn
- |> get("/api/v1/accounts/#{other_user.id}/followers")
-
- assert [] == json_response(conn, 200)
- end
-
- test "getting followers, hide_followers, same user requesting", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user, %{info: %{hide_followers: true}})
- {:ok, _user} = User.follow(user, other_user)
-
- conn =
- conn
- |> assign(:user, other_user)
- |> get("/api/v1/accounts/#{other_user.id}/followers")
-
- refute [] == json_response(conn, 200)
- end
-
- test "getting followers, pagination", %{conn: conn} do
- user = insert(:user)
- follower1 = insert(:user)
- follower2 = insert(:user)
- follower3 = insert(:user)
- {:ok, _} = User.follow(follower1, user)
- {:ok, _} = User.follow(follower2, user)
- {:ok, _} = User.follow(follower3, user)
-
- conn =
- conn
- |> assign(:user, user)
-
- res_conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
-
- assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
- assert id3 == follower3.id
- assert id2 == follower2.id
-
- res_conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
-
- assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
- assert id2 == follower2.id
- assert id1 == follower1.id
-
- res_conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
-
- assert [%{"id" => id2}] = json_response(res_conn, 200)
- assert id2 == follower2.id
-
- assert [link_header] = get_resp_header(res_conn, "link")
- assert link_header =~ ~r/min_id=#{follower2.id}/
- assert link_header =~ ~r/max_id=#{follower2.id}/
- end
-
- test "getting following", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
- {:ok, user} = User.follow(user, other_user)
-
- conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/following")
-
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(other_user.id)
- end
-
- test "getting following, hide_follows", %{conn: conn} do
- user = insert(:user, %{info: %{hide_follows: true}})
- other_user = insert(:user)
- {:ok, user} = User.follow(user, other_user)
-
- conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/following")
-
- assert [] == json_response(conn, 200)
- end
-
- test "getting following, hide_follows, same user requesting", %{conn: conn} do
- user = insert(:user, %{info: %{hide_follows: true}})
- other_user = insert(:user)
- {:ok, user} = User.follow(user, other_user)
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/#{user.id}/following")
-
- refute [] == json_response(conn, 200)
- end
-
- test "getting following, pagination", %{conn: conn} do
- user = insert(:user)
- following1 = insert(:user)
- following2 = insert(:user)
- following3 = insert(:user)
- {:ok, _} = User.follow(user, following1)
- {:ok, _} = User.follow(user, following2)
- {:ok, _} = User.follow(user, following3)
-
- conn =
- conn
- |> assign(:user, user)
-
- res_conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
-
- assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
- assert id3 == following3.id
- assert id2 == following2.id
-
- res_conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
-
- assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
- assert id2 == following2.id
- assert id1 == following1.id
-
- res_conn =
- conn
- |> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
-
- assert [%{"id" => id2}] = json_response(res_conn, 200)
- assert id2 == following2.id
-
- assert [link_header] = get_resp_header(res_conn, "link")
- assert link_header =~ ~r/min_id=#{following2.id}/
- assert link_header =~ ~r/max_id=#{following2.id}/
- end
-
- test "following / unfollowing a user", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/accounts/#{other_user.id}/follow")
-
- assert %{"id" => _id, "following" => true} = json_response(conn, 200)
-
- user = User.get_cached_by_id(user.id)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> post("/api/v1/accounts/#{other_user.id}/unfollow")
-
- assert %{"id" => _id, "following" => false} = json_response(conn, 200)
-
- user = User.get_cached_by_id(user.id)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> post("/api/v1/follows", %{"uri" => other_user.nickname})
-
- assert %{"id" => id} = json_response(conn, 200)
- assert id == to_string(other_user.id)
- end
-
- test "following without reblogs" do
- follower = insert(:user)
- followed = insert(:user)
- other_user = insert(:user)
-
- conn =
- build_conn()
- |> assign(:user, follower)
- |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=false")
-
- assert %{"showing_reblogs" => false} = json_response(conn, 200)
-
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"})
- {:ok, reblog, _} = CommonAPI.repeat(activity.id, followed)
-
- conn =
- build_conn()
- |> assign(:user, User.get_cached_by_id(follower.id))
- |> get("/api/v1/timelines/home")
-
- assert [] == json_response(conn, 200)
-
- conn =
- build_conn()
- |> assign(:user, follower)
- |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
-
- assert %{"showing_reblogs" => true} = json_response(conn, 200)
-
- conn =
- build_conn()
- |> assign(:user, User.get_cached_by_id(follower.id))
- |> get("/api/v1/timelines/home")
-
- expected_activity_id = reblog.id
- assert [%{"id" => ^expected_activity_id}] = json_response(conn, 200)
- end
-
- test "following / unfollowing errors" do
- user = insert(:user)
-
- conn =
- build_conn()
- |> assign(:user, user)
-
- # self follow
- conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
-
- # self unfollow
- user = User.get_cached_by_id(user.id)
- conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow")
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
-
- # self follow via uri
- user = User.get_cached_by_id(user.id)
- conn_res = post(conn, "/api/v1/follows", %{"uri" => user.nickname})
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
-
- # follow non existing user
- conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
-
- # follow non existing user via uri
- conn_res = post(conn, "/api/v1/follows", %{"uri" => "doesntexist"})
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
-
- # unfollow non existing user
- conn_res = post(conn, "/api/v1/accounts/doesntexist/unfollow")
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
- end
-
- describe "mute/unmute" do
- test "with notifications", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/accounts/#{other_user.id}/mute")
-
- response = json_response(conn, 200)
-
- assert %{"id" => _id, "muting" => true, "muting_notifications" => true} = response
- user = User.get_cached_by_id(user.id)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> post("/api/v1/accounts/#{other_user.id}/unmute")
-
- response = json_response(conn, 200)
- assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
- end
-
- test "without notifications", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
-
- response = json_response(conn, 200)
-
- assert %{"id" => _id, "muting" => true, "muting_notifications" => false} = response
- user = User.get_cached_by_id(user.id)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> post("/api/v1/accounts/#{other_user.id}/unmute")
-
- response = json_response(conn, 200)
- assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
- end
- end
-
- describe "subscribing / unsubscribing" do
- test "subscribing / unsubscribing to a user", %{conn: conn} do
- user = insert(:user)
- subscription_target = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
-
- assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
-
- assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
- end
- end
-
- describe "subscribing" do
- test "returns 404 when subscription_target not found", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/pleroma/accounts/target_id/subscribe")
-
- assert %{"error" => "Record not found"} = json_response(conn, 404)
- end
- end
-
- describe "unsubscribing" do
- test "returns 404 when subscription_target not found", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/pleroma/accounts/target_id/unsubscribe")
-
- assert %{"error" => "Record not found"} = json_response(conn, 404)
- end
- end
-
test "getting a list of mutes", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)
@@ -983,27 +38,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
end
- test "blocking / unblocking a user", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/accounts/#{other_user.id}/block")
-
- assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
-
- user = User.get_cached_by_id(user.id)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> post("/api/v1/accounts/#{other_user.id}/unblock")
-
- assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
- end
-
test "getting a list of blocks", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)
@@ -1080,199 +114,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
assert [] = json_response(third_conn, 200)
end
- describe "getting favorites timeline of specified user" do
- setup do
- [current_user, user] = insert_pair(:user, %{info: %{hide_favorites: false}})
- [current_user: current_user, user: user]
- end
-
- test "returns list of statuses favorited by specified user", %{
- conn: conn,
- current_user: current_user,
- user: user
- } do
- [activity | _] = insert_pair(:note_activity)
- CommonAPI.favorite(activity.id, user)
-
- response =
- conn
- |> assign(:user, current_user)
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(:ok)
-
- [like] = response
-
- assert length(response) == 1
- assert like["id"] == activity.id
- end
-
- test "returns favorites for specified user_id when user is not logged in", %{
- conn: conn,
- user: user
- } do
- activity = insert(:note_activity)
- CommonAPI.favorite(activity.id, user)
-
- response =
- conn
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(:ok)
-
- assert length(response) == 1
- end
-
- test "returns favorited DM only when user is logged in and he is one of recipients", %{
- conn: conn,
- current_user: current_user,
- user: user
- } do
- {:ok, direct} =
- CommonAPI.post(current_user, %{
- "status" => "Hi @#{user.nickname}!",
- "visibility" => "direct"
- })
-
- CommonAPI.favorite(direct.id, user)
-
- response =
- conn
- |> assign(:user, current_user)
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(:ok)
-
- assert length(response) == 1
-
- anonymous_response =
- conn
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(:ok)
-
- assert Enum.empty?(anonymous_response)
- end
-
- test "does not return others' favorited DM when user is not one of recipients", %{
- conn: conn,
- current_user: current_user,
- user: user
- } do
- user_two = insert(:user)
-
- {:ok, direct} =
- CommonAPI.post(user_two, %{
- "status" => "Hi @#{user.nickname}!",
- "visibility" => "direct"
- })
-
- CommonAPI.favorite(direct.id, user)
-
- response =
- conn
- |> assign(:user, current_user)
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(:ok)
-
- assert Enum.empty?(response)
- end
-
- test "paginates favorites using since_id and max_id", %{
- conn: conn,
- current_user: current_user,
- user: user
- } do
- activities = insert_list(10, :note_activity)
-
- Enum.each(activities, fn activity ->
- CommonAPI.favorite(activity.id, user)
- end)
-
- third_activity = Enum.at(activities, 2)
- seventh_activity = Enum.at(activities, 6)
-
- response =
- conn
- |> assign(:user, current_user)
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{
- since_id: third_activity.id,
- max_id: seventh_activity.id
- })
- |> json_response(:ok)
-
- assert length(response) == 3
- refute third_activity in response
- refute seventh_activity in response
- end
-
- test "limits favorites using limit parameter", %{
- conn: conn,
- current_user: current_user,
- user: user
- } do
- 7
- |> insert_list(:note_activity)
- |> Enum.each(fn activity ->
- CommonAPI.favorite(activity.id, user)
- end)
-
- response =
- conn
- |> assign(:user, current_user)
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{limit: "3"})
- |> json_response(:ok)
-
- assert length(response) == 3
- end
-
- test "returns empty response when user does not have any favorited statuses", %{
- conn: conn,
- current_user: current_user,
- user: user
- } do
- response =
- conn
- |> assign(:user, current_user)
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(:ok)
-
- assert Enum.empty?(response)
- end
-
- test "returns 404 error when specified user is not exist", %{conn: conn} do
- conn = get(conn, "/api/v1/pleroma/accounts/test/favourites")
-
- assert json_response(conn, 404) == %{"error" => "Record not found"}
- end
-
- test "returns 403 error when user has hidden own favorites", %{
- conn: conn,
- current_user: current_user
- } do
- user = insert(:user, %{info: %{hide_favorites: true}})
- activity = insert(:note_activity)
- CommonAPI.favorite(activity.id, user)
-
- conn =
- conn
- |> assign(:user, current_user)
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
-
- assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
- end
-
- test "hides favorites for new users by default", %{conn: conn, current_user: current_user} do
- user = insert(:user)
- activity = insert(:note_activity)
- CommonAPI.favorite(activity.id, user)
-
- conn =
- conn
- |> assign(:user, current_user)
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
-
- assert user.info.hide_favorites
- assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
- end
- end
-
test "get instance information", %{conn: conn} do
conn = get(conn, "/api/v1/instance")
assert result = json_response(conn, 200)
@@ -1292,7 +133,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
"thumbnail" => _,
"languages" => _,
"registrations" => _,
- "poll_limits" => _
+ "poll_limits" => _,
+ "upload_limit" => _,
+ "avatar_upload_limit" => _,
+ "background_upload_limit" => _,
+ "banner_upload_limit" => _
} = result
assert email == from_config_email
@@ -1357,108 +202,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
assert user.info.settings == %{"programming" => "socks"}
end
- describe "pinned statuses" do
- setup do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
-
- [user: user, activity: activity]
- end
-
- test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
- {:ok, _} = CommonAPI.pin(activity.id, user)
-
- result =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
- |> json_response(200)
-
- id_str = to_string(activity.id)
-
- assert [%{"id" => ^id_str, "pinned" => true}] = result
- end
- end
-
- describe "reports" do
- setup do
- reporter = insert(:user)
- target_user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
-
- [reporter: reporter, target_user: target_user, activity: activity]
- end
-
- test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
- assert %{"action_taken" => false, "id" => _} =
- conn
- |> assign(:user, reporter)
- |> post("/api/v1/reports", %{"account_id" => target_user.id})
- |> json_response(200)
- end
-
- test "submit a report with statuses and comment", %{
- conn: conn,
- reporter: reporter,
- target_user: target_user,
- activity: activity
- } do
- assert %{"action_taken" => false, "id" => _} =
- conn
- |> assign(:user, reporter)
- |> post("/api/v1/reports", %{
- "account_id" => target_user.id,
- "status_ids" => [activity.id],
- "comment" => "bad status!",
- "forward" => "false"
- })
- |> json_response(200)
- end
-
- test "account_id is required", %{
- conn: conn,
- reporter: reporter,
- activity: activity
- } do
- assert %{"error" => "Valid `account_id` required"} =
- conn
- |> assign(:user, reporter)
- |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
- |> json_response(400)
- end
-
- test "comment must be up to the size specified in the config", %{
- conn: conn,
- reporter: reporter,
- target_user: target_user
- } do
- max_size = Config.get([:instance, :max_report_comment_size], 1000)
- comment = String.pad_trailing("a", max_size + 1, "a")
-
- error = %{"error" => "Comment must be up to #{max_size} characters"}
-
- assert ^error =
- conn
- |> assign(:user, reporter)
- |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
- |> json_response(400)
- end
-
- test "returns error when account is not exist", %{
- conn: conn,
- reporter: reporter,
- activity: activity
- } do
- conn =
- conn
- |> assign(:user, reporter)
- |> post("/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"})
-
- assert json_response(conn, 400) == %{"error" => "Account not found"}
- end
- end
-
describe "link headers" do
test "preserves parameters in link headers", %{conn: conn} do
user = insert(:user)
@@ -1491,32 +234,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
end
end
- test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
- # Need to set an old-style integer ID to reproduce the problem
- # (these are no longer assigned to new accounts but were preserved
- # for existing accounts during the migration to flakeIDs)
- user_one = insert(:user, %{id: 1212})
- user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
-
- resp_one =
- conn
- |> get("/api/v1/accounts/#{user_one.id}")
-
- resp_two =
- conn
- |> get("/api/v1/accounts/#{user_two.nickname}")
-
- resp_three =
- conn
- |> get("/api/v1/accounts/#{user_two.id}")
-
- acc_one = json_response(resp_one, 200)
- acc_two = json_response(resp_two, 200)
- acc_three = json_response(resp_three, 200)
- refute acc_one == acc_two
- assert acc_two == acc_three
- end
-
describe "custom emoji" do
test "with tags", %{conn: conn} do
[emoji | _body] =
@@ -1588,609 +305,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
assert return_to == path
end
-
- test "redirects to the saved path after log in", %{conn: conn, path: path} do
- app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
- auth = insert(:oauth_authorization, app: app)
-
- conn =
- conn
- |> put_session(:return_to, path)
- |> get("/web/login", %{code: auth.token})
-
- assert conn.status == 302
- assert redirected_to(conn) == path
- end
-
- test "redirects to the getting-started page when referer is not present", %{conn: conn} do
- app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
- auth = insert(:oauth_authorization, app: app)
-
- conn = get(conn, "/web/login", %{code: auth.token})
-
- assert conn.status == 302
- assert redirected_to(conn) == "/web/getting-started"
- end
- end
-
- describe "create account by app" do
- setup do
- valid_params = %{
- username: "lain",
- email: "lain@example.org",
- password: "PlzDontHackLain",
- agreement: true
- }
-
- [valid_params: valid_params]
- end
-
- test "Account registration via Application", %{conn: conn} do
- conn =
- conn
- |> post("/api/v1/apps", %{
- client_name: "client_name",
- redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
- scopes: "read, write, follow"
- })
-
- %{
- "client_id" => client_id,
- "client_secret" => client_secret,
- "id" => _,
- "name" => "client_name",
- "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
- "vapid_key" => _,
- "website" => nil
- } = json_response(conn, 200)
-
- conn =
- conn
- |> post("/oauth/token", %{
- grant_type: "client_credentials",
- client_id: client_id,
- client_secret: client_secret
- })
-
- assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
- json_response(conn, 200)
-
- assert token
- token_from_db = Repo.get_by(Token, token: token)
- assert token_from_db
- assert refresh
- assert scope == "read write follow"
-
- conn =
- build_conn()
- |> put_req_header("authorization", "Bearer " <> token)
- |> post("/api/v1/accounts", %{
- username: "lain",
- email: "lain@example.org",
- password: "PlzDontHackLain",
- bio: "Test Bio",
- agreement: true
- })
-
- %{
- "access_token" => token,
- "created_at" => _created_at,
- "scope" => _scope,
- "token_type" => "Bearer"
- } = json_response(conn, 200)
-
- token_from_db = Repo.get_by(Token, token: token)
- assert token_from_db
- token_from_db = Repo.preload(token_from_db, :user)
- assert token_from_db.user
-
- assert token_from_db.user.info.confirmation_pending
- end
-
- test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
- _user = insert(:user, email: "lain@example.org")
- app_token = insert(:oauth_token, user: nil)
-
- conn =
- conn
- |> put_req_header("authorization", "Bearer " <> app_token.token)
-
- res = post(conn, "/api/v1/accounts", valid_params)
- assert json_response(res, 400) == %{"error" => "{\"email\":[\"has already been taken\"]}"}
- end
-
- test "rate limit", %{conn: conn} do
- app_token = insert(:oauth_token, user: nil)
-
- conn =
- put_req_header(conn, "authorization", "Bearer " <> app_token.token)
- |> Map.put(:remote_ip, {15, 15, 15, 15})
-
- for i <- 1..5 do
- conn =
- conn
- |> post("/api/v1/accounts", %{
- username: "#{i}lain",
- email: "#{i}lain@example.org",
- password: "PlzDontHackLain",
- agreement: true
- })
-
- %{
- "access_token" => token,
- "created_at" => _created_at,
- "scope" => _scope,
- "token_type" => "Bearer"
- } = json_response(conn, 200)
-
- token_from_db = Repo.get_by(Token, token: token)
- assert token_from_db
- token_from_db = Repo.preload(token_from_db, :user)
- assert token_from_db.user
-
- assert token_from_db.user.info.confirmation_pending
- end
-
- conn =
- conn
- |> post("/api/v1/accounts", %{
- username: "6lain",
- email: "6lain@example.org",
- password: "PlzDontHackLain",
- agreement: true
- })
-
- assert json_response(conn, :too_many_requests) == %{"error" => "Throttled"}
- end
-
- test "returns bad_request if missing required params", %{
- conn: conn,
- valid_params: valid_params
- } do
- app_token = insert(:oauth_token, user: nil)
-
- conn =
- conn
- |> put_req_header("authorization", "Bearer " <> app_token.token)
-
- res = post(conn, "/api/v1/accounts", valid_params)
- assert json_response(res, 200)
-
- [{127, 0, 0, 1}, {127, 0, 0, 2}, {127, 0, 0, 3}, {127, 0, 0, 4}]
- |> Stream.zip(valid_params)
- |> Enum.each(fn {ip, {attr, _}} ->
- res =
- conn
- |> Map.put(:remote_ip, ip)
- |> post("/api/v1/accounts", Map.delete(valid_params, attr))
- |> json_response(400)
-
- assert res == %{"error" => "Missing parameters"}
- end)
- end
-
- test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
- conn =
- conn
- |> put_req_header("authorization", "Bearer " <> "invalid-token")
-
- res = post(conn, "/api/v1/accounts", valid_params)
- assert json_response(res, 403) == %{"error" => "Invalid credentials"}
- end
- end
-
- describe "GET /api/v1/polls/:id" do
- test "returns poll entity for object id", %{conn: conn} do
- user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "Pleroma does",
- "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20}
- })
-
- object = Object.normalize(activity)
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/polls/#{object.id}")
-
- response = json_response(conn, 200)
- id = to_string(object.id)
- assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
- end
-
- test "does not expose polls for private statuses", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "Pleroma does",
- "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20},
- "visibility" => "private"
- })
-
- object = Object.normalize(activity)
-
- conn =
- conn
- |> assign(:user, other_user)
- |> get("/api/v1/polls/#{object.id}")
-
- assert json_response(conn, 404)
- end
- end
-
- describe "POST /api/v1/polls/:id/votes" do
- test "votes are added to the poll", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "A very delicious sandwich",
- "poll" => %{
- "options" => ["Lettuce", "Grilled Bacon", "Tomato"],
- "expires_in" => 20,
- "multiple" => true
- }
- })
-
- object = Object.normalize(activity)
-
- conn =
- conn
- |> assign(:user, other_user)
- |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
-
- assert json_response(conn, 200)
- object = Object.get_by_id(object.id)
-
- assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
- total_items == 1
- end)
- end
-
- test "author can't vote", %{conn: conn} do
- user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "Am I cute?",
- "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
- })
-
- object = Object.normalize(activity)
-
- assert conn
- |> assign(:user, user)
- |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [1]})
- |> json_response(422) == %{"error" => "Poll's author can't vote"}
-
- object = Object.get_by_id(object.id)
-
- refute Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 1
- end
-
- test "does not allow multiple choices on a single-choice question", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "The glass is",
- "poll" => %{"options" => ["half empty", "half full"], "expires_in" => 20}
- })
-
- object = Object.normalize(activity)
-
- assert conn
- |> assign(:user, other_user)
- |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1]})
- |> json_response(422) == %{"error" => "Too many choices"}
-
- object = Object.get_by_id(object.id)
-
- refute Enum.any?(object.data["oneOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
- total_items == 1
- end)
- end
-
- test "does not allow choice index to be greater than options count", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "Am I cute?",
- "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
- })
-
- object = Object.normalize(activity)
-
- conn =
- conn
- |> assign(:user, other_user)
- |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]})
-
- assert json_response(conn, 422) == %{"error" => "Invalid indices"}
- end
-
- test "returns 404 error when object is not exist", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/polls/1/votes", %{"choices" => [0]})
-
- assert json_response(conn, 404) == %{"error" => "Record not found"}
- end
-
- test "returns 404 when poll is private and not available for user", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "Am I cute?",
- "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20},
- "visibility" => "private"
- })
-
- object = Object.normalize(activity)
-
- conn =
- conn
- |> assign(:user, other_user)
- |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]})
-
- assert json_response(conn, 404) == %{"error" => "Record not found"}
- end
- end
-
- describe "POST /auth/password, with valid parameters" do
- setup %{conn: conn} do
- user = insert(:user)
- conn = post(conn, "/auth/password?email=#{user.email}")
- %{conn: conn, user: user}
- end
-
- test "it returns 204", %{conn: conn} do
- assert json_response(conn, :no_content)
- end
-
- test "it creates a PasswordResetToken record for user", %{user: user} do
- token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
- assert token_record
- end
-
- test "it sends an email to user", %{user: user} do
- ObanHelpers.perform_all()
- token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
-
- email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
- notify_email = Config.get([:instance, :notify_email])
- instance_name = Config.get([:instance, :name])
-
- assert_email_sent(
- from: {instance_name, notify_email},
- to: {user.name, user.email},
- html_body: email.html_body
- )
- end
- end
-
- describe "POST /auth/password, with invalid parameters" do
- setup do
- user = insert(:user)
- {:ok, user: user}
- end
-
- test "it returns 404 when user is not found", %{conn: conn, user: user} do
- conn = post(conn, "/auth/password?email=nonexisting_#{user.email}")
- assert conn.status == 404
- assert conn.resp_body == ""
- end
-
- test "it returns 400 when user is not local", %{conn: conn, user: user} do
- {:ok, user} = Repo.update(Changeset.change(user, local: false))
- conn = post(conn, "/auth/password?email=#{user.email}")
- assert conn.status == 400
- assert conn.resp_body == ""
- end
- end
-
- describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
- setup do
- {:ok, user} =
- insert(:user)
- |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true))
- |> Repo.update()
-
- assert user.info.confirmation_pending
-
- [user: user]
- end
-
- clear_config([:instance, :account_activation_required]) do
- Config.put([:instance, :account_activation_required], true)
- end
-
- test "resend account confirmation email", %{conn: conn, user: user} do
- conn
- |> assign(:user, user)
- |> post("/api/v1/pleroma/accounts/confirmation_resend?email=#{user.email}")
- |> json_response(:no_content)
-
- ObanHelpers.perform_all()
-
- email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
- notify_email = Config.get([:instance, :notify_email])
- instance_name = Config.get([:instance, :name])
-
- assert_email_sent(
- from: {instance_name, notify_email},
- to: {user.name, user.email},
- html_body: email.html_body
- )
- end
- end
-
- describe "GET /api/v1/suggestions" do
- setup do
- user = insert(:user)
- other_user = insert(:user)
- host = Config.get([Pleroma.Web.Endpoint, :url, :host])
- url500 = "http://test500?#{host}&#{user.nickname}"
- url200 = "http://test200?#{host}&#{user.nickname}"
-
- mock(fn
- %{method: :get, url: ^url500} ->
- %Tesla.Env{status: 500, body: "bad request"}
-
- %{method: :get, url: ^url200} ->
- %Tesla.Env{
- status: 200,
- body:
- ~s([{"acct":"yj455","avatar":"https://social.heldscal.la/avatar/201.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/201.jpeg"}, {"acct":"#{
- other_user.ap_id
- }","avatar":"https://social.heldscal.la/avatar/202.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/202.jpeg"}])
- }
- end)
-
- [user: user, other_user: other_user]
- end
-
- clear_config(:suggestions)
-
- test "returns empty result when suggestions disabled", %{conn: conn, user: user} do
- Config.put([:suggestions, :enabled], false)
-
- res =
- conn
- |> assign(:user, user)
- |> get("/api/v1/suggestions")
- |> json_response(200)
-
- assert res == []
- end
-
- test "returns error", %{conn: conn, user: user} do
- Config.put([:suggestions, :enabled], true)
- Config.put([:suggestions, :third_party_engine], "http://test500?{{host}}&{{user}}")
-
- assert capture_log(fn ->
- res =
- conn
- |> assign(:user, user)
- |> get("/api/v1/suggestions")
- |> json_response(500)
-
- assert res == "Something went wrong"
- end) =~ "Could not retrieve suggestions"
- end
-
- test "returns suggestions", %{conn: conn, user: user, other_user: other_user} do
- Config.put([:suggestions, :enabled], true)
- Config.put([:suggestions, :third_party_engine], "http://test200?{{host}}&{{user}}")
-
- res =
- conn
- |> assign(:user, user)
- |> get("/api/v1/suggestions")
- |> json_response(200)
-
- assert res == [
- %{
- "acct" => "yj455",
- "avatar" => "https://social.heldscal.la/avatar/201.jpeg",
- "avatar_static" => "https://social.heldscal.la/avatar/s/201.jpeg",
- "id" => 0
- },
- %{
- "acct" => other_user.ap_id,
- "avatar" => "https://social.heldscal.la/avatar/202.jpeg",
- "avatar_static" => "https://social.heldscal.la/avatar/s/202.jpeg",
- "id" => other_user.id
- }
- ]
- end
- end
-
- describe "PUT /api/v1/media/:id" do
- setup do
- actor = insert(:user)
-
- file = %Plug.Upload{
- content_type: "image/jpg",
- path: Path.absname("test/fixtures/image.jpg"),
- filename: "an_image.jpg"
- }
-
- {:ok, %Object{} = object} =
- ActivityPub.upload(
- file,
- actor: User.ap_id(actor),
- description: "test-m"
- )
-
- [actor: actor, object: object]
- end
-
- test "updates name of media", %{conn: conn, actor: actor, object: object} do
- media =
- conn
- |> assign(:user, actor)
- |> put("/api/v1/media/#{object.id}", %{"description" => "test-media"})
- |> json_response(:ok)
-
- assert media["description"] == "test-media"
- assert refresh_record(object).data["name"] == "test-media"
- end
-
- test "returns error wheb request is bad", %{conn: conn, actor: actor, object: object} do
- media =
- conn
- |> assign(:user, actor)
- |> put("/api/v1/media/#{object.id}", %{})
- |> json_response(400)
-
- assert media == %{"error" => "bad_request"}
- end
- end
-
- describe "DELETE /auth/sign_out" do
- test "redirect to root page", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> delete("/auth/sign_out")
-
- assert conn.status == 302
- assert redirected_to(conn) == "/"
- end
- end
-
- describe "GET /api/v1/accounts/:id/lists - account_lists" do
- test "returns lists to which the account belongs", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
- assert {:ok, %Pleroma.List{} = list} = Pleroma.List.create("Test List", user)
- {:ok, %{following: _following}} = Pleroma.List.follow(list, other_user)
-
- res =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/#{other_user.id}/lists")
- |> json_response(200)
-
- assert res == [%{"id" => to_string(list.id), "title" => "Test List"}]
- end
end
describe "empty_array, stubs for mastodon api" do
diff --git a/test/web/mastodon_api/mastodon_api_test.exs b/test/web/mastodon_api/mastodon_api_test.exs
index 848fce7ad..7fcb2bd55 100644
--- a/test/web/mastodon_api/mastodon_api_test.exs
+++ b/test/web/mastodon_api/mastodon_api_test.exs
@@ -75,9 +75,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPITest do
User.subscribe(subscriber, user)
- {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin @#{subscriber.nickname}"})
+ {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
- {:ok, status1} = CommonAPI.post(user, %{"status" => "Magi @#{subscriber.nickname}"})
+ {:ok, status1} = CommonAPI.post(user, %{"status" => "Magi"})
{:ok, [notification]} = Notification.create_notifications(status)
{:ok, [notification1]} = Notification.create_notifications(status1)
res = MastodonAPI.get_notifications(subscriber)
diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs
index f2f334992..62b2ab7e3 100644
--- a/test/web/mastodon_api/views/account_view_test.exs
+++ b/test/web/mastodon_api/views/account_view_test.exs
@@ -88,7 +88,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
}
}
- assert expected == AccountView.render("account.json", %{user: user})
+ assert expected == AccountView.render("show.json", %{user: user})
end
test "Represent the user account for the account owner" do
@@ -106,7 +106,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
assert %{
pleroma: %{notification_settings: ^notification_settings},
source: %{privacy: ^privacy}
- } = AccountView.render("account.json", %{user: user, for: user})
+ } = AccountView.render("show.json", %{user: user, for: user})
end
test "Represent a Service(bot) account" do
@@ -160,13 +160,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
}
}
- assert expected == AccountView.render("account.json", %{user: user})
+ assert expected == AccountView.render("show.json", %{user: user})
end
test "Represent a deactivated user for an admin" do
admin = insert(:user, %{info: %{is_admin: true}})
deactivated_user = insert(:user, %{info: %{deactivated: true}})
- represented = AccountView.render("account.json", %{user: deactivated_user, for: admin})
+ represented = AccountView.render("show.json", %{user: deactivated_user, for: admin})
assert represented[:pleroma][:deactivated] == true
end
@@ -348,27 +348,27 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
}
}
- assert expected == AccountView.render("account.json", %{user: user, for: other_user})
+ assert expected == AccountView.render("show.json", %{user: user, for: other_user})
end
test "returns the settings store if the requesting user is the represented user and it's requested specifically" do
user = insert(:user, %{info: %User.Info{pleroma_settings_store: %{fe: "test"}}})
result =
- AccountView.render("account.json", %{user: user, for: user, with_pleroma_settings: true})
+ AccountView.render("show.json", %{user: user, for: user, with_pleroma_settings: true})
assert result.pleroma.settings_store == %{:fe => "test"}
- result = AccountView.render("account.json", %{user: user, with_pleroma_settings: true})
+ result = AccountView.render("show.json", %{user: user, with_pleroma_settings: true})
assert result.pleroma[:settings_store] == nil
- result = AccountView.render("account.json", %{user: user, for: user})
+ result = AccountView.render("show.json", %{user: user, for: user})
assert result.pleroma[:settings_store] == nil
end
test "sanitizes display names" do
user = insert(:user, name: "<marquee> username </marquee>")
- result = AccountView.render("account.json", %{user: user})
+ result = AccountView.render("show.json", %{user: user})
refute result.display_name == "<marquee> username </marquee>"
end
@@ -391,7 +391,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
followers_count: 0,
following_count: 0,
pleroma: %{hide_follows_count: true, hide_followers_count: true}
- } = AccountView.render("account.json", %{user: user})
+ } = AccountView.render("show.json", %{user: user})
end
test "shows when follows/followers are hidden" do
@@ -404,7 +404,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
followers_count: 1,
following_count: 1,
pleroma: %{hide_follows: true, hide_followers: true}
- } = AccountView.render("account.json", %{user: user})
+ } = AccountView.render("show.json", %{user: user})
end
test "shows actual follower/following count to the account owner" do
@@ -416,7 +416,82 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
assert %{
followers_count: 1,
following_count: 1
- } = AccountView.render("account.json", %{user: user, for: user})
+ } = AccountView.render("show.json", %{user: user, for: user})
+ end
+ end
+
+ describe "follow requests counter" do
+ test "shows zero when no follow requests are pending" do
+ user = insert(:user)
+
+ assert %{follow_requests_count: 0} =
+ AccountView.render("show.json", %{user: user, for: user})
+
+ other_user = insert(:user)
+ {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
+
+ assert %{follow_requests_count: 0} =
+ AccountView.render("show.json", %{user: user, for: user})
+ end
+
+ test "shows non-zero when follow requests are pending" do
+ user = insert(:user, %{info: %{locked: true}})
+
+ assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
+
+ other_user = insert(:user)
+ {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
+
+ assert %{locked: true, follow_requests_count: 1} =
+ AccountView.render("show.json", %{user: user, for: user})
+ end
+
+ test "decreases when accepting a follow request" do
+ user = insert(:user, %{info: %{locked: true}})
+
+ assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
+
+ other_user = insert(:user)
+ {:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
+
+ assert %{locked: true, follow_requests_count: 1} =
+ AccountView.render("show.json", %{user: user, for: user})
+
+ {:ok, _other_user} = CommonAPI.accept_follow_request(other_user, user)
+
+ assert %{locked: true, follow_requests_count: 0} =
+ AccountView.render("show.json", %{user: user, for: user})
+ end
+
+ test "decreases when rejecting a follow request" do
+ user = insert(:user, %{info: %{locked: true}})
+
+ assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
+
+ other_user = insert(:user)
+ {:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
+
+ assert %{locked: true, follow_requests_count: 1} =
+ AccountView.render("show.json", %{user: user, for: user})
+
+ {:ok, _other_user} = CommonAPI.reject_follow_request(other_user, user)
+
+ assert %{locked: true, follow_requests_count: 0} =
+ AccountView.render("show.json", %{user: user, for: user})
+ end
+
+ test "shows non-zero when historical unapproved requests are present" do
+ user = insert(:user, %{info: %{locked: true}})
+
+ assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
+
+ other_user = insert(:user)
+ {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
+
+ {:ok, user} = User.update_info(user, &User.Info.user_upgrade(&1, %{locked: false}))
+
+ assert %{locked: false, follow_requests_count: 1} =
+ AccountView.render("show.json", %{user: user, for: user})
end
end
end
diff --git a/test/web/mastodon_api/views/notification_view_test.exs b/test/web/mastodon_api/views/notification_view_test.exs
index 86268fcfa..81ab82e2b 100644
--- a/test/web/mastodon_api/views/notification_view_test.exs
+++ b/test/web/mastodon_api/views/notification_view_test.exs
@@ -27,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
id: to_string(notification.id),
pleroma: %{is_seen: false},
type: "mention",
- account: AccountView.render("account.json", %{user: user, for: mentioned_user}),
+ account: AccountView.render("show.json", %{user: user, for: mentioned_user}),
status: StatusView.render("show.json", %{activity: activity, for: mentioned_user}),
created_at: Utils.to_masto_date(notification.inserted_at)
}
@@ -50,7 +50,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
id: to_string(notification.id),
pleroma: %{is_seen: false},
type: "favourite",
- account: AccountView.render("account.json", %{user: another_user, for: user}),
+ account: AccountView.render("show.json", %{user: another_user, for: user}),
status: StatusView.render("show.json", %{activity: create_activity, for: user}),
created_at: Utils.to_masto_date(notification.inserted_at)
}
@@ -72,7 +72,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
id: to_string(notification.id),
pleroma: %{is_seen: false},
type: "reblog",
- account: AccountView.render("account.json", %{user: another_user, for: user}),
+ account: AccountView.render("show.json", %{user: another_user, for: user}),
status: StatusView.render("show.json", %{activity: reblog_activity, for: user}),
created_at: Utils.to_masto_date(notification.inserted_at)
}
@@ -92,7 +92,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
id: to_string(notification.id),
pleroma: %{is_seen: false},
type: "follow",
- account: AccountView.render("account.json", %{user: follower, for: followed}),
+ account: AccountView.render("show.json", %{user: follower, for: followed}),
created_at: Utils.to_masto_date(notification.inserted_at)
}
diff --git a/test/web/mastodon_api/views/poll_view_test.exs b/test/web/mastodon_api/views/poll_view_test.exs
new file mode 100644
index 000000000..8cd7636a5
--- /dev/null
+++ b/test/web/mastodon_api/views/poll_view_test.exs
@@ -0,0 +1,126 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.PollViewTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Object
+ alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.MastodonAPI.PollView
+
+ import Pleroma.Factory
+ import Tesla.Mock
+
+ setup do
+ mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
+ :ok
+ end
+
+ test "renders a poll" do
+ user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "Is Tenshi eating a corndog cute?",
+ "poll" => %{
+ "options" => ["absolutely!", "sure", "yes", "why are you even asking?"],
+ "expires_in" => 20
+ }
+ })
+
+ object = Object.normalize(activity)
+
+ expected = %{
+ emojis: [],
+ expired: false,
+ id: to_string(object.id),
+ multiple: false,
+ options: [
+ %{title: "absolutely!", votes_count: 0},
+ %{title: "sure", votes_count: 0},
+ %{title: "yes", votes_count: 0},
+ %{title: "why are you even asking?", votes_count: 0}
+ ],
+ voted: false,
+ votes_count: 0
+ }
+
+ result = PollView.render("show.json", %{object: object})
+ expires_at = result.expires_at
+ result = Map.delete(result, :expires_at)
+
+ assert result == expected
+
+ expires_at = NaiveDateTime.from_iso8601!(expires_at)
+ assert NaiveDateTime.diff(expires_at, NaiveDateTime.utc_now()) in 15..20
+ end
+
+ test "detects if it is multiple choice" do
+ user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "Which Mastodon developer is your favourite?",
+ "poll" => %{
+ "options" => ["Gargron", "Eugen"],
+ "expires_in" => 20,
+ "multiple" => true
+ }
+ })
+
+ object = Object.normalize(activity)
+
+ assert %{multiple: true} = PollView.render("show.json", %{object: object})
+ end
+
+ test "detects emoji" do
+ user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "What's with the smug face?",
+ "poll" => %{
+ "options" => [":blank: sip", ":blank::blank: sip", ":blank::blank::blank: sip"],
+ "expires_in" => 20
+ }
+ })
+
+ object = Object.normalize(activity)
+
+ assert %{emojis: [%{shortcode: "blank"}]} = PollView.render("show.json", %{object: object})
+ end
+
+ test "detects vote status" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "Which input devices do you use?",
+ "poll" => %{
+ "options" => ["mouse", "trackball", "trackpoint"],
+ "multiple" => true,
+ "expires_in" => 20
+ }
+ })
+
+ object = Object.normalize(activity)
+
+ {:ok, _, object} = CommonAPI.vote(other_user, object, [1, 2])
+
+ result = PollView.render("show.json", %{object: object, for: other_user})
+
+ assert result[:voted] == true
+ assert Enum.at(result[:options], 1)[:votes_count] == 1
+ assert Enum.at(result[:options], 2)[:votes_count] == 1
+ end
+
+ test "does not crash on polls with no end date" do
+ object = Object.normalize("https://skippers-bin.com/notes/7x9tmrp97i")
+ result = PollView.render("show.json", %{object: object})
+
+ assert result[:expires_at] == nil
+ assert result[:expired] == false
+ end
+end
diff --git a/test/web/mastodon_api/views/status_view_test.exs b/test/web/mastodon_api/views/status_view_test.exs
index c17d0ef95..1d5a6e956 100644
--- a/test/web/mastodon_api/views/status_view_test.exs
+++ b/test/web/mastodon_api/views/status_view_test.exs
@@ -103,7 +103,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
id: to_string(note.id),
uri: object_data["id"],
url: Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, note),
- account: AccountView.render("account.json", %{user: user}),
+ account: AccountView.render("show.json", %{user: user}),
in_reply_to_id: nil,
in_reply_to_account_id: nil,
card: nil,
@@ -451,116 +451,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
end
end
- describe "poll view" do
- test "renders a poll" do
- user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "Is Tenshi eating a corndog cute?",
- "poll" => %{
- "options" => ["absolutely!", "sure", "yes", "why are you even asking?"],
- "expires_in" => 20
- }
- })
-
- object = Object.normalize(activity)
-
- expected = %{
- emojis: [],
- expired: false,
- id: to_string(object.id),
- multiple: false,
- options: [
- %{title: "absolutely!", votes_count: 0},
- %{title: "sure", votes_count: 0},
- %{title: "yes", votes_count: 0},
- %{title: "why are you even asking?", votes_count: 0}
- ],
- voted: false,
- votes_count: 0
- }
-
- result = StatusView.render("poll.json", %{object: object})
- expires_at = result.expires_at
- result = Map.delete(result, :expires_at)
-
- assert result == expected
-
- expires_at = NaiveDateTime.from_iso8601!(expires_at)
- assert NaiveDateTime.diff(expires_at, NaiveDateTime.utc_now()) in 15..20
- end
-
- test "detects if it is multiple choice" do
- user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "Which Mastodon developer is your favourite?",
- "poll" => %{
- "options" => ["Gargron", "Eugen"],
- "expires_in" => 20,
- "multiple" => true
- }
- })
-
- object = Object.normalize(activity)
-
- assert %{multiple: true} = StatusView.render("poll.json", %{object: object})
- end
-
- test "detects emoji" do
- user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "What's with the smug face?",
- "poll" => %{
- "options" => [":blank: sip", ":blank::blank: sip", ":blank::blank::blank: sip"],
- "expires_in" => 20
- }
- })
-
- object = Object.normalize(activity)
-
- assert %{emojis: [%{shortcode: "blank"}]} =
- StatusView.render("poll.json", %{object: object})
- end
-
- test "detects vote status" do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "Which input devices do you use?",
- "poll" => %{
- "options" => ["mouse", "trackball", "trackpoint"],
- "multiple" => true,
- "expires_in" => 20
- }
- })
-
- object = Object.normalize(activity)
-
- {:ok, _, object} = CommonAPI.vote(other_user, object, [1, 2])
-
- result = StatusView.render("poll.json", %{object: object, for: other_user})
-
- assert result[:voted] == true
- assert Enum.at(result[:options], 1)[:votes_count] == 1
- assert Enum.at(result[:options], 2)[:votes_count] == 1
- end
-
- test "does not crash on polls with no end date" do
- object = Object.normalize("https://skippers-bin.com/notes/7x9tmrp97i")
- result = StatusView.render("poll.json", %{object: object})
-
- assert result[:expires_at] == nil
- assert result[:expired] == false
- end
- end
-
test "embeds a relationship in the account" do
user = insert(:user)
other_user = insert(:user)
@@ -608,4 +498,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
assert status.visibility == "list"
end
+
+ test "successfully renders a Listen activity (pleroma extension)" do
+ listen_activity = insert(:listen)
+
+ status = StatusView.render("listen.json", activity: listen_activity)
+
+ assert status.length == listen_activity.data["object"]["length"]
+ assert status.title == listen_activity.data["object"]["title"]
+ end
end
diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs
index 2b40fb47e..f06023dff 100644
--- a/test/web/ostatus/ostatus_controller_test.exs
+++ b/test/web/ostatus/ostatus_controller_test.exs
@@ -396,7 +396,8 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
"oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
"oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
"oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
- "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox"
+ "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox",
+ "uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media"
}
assert response["@context"] == [
@@ -458,7 +459,8 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
"oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
"oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
"oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
- "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox"
+ "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox",
+ "uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media"
}
assert response["@context"] == [
diff --git a/test/web/pleroma_api/controllers/account_controller_test.exs b/test/web/pleroma_api/controllers/account_controller_test.exs
new file mode 100644
index 000000000..3b4665afd
--- /dev/null
+++ b/test/web/pleroma_api/controllers/account_controller_test.exs
@@ -0,0 +1,395 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Config
+ alias Pleroma.Repo
+ alias Pleroma.Tests.ObanHelpers
+ alias Pleroma.User
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+ import Swoosh.TestAssertions
+
+ @image "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
+
+ describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
+ setup do
+ {:ok, user} =
+ insert(:user)
+ |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true))
+ |> Repo.update()
+
+ assert user.info.confirmation_pending
+
+ [user: user]
+ end
+
+ clear_config([:instance, :account_activation_required]) do
+ Config.put([:instance, :account_activation_required], true)
+ end
+
+ test "resend account confirmation email", %{conn: conn, user: user} do
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/accounts/confirmation_resend?email=#{user.email}")
+ |> json_response(:no_content)
+
+ ObanHelpers.perform_all()
+
+ email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
+ notify_email = Config.get([:instance, :notify_email])
+ instance_name = Config.get([:instance, :name])
+
+ assert_email_sent(
+ from: {instance_name, notify_email},
+ to: {user.name, user.email},
+ html_body: email.html_body
+ )
+ end
+ end
+
+ describe "PATCH /api/v1/pleroma/accounts/update_avatar" do
+ test "user avatar can be set", %{conn: conn} do
+ user = insert(:user)
+ avatar_image = File.read!("test/fixtures/avatar_data_uri")
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image})
+
+ user = refresh_record(user)
+
+ assert %{
+ "name" => _,
+ "type" => _,
+ "url" => [
+ %{
+ "href" => _,
+ "mediaType" => _,
+ "type" => _
+ }
+ ]
+ } = user.avatar
+
+ assert %{"url" => _} = json_response(conn, 200)
+ end
+
+ test "user avatar can be reset", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""})
+
+ user = User.get_cached_by_id(user.id)
+
+ assert user.avatar == nil
+
+ assert %{"url" => nil} = json_response(conn, 200)
+ end
+ end
+
+ describe "PATCH /api/v1/pleroma/accounts/update_banner" do
+ test "can set profile banner", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})
+
+ user = refresh_record(user)
+ assert user.info.banner["type"] == "Image"
+
+ assert %{"url" => _} = json_response(conn, 200)
+ end
+
+ test "can reset profile banner", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})
+
+ user = refresh_record(user)
+ assert user.info.banner == %{}
+
+ assert %{"url" => nil} = json_response(conn, 200)
+ end
+ end
+
+ describe "PATCH /api/v1/pleroma/accounts/update_background" do
+ test "background image can be set", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image})
+
+ user = refresh_record(user)
+ assert user.info.background["type"] == "Image"
+ assert %{"url" => _} = json_response(conn, 200)
+ end
+
+ test "background image can be reset", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""})
+
+ user = refresh_record(user)
+ assert user.info.background == %{}
+ assert %{"url" => nil} = json_response(conn, 200)
+ end
+ end
+
+ describe "getting favorites timeline of specified user" do
+ setup do
+ [current_user, user] = insert_pair(:user, %{info: %{hide_favorites: false}})
+ [current_user: current_user, user: user]
+ end
+
+ test "returns list of statuses favorited by specified user", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ [activity | _] = insert_pair(:note_activity)
+ CommonAPI.favorite(activity.id, user)
+
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ [like] = response
+
+ assert length(response) == 1
+ assert like["id"] == activity.id
+ end
+
+ test "returns favorites for specified user_id when user is not logged in", %{
+ conn: conn,
+ user: user
+ } do
+ activity = insert(:note_activity)
+ CommonAPI.favorite(activity.id, user)
+
+ response =
+ conn
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ assert length(response) == 1
+ end
+
+ test "returns favorited DM only when user is logged in and he is one of recipients", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ {:ok, direct} =
+ CommonAPI.post(current_user, %{
+ "status" => "Hi @#{user.nickname}!",
+ "visibility" => "direct"
+ })
+
+ CommonAPI.favorite(direct.id, user)
+
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ assert length(response) == 1
+
+ anonymous_response =
+ conn
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ assert Enum.empty?(anonymous_response)
+ end
+
+ test "does not return others' favorited DM when user is not one of recipients", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ user_two = insert(:user)
+
+ {:ok, direct} =
+ CommonAPI.post(user_two, %{
+ "status" => "Hi @#{user.nickname}!",
+ "visibility" => "direct"
+ })
+
+ CommonAPI.favorite(direct.id, user)
+
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ assert Enum.empty?(response)
+ end
+
+ test "paginates favorites using since_id and max_id", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ activities = insert_list(10, :note_activity)
+
+ Enum.each(activities, fn activity ->
+ CommonAPI.favorite(activity.id, user)
+ end)
+
+ third_activity = Enum.at(activities, 2)
+ seventh_activity = Enum.at(activities, 6)
+
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{
+ since_id: third_activity.id,
+ max_id: seventh_activity.id
+ })
+ |> json_response(:ok)
+
+ assert length(response) == 3
+ refute third_activity in response
+ refute seventh_activity in response
+ end
+
+ test "limits favorites using limit parameter", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ 7
+ |> insert_list(:note_activity)
+ |> Enum.each(fn activity ->
+ CommonAPI.favorite(activity.id, user)
+ end)
+
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{limit: "3"})
+ |> json_response(:ok)
+
+ assert length(response) == 3
+ end
+
+ test "returns empty response when user does not have any favorited statuses", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ assert Enum.empty?(response)
+ end
+
+ test "returns 404 error when specified user is not exist", %{conn: conn} do
+ conn = get(conn, "/api/v1/pleroma/accounts/test/favourites")
+
+ assert json_response(conn, 404) == %{"error" => "Record not found"}
+ end
+
+ test "returns 403 error when user has hidden own favorites", %{
+ conn: conn,
+ current_user: current_user
+ } do
+ user = insert(:user, %{info: %{hide_favorites: true}})
+ activity = insert(:note_activity)
+ CommonAPI.favorite(activity.id, user)
+
+ conn =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+
+ assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
+ end
+
+ test "hides favorites for new users by default", %{conn: conn, current_user: current_user} do
+ user = insert(:user)
+ activity = insert(:note_activity)
+ CommonAPI.favorite(activity.id, user)
+
+ conn =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+
+ assert user.info.hide_favorites
+ assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
+ end
+ end
+
+ describe "subscribing / unsubscribing" do
+ test "subscribing / unsubscribing to a user", %{conn: conn} do
+ user = insert(:user)
+ subscription_target = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
+
+ assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
+
+ assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
+ end
+ end
+
+ describe "subscribing" do
+ test "returns 404 when subscription_target not found", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/accounts/target_id/subscribe")
+
+ assert %{"error" => "Record not found"} = json_response(conn, 404)
+ end
+ end
+
+ describe "unsubscribing" do
+ test "returns 404 when subscription_target not found", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/accounts/target_id/unsubscribe")
+
+ assert %{"error" => "Record not found"} = json_response(conn, 404)
+ end
+ end
+end
diff --git a/test/web/pleroma_api/emoji_api_controller_test.exs b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
index 93a507a01..5f74460e8 100644
--- a/test/web/pleroma_api/emoji_api_controller_test.exs
+++ b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
@@ -1,3 +1,7 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
use Pleroma.Web.ConnCase
diff --git a/test/web/pleroma_api/controllers/mascot_controller_test.exs b/test/web/pleroma_api/controllers/mascot_controller_test.exs
new file mode 100644
index 000000000..ae9539b04
--- /dev/null
+++ b/test/web/pleroma_api/controllers/mascot_controller_test.exs
@@ -0,0 +1,77 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.User
+
+ import Pleroma.Factory
+
+ test "mascot upload", %{conn: conn} do
+ user = insert(:user)
+
+ non_image_file = %Plug.Upload{
+ content_type: "audio/mpeg",
+ path: Path.absname("test/fixtures/sound.mp3"),
+ filename: "sound.mp3"
+ }
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> put("/api/v1/pleroma/mascot", %{"file" => non_image_file})
+
+ assert json_response(conn, 415)
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> put("/api/v1/pleroma/mascot", %{"file" => file})
+
+ assert %{"id" => _, "type" => image} = json_response(conn, 200)
+ end
+
+ test "mascot retrieving", %{conn: conn} do
+ user = insert(:user)
+ # When user hasn't set a mascot, we should just get pleroma tan back
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/pleroma/mascot")
+
+ assert %{"url" => url} = json_response(conn, 200)
+ assert url =~ "pleroma-fox-tan-smol"
+
+ # When a user sets their mascot, we should get that back
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> put("/api/v1/pleroma/mascot", %{"file" => file})
+
+ assert json_response(conn, 200)
+
+ user = User.get_cached_by_id(user.id)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> get("/api/v1/pleroma/mascot")
+
+ assert %{"url" => url, "type" => "image"} = json_response(conn, 200)
+ assert url =~ "an_image"
+ end
+end
diff --git a/test/web/pleroma_api/controllers/scrobble_controller_test.exs b/test/web/pleroma_api/controllers/scrobble_controller_test.exs
new file mode 100644
index 000000000..881f8012c
--- /dev/null
+++ b/test/web/pleroma_api/controllers/scrobble_controller_test.exs
@@ -0,0 +1,63 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Web.CommonAPI
+ import Pleroma.Factory
+
+ describe "POST /api/v1/pleroma/scrobble" do
+ test "works correctly", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/scrobble", %{
+ "title" => "lain radio episode 1",
+ "artist" => "lain",
+ "album" => "lain radio",
+ "length" => "180000"
+ })
+
+ assert %{"title" => "lain radio episode 1"} = json_response(conn, 200)
+ end
+ end
+
+ describe "GET /api/v1/pleroma/accounts/:id/scrobbles" do
+ test "works correctly", %{conn: conn} do
+ user = insert(:user)
+
+ {:ok, _activity} =
+ CommonAPI.listen(user, %{
+ "title" => "lain radio episode 1",
+ "artist" => "lain",
+ "album" => "lain radio"
+ })
+
+ {:ok, _activity} =
+ CommonAPI.listen(user, %{
+ "title" => "lain radio episode 2",
+ "artist" => "lain",
+ "album" => "lain radio"
+ })
+
+ {:ok, _activity} =
+ CommonAPI.listen(user, %{
+ "title" => "lain radio episode 3",
+ "artist" => "lain",
+ "album" => "lain radio"
+ })
+
+ conn =
+ conn
+ |> get("/api/v1/pleroma/accounts/#{user.id}/scrobbles")
+
+ result = json_response(conn, 200)
+
+ assert length(result) == 3
+ end
+ end
+end
diff --git a/test/web/pleroma_api/controllers/subscription_notification_controller_test.exs b/test/web/pleroma_api/controllers/subscription_notification_controller_test.exs
deleted file mode 100644
index c6a71732d..000000000
--- a/test/web/pleroma_api/controllers/subscription_notification_controller_test.exs
+++ /dev/null
@@ -1,234 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.PleromaAPI.SubscriptionNotificationControllerTest do
- use Pleroma.Web.ConnCase
-
- alias Pleroma.Repo
- alias Pleroma.SubscriptionNotification
- alias Pleroma.User
- alias Pleroma.Web.CommonAPI
- import Pleroma.Factory
- import Tesla.Mock
-
- setup do
- mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
- :ok
- end
-
- clear_config([:instance, :public])
- clear_config([:rich_media, :enabled])
-
- describe "subscription_notifications" do
- setup do
- user = insert(:user)
- subscriber = insert(:user)
-
- User.subscribe(subscriber, user)
-
- {:ok, %{user: user, subscriber: subscriber}}
- end
-
- test "list of notifications", %{conn: conn, user: user, subscriber: subscriber} do
- status_text = "Hello"
- {:ok, _activity} = CommonAPI.post(user, %{"status" => status_text})
- path = subscription_notification_path(conn, :index)
-
- conn =
- conn
- |> assign(:user, subscriber)
- |> get(path)
-
- assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
- assert response == status_text
- end
-
- test "getting a single notification", %{conn: conn, user: user, subscriber: subscriber} do
- status_text = "Hello"
-
- {:ok, _activity} = CommonAPI.post(user, %{"status" => status_text})
- [notification] = Repo.all(SubscriptionNotification)
-
- path = subscription_notification_path(conn, :show, notification)
-
- conn =
- conn
- |> assign(:user, subscriber)
- |> get(path)
-
- assert %{"status" => %{"content" => response}} = json_response(conn, 200)
- assert response == status_text
- end
-
- test "dismissing a single notification also deletes it", %{
- conn: conn,
- user: user,
- subscriber: subscriber
- } do
- status_text = "Hello"
- {:ok, _activity} = CommonAPI.post(user, %{"status" => status_text})
-
- [notification] = Repo.all(SubscriptionNotification)
-
- conn =
- conn
- |> assign(:user, subscriber)
- |> post(subscription_notification_path(conn, :dismiss), %{"id" => notification.id})
-
- assert %{} = json_response(conn, 200)
-
- assert Repo.all(SubscriptionNotification) == []
- end
-
- test "clearing all notifications also deletes them", %{
- conn: conn,
- user: user,
- subscriber: subscriber
- } do
- status_text1 = "Hello"
- status_text2 = "Hello again"
- {:ok, _activity1} = CommonAPI.post(user, %{"status" => status_text1})
- {:ok, _activity2} = CommonAPI.post(user, %{"status" => status_text2})
-
- conn =
- conn
- |> assign(:user, subscriber)
- |> post(subscription_notification_path(conn, :clear))
-
- assert %{} = json_response(conn, 200)
-
- conn =
- build_conn()
- |> assign(:user, subscriber)
- |> get(subscription_notification_path(conn, :index))
-
- assert json_response(conn, 200) == []
-
- assert Repo.all(SubscriptionNotification) == []
- end
-
- test "paginates notifications using min_id, since_id, max_id, and limit", %{
- conn: conn,
- user: user,
- subscriber: subscriber
- } do
- {:ok, activity1} = CommonAPI.post(user, %{"status" => "Hello 1"})
- {:ok, activity2} = CommonAPI.post(user, %{"status" => "Hello 2"})
- {:ok, activity3} = CommonAPI.post(user, %{"status" => "Hello 3"})
- {:ok, activity4} = CommonAPI.post(user, %{"status" => "Hello 4"})
-
- notification1_id =
- Repo.get_by(SubscriptionNotification, activity_id: activity1.id).id |> to_string()
-
- notification2_id =
- Repo.get_by(SubscriptionNotification, activity_id: activity2.id).id |> to_string()
-
- notification3_id =
- Repo.get_by(SubscriptionNotification, activity_id: activity3.id).id |> to_string()
-
- notification4_id =
- Repo.get_by(SubscriptionNotification, activity_id: activity4.id).id |> to_string()
-
- conn = assign(conn, :user, subscriber)
-
- # min_id
- conn_res =
- get(
- conn,
- subscription_notification_path(conn, :index, %{
- "limit" => 2,
- "min_id" => notification1_id
- })
- )
-
- result = json_response(conn_res, 200)
- assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
-
- # since_id
- conn_res =
- get(
- conn,
- subscription_notification_path(conn, :index, %{
- "limit" => 2,
- "since_id" => notification1_id
- })
- )
-
- result = json_response(conn_res, 200)
- assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
-
- # max_id
- conn_res =
- get(
- conn,
- subscription_notification_path(conn, :index, %{
- "limit" => 2,
- "max_id" => notification4_id
- })
- )
-
- result = json_response(conn_res, 200)
- assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
- end
-
- test "destroy multiple", %{conn: conn, user: user1, subscriber: user2} do
- # mutual subscription
- User.subscribe(user1, user2)
-
- {:ok, activity1} = CommonAPI.post(user1, %{"status" => "Hello 1"})
- {:ok, activity2} = CommonAPI.post(user1, %{"status" => "World 1"})
- {:ok, activity3} = CommonAPI.post(user2, %{"status" => "Hello 2"})
- {:ok, activity4} = CommonAPI.post(user2, %{"status" => "World 2"})
-
- notification1_id =
- Repo.get_by(SubscriptionNotification, activity_id: activity1.id).id |> to_string()
-
- notification2_id =
- Repo.get_by(SubscriptionNotification, activity_id: activity2.id).id |> to_string()
-
- notification3_id =
- Repo.get_by(SubscriptionNotification, activity_id: activity3.id).id |> to_string()
-
- notification4_id =
- Repo.get_by(SubscriptionNotification, activity_id: activity4.id).id |> to_string()
-
- conn = assign(conn, :user, user1)
-
- conn_res = get(conn, subscription_notification_path(conn, :index))
-
- result = json_response(conn_res, 200)
-
- Enum.each(result, fn %{"id" => id} ->
- assert id in [notification3_id, notification4_id]
- end)
-
- conn2 = assign(conn, :user, user2)
-
- conn_res = get(conn2, subscription_notification_path(conn, :index))
-
- result = json_response(conn_res, 200)
-
- Enum.each(result, fn %{"id" => id} ->
- assert id in [notification1_id, notification2_id]
- end)
-
- conn_destroy =
- delete(conn, subscription_notification_path(conn, :destroy_multiple), %{
- "ids" => [notification3_id, notification4_id]
- })
-
- assert json_response(conn_destroy, 200) == %{}
-
- conn_res = get(conn2, subscription_notification_path(conn, :index))
-
- result = json_response(conn_res, 200)
-
- Enum.each(result, fn %{"id" => id} ->
- assert id in [notification1_id, notification2_id]
- end)
-
- assert length(Repo.all(SubscriptionNotification)) == 2
- end
- end
-end
diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs
index bf1e233f5..d1d61d11a 100644
--- a/test/web/twitter_api/twitter_api_test.exs
+++ b/test/web/twitter_api/twitter_api_test.exs
@@ -29,8 +29,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
fetched_user = User.get_cached_by_nickname("lain")
- assert AccountView.render("account.json", %{user: user}) ==
- AccountView.render("account.json", %{user: fetched_user})
+ assert AccountView.render("show.json", %{user: user}) ==
+ AccountView.render("show.json", %{user: fetched_user})
end
test "it registers a new user with empty string in bio and returns the user." do
@@ -47,8 +47,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
fetched_user = User.get_cached_by_nickname("lain")
- assert AccountView.render("account.json", %{user: user}) ==
- AccountView.render("account.json", %{user: fetched_user})
+ assert AccountView.render("show.json", %{user: user}) ==
+ AccountView.render("show.json", %{user: fetched_user})
end
test "it sends confirmation email if :account_activation_required is specified in instance config" do
@@ -148,8 +148,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
assert invite.used == true
- assert AccountView.render("account.json", %{user: user}) ==
- AccountView.render("account.json", %{user: fetched_user})
+ assert AccountView.render("show.json", %{user: user}) ==
+ AccountView.render("show.json", %{user: fetched_user})
end
test "returns error on invalid token" do
@@ -213,8 +213,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
{:ok, user} = TwitterAPI.register_user(data)
fetched_user = User.get_cached_by_nickname("vinny")
- assert AccountView.render("account.json", %{user: user}) ==
- AccountView.render("account.json", %{user: fetched_user})
+ assert AccountView.render("show.json", %{user: user}) ==
+ AccountView.render("show.json", %{user: fetched_user})
end
{:ok, data: data, check_fn: check_fn}
@@ -288,8 +288,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
assert invite.used == true
- assert AccountView.render("account.json", %{user: user}) ==
- AccountView.render("account.json", %{user: fetched_user})
+ assert AccountView.render("show.json", %{user: user}) ==
+ AccountView.render("show.json", %{user: fetched_user})
data = %{
"nickname" => "GrimReaper",
@@ -339,8 +339,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
refute invite.used
- assert AccountView.render("account.json", %{user: user}) ==
- AccountView.render("account.json", %{user: fetched_user})
+ assert AccountView.render("show.json", %{user: user}) ==
+ AccountView.render("show.json", %{user: fetched_user})
end
test "error after max uses" do
@@ -363,8 +363,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
invite = Repo.get_by(UserInviteToken, token: invite.token)
assert invite.used == true
- assert AccountView.render("account.json", %{user: user}) ==
- AccountView.render("account.json", %{user: fetched_user})
+ assert AccountView.render("show.json", %{user: user}) ==
+ AccountView.render("show.json", %{user: fetched_user})
data = %{
"nickname" => "GrimReaper",