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
13 alias Pleroma.ScheduledActivity
15 alias Pleroma.Web.ActivityPub.ActivityPub
16 alias Pleroma.Web.CommonAPI
17 alias Pleroma.Web.MastodonAPI.FilterView
18 alias Pleroma.Web.OAuth.App
19 alias Pleroma.Web.OStatus
20 alias Pleroma.Web.Push
21 alias Pleroma.Web.TwitterAPI.TwitterAPI
22 import Pleroma.Factory
23 import ExUnit.CaptureLog
27 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
31 test "the home timeline", %{conn: conn} do
33 following = insert(:user)
35 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
39 |> assign(:user, user)
40 |> get("/api/v1/timelines/home")
42 assert Enum.empty?(json_response(conn, 200))
44 {:ok, user} = User.follow(user, following)
48 |> assign(:user, user)
49 |> get("/api/v1/timelines/home")
51 assert [%{"content" => "test"}] = json_response(conn, 200)
54 test "the public timeline", %{conn: conn} do
55 following = insert(:user)
58 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
61 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
65 |> get("/api/v1/timelines/public", %{"local" => "False"})
67 assert length(json_response(conn, 200)) == 2
71 |> get("/api/v1/timelines/public", %{"local" => "True"})
73 assert [%{"content" => "test"}] = json_response(conn, 200)
77 |> get("/api/v1/timelines/public", %{"local" => "1"})
79 assert [%{"content" => "test"}] = json_response(conn, 200)
83 test "posting a status", %{conn: conn} do
86 idempotency_key = "Pikachu rocks!"
90 |> assign(:user, user)
91 |> put_req_header("idempotency-key", idempotency_key)
92 |> post("/api/v1/statuses", %{
94 "spoiler_text" => "2hu",
95 "sensitive" => "false"
98 {:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key)
100 assert ttl > :timer.seconds(6 * 60 * 60 - 1)
102 assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} =
103 json_response(conn_one, 200)
105 assert Activity.get_by_id(id)
109 |> assign(:user, user)
110 |> put_req_header("idempotency-key", idempotency_key)
111 |> post("/api/v1/statuses", %{
113 "spoiler_text" => "2hu",
114 "sensitive" => "false"
117 assert %{"id" => second_id} = json_response(conn_two, 200)
119 assert id == second_id
123 |> assign(:user, user)
124 |> post("/api/v1/statuses", %{
126 "spoiler_text" => "2hu",
127 "sensitive" => "false"
130 assert %{"id" => third_id} = json_response(conn_three, 200)
132 refute id == third_id
135 test "posting a sensitive status", %{conn: conn} do
140 |> assign(:user, user)
141 |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true})
143 assert %{"content" => "cofe", "id" => id, "sensitive" => true} = json_response(conn, 200)
144 assert Activity.get_by_id(id)
147 test "posting a fake status", %{conn: conn} do
152 |> assign(:user, user)
153 |> post("/api/v1/statuses", %{
155 "\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it"
158 real_status = json_response(real_conn, 200)
161 assert Object.get_by_ap_id(real_status["uri"])
165 |> Map.put("id", nil)
166 |> Map.put("url", nil)
167 |> Map.put("uri", nil)
168 |> Map.put("created_at", nil)
169 |> Kernel.put_in(["pleroma", "conversation_id"], nil)
173 |> assign(:user, user)
174 |> post("/api/v1/statuses", %{
176 "\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it",
180 fake_status = json_response(fake_conn, 200)
183 refute Object.get_by_ap_id(fake_status["uri"])
187 |> Map.put("id", nil)
188 |> Map.put("url", nil)
189 |> Map.put("uri", nil)
190 |> Map.put("created_at", nil)
191 |> Kernel.put_in(["pleroma", "conversation_id"], nil)
193 assert real_status == fake_status
196 test "posting a status with OGP link preview", %{conn: conn} do
197 Pleroma.Config.put([:rich_media, :enabled], true)
202 |> assign(:user, user)
203 |> post("/api/v1/statuses", %{
204 "status" => "http://example.com/ogp"
207 assert %{"id" => id, "card" => %{"title" => "The Rock"}} = json_response(conn, 200)
208 assert Activity.get_by_id(id)
209 Pleroma.Config.put([:rich_media, :enabled], false)
212 test "posting a direct status", %{conn: conn} do
213 user1 = insert(:user)
214 user2 = insert(:user)
215 content = "direct cofe @#{user2.nickname}"
219 |> assign(:user, user1)
220 |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"})
222 assert %{"id" => id, "visibility" => "direct"} = json_response(conn, 200)
223 assert activity = Activity.get_by_id(id)
224 assert activity.recipients == [user2.ap_id, user1.ap_id]
225 assert activity.data["to"] == [user2.ap_id]
226 assert activity.data["cc"] == []
229 test "direct timeline", %{conn: conn} do
230 user_one = insert(:user)
231 user_two = insert(:user)
233 {:ok, user_two} = User.follow(user_two, user_one)
236 CommonAPI.post(user_one, %{
237 "status" => "Hi @#{user_two.nickname}!",
238 "visibility" => "direct"
241 {:ok, _follower_only} =
242 CommonAPI.post(user_one, %{
243 "status" => "Hi @#{user_two.nickname}!",
244 "visibility" => "private"
247 # Only direct should be visible here
250 |> assign(:user, user_two)
251 |> get("api/v1/timelines/direct")
253 [status] = json_response(res_conn, 200)
255 assert %{"visibility" => "direct"} = status
256 assert status["url"] != direct.data["id"]
258 # User should be able to see his own direct message
261 |> assign(:user, user_one)
262 |> get("api/v1/timelines/direct")
264 [status] = json_response(res_conn, 200)
266 assert %{"visibility" => "direct"} = status
268 # Both should be visible here
271 |> assign(:user, user_two)
272 |> get("api/v1/timelines/home")
274 [_s1, _s2] = json_response(res_conn, 200)
277 Enum.each(1..20, fn _ ->
279 CommonAPI.post(user_one, %{
280 "status" => "Hi @#{user_two.nickname}!",
281 "visibility" => "direct"
287 |> assign(:user, user_two)
288 |> get("api/v1/timelines/direct")
290 statuses = json_response(res_conn, 200)
291 assert length(statuses) == 20
295 |> assign(:user, user_two)
296 |> get("api/v1/timelines/direct", %{max_id: List.last(statuses)["id"]})
298 [status] = json_response(res_conn, 200)
300 assert status["url"] != direct.data["id"]
303 test "doesn't include DMs from blocked users", %{conn: conn} do
304 blocker = insert(:user)
305 blocked = insert(:user)
307 {:ok, blocker} = User.block(blocker, blocked)
309 {:ok, _blocked_direct} =
310 CommonAPI.post(blocked, %{
311 "status" => "Hi @#{blocker.nickname}!",
312 "visibility" => "direct"
316 CommonAPI.post(user, %{
317 "status" => "Hi @#{blocker.nickname}!",
318 "visibility" => "direct"
323 |> assign(:user, user)
324 |> get("api/v1/timelines/direct")
326 [status] = json_response(res_conn, 200)
327 assert status["id"] == direct.id
330 test "replying to a status", %{conn: conn} do
333 {:ok, replied_to} = TwitterAPI.create_status(user, %{"status" => "cofe"})
337 |> assign(:user, user)
338 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
340 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
342 activity = Activity.get_by_id(id)
344 assert activity.data["context"] == replied_to.data["context"]
345 assert activity.data["object"]["inReplyToStatusId"] == replied_to.id
348 test "posting a status with an invalid in_reply_to_id", %{conn: conn} do
353 |> assign(:user, user)
354 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""})
356 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
358 activity = Activity.get_by_id(id)
363 test "verify_credentials", %{conn: conn} do
368 |> assign(:user, user)
369 |> get("/api/v1/accounts/verify_credentials")
371 assert %{"id" => id, "source" => %{"privacy" => "public"}} = json_response(conn, 200)
372 assert id == to_string(user.id)
375 test "verify_credentials default scope unlisted", %{conn: conn} do
376 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "unlisted"}})
380 |> assign(:user, user)
381 |> get("/api/v1/accounts/verify_credentials")
383 assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
384 assert id == to_string(user.id)
387 test "apps/verify_credentials", %{conn: conn} do
388 token = insert(:oauth_token)
392 |> assign(:user, token.user)
393 |> assign(:token, token)
394 |> get("/api/v1/apps/verify_credentials")
396 app = Repo.preload(token, :app).app
399 "name" => app.client_name,
400 "website" => app.website,
401 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
404 assert expected == json_response(conn, 200)
407 test "creates an oauth app", %{conn: conn} do
409 app_attrs = build(:oauth_app)
413 |> assign(:user, user)
414 |> post("/api/v1/apps", %{
415 client_name: app_attrs.client_name,
416 redirect_uris: app_attrs.redirect_uris
419 [app] = Repo.all(App)
422 "name" => app.client_name,
423 "website" => app.website,
424 "client_id" => app.client_id,
425 "client_secret" => app.client_secret,
426 "id" => app.id |> to_string(),
427 "redirect_uri" => app.redirect_uris,
428 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
431 assert expected == json_response(conn, 200)
434 test "get a status", %{conn: conn} do
435 activity = insert(:note_activity)
439 |> get("/api/v1/statuses/#{activity.id}")
441 assert %{"id" => id} = json_response(conn, 200)
442 assert id == to_string(activity.id)
445 describe "deleting a status" do
446 test "when you created it", %{conn: conn} do
447 activity = insert(:note_activity)
448 author = User.get_by_ap_id(activity.data["actor"])
452 |> assign(:user, author)
453 |> delete("/api/v1/statuses/#{activity.id}")
455 assert %{} = json_response(conn, 200)
457 refute Activity.get_by_id(activity.id)
460 test "when you didn't create it", %{conn: conn} do
461 activity = insert(:note_activity)
466 |> assign(:user, user)
467 |> delete("/api/v1/statuses/#{activity.id}")
469 assert %{"error" => _} = json_response(conn, 403)
471 assert Activity.get_by_id(activity.id) == activity
474 test "when you're an admin or moderator", %{conn: conn} do
475 activity1 = insert(:note_activity)
476 activity2 = insert(:note_activity)
477 admin = insert(:user, info: %{is_admin: true})
478 moderator = insert(:user, info: %{is_moderator: true})
482 |> assign(:user, admin)
483 |> delete("/api/v1/statuses/#{activity1.id}")
485 assert %{} = json_response(res_conn, 200)
489 |> assign(:user, moderator)
490 |> delete("/api/v1/statuses/#{activity2.id}")
492 assert %{} = json_response(res_conn, 200)
494 refute Activity.get_by_id(activity1.id)
495 refute Activity.get_by_id(activity2.id)
499 describe "filters" do
500 test "creating a filter", %{conn: conn} do
503 filter = %Pleroma.Filter{
510 |> assign(:user, user)
511 |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
513 assert response = json_response(conn, 200)
514 assert response["phrase"] == filter.phrase
515 assert response["context"] == filter.context
516 assert response["id"] != nil
517 assert response["id"] != ""
520 test "fetching a list of filters", %{conn: conn} do
523 query_one = %Pleroma.Filter{
530 query_two = %Pleroma.Filter{
537 {:ok, filter_one} = Pleroma.Filter.create(query_one)
538 {:ok, filter_two} = Pleroma.Filter.create(query_two)
542 |> assign(:user, user)
543 |> get("/api/v1/filters")
544 |> json_response(200)
550 filters: [filter_two, filter_one]
554 test "get a filter", %{conn: conn} do
557 query = %Pleroma.Filter{
564 {:ok, filter} = Pleroma.Filter.create(query)
568 |> assign(:user, user)
569 |> get("/api/v1/filters/#{filter.filter_id}")
571 assert _response = json_response(conn, 200)
574 test "update a filter", %{conn: conn} do
577 query = %Pleroma.Filter{
584 {:ok, _filter} = Pleroma.Filter.create(query)
586 new = %Pleroma.Filter{
593 |> assign(:user, user)
594 |> put("/api/v1/filters/#{query.filter_id}", %{
599 assert response = json_response(conn, 200)
600 assert response["phrase"] == new.phrase
601 assert response["context"] == new.context
604 test "delete a filter", %{conn: conn} do
607 query = %Pleroma.Filter{
614 {:ok, filter} = Pleroma.Filter.create(query)
618 |> assign(:user, user)
619 |> delete("/api/v1/filters/#{filter.filter_id}")
621 assert response = json_response(conn, 200)
622 assert response == %{}
627 test "creating a list", %{conn: conn} do
632 |> assign(:user, user)
633 |> post("/api/v1/lists", %{"title" => "cuties"})
635 assert %{"title" => title} = json_response(conn, 200)
636 assert title == "cuties"
639 test "adding users to a list", %{conn: conn} do
641 other_user = insert(:user)
642 {:ok, list} = Pleroma.List.create("name", user)
646 |> assign(:user, user)
647 |> post("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
649 assert %{} == json_response(conn, 200)
650 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
651 assert following == [other_user.follower_address]
654 test "removing users from a list", %{conn: conn} do
656 other_user = insert(:user)
657 third_user = insert(:user)
658 {:ok, list} = Pleroma.List.create("name", user)
659 {:ok, list} = Pleroma.List.follow(list, other_user)
660 {:ok, list} = Pleroma.List.follow(list, third_user)
664 |> assign(:user, user)
665 |> delete("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
667 assert %{} == json_response(conn, 200)
668 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
669 assert following == [third_user.follower_address]
672 test "listing users in a list", %{conn: conn} do
674 other_user = insert(:user)
675 {:ok, list} = Pleroma.List.create("name", user)
676 {:ok, list} = Pleroma.List.follow(list, other_user)
680 |> assign(:user, user)
681 |> get("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
683 assert [%{"id" => id}] = json_response(conn, 200)
684 assert id == to_string(other_user.id)
687 test "retrieving a list", %{conn: conn} do
689 {:ok, list} = Pleroma.List.create("name", user)
693 |> assign(:user, user)
694 |> get("/api/v1/lists/#{list.id}")
696 assert %{"id" => id} = json_response(conn, 200)
697 assert id == to_string(list.id)
700 test "renaming a list", %{conn: conn} do
702 {:ok, list} = Pleroma.List.create("name", user)
706 |> assign(:user, user)
707 |> put("/api/v1/lists/#{list.id}", %{"title" => "newname"})
709 assert %{"title" => name} = json_response(conn, 200)
710 assert name == "newname"
713 test "deleting a list", %{conn: conn} do
715 {:ok, list} = Pleroma.List.create("name", user)
719 |> assign(:user, user)
720 |> delete("/api/v1/lists/#{list.id}")
722 assert %{} = json_response(conn, 200)
723 assert is_nil(Repo.get(Pleroma.List, list.id))
726 test "list timeline", %{conn: conn} do
728 other_user = insert(:user)
729 {:ok, _activity_one} = TwitterAPI.create_status(user, %{"status" => "Marisa is cute."})
730 {:ok, activity_two} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
731 {:ok, list} = Pleroma.List.create("name", user)
732 {:ok, list} = Pleroma.List.follow(list, other_user)
736 |> assign(:user, user)
737 |> get("/api/v1/timelines/list/#{list.id}")
739 assert [%{"id" => id}] = json_response(conn, 200)
741 assert id == to_string(activity_two.id)
744 test "list timeline does not leak non-public statuses for unfollowed users", %{conn: conn} do
746 other_user = insert(:user)
747 {:ok, activity_one} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
749 {:ok, _activity_two} =
750 TwitterAPI.create_status(other_user, %{
751 "status" => "Marisa is cute.",
752 "visibility" => "private"
755 {:ok, list} = Pleroma.List.create("name", user)
756 {:ok, list} = Pleroma.List.follow(list, other_user)
760 |> assign(:user, user)
761 |> get("/api/v1/timelines/list/#{list.id}")
763 assert [%{"id" => id}] = json_response(conn, 200)
765 assert id == to_string(activity_one.id)
769 describe "notifications" do
770 test "list of notifications", %{conn: conn} do
772 other_user = insert(:user)
775 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
777 {:ok, [_notification]} = Notification.create_notifications(activity)
781 |> assign(:user, user)
782 |> get("/api/v1/notifications")
785 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
787 }\">@<span>#{user.nickname}</span></a></span>"
789 assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
790 assert response == expected_response
793 test "getting a single notification", %{conn: conn} do
795 other_user = insert(:user)
798 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
800 {:ok, [notification]} = Notification.create_notifications(activity)
804 |> assign(:user, user)
805 |> get("/api/v1/notifications/#{notification.id}")
808 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
810 }\">@<span>#{user.nickname}</span></a></span>"
812 assert %{"status" => %{"content" => response}} = json_response(conn, 200)
813 assert response == expected_response
816 test "dismissing a single notification", %{conn: conn} do
818 other_user = insert(:user)
821 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
823 {:ok, [notification]} = Notification.create_notifications(activity)
827 |> assign(:user, user)
828 |> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
830 assert %{} = json_response(conn, 200)
833 test "clearing all notifications", %{conn: conn} do
835 other_user = insert(:user)
838 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
840 {:ok, [_notification]} = Notification.create_notifications(activity)
844 |> assign(:user, user)
845 |> post("/api/v1/notifications/clear")
847 assert %{} = json_response(conn, 200)
851 |> assign(:user, user)
852 |> get("/api/v1/notifications")
854 assert all = json_response(conn, 200)
858 test "paginates notifications using min_id, since_id, max_id, and limit", %{conn: conn} do
860 other_user = insert(:user)
862 {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
863 {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
864 {:ok, activity3} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
865 {:ok, activity4} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
867 notification1_id = Repo.get_by(Notification, activity_id: activity1.id).id |> to_string()
868 notification2_id = Repo.get_by(Notification, activity_id: activity2.id).id |> to_string()
869 notification3_id = Repo.get_by(Notification, activity_id: activity3.id).id |> to_string()
870 notification4_id = Repo.get_by(Notification, activity_id: activity4.id).id |> to_string()
874 |> assign(:user, user)
879 |> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
881 result = json_response(conn_res, 200)
882 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
887 |> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
889 result = json_response(conn_res, 200)
890 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
895 |> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
897 result = json_response(conn_res, 200)
898 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
901 test "filters notifications using exclude_types", %{conn: conn} do
903 other_user = insert(:user)
905 {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
906 {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
907 {:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, other_user)
908 {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
909 {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
911 mention_notification_id =
912 Repo.get_by(Notification, activity_id: mention_activity.id).id |> to_string()
914 favorite_notification_id =
915 Repo.get_by(Notification, activity_id: favorite_activity.id).id |> to_string()
917 reblog_notification_id =
918 Repo.get_by(Notification, activity_id: reblog_activity.id).id |> to_string()
920 follow_notification_id =
921 Repo.get_by(Notification, activity_id: follow_activity.id).id |> to_string()
925 |> assign(:user, user)
928 get(conn, "/api/v1/notifications", %{exclude_types: ["mention", "favourite", "reblog"]})
930 assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
933 get(conn, "/api/v1/notifications", %{exclude_types: ["favourite", "reblog", "follow"]})
935 assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
938 get(conn, "/api/v1/notifications", %{exclude_types: ["reblog", "follow", "mention"]})
940 assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
943 get(conn, "/api/v1/notifications", %{exclude_types: ["follow", "mention", "favourite"]})
945 assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
948 test "destroy multiple", %{conn: conn} do
950 other_user = insert(:user)
952 {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
953 {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
954 {:ok, activity3} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"})
955 {:ok, activity4} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"})
957 notification1_id = Repo.get_by(Notification, activity_id: activity1.id).id |> to_string()
958 notification2_id = Repo.get_by(Notification, activity_id: activity2.id).id |> to_string()
959 notification3_id = Repo.get_by(Notification, activity_id: activity3.id).id |> to_string()
960 notification4_id = Repo.get_by(Notification, activity_id: activity4.id).id |> to_string()
964 |> assign(:user, user)
968 |> get("/api/v1/notifications")
970 result = json_response(conn_res, 200)
971 assert [%{"id" => ^notification2_id}, %{"id" => ^notification1_id}] = result
975 |> assign(:user, other_user)
979 |> get("/api/v1/notifications")
981 result = json_response(conn_res, 200)
982 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
986 |> delete("/api/v1/notifications/destroy_multiple", %{
987 "ids" => [notification1_id, notification2_id]
990 assert json_response(conn_destroy, 200) == %{}
994 |> get("/api/v1/notifications")
996 result = json_response(conn_res, 200)
997 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
1001 describe "reblogging" do
1002 test "reblogs and returns the reblogged status", %{conn: conn} do
1003 activity = insert(:note_activity)
1004 user = insert(:user)
1008 |> assign(:user, user)
1009 |> post("/api/v1/statuses/#{activity.id}/reblog")
1011 assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
1012 json_response(conn, 200)
1014 assert to_string(activity.id) == id
1018 describe "unreblogging" do
1019 test "unreblogs and returns the unreblogged status", %{conn: conn} do
1020 activity = insert(:note_activity)
1021 user = insert(:user)
1023 {:ok, _, _} = CommonAPI.repeat(activity.id, user)
1027 |> assign(:user, user)
1028 |> post("/api/v1/statuses/#{activity.id}/unreblog")
1030 assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} = json_response(conn, 200)
1032 assert to_string(activity.id) == id
1036 describe "favoriting" do
1037 test "favs a status and returns it", %{conn: conn} do
1038 activity = insert(:note_activity)
1039 user = insert(:user)
1043 |> assign(:user, user)
1044 |> post("/api/v1/statuses/#{activity.id}/favourite")
1046 assert %{"id" => id, "favourites_count" => 1, "favourited" => true} =
1047 json_response(conn, 200)
1049 assert to_string(activity.id) == id
1052 test "returns 500 for a wrong id", %{conn: conn} do
1053 user = insert(:user)
1057 |> assign(:user, user)
1058 |> post("/api/v1/statuses/1/favourite")
1059 |> json_response(500)
1061 assert resp == "Something went wrong"
1065 describe "unfavoriting" do
1066 test "unfavorites a status and returns it", %{conn: conn} do
1067 activity = insert(:note_activity)
1068 user = insert(:user)
1070 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1074 |> assign(:user, user)
1075 |> post("/api/v1/statuses/#{activity.id}/unfavourite")
1077 assert %{"id" => id, "favourites_count" => 0, "favourited" => false} =
1078 json_response(conn, 200)
1080 assert to_string(activity.id) == id
1084 describe "user timelines" do
1085 test "gets a users statuses", %{conn: conn} do
1086 user_one = insert(:user)
1087 user_two = insert(:user)
1088 user_three = insert(:user)
1090 {:ok, user_three} = User.follow(user_three, user_one)
1092 {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
1094 {:ok, direct_activity} =
1095 CommonAPI.post(user_one, %{
1096 "status" => "Hi, @#{user_two.nickname}.",
1097 "visibility" => "direct"
1100 {:ok, private_activity} =
1101 CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
1105 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1107 assert [%{"id" => id}] = json_response(resp, 200)
1108 assert id == to_string(activity.id)
1112 |> assign(:user, user_two)
1113 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1115 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
1116 assert id_one == to_string(direct_activity.id)
1117 assert id_two == to_string(activity.id)
1121 |> assign(:user, user_three)
1122 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1124 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
1125 assert id_one == to_string(private_activity.id)
1126 assert id_two == to_string(activity.id)
1129 test "unimplemented pinned statuses feature", %{conn: conn} do
1130 note = insert(:note_activity)
1131 user = User.get_by_ap_id(note.data["actor"])
1135 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1137 assert json_response(conn, 200) == []
1140 test "gets an users media", %{conn: conn} do
1141 note = insert(:note_activity)
1142 user = User.get_by_ap_id(note.data["actor"])
1144 file = %Plug.Upload{
1145 content_type: "image/jpg",
1146 path: Path.absname("test/fixtures/image.jpg"),
1147 filename: "an_image.jpg"
1151 TwitterAPI.upload(file, user, "json")
1155 TwitterAPI.create_status(user, %{"status" => "cofe", "media_ids" => [media["media_id"]]})
1159 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
1161 assert [%{"id" => id}] = json_response(conn, 200)
1162 assert id == to_string(image_post.id)
1166 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
1168 assert [%{"id" => id}] = json_response(conn, 200)
1169 assert id == to_string(image_post.id)
1172 test "gets a user's statuses without reblogs", %{conn: conn} do
1173 user = insert(:user)
1174 {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
1175 {:ok, _, _} = CommonAPI.repeat(post.id, user)
1179 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
1181 assert [%{"id" => id}] = json_response(conn, 200)
1182 assert id == to_string(post.id)
1186 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
1188 assert [%{"id" => id}] = json_response(conn, 200)
1189 assert id == to_string(post.id)
1193 describe "user relationships" do
1194 test "returns the relationships for the current user", %{conn: conn} do
1195 user = insert(:user)
1196 other_user = insert(:user)
1197 {:ok, user} = User.follow(user, other_user)
1201 |> assign(:user, user)
1202 |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]})
1204 assert [relationship] = json_response(conn, 200)
1206 assert to_string(other_user.id) == relationship["id"]
1210 describe "locked accounts" do
1211 test "/api/v1/follow_requests works" do
1212 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
1213 other_user = insert(:user)
1215 {:ok, _activity} = ActivityPub.follow(other_user, user)
1217 user = User.get_by_id(user.id)
1218 other_user = User.get_by_id(other_user.id)
1220 assert User.following?(other_user, user) == false
1224 |> assign(:user, user)
1225 |> get("/api/v1/follow_requests")
1227 assert [relationship] = json_response(conn, 200)
1228 assert to_string(other_user.id) == relationship["id"]
1231 test "/api/v1/follow_requests/:id/authorize works" do
1232 user = insert(:user, %{info: %User.Info{locked: true}})
1233 other_user = insert(:user)
1235 {:ok, _activity} = ActivityPub.follow(other_user, user)
1237 user = User.get_by_id(user.id)
1238 other_user = User.get_by_id(other_user.id)
1240 assert User.following?(other_user, user) == false
1244 |> assign(:user, user)
1245 |> post("/api/v1/follow_requests/#{other_user.id}/authorize")
1247 assert relationship = json_response(conn, 200)
1248 assert to_string(other_user.id) == relationship["id"]
1250 user = User.get_by_id(user.id)
1251 other_user = User.get_by_id(other_user.id)
1253 assert User.following?(other_user, user) == true
1256 test "verify_credentials", %{conn: conn} do
1257 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "private"}})
1261 |> assign(:user, user)
1262 |> get("/api/v1/accounts/verify_credentials")
1264 assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
1265 assert id == to_string(user.id)
1268 test "/api/v1/follow_requests/:id/reject works" do
1269 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
1270 other_user = insert(:user)
1272 {:ok, _activity} = ActivityPub.follow(other_user, user)
1274 user = User.get_by_id(user.id)
1278 |> assign(:user, user)
1279 |> post("/api/v1/follow_requests/#{other_user.id}/reject")
1281 assert relationship = json_response(conn, 200)
1282 assert to_string(other_user.id) == relationship["id"]
1284 user = User.get_by_id(user.id)
1285 other_user = User.get_by_id(other_user.id)
1287 assert User.following?(other_user, user) == false
1291 test "account fetching", %{conn: conn} do
1292 user = insert(:user)
1296 |> get("/api/v1/accounts/#{user.id}")
1298 assert %{"id" => id} = json_response(conn, 200)
1299 assert id == to_string(user.id)
1303 |> get("/api/v1/accounts/-1")
1305 assert %{"error" => "Can't find user"} = json_response(conn, 404)
1308 test "account fetching also works nickname", %{conn: conn} do
1309 user = insert(:user)
1313 |> get("/api/v1/accounts/#{user.nickname}")
1315 assert %{"id" => id} = json_response(conn, 200)
1316 assert id == user.id
1319 test "media upload", %{conn: conn} do
1320 file = %Plug.Upload{
1321 content_type: "image/jpg",
1322 path: Path.absname("test/fixtures/image.jpg"),
1323 filename: "an_image.jpg"
1326 desc = "Description of the image"
1328 user = insert(:user)
1332 |> assign(:user, user)
1333 |> post("/api/v1/media", %{"file" => file, "description" => desc})
1335 assert media = json_response(conn, 200)
1337 assert media["type"] == "image"
1338 assert media["description"] == desc
1341 object = Repo.get(Object, media["id"])
1342 assert object.data["actor"] == User.ap_id(user)
1345 test "hashtag timeline", %{conn: conn} do
1346 following = insert(:user)
1349 {:ok, activity} = TwitterAPI.create_status(following, %{"status" => "test #2hu"})
1351 {:ok, [_activity]} =
1352 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
1356 |> get("/api/v1/timelines/tag/2hu")
1358 assert [%{"id" => id}] = json_response(nconn, 200)
1360 assert id == to_string(activity.id)
1362 # works for different capitalization too
1365 |> get("/api/v1/timelines/tag/2HU")
1367 assert [%{"id" => id}] = json_response(nconn, 200)
1369 assert id == to_string(activity.id)
1373 test "multi-hashtag timeline", %{conn: conn} do
1374 user = insert(:user)
1376 {:ok, activity_test} = CommonAPI.post(user, %{"status" => "#test"})
1377 {:ok, activity_test1} = CommonAPI.post(user, %{"status" => "#test #test1"})
1378 {:ok, activity_none} = CommonAPI.post(user, %{"status" => "#test #none"})
1382 |> get("/api/v1/timelines/tag/test", %{"any" => ["test1"]})
1384 [status_none, status_test1, status_test] = json_response(any_test, 200)
1386 assert to_string(activity_test.id) == status_test["id"]
1387 assert to_string(activity_test1.id) == status_test1["id"]
1388 assert to_string(activity_none.id) == status_none["id"]
1392 |> get("/api/v1/timelines/tag/test", %{"all" => ["test1"], "none" => ["none"]})
1394 assert [status_test1] == json_response(restricted_test, 200)
1396 all_test = conn |> get("/api/v1/timelines/tag/test", %{"all" => ["none"]})
1398 assert [status_none] == json_response(all_test, 200)
1401 test "getting followers", %{conn: conn} do
1402 user = insert(:user)
1403 other_user = insert(:user)
1404 {:ok, user} = User.follow(user, other_user)
1408 |> get("/api/v1/accounts/#{other_user.id}/followers")
1410 assert [%{"id" => id}] = json_response(conn, 200)
1411 assert id == to_string(user.id)
1414 test "getting followers, hide_followers", %{conn: conn} do
1415 user = insert(:user)
1416 other_user = insert(:user, %{info: %{hide_followers: true}})
1417 {:ok, _user} = User.follow(user, other_user)
1421 |> get("/api/v1/accounts/#{other_user.id}/followers")
1423 assert [] == json_response(conn, 200)
1426 test "getting followers, hide_followers, same user requesting", %{conn: conn} do
1427 user = insert(:user)
1428 other_user = insert(:user, %{info: %{hide_followers: true}})
1429 {:ok, _user} = User.follow(user, other_user)
1433 |> assign(:user, other_user)
1434 |> get("/api/v1/accounts/#{other_user.id}/followers")
1436 refute [] == json_response(conn, 200)
1439 test "getting followers, pagination", %{conn: conn} do
1440 user = insert(:user)
1441 follower1 = insert(:user)
1442 follower2 = insert(:user)
1443 follower3 = insert(:user)
1444 {:ok, _} = User.follow(follower1, user)
1445 {:ok, _} = User.follow(follower2, user)
1446 {:ok, _} = User.follow(follower3, user)
1450 |> assign(:user, user)
1454 |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
1456 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1457 assert id3 == follower3.id
1458 assert id2 == follower2.id
1462 |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
1464 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1465 assert id2 == follower2.id
1466 assert id1 == follower1.id
1470 |> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
1472 assert [%{"id" => id2}] = json_response(res_conn, 200)
1473 assert id2 == follower2.id
1475 assert [link_header] = get_resp_header(res_conn, "link")
1476 assert link_header =~ ~r/min_id=#{follower2.id}/
1477 assert link_header =~ ~r/max_id=#{follower2.id}/
1480 test "getting following", %{conn: conn} do
1481 user = insert(:user)
1482 other_user = insert(:user)
1483 {:ok, user} = User.follow(user, other_user)
1487 |> get("/api/v1/accounts/#{user.id}/following")
1489 assert [%{"id" => id}] = json_response(conn, 200)
1490 assert id == to_string(other_user.id)
1493 test "getting following, hide_follows", %{conn: conn} do
1494 user = insert(:user, %{info: %{hide_follows: true}})
1495 other_user = insert(:user)
1496 {:ok, user} = User.follow(user, other_user)
1500 |> get("/api/v1/accounts/#{user.id}/following")
1502 assert [] == json_response(conn, 200)
1505 test "getting following, hide_follows, same user requesting", %{conn: conn} do
1506 user = insert(:user, %{info: %{hide_follows: true}})
1507 other_user = insert(:user)
1508 {:ok, user} = User.follow(user, other_user)
1512 |> assign(:user, user)
1513 |> get("/api/v1/accounts/#{user.id}/following")
1515 refute [] == json_response(conn, 200)
1518 test "getting following, pagination", %{conn: conn} do
1519 user = insert(:user)
1520 following1 = insert(:user)
1521 following2 = insert(:user)
1522 following3 = insert(:user)
1523 {:ok, _} = User.follow(user, following1)
1524 {:ok, _} = User.follow(user, following2)
1525 {:ok, _} = User.follow(user, following3)
1529 |> assign(:user, user)
1533 |> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
1535 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1536 assert id3 == following3.id
1537 assert id2 == following2.id
1541 |> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
1543 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1544 assert id2 == following2.id
1545 assert id1 == following1.id
1549 |> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
1551 assert [%{"id" => id2}] = json_response(res_conn, 200)
1552 assert id2 == following2.id
1554 assert [link_header] = get_resp_header(res_conn, "link")
1555 assert link_header =~ ~r/min_id=#{following2.id}/
1556 assert link_header =~ ~r/max_id=#{following2.id}/
1559 test "following / unfollowing a user", %{conn: conn} do
1560 user = insert(:user)
1561 other_user = insert(:user)
1565 |> assign(:user, user)
1566 |> post("/api/v1/accounts/#{other_user.id}/follow")
1568 assert %{"id" => _id, "following" => true} = json_response(conn, 200)
1570 user = User.get_by_id(user.id)
1574 |> assign(:user, user)
1575 |> post("/api/v1/accounts/#{other_user.id}/unfollow")
1577 assert %{"id" => _id, "following" => false} = json_response(conn, 200)
1579 user = User.get_by_id(user.id)
1583 |> assign(:user, user)
1584 |> post("/api/v1/follows", %{"uri" => other_user.nickname})
1586 assert %{"id" => id} = json_response(conn, 200)
1587 assert id == to_string(other_user.id)
1590 test "following / unfollowing errors" do
1591 user = insert(:user)
1595 |> assign(:user, user)
1598 conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
1599 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1602 user = User.get_by_id(user.id)
1603 conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow")
1604 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1606 # self follow via uri
1607 user = User.get_by_id(user.id)
1608 conn_res = post(conn, "/api/v1/follows", %{"uri" => user.nickname})
1609 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1611 # follow non existing user
1612 conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
1613 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1615 # follow non existing user via uri
1616 conn_res = post(conn, "/api/v1/follows", %{"uri" => "doesntexist"})
1617 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1619 # unfollow non existing user
1620 conn_res = post(conn, "/api/v1/accounts/doesntexist/unfollow")
1621 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1624 test "muting / unmuting a user", %{conn: conn} do
1625 user = insert(:user)
1626 other_user = insert(:user)
1630 |> assign(:user, user)
1631 |> post("/api/v1/accounts/#{other_user.id}/mute")
1633 assert %{"id" => _id, "muting" => true} = json_response(conn, 200)
1635 user = User.get_by_id(user.id)
1639 |> assign(:user, user)
1640 |> post("/api/v1/accounts/#{other_user.id}/unmute")
1642 assert %{"id" => _id, "muting" => false} = json_response(conn, 200)
1645 test "subscribing / unsubscribing to a user", %{conn: conn} do
1646 user = insert(:user)
1647 subscription_target = insert(:user)
1651 |> assign(:user, user)
1652 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
1654 assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
1658 |> assign(:user, user)
1659 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
1661 assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
1664 test "getting a list of mutes", %{conn: conn} do
1665 user = insert(:user)
1666 other_user = insert(:user)
1668 {:ok, user} = User.mute(user, other_user)
1672 |> assign(:user, user)
1673 |> get("/api/v1/mutes")
1675 other_user_id = to_string(other_user.id)
1676 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1679 test "blocking / unblocking a user", %{conn: conn} do
1680 user = insert(:user)
1681 other_user = insert(:user)
1685 |> assign(:user, user)
1686 |> post("/api/v1/accounts/#{other_user.id}/block")
1688 assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
1690 user = User.get_by_id(user.id)
1694 |> assign(:user, user)
1695 |> post("/api/v1/accounts/#{other_user.id}/unblock")
1697 assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
1700 test "getting a list of blocks", %{conn: conn} do
1701 user = insert(:user)
1702 other_user = insert(:user)
1704 {:ok, user} = User.block(user, other_user)
1708 |> assign(:user, user)
1709 |> get("/api/v1/blocks")
1711 other_user_id = to_string(other_user.id)
1712 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1715 test "blocking / unblocking a domain", %{conn: conn} do
1716 user = insert(:user)
1717 other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
1721 |> assign(:user, user)
1722 |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1724 assert %{} = json_response(conn, 200)
1725 user = User.get_cached_by_ap_id(user.ap_id)
1726 assert User.blocks?(user, other_user)
1730 |> assign(:user, user)
1731 |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1733 assert %{} = json_response(conn, 200)
1734 user = User.get_cached_by_ap_id(user.ap_id)
1735 refute User.blocks?(user, other_user)
1738 test "getting a list of domain blocks", %{conn: conn} do
1739 user = insert(:user)
1741 {:ok, user} = User.block_domain(user, "bad.site")
1742 {:ok, user} = User.block_domain(user, "even.worse.site")
1746 |> assign(:user, user)
1747 |> get("/api/v1/domain_blocks")
1749 domain_blocks = json_response(conn, 200)
1751 assert "bad.site" in domain_blocks
1752 assert "even.worse.site" in domain_blocks
1755 test "unimplemented follow_requests, blocks, domain blocks" do
1756 user = insert(:user)
1758 ["blocks", "domain_blocks", "follow_requests"]
1759 |> Enum.each(fn endpoint ->
1762 |> assign(:user, user)
1763 |> get("/api/v1/#{endpoint}")
1765 assert [] = json_response(conn, 200)
1769 test "account search", %{conn: conn} do
1770 user = insert(:user)
1771 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1772 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1776 |> assign(:user, user)
1777 |> get("/api/v1/accounts/search", %{"q" => "shp"})
1778 |> json_response(200)
1780 result_ids = for result <- results, do: result["acct"]
1782 assert user_two.nickname in result_ids
1783 assert user_three.nickname in result_ids
1787 |> assign(:user, user)
1788 |> get("/api/v1/accounts/search", %{"q" => "2hu"})
1789 |> json_response(200)
1791 result_ids = for result <- results, do: result["acct"]
1793 assert user_three.nickname in result_ids
1796 test "search", %{conn: conn} do
1797 user = insert(:user)
1798 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1799 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1801 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1804 CommonAPI.post(user, %{
1805 "status" => "This is about 2hu, but private",
1806 "visibility" => "private"
1809 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1813 |> get("/api/v1/search", %{"q" => "2hu"})
1815 assert results = json_response(conn, 200)
1817 [account | _] = results["accounts"]
1818 assert account["id"] == to_string(user_three.id)
1820 assert results["hashtags"] == []
1822 [status] = results["statuses"]
1823 assert status["id"] == to_string(activity.id)
1826 test "search fetches remote statuses", %{conn: conn} do
1830 |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
1832 assert results = json_response(conn, 200)
1834 [status] = results["statuses"]
1835 assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
1839 test "search doesn't show statuses that it shouldn't", %{conn: conn} do
1841 CommonAPI.post(insert(:user), %{
1842 "status" => "This is about 2hu, but private",
1843 "visibility" => "private"
1849 |> get("/api/v1/search", %{"q" => activity.data["object"]["id"]})
1851 assert results = json_response(conn, 200)
1853 [] = results["statuses"]
1857 test "search fetches remote accounts", %{conn: conn} do
1860 |> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"})
1862 assert results = json_response(conn, 200)
1863 [account] = results["accounts"]
1864 assert account["acct"] == "shp@social.heldscal.la"
1867 test "returns the favorites of a user", %{conn: conn} do
1868 user = insert(:user)
1869 other_user = insert(:user)
1871 {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
1872 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
1874 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1878 |> assign(:user, user)
1879 |> get("/api/v1/favourites")
1881 assert [status] = json_response(first_conn, 200)
1882 assert status["id"] == to_string(activity.id)
1884 assert [{"link", _link_header}] =
1885 Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
1887 # Honours query params
1888 {:ok, second_activity} =
1889 CommonAPI.post(other_user, %{
1891 "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
1894 {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
1896 last_like = status["id"]
1900 |> assign(:user, user)
1901 |> get("/api/v1/favourites?since_id=#{last_like}")
1903 assert [second_status] = json_response(second_conn, 200)
1904 assert second_status["id"] == to_string(second_activity.id)
1908 |> assign(:user, user)
1909 |> get("/api/v1/favourites?limit=0")
1911 assert [] = json_response(third_conn, 200)
1914 describe "updating credentials" do
1915 test "updates the user's bio", %{conn: conn} do
1916 user = insert(:user)
1917 user2 = insert(:user)
1921 |> assign(:user, user)
1922 |> patch("/api/v1/accounts/update_credentials", %{
1923 "note" => "I drink #cofe with @#{user2.nickname}"
1926 assert user = json_response(conn, 200)
1928 assert user["note"] ==
1929 ~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=") <>
1931 ~s(" class="u-url mention" href=") <>
1932 user2.ap_id <> ~s(">@<span>) <> user2.nickname <> ~s(</span></a></span>)
1935 test "updates the user's locking status", %{conn: conn} do
1936 user = insert(:user)
1940 |> assign(:user, user)
1941 |> patch("/api/v1/accounts/update_credentials", %{locked: "true"})
1943 assert user = json_response(conn, 200)
1944 assert user["locked"] == true
1947 test "updates the user's name", %{conn: conn} do
1948 user = insert(:user)
1952 |> assign(:user, user)
1953 |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
1955 assert user = json_response(conn, 200)
1956 assert user["display_name"] == "markorepairs"
1959 test "updates the user's avatar", %{conn: conn} do
1960 user = insert(:user)
1962 new_avatar = %Plug.Upload{
1963 content_type: "image/jpg",
1964 path: Path.absname("test/fixtures/image.jpg"),
1965 filename: "an_image.jpg"
1970 |> assign(:user, user)
1971 |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
1973 assert user_response = json_response(conn, 200)
1974 assert user_response["avatar"] != User.avatar_url(user)
1977 test "updates the user's banner", %{conn: conn} do
1978 user = insert(:user)
1980 new_header = %Plug.Upload{
1981 content_type: "image/jpg",
1982 path: Path.absname("test/fixtures/image.jpg"),
1983 filename: "an_image.jpg"
1988 |> assign(:user, user)
1989 |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
1991 assert user_response = json_response(conn, 200)
1992 assert user_response["header"] != User.banner_url(user)
1995 test "requires 'write' permission", %{conn: conn} do
1996 token1 = insert(:oauth_token, scopes: ["read"])
1997 token2 = insert(:oauth_token, scopes: ["write", "follow"])
1999 for token <- [token1, token2] do
2002 |> put_req_header("authorization", "Bearer #{token.token}")
2003 |> patch("/api/v1/accounts/update_credentials", %{})
2005 if token == token1 do
2006 assert %{"error" => "Insufficient permissions: write."} == json_response(conn, 403)
2008 assert json_response(conn, 200)
2014 test "get instance information", %{conn: conn} do
2015 conn = get(conn, "/api/v1/instance")
2016 assert result = json_response(conn, 200)
2018 # Note: not checking for "max_toot_chars" since it's optional
2026 "streaming_api" => _
2031 "registrations" => _
2035 test "get instance stats", %{conn: conn} do
2036 user = insert(:user, %{local: true})
2038 user2 = insert(:user, %{local: true})
2039 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
2041 insert(:user, %{local: false, nickname: "u@peer1.com"})
2042 insert(:user, %{local: false, nickname: "u@peer2.com"})
2044 {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
2046 # Stats should count users with missing or nil `info.deactivated` value
2047 user = User.get_by_id(user.id)
2048 info_change = Changeset.change(user.info, %{deactivated: nil})
2052 |> Changeset.change()
2053 |> Changeset.put_embed(:info, info_change)
2054 |> User.update_and_set_cache()
2056 Pleroma.Stats.update_stats()
2058 conn = get(conn, "/api/v1/instance")
2060 assert result = json_response(conn, 200)
2062 stats = result["stats"]
2065 assert stats["user_count"] == 1
2066 assert stats["status_count"] == 1
2067 assert stats["domain_count"] == 2
2070 test "get peers", %{conn: conn} do
2071 insert(:user, %{local: false, nickname: "u@peer1.com"})
2072 insert(:user, %{local: false, nickname: "u@peer2.com"})
2074 Pleroma.Stats.update_stats()
2076 conn = get(conn, "/api/v1/instance/peers")
2078 assert result = json_response(conn, 200)
2080 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
2083 test "put settings", %{conn: conn} do
2084 user = insert(:user)
2088 |> assign(:user, user)
2089 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
2091 assert _result = json_response(conn, 200)
2093 user = User.get_cached_by_ap_id(user.ap_id)
2094 assert user.info.settings == %{"programming" => "socks"}
2097 describe "pinned statuses" do
2099 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2101 user = insert(:user)
2102 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
2104 [user: user, activity: activity]
2107 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
2108 {:ok, _} = CommonAPI.pin(activity.id, user)
2112 |> assign(:user, user)
2113 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2114 |> json_response(200)
2116 id_str = to_string(activity.id)
2118 assert [%{"id" => ^id_str, "pinned" => true}] = result
2121 test "pin status", %{conn: conn, user: user, activity: activity} do
2122 id_str = to_string(activity.id)
2124 assert %{"id" => ^id_str, "pinned" => true} =
2126 |> assign(:user, user)
2127 |> post("/api/v1/statuses/#{activity.id}/pin")
2128 |> json_response(200)
2130 assert [%{"id" => ^id_str, "pinned" => true}] =
2132 |> assign(:user, user)
2133 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2134 |> json_response(200)
2137 test "unpin status", %{conn: conn, user: user, activity: activity} do
2138 {:ok, _} = CommonAPI.pin(activity.id, user)
2140 id_str = to_string(activity.id)
2141 user = refresh_record(user)
2143 assert %{"id" => ^id_str, "pinned" => false} =
2145 |> assign(:user, user)
2146 |> post("/api/v1/statuses/#{activity.id}/unpin")
2147 |> json_response(200)
2151 |> assign(:user, user)
2152 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2153 |> json_response(200)
2156 test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
2157 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
2159 id_str_one = to_string(activity_one.id)
2161 assert %{"id" => ^id_str_one, "pinned" => true} =
2163 |> assign(:user, user)
2164 |> post("/api/v1/statuses/#{id_str_one}/pin")
2165 |> json_response(200)
2167 user = refresh_record(user)
2169 assert %{"error" => "You have already pinned the maximum number of statuses"} =
2171 |> assign(:user, user)
2172 |> post("/api/v1/statuses/#{activity_two.id}/pin")
2173 |> json_response(400)
2176 test "Status rich-media Card", %{conn: conn, user: user} do
2177 Pleroma.Config.put([:rich_media, :enabled], true)
2178 {:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp"})
2182 |> get("/api/v1/statuses/#{activity.id}/card")
2183 |> json_response(200)
2185 assert response == %{
2186 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2187 "provider_name" => "www.imdb.com",
2188 "provider_url" => "http://www.imdb.com",
2189 "title" => "The Rock",
2191 "url" => "http://www.imdb.com/title/tt0117500/",
2192 "description" => nil,
2195 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2196 "title" => "The Rock",
2197 "type" => "video.movie",
2198 "url" => "http://www.imdb.com/title/tt0117500/"
2203 # works with private posts
2205 CommonAPI.post(user, %{"status" => "http://example.com/ogp", "visibility" => "direct"})
2209 |> assign(:user, user)
2210 |> get("/api/v1/statuses/#{activity.id}/card")
2211 |> json_response(200)
2213 assert response_two == response
2215 Pleroma.Config.put([:rich_media, :enabled], false)
2220 user = insert(:user)
2221 for_user = insert(:user)
2224 CommonAPI.post(user, %{
2225 "status" => "heweoo?"
2229 CommonAPI.post(user, %{
2230 "status" => "heweoo!"
2235 |> assign(:user, for_user)
2236 |> post("/api/v1/statuses/#{activity1.id}/bookmark")
2238 assert json_response(response1, 200)["bookmarked"] == true
2242 |> assign(:user, for_user)
2243 |> post("/api/v1/statuses/#{activity2.id}/bookmark")
2245 assert json_response(response2, 200)["bookmarked"] == true
2249 |> assign(:user, for_user)
2250 |> get("/api/v1/bookmarks")
2252 assert [json_response(response2, 200), json_response(response1, 200)] ==
2253 json_response(bookmarks, 200)
2257 |> assign(:user, for_user)
2258 |> post("/api/v1/statuses/#{activity1.id}/unbookmark")
2260 assert json_response(response1, 200)["bookmarked"] == false
2264 |> assign(:user, for_user)
2265 |> get("/api/v1/bookmarks")
2267 assert [json_response(response2, 200)] == json_response(bookmarks, 200)
2270 describe "conversation muting" do
2272 user = insert(:user)
2273 {:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
2275 [user: user, activity: activity]
2278 test "mute conversation", %{conn: conn, user: user, activity: activity} do
2279 id_str = to_string(activity.id)
2281 assert %{"id" => ^id_str, "muted" => true} =
2283 |> assign(:user, user)
2284 |> post("/api/v1/statuses/#{activity.id}/mute")
2285 |> json_response(200)
2288 test "unmute conversation", %{conn: conn, user: user, activity: activity} do
2289 {:ok, _} = CommonAPI.add_mute(user, activity)
2291 id_str = to_string(activity.id)
2292 user = refresh_record(user)
2294 assert %{"id" => ^id_str, "muted" => false} =
2296 |> assign(:user, user)
2297 |> post("/api/v1/statuses/#{activity.id}/unmute")
2298 |> json_response(200)
2302 test "flavours switching (Pleroma Extension)", %{conn: conn} do
2303 user = insert(:user)
2307 |> assign(:user, user)
2308 |> get("/api/v1/pleroma/flavour")
2310 assert "glitch" == json_response(get_old_flavour, 200)
2314 |> assign(:user, user)
2315 |> post("/api/v1/pleroma/flavour/vanilla")
2317 assert "vanilla" == json_response(set_flavour, 200)
2321 |> assign(:user, user)
2322 |> post("/api/v1/pleroma/flavour/vanilla")
2324 assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
2327 describe "reports" do
2329 reporter = insert(:user)
2330 target_user = insert(:user)
2332 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
2334 [reporter: reporter, target_user: target_user, activity: activity]
2337 test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
2338 assert %{"action_taken" => false, "id" => _} =
2340 |> assign(:user, reporter)
2341 |> post("/api/v1/reports", %{"account_id" => target_user.id})
2342 |> json_response(200)
2345 test "submit a report with statuses and comment", %{
2348 target_user: target_user,
2351 assert %{"action_taken" => false, "id" => _} =
2353 |> assign(:user, reporter)
2354 |> post("/api/v1/reports", %{
2355 "account_id" => target_user.id,
2356 "status_ids" => [activity.id],
2357 "comment" => "bad status!"
2359 |> json_response(200)
2362 test "account_id is required", %{
2367 assert %{"error" => "Valid `account_id` required"} =
2369 |> assign(:user, reporter)
2370 |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
2371 |> json_response(400)
2374 test "comment must be up to the size specified in the config", %{
2377 target_user: target_user
2379 max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
2380 comment = String.pad_trailing("a", max_size + 1, "a")
2382 error = %{"error" => "Comment must be up to #{max_size} characters"}
2386 |> assign(:user, reporter)
2387 |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
2388 |> json_response(400)
2392 describe "link headers" do
2393 test "preserves parameters in link headers", %{conn: conn} do
2394 user = insert(:user)
2395 other_user = insert(:user)
2398 CommonAPI.post(other_user, %{
2399 "status" => "hi @#{user.nickname}",
2400 "visibility" => "public"
2404 CommonAPI.post(other_user, %{
2405 "status" => "hi @#{user.nickname}",
2406 "visibility" => "public"
2409 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
2410 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
2414 |> assign(:user, user)
2415 |> get("/api/v1/notifications", %{media_only: true})
2417 assert [link_header] = get_resp_header(conn, "link")
2418 assert link_header =~ ~r/media_only=true/
2419 assert link_header =~ ~r/min_id=#{notification2.id}/
2420 assert link_header =~ ~r/max_id=#{notification1.id}/
2424 test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
2425 # Need to set an old-style integer ID to reproduce the problem
2426 # (these are no longer assigned to new accounts but were preserved
2427 # for existing accounts during the migration to flakeIDs)
2428 user_one = insert(:user, %{id: 1212})
2429 user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
2433 |> get("/api/v1/accounts/#{user_one.id}")
2437 |> get("/api/v1/accounts/#{user_two.nickname}")
2441 |> get("/api/v1/accounts/#{user_two.id}")
2443 acc_one = json_response(resp_one, 200)
2444 acc_two = json_response(resp_two, 200)
2445 acc_three = json_response(resp_three, 200)
2446 refute acc_one == acc_two
2447 assert acc_two == acc_three
2450 describe "custom emoji" do
2451 test "with tags", %{conn: conn} do
2454 |> get("/api/v1/custom_emojis")
2455 |> json_response(200)
2457 assert Map.has_key?(emoji, "shortcode")
2458 assert Map.has_key?(emoji, "static_url")
2459 assert Map.has_key?(emoji, "tags")
2460 assert is_list(emoji["tags"])
2461 assert Map.has_key?(emoji, "url")
2462 assert Map.has_key?(emoji, "visible_in_picker")
2466 describe "index/2 redirections" do
2467 setup %{conn: conn} do
2471 signing_salt: "cooldude"
2476 |> Plug.Session.call(Plug.Session.init(session_opts))
2479 test_path = "/web/statuses/test"
2480 %{conn: conn, path: test_path}
2483 test "redirects not logged-in users to the login page", %{conn: conn, path: path} do
2484 conn = get(conn, path)
2486 assert conn.status == 302
2487 assert redirected_to(conn) == "/web/login"
2490 test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
2491 token = insert(:oauth_token)
2495 |> assign(:user, token.user)
2496 |> put_session(:oauth_token, token.token)
2499 assert conn.status == 200
2502 test "saves referer path to session", %{conn: conn, path: path} do
2503 conn = get(conn, path)
2504 return_to = Plug.Conn.get_session(conn, :return_to)
2506 assert return_to == path
2509 test "redirects to the saved path after log in", %{conn: conn, path: path} do
2510 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
2511 auth = insert(:oauth_authorization, app: app)
2515 |> put_session(:return_to, path)
2516 |> get("/web/login", %{code: auth.token})
2518 assert conn.status == 302
2519 assert redirected_to(conn) == path
2522 test "redirects to the getting-started page when referer is not present", %{conn: conn} do
2523 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
2524 auth = insert(:oauth_authorization, app: app)
2526 conn = get(conn, "/web/login", %{code: auth.token})
2528 assert conn.status == 302
2529 assert redirected_to(conn) == "/web/getting-started"
2533 describe "scheduled activities" do
2534 test "creates a scheduled activity", %{conn: conn} do
2535 user = insert(:user)
2536 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2540 |> assign(:user, user)
2541 |> post("/api/v1/statuses", %{
2542 "status" => "scheduled",
2543 "scheduled_at" => scheduled_at
2546 assert %{"scheduled_at" => expected_scheduled_at} = json_response(conn, 200)
2547 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(scheduled_at)
2548 assert [] == Repo.all(Activity)
2551 test "creates a scheduled activity with a media attachment", %{conn: conn} do
2552 user = insert(:user)
2553 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2555 file = %Plug.Upload{
2556 content_type: "image/jpg",
2557 path: Path.absname("test/fixtures/image.jpg"),
2558 filename: "an_image.jpg"
2561 {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
2565 |> assign(:user, user)
2566 |> post("/api/v1/statuses", %{
2567 "media_ids" => [to_string(upload.id)],
2568 "status" => "scheduled",
2569 "scheduled_at" => scheduled_at
2572 assert %{"media_attachments" => [media_attachment]} = json_response(conn, 200)
2573 assert %{"type" => "image"} = media_attachment
2576 test "skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now",
2578 user = insert(:user)
2581 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(5) - 1, :millisecond)
2585 |> assign(:user, user)
2586 |> post("/api/v1/statuses", %{
2587 "status" => "not scheduled",
2588 "scheduled_at" => scheduled_at
2591 assert %{"content" => "not scheduled"} = json_response(conn, 200)
2592 assert [] == Repo.all(ScheduledActivity)
2595 test "returns error when daily user limit is exceeded", %{conn: conn} do
2596 user = insert(:user)
2599 NaiveDateTime.utc_now()
2600 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
2601 |> NaiveDateTime.to_iso8601()
2603 attrs = %{params: %{}, scheduled_at: today}
2604 {:ok, _} = ScheduledActivity.create(user, attrs)
2605 {:ok, _} = ScheduledActivity.create(user, attrs)
2609 |> assign(:user, user)
2610 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today})
2612 assert %{"error" => "daily limit exceeded"} == json_response(conn, 422)
2615 test "returns error when total user limit is exceeded", %{conn: conn} do
2616 user = insert(:user)
2619 NaiveDateTime.utc_now()
2620 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
2621 |> NaiveDateTime.to_iso8601()
2624 NaiveDateTime.utc_now()
2625 |> NaiveDateTime.add(:timer.hours(36), :millisecond)
2626 |> NaiveDateTime.to_iso8601()
2628 attrs = %{params: %{}, scheduled_at: today}
2629 {:ok, _} = ScheduledActivity.create(user, attrs)
2630 {:ok, _} = ScheduledActivity.create(user, attrs)
2631 {:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow})
2635 |> assign(:user, user)
2636 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow})
2638 assert %{"error" => "total limit exceeded"} == json_response(conn, 422)
2641 test "shows scheduled activities", %{conn: conn} do
2642 user = insert(:user)
2643 scheduled_activity_id1 = insert(:scheduled_activity, user: user).id |> to_string()
2644 scheduled_activity_id2 = insert(:scheduled_activity, user: user).id |> to_string()
2645 scheduled_activity_id3 = insert(:scheduled_activity, user: user).id |> to_string()
2646 scheduled_activity_id4 = insert(:scheduled_activity, user: user).id |> to_string()
2650 |> assign(:user, user)
2655 |> get("/api/v1/scheduled_statuses?limit=2&min_id=#{scheduled_activity_id1}")
2657 result = json_response(conn_res, 200)
2658 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
2663 |> get("/api/v1/scheduled_statuses?limit=2&since_id=#{scheduled_activity_id1}")
2665 result = json_response(conn_res, 200)
2666 assert [%{"id" => ^scheduled_activity_id4}, %{"id" => ^scheduled_activity_id3}] = result
2671 |> get("/api/v1/scheduled_statuses?limit=2&max_id=#{scheduled_activity_id4}")
2673 result = json_response(conn_res, 200)
2674 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
2677 test "shows a scheduled activity", %{conn: conn} do
2678 user = insert(:user)
2679 scheduled_activity = insert(:scheduled_activity, user: user)
2683 |> assign(:user, user)
2684 |> get("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
2686 assert %{"id" => scheduled_activity_id} = json_response(res_conn, 200)
2687 assert scheduled_activity_id == scheduled_activity.id |> to_string()
2691 |> assign(:user, user)
2692 |> get("/api/v1/scheduled_statuses/404")
2694 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
2697 test "updates a scheduled activity", %{conn: conn} do
2698 user = insert(:user)
2699 scheduled_activity = insert(:scheduled_activity, user: user)
2702 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2706 |> assign(:user, user)
2707 |> put("/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{
2708 scheduled_at: new_scheduled_at
2711 assert %{"scheduled_at" => expected_scheduled_at} = json_response(res_conn, 200)
2712 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(new_scheduled_at)
2716 |> assign(:user, user)
2717 |> put("/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at})
2719 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
2722 test "deletes a scheduled activity", %{conn: conn} do
2723 user = insert(:user)
2724 scheduled_activity = insert(:scheduled_activity, user: user)
2728 |> assign(:user, user)
2729 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
2731 assert %{} = json_response(res_conn, 200)
2732 assert nil == Repo.get(ScheduledActivity, scheduled_activity.id)
2736 |> assign(:user, user)
2737 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
2739 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
2743 test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{conn: conn} do
2744 user1 = insert(:user)
2745 user2 = insert(:user)
2746 user3 = insert(:user)
2748 {:ok, replied_to} = TwitterAPI.create_status(user1, %{"status" => "cofe"})
2750 # Reply to status from another user
2753 |> assign(:user, user2)
2754 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
2756 assert %{"content" => "xD", "id" => id} = json_response(conn1, 200)
2758 activity = Activity.get_by_id(id)
2760 assert activity.data["object"]["inReplyTo"] == replied_to.data["object"]["id"]
2761 assert activity.data["object"]["inReplyToStatusId"] == replied_to.id
2763 # Reblog from the third user
2766 |> assign(:user, user3)
2767 |> post("/api/v1/statuses/#{activity.id}/reblog")
2769 assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
2770 json_response(conn2, 200)
2772 assert to_string(activity.id) == id
2774 # Getting third user status
2777 |> assign(:user, user3)
2778 |> get("api/v1/timelines/home")
2780 [reblogged_activity] = json_response(conn3, 200)
2782 assert reblogged_activity["reblog"]["in_reply_to_id"] == replied_to.id
2784 replied_to_user = User.get_by_ap_id(replied_to.data["actor"])
2785 assert reblogged_activity["reblog"]["in_reply_to_account_id"] == replied_to_user.id