1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
6 use Pleroma.Web.ConnCase
10 alias Pleroma.Notification
14 alias Pleroma.Web.ActivityPub.ActivityPub
15 alias Pleroma.Web.CommonAPI
16 alias Pleroma.Web.MastodonAPI.FilterView
17 alias Pleroma.Web.OAuth.App
18 alias Pleroma.Web.OStatus
19 alias Pleroma.Web.Push
20 alias Pleroma.Web.TwitterAPI.TwitterAPI
21 import Pleroma.Factory
22 import ExUnit.CaptureLog
26 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
30 test "the home timeline", %{conn: conn} do
32 following = insert(:user)
34 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
38 |> assign(:user, user)
39 |> get("/api/v1/timelines/home")
41 assert Enum.empty?(json_response(conn, 200))
43 {:ok, user} = User.follow(user, following)
47 |> assign(:user, user)
48 |> get("/api/v1/timelines/home")
50 assert [%{"content" => "test"}] = json_response(conn, 200)
53 test "the public timeline", %{conn: conn} do
54 following = insert(:user)
57 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
60 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
64 |> get("/api/v1/timelines/public", %{"local" => "False"})
66 assert length(json_response(conn, 200)) == 2
70 |> get("/api/v1/timelines/public", %{"local" => "True"})
72 assert [%{"content" => "test"}] = json_response(conn, 200)
76 |> get("/api/v1/timelines/public", %{"local" => "1"})
78 assert [%{"content" => "test"}] = json_response(conn, 200)
82 test "posting a status", %{conn: conn} do
85 idempotency_key = "Pikachu rocks!"
89 |> assign(:user, user)
90 |> put_req_header("idempotency-key", idempotency_key)
91 |> post("/api/v1/statuses", %{
93 "spoiler_text" => "2hu",
94 "sensitive" => "false"
97 {:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key)
99 assert ttl > :timer.seconds(6 * 60 * 60 - 1)
101 assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} =
102 json_response(conn_one, 200)
104 assert Repo.get(Activity, id)
108 |> assign(:user, user)
109 |> put_req_header("idempotency-key", idempotency_key)
110 |> post("/api/v1/statuses", %{
112 "spoiler_text" => "2hu",
113 "sensitive" => "false"
116 assert %{"id" => second_id} = json_response(conn_two, 200)
118 assert id == second_id
122 |> assign(:user, user)
123 |> post("/api/v1/statuses", %{
125 "spoiler_text" => "2hu",
126 "sensitive" => "false"
129 assert %{"id" => third_id} = json_response(conn_three, 200)
131 refute id == third_id
134 test "posting a sensitive status", %{conn: conn} do
139 |> assign(:user, user)
140 |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true})
142 assert %{"content" => "cofe", "id" => id, "sensitive" => true} = json_response(conn, 200)
143 assert Repo.get(Activity, id)
146 test "posting a status with OGP link preview", %{conn: conn} do
147 Pleroma.Config.put([:rich_media, :enabled], true)
152 |> assign(:user, user)
153 |> post("/api/v1/statuses", %{
154 "status" => "http://example.com/ogp"
157 assert %{"id" => id, "card" => %{"title" => "The Rock"}} = json_response(conn, 200)
158 assert Repo.get(Activity, id)
159 Pleroma.Config.put([:rich_media, :enabled], false)
162 test "posting a direct status", %{conn: conn} do
163 user1 = insert(:user)
164 user2 = insert(:user)
165 content = "direct cofe @#{user2.nickname}"
169 |> assign(:user, user1)
170 |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"})
172 assert %{"id" => id, "visibility" => "direct"} = json_response(conn, 200)
173 assert activity = Repo.get(Activity, id)
174 assert activity.recipients == [user2.ap_id, user1.ap_id]
175 assert activity.data["to"] == [user2.ap_id]
176 assert activity.data["cc"] == []
179 test "direct timeline", %{conn: conn} do
180 user_one = insert(:user)
181 user_two = insert(:user)
183 {:ok, user_two} = User.follow(user_two, user_one)
186 CommonAPI.post(user_one, %{
187 "status" => "Hi @#{user_two.nickname}!",
188 "visibility" => "direct"
191 {:ok, _follower_only} =
192 CommonAPI.post(user_one, %{
193 "status" => "Hi @#{user_two.nickname}!",
194 "visibility" => "private"
197 # Only direct should be visible here
200 |> assign(:user, user_two)
201 |> get("api/v1/timelines/direct")
203 [status] = json_response(res_conn, 200)
205 assert %{"visibility" => "direct"} = status
206 assert status["url"] != direct.data["id"]
208 # User should be able to see his own direct message
211 |> assign(:user, user_one)
212 |> get("api/v1/timelines/direct")
214 [status] = json_response(res_conn, 200)
216 assert %{"visibility" => "direct"} = status
218 # Both should be visible here
221 |> assign(:user, user_two)
222 |> get("api/v1/timelines/home")
224 [_s1, _s2] = json_response(res_conn, 200)
227 Enum.each(1..20, fn _ ->
229 CommonAPI.post(user_one, %{
230 "status" => "Hi @#{user_two.nickname}!",
231 "visibility" => "direct"
237 |> assign(:user, user_two)
238 |> get("api/v1/timelines/direct")
240 statuses = json_response(res_conn, 200)
241 assert length(statuses) == 20
245 |> assign(:user, user_two)
246 |> get("api/v1/timelines/direct", %{max_id: List.last(statuses)["id"]})
248 [status] = json_response(res_conn, 200)
250 assert status["url"] != direct.data["id"]
253 test "Conversations", %{conn: conn} do
254 user_one = insert(:user)
255 user_two = insert(:user)
257 {:ok, user_two} = User.follow(user_two, user_one)
260 CommonAPI.post(user_one, %{
261 "status" => "Hi @#{user_two.nickname}!",
262 "visibility" => "direct"
265 {:ok, _follower_only} =
266 CommonAPI.post(user_one, %{
267 "status" => "Hi @#{user_two.nickname}!",
268 "visibility" => "private"
273 |> assign(:user, user)
274 |> get("/api/v1/conversations")
276 assert response = json_response(res_conn, 200)
280 "accounts" => res_accounts,
281 "last_status" => res_last_status,
285 assert unread == false
287 # Apparently undocumented API endpoint
290 |> assign(:user, user)
291 |> get("/api/v1/conversations/#{res_id}/read")
293 assert response == json_response(res_conn, 200)
295 # (vanilla) Mastodon frontend behaviour
298 |> assign(:user, user)
299 |> get("/api/v1/statuses/#{res_last_status.id}/context")
301 assert %{ancestors: [], descendants: []} == json_response(res_conn, 200)
304 test "doesn't include DMs from blocked users", %{conn: conn} do
305 blocker = insert(:user)
306 blocked = insert(:user)
308 {:ok, blocker} = User.block(blocker, blocked)
310 {:ok, _blocked_direct} =
311 CommonAPI.post(blocked, %{
312 "status" => "Hi @#{blocker.nickname}!",
313 "visibility" => "direct"
317 CommonAPI.post(user, %{
318 "status" => "Hi @#{blocker.nickname}!",
319 "visibility" => "direct"
324 |> assign(:user, user)
325 |> get("api/v1/timelines/direct")
327 [status] = json_response(res_conn, 200)
328 assert status["id"] == direct.id
331 test "replying to a status", %{conn: conn} do
334 {:ok, replied_to} = TwitterAPI.create_status(user, %{"status" => "cofe"})
338 |> assign(:user, user)
339 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
341 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
343 activity = Repo.get(Activity, id)
345 assert activity.data["context"] == replied_to.data["context"]
346 assert activity.data["object"]["inReplyToStatusId"] == replied_to.id
349 test "posting a status with an invalid in_reply_to_id", %{conn: conn} do
354 |> assign(:user, user)
355 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""})
357 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
359 activity = Repo.get(Activity, id)
364 test "verify_credentials", %{conn: conn} do
369 |> assign(:user, user)
370 |> get("/api/v1/accounts/verify_credentials")
372 assert %{"id" => id, "source" => %{"privacy" => "public"}} = json_response(conn, 200)
373 assert id == to_string(user.id)
376 test "verify_credentials default scope unlisted", %{conn: conn} do
377 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "unlisted"}})
381 |> assign(:user, user)
382 |> get("/api/v1/accounts/verify_credentials")
384 assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
385 assert id == to_string(user.id)
388 test "apps/verify_credentials", %{conn: conn} do
389 token = insert(:oauth_token)
393 |> assign(:user, token.user)
394 |> assign(:token, token)
395 |> get("/api/v1/apps/verify_credentials")
397 app = Repo.preload(token, :app).app
400 "name" => app.client_name,
401 "website" => app.website,
402 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
405 assert expected == json_response(conn, 200)
408 test "creates an oauth app", %{conn: conn} do
410 app_attrs = build(:oauth_app)
414 |> assign(:user, user)
415 |> post("/api/v1/apps", %{
416 client_name: app_attrs.client_name,
417 redirect_uris: app_attrs.redirect_uris
420 [app] = Repo.all(App)
423 "name" => app.client_name,
424 "website" => app.website,
425 "client_id" => app.client_id,
426 "client_secret" => app.client_secret,
427 "id" => app.id |> to_string(),
428 "redirect_uri" => app.redirect_uris,
429 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
432 assert expected == json_response(conn, 200)
435 test "get a status", %{conn: conn} do
436 activity = insert(:note_activity)
440 |> get("/api/v1/statuses/#{activity.id}")
442 assert %{"id" => id} = json_response(conn, 200)
443 assert id == to_string(activity.id)
446 describe "deleting a status" do
447 test "when you created it", %{conn: conn} do
448 activity = insert(:note_activity)
449 author = User.get_by_ap_id(activity.data["actor"])
453 |> assign(:user, author)
454 |> delete("/api/v1/statuses/#{activity.id}")
456 assert %{} = json_response(conn, 200)
458 refute Repo.get(Activity, activity.id)
461 test "when you didn't create it", %{conn: conn} do
462 activity = insert(:note_activity)
467 |> assign(:user, user)
468 |> delete("/api/v1/statuses/#{activity.id}")
470 assert %{"error" => _} = json_response(conn, 403)
472 assert Repo.get(Activity, activity.id) == activity
475 test "when you're an admin or moderator", %{conn: conn} do
476 activity1 = insert(:note_activity)
477 activity2 = insert(:note_activity)
478 admin = insert(:user, info: %{is_admin: true})
479 moderator = insert(:user, info: %{is_moderator: true})
483 |> assign(:user, admin)
484 |> delete("/api/v1/statuses/#{activity1.id}")
486 assert %{} = json_response(res_conn, 200)
490 |> assign(:user, moderator)
491 |> delete("/api/v1/statuses/#{activity2.id}")
493 assert %{} = json_response(res_conn, 200)
495 refute Repo.get(Activity, activity1.id)
496 refute Repo.get(Activity, activity2.id)
500 describe "filters" do
501 test "creating a filter", %{conn: conn} do
504 filter = %Pleroma.Filter{
511 |> assign(:user, user)
512 |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
514 assert response = json_response(conn, 200)
515 assert response["phrase"] == filter.phrase
516 assert response["context"] == filter.context
517 assert response["id"] != nil
518 assert response["id"] != ""
521 test "fetching a list of filters", %{conn: conn} do
524 query_one = %Pleroma.Filter{
531 query_two = %Pleroma.Filter{
538 {:ok, filter_one} = Pleroma.Filter.create(query_one)
539 {:ok, filter_two} = Pleroma.Filter.create(query_two)
543 |> assign(:user, user)
544 |> get("/api/v1/filters")
545 |> json_response(200)
551 filters: [filter_two, filter_one]
555 test "get a filter", %{conn: conn} do
558 query = %Pleroma.Filter{
565 {:ok, filter} = Pleroma.Filter.create(query)
569 |> assign(:user, user)
570 |> get("/api/v1/filters/#{filter.filter_id}")
572 assert _response = json_response(conn, 200)
575 test "update a filter", %{conn: conn} do
578 query = %Pleroma.Filter{
585 {:ok, _filter} = Pleroma.Filter.create(query)
587 new = %Pleroma.Filter{
594 |> assign(:user, user)
595 |> put("/api/v1/filters/#{query.filter_id}", %{
600 assert response = json_response(conn, 200)
601 assert response["phrase"] == new.phrase
602 assert response["context"] == new.context
605 test "delete a filter", %{conn: conn} do
608 query = %Pleroma.Filter{
615 {:ok, filter} = Pleroma.Filter.create(query)
619 |> assign(:user, user)
620 |> delete("/api/v1/filters/#{filter.filter_id}")
622 assert response = json_response(conn, 200)
623 assert response == %{}
628 test "creating a list", %{conn: conn} do
633 |> assign(:user, user)
634 |> post("/api/v1/lists", %{"title" => "cuties"})
636 assert %{"title" => title} = json_response(conn, 200)
637 assert title == "cuties"
640 test "adding users to a list", %{conn: conn} do
642 other_user = insert(:user)
643 {:ok, list} = Pleroma.List.create("name", user)
647 |> assign(:user, user)
648 |> post("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
650 assert %{} == json_response(conn, 200)
651 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
652 assert following == [other_user.follower_address]
655 test "removing users from a list", %{conn: conn} do
657 other_user = insert(:user)
658 third_user = insert(:user)
659 {:ok, list} = Pleroma.List.create("name", user)
660 {:ok, list} = Pleroma.List.follow(list, other_user)
661 {:ok, list} = Pleroma.List.follow(list, third_user)
665 |> assign(:user, user)
666 |> delete("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
668 assert %{} == json_response(conn, 200)
669 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
670 assert following == [third_user.follower_address]
673 test "listing users in a list", %{conn: conn} do
675 other_user = insert(:user)
676 {:ok, list} = Pleroma.List.create("name", user)
677 {:ok, list} = Pleroma.List.follow(list, other_user)
681 |> assign(:user, user)
682 |> get("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
684 assert [%{"id" => id}] = json_response(conn, 200)
685 assert id == to_string(other_user.id)
688 test "retrieving a list", %{conn: conn} do
690 {:ok, list} = Pleroma.List.create("name", user)
694 |> assign(:user, user)
695 |> get("/api/v1/lists/#{list.id}")
697 assert %{"id" => id} = json_response(conn, 200)
698 assert id == to_string(list.id)
701 test "renaming a list", %{conn: conn} do
703 {:ok, list} = Pleroma.List.create("name", user)
707 |> assign(:user, user)
708 |> put("/api/v1/lists/#{list.id}", %{"title" => "newname"})
710 assert %{"title" => name} = json_response(conn, 200)
711 assert name == "newname"
714 test "deleting a list", %{conn: conn} do
716 {:ok, list} = Pleroma.List.create("name", user)
720 |> assign(:user, user)
721 |> delete("/api/v1/lists/#{list.id}")
723 assert %{} = json_response(conn, 200)
724 assert is_nil(Repo.get(Pleroma.List, list.id))
727 test "list timeline", %{conn: conn} do
729 other_user = insert(:user)
730 {:ok, _activity_one} = TwitterAPI.create_status(user, %{"status" => "Marisa is cute."})
731 {:ok, activity_two} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
732 {:ok, list} = Pleroma.List.create("name", user)
733 {:ok, list} = Pleroma.List.follow(list, other_user)
737 |> assign(:user, user)
738 |> get("/api/v1/timelines/list/#{list.id}")
740 assert [%{"id" => id}] = json_response(conn, 200)
742 assert id == to_string(activity_two.id)
745 test "list timeline does not leak non-public statuses for unfollowed users", %{conn: conn} do
747 other_user = insert(:user)
748 {:ok, activity_one} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
750 {:ok, _activity_two} =
751 TwitterAPI.create_status(other_user, %{
752 "status" => "Marisa is cute.",
753 "visibility" => "private"
756 {:ok, list} = Pleroma.List.create("name", user)
757 {:ok, list} = Pleroma.List.follow(list, other_user)
761 |> assign(:user, user)
762 |> get("/api/v1/timelines/list/#{list.id}")
764 assert [%{"id" => id}] = json_response(conn, 200)
766 assert id == to_string(activity_one.id)
770 describe "notifications" do
771 test "list of notifications", %{conn: conn} do
773 other_user = insert(:user)
776 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
778 {:ok, [_notification]} = Notification.create_notifications(activity)
782 |> assign(:user, user)
783 |> get("/api/v1/notifications")
786 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
788 }\">@<span>#{user.nickname}</span></a></span>"
790 assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
791 assert response == expected_response
794 test "getting a single notification", %{conn: conn} do
796 other_user = insert(:user)
799 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
801 {:ok, [notification]} = Notification.create_notifications(activity)
805 |> assign(:user, user)
806 |> get("/api/v1/notifications/#{notification.id}")
809 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
811 }\">@<span>#{user.nickname}</span></a></span>"
813 assert %{"status" => %{"content" => response}} = json_response(conn, 200)
814 assert response == expected_response
817 test "dismissing a single notification", %{conn: conn} do
819 other_user = insert(:user)
822 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
824 {:ok, [notification]} = Notification.create_notifications(activity)
828 |> assign(:user, user)
829 |> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
831 assert %{} = json_response(conn, 200)
834 test "clearing all notifications", %{conn: conn} do
836 other_user = insert(:user)
839 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
841 {:ok, [_notification]} = Notification.create_notifications(activity)
845 |> assign(:user, user)
846 |> post("/api/v1/notifications/clear")
848 assert %{} = json_response(conn, 200)
852 |> assign(:user, user)
853 |> get("/api/v1/notifications")
855 assert all = json_response(conn, 200)
859 test "paginates notifications using min_id, since_id, max_id, and limit", %{conn: conn} do
861 other_user = insert(:user)
863 {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
864 {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
865 {:ok, activity3} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
866 {:ok, activity4} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
868 notification1_id = Repo.get_by(Notification, activity_id: activity1.id).id |> to_string()
869 notification2_id = Repo.get_by(Notification, activity_id: activity2.id).id |> to_string()
870 notification3_id = Repo.get_by(Notification, activity_id: activity3.id).id |> to_string()
871 notification4_id = Repo.get_by(Notification, activity_id: activity4.id).id |> to_string()
875 |> assign(:user, user)
880 |> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
882 result = json_response(conn_res, 200)
883 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
888 |> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
890 result = json_response(conn_res, 200)
891 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
896 |> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
898 result = json_response(conn_res, 200)
899 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
902 test "filters notifications using exclude_types", %{conn: conn} do
904 other_user = insert(:user)
906 {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
907 {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
908 {:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, other_user)
909 {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
910 {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
912 mention_notification_id =
913 Repo.get_by(Notification, activity_id: mention_activity.id).id |> to_string()
915 favorite_notification_id =
916 Repo.get_by(Notification, activity_id: favorite_activity.id).id |> to_string()
918 reblog_notification_id =
919 Repo.get_by(Notification, activity_id: reblog_activity.id).id |> to_string()
921 follow_notification_id =
922 Repo.get_by(Notification, activity_id: follow_activity.id).id |> to_string()
926 |> assign(:user, user)
929 get(conn, "/api/v1/notifications", %{exclude_types: ["mention", "favourite", "reblog"]})
931 assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
934 get(conn, "/api/v1/notifications", %{exclude_types: ["favourite", "reblog", "follow"]})
936 assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
939 get(conn, "/api/v1/notifications", %{exclude_types: ["reblog", "follow", "mention"]})
941 assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
944 get(conn, "/api/v1/notifications", %{exclude_types: ["follow", "mention", "favourite"]})
946 assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
950 describe "reblogging" do
951 test "reblogs and returns the reblogged status", %{conn: conn} do
952 activity = insert(:note_activity)
957 |> assign(:user, user)
958 |> post("/api/v1/statuses/#{activity.id}/reblog")
960 assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
961 json_response(conn, 200)
963 assert to_string(activity.id) == id
967 describe "unreblogging" do
968 test "unreblogs and returns the unreblogged status", %{conn: conn} do
969 activity = insert(:note_activity)
972 {:ok, _, _} = CommonAPI.repeat(activity.id, user)
976 |> assign(:user, user)
977 |> post("/api/v1/statuses/#{activity.id}/unreblog")
979 assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} = json_response(conn, 200)
981 assert to_string(activity.id) == id
985 describe "favoriting" do
986 test "favs a status and returns it", %{conn: conn} do
987 activity = insert(:note_activity)
992 |> assign(:user, user)
993 |> post("/api/v1/statuses/#{activity.id}/favourite")
995 assert %{"id" => id, "favourites_count" => 1, "favourited" => true} =
996 json_response(conn, 200)
998 assert to_string(activity.id) == id
1001 test "returns 500 for a wrong id", %{conn: conn} do
1002 user = insert(:user)
1006 |> assign(:user, user)
1007 |> post("/api/v1/statuses/1/favourite")
1008 |> json_response(500)
1010 assert resp == "Something went wrong"
1014 describe "unfavoriting" do
1015 test "unfavorites a status and returns it", %{conn: conn} do
1016 activity = insert(:note_activity)
1017 user = insert(:user)
1019 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1023 |> assign(:user, user)
1024 |> post("/api/v1/statuses/#{activity.id}/unfavourite")
1026 assert %{"id" => id, "favourites_count" => 0, "favourited" => false} =
1027 json_response(conn, 200)
1029 assert to_string(activity.id) == id
1033 describe "user timelines" do
1034 test "gets a users statuses", %{conn: conn} do
1035 user_one = insert(:user)
1036 user_two = insert(:user)
1037 user_three = insert(:user)
1039 {:ok, user_three} = User.follow(user_three, user_one)
1041 {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
1043 {:ok, direct_activity} =
1044 CommonAPI.post(user_one, %{
1045 "status" => "Hi, @#{user_two.nickname}.",
1046 "visibility" => "direct"
1049 {:ok, private_activity} =
1050 CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
1054 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1056 assert [%{"id" => id}] = json_response(resp, 200)
1057 assert id == to_string(activity.id)
1061 |> assign(:user, user_two)
1062 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1064 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
1065 assert id_one == to_string(direct_activity.id)
1066 assert id_two == to_string(activity.id)
1070 |> assign(:user, user_three)
1071 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1073 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
1074 assert id_one == to_string(private_activity.id)
1075 assert id_two == to_string(activity.id)
1078 test "unimplemented pinned statuses feature", %{conn: conn} do
1079 note = insert(:note_activity)
1080 user = User.get_by_ap_id(note.data["actor"])
1084 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1086 assert json_response(conn, 200) == []
1089 test "gets an users media", %{conn: conn} do
1090 note = insert(:note_activity)
1091 user = User.get_by_ap_id(note.data["actor"])
1093 file = %Plug.Upload{
1094 content_type: "image/jpg",
1095 path: Path.absname("test/fixtures/image.jpg"),
1096 filename: "an_image.jpg"
1100 TwitterAPI.upload(file, user, "json")
1104 TwitterAPI.create_status(user, %{"status" => "cofe", "media_ids" => [media["media_id"]]})
1108 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
1110 assert [%{"id" => id}] = json_response(conn, 200)
1111 assert id == to_string(image_post.id)
1115 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
1117 assert [%{"id" => id}] = json_response(conn, 200)
1118 assert id == to_string(image_post.id)
1121 test "gets a user's statuses without reblogs", %{conn: conn} do
1122 user = insert(:user)
1123 {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
1124 {:ok, _, _} = CommonAPI.repeat(post.id, user)
1128 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
1130 assert [%{"id" => id}] = json_response(conn, 200)
1131 assert id == to_string(post.id)
1135 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
1137 assert [%{"id" => id}] = json_response(conn, 200)
1138 assert id == to_string(post.id)
1142 describe "user relationships" do
1143 test "returns the relationships for the current user", %{conn: conn} do
1144 user = insert(:user)
1145 other_user = insert(:user)
1146 {:ok, user} = User.follow(user, other_user)
1150 |> assign(:user, user)
1151 |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]})
1153 assert [relationship] = json_response(conn, 200)
1155 assert to_string(other_user.id) == relationship["id"]
1159 describe "locked accounts" do
1160 test "/api/v1/follow_requests works" do
1161 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
1162 other_user = insert(:user)
1164 {:ok, _activity} = ActivityPub.follow(other_user, user)
1166 user = Repo.get(User, user.id)
1167 other_user = Repo.get(User, other_user.id)
1169 assert User.following?(other_user, user) == false
1173 |> assign(:user, user)
1174 |> get("/api/v1/follow_requests")
1176 assert [relationship] = json_response(conn, 200)
1177 assert to_string(other_user.id) == relationship["id"]
1180 test "/api/v1/follow_requests/:id/authorize works" do
1181 user = insert(:user, %{info: %User.Info{locked: true}})
1182 other_user = insert(:user)
1184 {:ok, _activity} = ActivityPub.follow(other_user, user)
1186 user = Repo.get(User, user.id)
1187 other_user = Repo.get(User, other_user.id)
1189 assert User.following?(other_user, user) == false
1193 |> assign(:user, user)
1194 |> post("/api/v1/follow_requests/#{other_user.id}/authorize")
1196 assert relationship = json_response(conn, 200)
1197 assert to_string(other_user.id) == relationship["id"]
1199 user = Repo.get(User, user.id)
1200 other_user = Repo.get(User, other_user.id)
1202 assert User.following?(other_user, user) == true
1205 test "verify_credentials", %{conn: conn} do
1206 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "private"}})
1210 |> assign(:user, user)
1211 |> get("/api/v1/accounts/verify_credentials")
1213 assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
1214 assert id == to_string(user.id)
1217 test "/api/v1/follow_requests/:id/reject works" do
1218 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
1219 other_user = insert(:user)
1221 {:ok, _activity} = ActivityPub.follow(other_user, user)
1223 user = Repo.get(User, user.id)
1227 |> assign(:user, user)
1228 |> post("/api/v1/follow_requests/#{other_user.id}/reject")
1230 assert relationship = json_response(conn, 200)
1231 assert to_string(other_user.id) == relationship["id"]
1233 user = Repo.get(User, user.id)
1234 other_user = Repo.get(User, other_user.id)
1236 assert User.following?(other_user, user) == false
1240 test "account fetching", %{conn: conn} do
1241 user = insert(:user)
1245 |> get("/api/v1/accounts/#{user.id}")
1247 assert %{"id" => id} = json_response(conn, 200)
1248 assert id == to_string(user.id)
1252 |> get("/api/v1/accounts/-1")
1254 assert %{"error" => "Can't find user"} = json_response(conn, 404)
1257 test "account fetching also works nickname", %{conn: conn} do
1258 user = insert(:user)
1262 |> get("/api/v1/accounts/#{user.nickname}")
1264 assert %{"id" => id} = json_response(conn, 200)
1265 assert id == user.id
1268 test "media upload", %{conn: conn} do
1269 file = %Plug.Upload{
1270 content_type: "image/jpg",
1271 path: Path.absname("test/fixtures/image.jpg"),
1272 filename: "an_image.jpg"
1275 desc = "Description of the image"
1277 user = insert(:user)
1281 |> assign(:user, user)
1282 |> post("/api/v1/media", %{"file" => file, "description" => desc})
1284 assert media = json_response(conn, 200)
1286 assert media["type"] == "image"
1287 assert media["description"] == desc
1290 object = Repo.get(Object, media["id"])
1291 assert object.data["actor"] == User.ap_id(user)
1294 test "hashtag timeline", %{conn: conn} do
1295 following = insert(:user)
1298 {:ok, activity} = TwitterAPI.create_status(following, %{"status" => "test #2hu"})
1300 {:ok, [_activity]} =
1301 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
1305 |> get("/api/v1/timelines/tag/2hu")
1307 assert [%{"id" => id}] = json_response(nconn, 200)
1309 assert id == to_string(activity.id)
1311 # works for different capitalization too
1314 |> get("/api/v1/timelines/tag/2HU")
1316 assert [%{"id" => id}] = json_response(nconn, 200)
1318 assert id == to_string(activity.id)
1322 test "multi-hashtag timeline", %{conn: conn} do
1323 user = insert(:user)
1325 {:ok, activity_test} = CommonAPI.post(user, %{"status" => "#test"})
1326 {:ok, activity_test1} = CommonAPI.post(user, %{"status" => "#test #test1"})
1327 {:ok, activity_none} = CommonAPI.post(user, %{"status" => "#test #none"})
1331 |> get("/api/v1/timelines/tag/test", %{"any" => ["test1"]})
1333 [status_none, status_test1, status_test] = json_response(any_test, 200)
1335 assert to_string(activity_test.id) == status_test["id"]
1336 assert to_string(activity_test1.id) == status_test1["id"]
1337 assert to_string(activity_none.id) == status_none["id"]
1341 |> get("/api/v1/timelines/tag/test", %{"all" => ["test1"], "none" => ["none"]})
1343 assert [status_test1] == json_response(restricted_test, 200)
1345 all_test = conn |> get("/api/v1/timelines/tag/test", %{"all" => ["none"]})
1347 assert [status_none] == json_response(all_test, 200)
1350 test "getting followers", %{conn: conn} do
1351 user = insert(:user)
1352 other_user = insert(:user)
1353 {:ok, user} = User.follow(user, other_user)
1357 |> get("/api/v1/accounts/#{other_user.id}/followers")
1359 assert [%{"id" => id}] = json_response(conn, 200)
1360 assert id == to_string(user.id)
1363 test "getting followers, hide_followers", %{conn: conn} do
1364 user = insert(:user)
1365 other_user = insert(:user, %{info: %{hide_followers: true}})
1366 {:ok, _user} = User.follow(user, other_user)
1370 |> get("/api/v1/accounts/#{other_user.id}/followers")
1372 assert [] == json_response(conn, 200)
1375 test "getting followers, hide_followers, same user requesting", %{conn: conn} do
1376 user = insert(:user)
1377 other_user = insert(:user, %{info: %{hide_followers: true}})
1378 {:ok, _user} = User.follow(user, other_user)
1382 |> assign(:user, other_user)
1383 |> get("/api/v1/accounts/#{other_user.id}/followers")
1385 refute [] == json_response(conn, 200)
1388 test "getting followers, pagination", %{conn: conn} do
1389 user = insert(:user)
1390 follower1 = insert(:user)
1391 follower2 = insert(:user)
1392 follower3 = insert(:user)
1393 {:ok, _} = User.follow(follower1, user)
1394 {:ok, _} = User.follow(follower2, user)
1395 {:ok, _} = User.follow(follower3, user)
1399 |> assign(:user, user)
1403 |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
1405 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1406 assert id3 == follower3.id
1407 assert id2 == follower2.id
1411 |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
1413 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1414 assert id2 == follower2.id
1415 assert id1 == follower1.id
1419 |> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
1421 assert [%{"id" => id2}] = json_response(res_conn, 200)
1422 assert id2 == follower2.id
1424 assert [link_header] = get_resp_header(res_conn, "link")
1425 assert link_header =~ ~r/since_id=#{follower2.id}/
1426 assert link_header =~ ~r/max_id=#{follower2.id}/
1429 test "getting following", %{conn: conn} do
1430 user = insert(:user)
1431 other_user = insert(:user)
1432 {:ok, user} = User.follow(user, other_user)
1436 |> get("/api/v1/accounts/#{user.id}/following")
1438 assert [%{"id" => id}] = json_response(conn, 200)
1439 assert id == to_string(other_user.id)
1442 test "getting following, hide_follows", %{conn: conn} do
1443 user = insert(:user, %{info: %{hide_follows: true}})
1444 other_user = insert(:user)
1445 {:ok, user} = User.follow(user, other_user)
1449 |> get("/api/v1/accounts/#{user.id}/following")
1451 assert [] == json_response(conn, 200)
1454 test "getting following, hide_follows, same user requesting", %{conn: conn} do
1455 user = insert(:user, %{info: %{hide_follows: true}})
1456 other_user = insert(:user)
1457 {:ok, user} = User.follow(user, other_user)
1461 |> assign(:user, user)
1462 |> get("/api/v1/accounts/#{user.id}/following")
1464 refute [] == json_response(conn, 200)
1467 test "getting following, pagination", %{conn: conn} do
1468 user = insert(:user)
1469 following1 = insert(:user)
1470 following2 = insert(:user)
1471 following3 = insert(:user)
1472 {:ok, _} = User.follow(user, following1)
1473 {:ok, _} = User.follow(user, following2)
1474 {:ok, _} = User.follow(user, following3)
1478 |> assign(:user, user)
1482 |> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
1484 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1485 assert id3 == following3.id
1486 assert id2 == following2.id
1490 |> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
1492 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1493 assert id2 == following2.id
1494 assert id1 == following1.id
1498 |> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
1500 assert [%{"id" => id2}] = json_response(res_conn, 200)
1501 assert id2 == following2.id
1503 assert [link_header] = get_resp_header(res_conn, "link")
1504 assert link_header =~ ~r/since_id=#{following2.id}/
1505 assert link_header =~ ~r/max_id=#{following2.id}/
1508 test "following / unfollowing a user", %{conn: conn} do
1509 user = insert(:user)
1510 other_user = insert(:user)
1514 |> assign(:user, user)
1515 |> post("/api/v1/accounts/#{other_user.id}/follow")
1517 assert %{"id" => _id, "following" => true} = json_response(conn, 200)
1519 user = Repo.get(User, user.id)
1523 |> assign(:user, user)
1524 |> post("/api/v1/accounts/#{other_user.id}/unfollow")
1526 assert %{"id" => _id, "following" => false} = json_response(conn, 200)
1528 user = Repo.get(User, user.id)
1532 |> assign(:user, user)
1533 |> post("/api/v1/follows", %{"uri" => other_user.nickname})
1535 assert %{"id" => id} = json_response(conn, 200)
1536 assert id == to_string(other_user.id)
1539 test "muting / unmuting a user", %{conn: conn} do
1540 user = insert(:user)
1541 other_user = insert(:user)
1545 |> assign(:user, user)
1546 |> post("/api/v1/accounts/#{other_user.id}/mute")
1548 assert %{"id" => _id, "muting" => true} = json_response(conn, 200)
1550 user = Repo.get(User, user.id)
1554 |> assign(:user, user)
1555 |> post("/api/v1/accounts/#{other_user.id}/unmute")
1557 assert %{"id" => _id, "muting" => false} = json_response(conn, 200)
1560 test "getting a list of mutes", %{conn: conn} do
1561 user = insert(:user)
1562 other_user = insert(:user)
1564 {:ok, user} = User.mute(user, other_user)
1568 |> assign(:user, user)
1569 |> get("/api/v1/mutes")
1571 other_user_id = to_string(other_user.id)
1572 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1575 test "blocking / unblocking a user", %{conn: conn} do
1576 user = insert(:user)
1577 other_user = insert(:user)
1581 |> assign(:user, user)
1582 |> post("/api/v1/accounts/#{other_user.id}/block")
1584 assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
1586 user = Repo.get(User, user.id)
1590 |> assign(:user, user)
1591 |> post("/api/v1/accounts/#{other_user.id}/unblock")
1593 assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
1596 test "getting a list of blocks", %{conn: conn} do
1597 user = insert(:user)
1598 other_user = insert(:user)
1600 {:ok, user} = User.block(user, other_user)
1604 |> assign(:user, user)
1605 |> get("/api/v1/blocks")
1607 other_user_id = to_string(other_user.id)
1608 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1611 test "blocking / unblocking a domain", %{conn: conn} do
1612 user = insert(:user)
1613 other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
1617 |> assign(:user, user)
1618 |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1620 assert %{} = json_response(conn, 200)
1621 user = User.get_cached_by_ap_id(user.ap_id)
1622 assert User.blocks?(user, other_user)
1626 |> assign(:user, user)
1627 |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1629 assert %{} = json_response(conn, 200)
1630 user = User.get_cached_by_ap_id(user.ap_id)
1631 refute User.blocks?(user, other_user)
1634 test "getting a list of domain blocks", %{conn: conn} do
1635 user = insert(:user)
1637 {:ok, user} = User.block_domain(user, "bad.site")
1638 {:ok, user} = User.block_domain(user, "even.worse.site")
1642 |> assign(:user, user)
1643 |> get("/api/v1/domain_blocks")
1645 domain_blocks = json_response(conn, 200)
1647 assert "bad.site" in domain_blocks
1648 assert "even.worse.site" in domain_blocks
1651 test "unimplemented follow_requests, blocks, domain blocks" do
1652 user = insert(:user)
1654 ["blocks", "domain_blocks", "follow_requests"]
1655 |> Enum.each(fn endpoint ->
1658 |> assign(:user, user)
1659 |> get("/api/v1/#{endpoint}")
1661 assert [] = json_response(conn, 200)
1665 test "account search", %{conn: conn} do
1666 user = insert(:user)
1667 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1668 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1672 |> assign(:user, user)
1673 |> get("/api/v1/accounts/search", %{"q" => "shp"})
1674 |> json_response(200)
1676 result_ids = for result <- results, do: result["acct"]
1678 assert user_two.nickname in result_ids
1679 assert user_three.nickname in result_ids
1683 |> assign(:user, user)
1684 |> get("/api/v1/accounts/search", %{"q" => "2hu"})
1685 |> json_response(200)
1687 result_ids = for result <- results, do: result["acct"]
1689 assert user_three.nickname in result_ids
1692 test "search", %{conn: conn} do
1693 user = insert(:user)
1694 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1695 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1697 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1700 CommonAPI.post(user, %{
1701 "status" => "This is about 2hu, but private",
1702 "visibility" => "private"
1705 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1709 |> get("/api/v1/search", %{"q" => "2hu"})
1711 assert results = json_response(conn, 200)
1713 [account | _] = results["accounts"]
1714 assert account["id"] == to_string(user_three.id)
1716 assert results["hashtags"] == []
1718 [status] = results["statuses"]
1719 assert status["id"] == to_string(activity.id)
1722 test "search fetches remote statuses", %{conn: conn} do
1726 |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
1728 assert results = json_response(conn, 200)
1730 [status] = results["statuses"]
1731 assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
1735 test "search doesn't show statuses that it shouldn't", %{conn: conn} do
1737 CommonAPI.post(insert(:user), %{
1738 "status" => "This is about 2hu, but private",
1739 "visibility" => "private"
1745 |> get("/api/v1/search", %{"q" => activity.data["object"]["id"]})
1747 assert results = json_response(conn, 200)
1749 [] = results["statuses"]
1753 test "search fetches remote accounts", %{conn: conn} do
1756 |> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"})
1758 assert results = json_response(conn, 200)
1759 [account] = results["accounts"]
1760 assert account["acct"] == "shp@social.heldscal.la"
1763 test "returns the favorites of a user", %{conn: conn} do
1764 user = insert(:user)
1765 other_user = insert(:user)
1767 {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
1768 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
1770 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1774 |> assign(:user, user)
1775 |> get("/api/v1/favourites")
1777 assert [status] = json_response(first_conn, 200)
1778 assert status["id"] == to_string(activity.id)
1780 assert [{"link", _link_header}] =
1781 Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
1783 # Honours query params
1784 {:ok, second_activity} =
1785 CommonAPI.post(other_user, %{
1787 "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
1790 {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
1792 last_like = status["id"]
1796 |> assign(:user, user)
1797 |> get("/api/v1/favourites?since_id=#{last_like}")
1799 assert [second_status] = json_response(second_conn, 200)
1800 assert second_status["id"] == to_string(second_activity.id)
1804 |> assign(:user, user)
1805 |> get("/api/v1/favourites?limit=0")
1807 assert [] = json_response(third_conn, 200)
1810 describe "updating credentials" do
1811 test "updates the user's bio", %{conn: conn} do
1812 user = insert(:user)
1813 user2 = insert(:user)
1817 |> assign(:user, user)
1818 |> patch("/api/v1/accounts/update_credentials", %{
1819 "note" => "I drink #cofe with @#{user2.nickname}"
1822 assert user = json_response(conn, 200)
1824 assert user["note"] ==
1825 ~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe" rel="tag">#cofe</a> with <span class="h-card"><a data-user=") <>
1827 ~s(" class="u-url mention" href=") <>
1828 user2.ap_id <> ~s(">@<span>) <> user2.nickname <> ~s(</span></a></span>)
1831 test "updates the user's locking status", %{conn: conn} do
1832 user = insert(:user)
1836 |> assign(:user, user)
1837 |> patch("/api/v1/accounts/update_credentials", %{locked: "true"})
1839 assert user = json_response(conn, 200)
1840 assert user["locked"] == true
1843 test "updates the user's name", %{conn: conn} do
1844 user = insert(:user)
1848 |> assign(:user, user)
1849 |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
1851 assert user = json_response(conn, 200)
1852 assert user["display_name"] == "markorepairs"
1855 test "updates the user's avatar", %{conn: conn} do
1856 user = insert(:user)
1858 new_avatar = %Plug.Upload{
1859 content_type: "image/jpg",
1860 path: Path.absname("test/fixtures/image.jpg"),
1861 filename: "an_image.jpg"
1866 |> assign(:user, user)
1867 |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
1869 assert user_response = json_response(conn, 200)
1870 assert user_response["avatar"] != User.avatar_url(user)
1873 test "updates the user's banner", %{conn: conn} do
1874 user = insert(:user)
1876 new_header = %Plug.Upload{
1877 content_type: "image/jpg",
1878 path: Path.absname("test/fixtures/image.jpg"),
1879 filename: "an_image.jpg"
1884 |> assign(:user, user)
1885 |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
1887 assert user_response = json_response(conn, 200)
1888 assert user_response["header"] != User.banner_url(user)
1891 test "requires 'write' permission", %{conn: conn} do
1892 token1 = insert(:oauth_token, scopes: ["read"])
1893 token2 = insert(:oauth_token, scopes: ["write", "follow"])
1895 for token <- [token1, token2] do
1898 |> put_req_header("authorization", "Bearer #{token.token}")
1899 |> patch("/api/v1/accounts/update_credentials", %{})
1901 if token == token1 do
1902 assert %{"error" => "Insufficient permissions: write."} == json_response(conn, 403)
1904 assert json_response(conn, 200)
1910 test "get instance information", %{conn: conn} do
1911 conn = get(conn, "/api/v1/instance")
1912 assert result = json_response(conn, 200)
1914 # Note: not checking for "max_toot_chars" since it's optional
1922 "streaming_api" => _
1927 "registrations" => _
1931 test "get instance stats", %{conn: conn} do
1932 user = insert(:user, %{local: true})
1934 user2 = insert(:user, %{local: true})
1935 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
1937 insert(:user, %{local: false, nickname: "u@peer1.com"})
1938 insert(:user, %{local: false, nickname: "u@peer2.com"})
1940 {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
1942 # Stats should count users with missing or nil `info.deactivated` value
1943 user = Repo.get(User, user.id)
1944 info_change = Changeset.change(user.info, %{deactivated: nil})
1948 |> Changeset.change()
1949 |> Changeset.put_embed(:info, info_change)
1950 |> User.update_and_set_cache()
1952 Pleroma.Stats.update_stats()
1954 conn = get(conn, "/api/v1/instance")
1956 assert result = json_response(conn, 200)
1958 stats = result["stats"]
1961 assert stats["user_count"] == 1
1962 assert stats["status_count"] == 1
1963 assert stats["domain_count"] == 2
1966 test "get peers", %{conn: conn} do
1967 insert(:user, %{local: false, nickname: "u@peer1.com"})
1968 insert(:user, %{local: false, nickname: "u@peer2.com"})
1970 Pleroma.Stats.update_stats()
1972 conn = get(conn, "/api/v1/instance/peers")
1974 assert result = json_response(conn, 200)
1976 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
1979 test "put settings", %{conn: conn} do
1980 user = insert(:user)
1984 |> assign(:user, user)
1985 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
1987 assert _result = json_response(conn, 200)
1989 user = User.get_cached_by_ap_id(user.ap_id)
1990 assert user.info.settings == %{"programming" => "socks"}
1993 describe "pinned statuses" do
1995 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1997 user = insert(:user)
1998 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
2000 [user: user, activity: activity]
2003 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
2004 {:ok, _} = CommonAPI.pin(activity.id, user)
2008 |> assign(:user, user)
2009 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2010 |> json_response(200)
2012 id_str = to_string(activity.id)
2014 assert [%{"id" => ^id_str, "pinned" => true}] = result
2017 test "pin status", %{conn: conn, user: user, activity: activity} do
2018 id_str = to_string(activity.id)
2020 assert %{"id" => ^id_str, "pinned" => true} =
2022 |> assign(:user, user)
2023 |> post("/api/v1/statuses/#{activity.id}/pin")
2024 |> json_response(200)
2026 assert [%{"id" => ^id_str, "pinned" => true}] =
2028 |> assign(:user, user)
2029 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2030 |> json_response(200)
2033 test "unpin status", %{conn: conn, user: user, activity: activity} do
2034 {:ok, _} = CommonAPI.pin(activity.id, user)
2036 id_str = to_string(activity.id)
2037 user = refresh_record(user)
2039 assert %{"id" => ^id_str, "pinned" => false} =
2041 |> assign(:user, user)
2042 |> post("/api/v1/statuses/#{activity.id}/unpin")
2043 |> json_response(200)
2047 |> assign(:user, user)
2048 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2049 |> json_response(200)
2052 test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
2053 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
2055 id_str_one = to_string(activity_one.id)
2057 assert %{"id" => ^id_str_one, "pinned" => true} =
2059 |> assign(:user, user)
2060 |> post("/api/v1/statuses/#{id_str_one}/pin")
2061 |> json_response(200)
2063 user = refresh_record(user)
2065 assert %{"error" => "You have already pinned the maximum number of statuses"} =
2067 |> assign(:user, user)
2068 |> post("/api/v1/statuses/#{activity_two.id}/pin")
2069 |> json_response(400)
2072 test "Status rich-media Card", %{conn: conn, user: user} do
2073 Pleroma.Config.put([:rich_media, :enabled], true)
2074 {:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp"})
2078 |> get("/api/v1/statuses/#{activity.id}/card")
2079 |> json_response(200)
2081 assert response == %{
2082 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2083 "provider_name" => "www.imdb.com",
2084 "provider_url" => "http://www.imdb.com",
2085 "title" => "The Rock",
2087 "url" => "http://www.imdb.com/title/tt0117500/",
2088 "description" => nil,
2091 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2092 "title" => "The Rock",
2093 "type" => "video.movie",
2094 "url" => "http://www.imdb.com/title/tt0117500/"
2099 # works with private posts
2101 CommonAPI.post(user, %{"status" => "http://example.com/ogp", "visibility" => "direct"})
2105 |> assign(:user, user)
2106 |> get("/api/v1/statuses/#{activity.id}/card")
2107 |> json_response(200)
2109 assert response_two == response
2111 Pleroma.Config.put([:rich_media, :enabled], false)
2116 user = insert(:user)
2117 for_user = insert(:user)
2120 CommonAPI.post(user, %{
2121 "status" => "heweoo?"
2125 CommonAPI.post(user, %{
2126 "status" => "heweoo!"
2131 |> assign(:user, for_user)
2132 |> post("/api/v1/statuses/#{activity1.id}/bookmark")
2134 assert json_response(response1, 200)["bookmarked"] == true
2138 |> assign(:user, for_user)
2139 |> post("/api/v1/statuses/#{activity2.id}/bookmark")
2141 assert json_response(response2, 200)["bookmarked"] == true
2145 |> assign(:user, for_user)
2146 |> get("/api/v1/bookmarks")
2148 assert [json_response(response2, 200), json_response(response1, 200)] ==
2149 json_response(bookmarks, 200)
2153 |> assign(:user, for_user)
2154 |> post("/api/v1/statuses/#{activity1.id}/unbookmark")
2156 assert json_response(response1, 200)["bookmarked"] == false
2160 |> assign(:user, for_user)
2161 |> get("/api/v1/bookmarks")
2163 assert [json_response(response2, 200)] == json_response(bookmarks, 200)
2166 describe "conversation muting" do
2168 user = insert(:user)
2169 {:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
2171 [user: user, activity: activity]
2174 test "mute conversation", %{conn: conn, user: user, activity: activity} do
2175 id_str = to_string(activity.id)
2177 assert %{"id" => ^id_str, "muted" => true} =
2179 |> assign(:user, user)
2180 |> post("/api/v1/statuses/#{activity.id}/mute")
2181 |> json_response(200)
2184 test "unmute conversation", %{conn: conn, user: user, activity: activity} do
2185 {:ok, _} = CommonAPI.add_mute(user, activity)
2187 id_str = to_string(activity.id)
2188 user = refresh_record(user)
2190 assert %{"id" => ^id_str, "muted" => false} =
2192 |> assign(:user, user)
2193 |> post("/api/v1/statuses/#{activity.id}/unmute")
2194 |> json_response(200)
2198 test "flavours switching (Pleroma Extension)", %{conn: conn} do
2199 user = insert(:user)
2203 |> assign(:user, user)
2204 |> get("/api/v1/pleroma/flavour")
2206 assert "glitch" == json_response(get_old_flavour, 200)
2210 |> assign(:user, user)
2211 |> post("/api/v1/pleroma/flavour/vanilla")
2213 assert "vanilla" == json_response(set_flavour, 200)
2217 |> assign(:user, user)
2218 |> post("/api/v1/pleroma/flavour/vanilla")
2220 assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
2223 describe "reports" do
2225 reporter = insert(:user)
2226 target_user = insert(:user)
2228 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
2230 [reporter: reporter, target_user: target_user, activity: activity]
2233 test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
2234 assert %{"action_taken" => false, "id" => _} =
2236 |> assign(:user, reporter)
2237 |> post("/api/v1/reports", %{"account_id" => target_user.id})
2238 |> json_response(200)
2241 test "submit a report with statuses and comment", %{
2244 target_user: target_user,
2247 assert %{"action_taken" => false, "id" => _} =
2249 |> assign(:user, reporter)
2250 |> post("/api/v1/reports", %{
2251 "account_id" => target_user.id,
2252 "status_ids" => [activity.id],
2253 "comment" => "bad status!"
2255 |> json_response(200)
2258 test "account_id is required", %{
2263 assert %{"error" => "Valid `account_id` required"} =
2265 |> assign(:user, reporter)
2266 |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
2267 |> json_response(400)
2270 test "comment must be up to the size specified in the config", %{
2273 target_user: target_user
2275 max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
2276 comment = String.pad_trailing("a", max_size + 1, "a")
2278 error = %{"error" => "Comment must be up to #{max_size} characters"}
2282 |> assign(:user, reporter)
2283 |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
2284 |> json_response(400)
2288 describe "link headers" do
2289 test "preserves parameters in link headers", %{conn: conn} do
2290 user = insert(:user)
2291 other_user = insert(:user)
2294 CommonAPI.post(other_user, %{
2295 "status" => "hi @#{user.nickname}",
2296 "visibility" => "public"
2300 CommonAPI.post(other_user, %{
2301 "status" => "hi @#{user.nickname}",
2302 "visibility" => "public"
2305 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
2306 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
2310 |> assign(:user, user)
2311 |> get("/api/v1/notifications", %{media_only: true})
2313 assert [link_header] = get_resp_header(conn, "link")
2314 assert link_header =~ ~r/media_only=true/
2315 assert link_header =~ ~r/since_id=#{notification2.id}/
2316 assert link_header =~ ~r/max_id=#{notification1.id}/