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 "muting / unmuting a user", %{conn: conn} do
1591 user = insert(:user)
1592 other_user = insert(:user)
1596 |> assign(:user, user)
1597 |> post("/api/v1/accounts/#{other_user.id}/mute")
1599 assert %{"id" => _id, "muting" => true} = json_response(conn, 200)
1601 user = User.get_by_id(user.id)
1605 |> assign(:user, user)
1606 |> post("/api/v1/accounts/#{other_user.id}/unmute")
1608 assert %{"id" => _id, "muting" => false} = json_response(conn, 200)
1611 test "subscribing / unsubscribing to a user", %{conn: conn} do
1612 user = insert(:user)
1613 subscription_target = insert(:user)
1617 |> assign(:user, user)
1618 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
1620 assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
1624 |> assign(:user, user)
1625 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
1627 assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
1630 test "getting a list of mutes", %{conn: conn} do
1631 user = insert(:user)
1632 other_user = insert(:user)
1634 {:ok, user} = User.mute(user, other_user)
1638 |> assign(:user, user)
1639 |> get("/api/v1/mutes")
1641 other_user_id = to_string(other_user.id)
1642 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1645 test "blocking / unblocking a user", %{conn: conn} do
1646 user = insert(:user)
1647 other_user = insert(:user)
1651 |> assign(:user, user)
1652 |> post("/api/v1/accounts/#{other_user.id}/block")
1654 assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
1656 user = User.get_by_id(user.id)
1660 |> assign(:user, user)
1661 |> post("/api/v1/accounts/#{other_user.id}/unblock")
1663 assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
1666 test "getting a list of blocks", %{conn: conn} do
1667 user = insert(:user)
1668 other_user = insert(:user)
1670 {:ok, user} = User.block(user, other_user)
1674 |> assign(:user, user)
1675 |> get("/api/v1/blocks")
1677 other_user_id = to_string(other_user.id)
1678 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1681 test "blocking / unblocking a domain", %{conn: conn} do
1682 user = insert(:user)
1683 other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
1687 |> assign(:user, user)
1688 |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1690 assert %{} = json_response(conn, 200)
1691 user = User.get_cached_by_ap_id(user.ap_id)
1692 assert User.blocks?(user, other_user)
1696 |> assign(:user, user)
1697 |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1699 assert %{} = json_response(conn, 200)
1700 user = User.get_cached_by_ap_id(user.ap_id)
1701 refute User.blocks?(user, other_user)
1704 test "getting a list of domain blocks", %{conn: conn} do
1705 user = insert(:user)
1707 {:ok, user} = User.block_domain(user, "bad.site")
1708 {:ok, user} = User.block_domain(user, "even.worse.site")
1712 |> assign(:user, user)
1713 |> get("/api/v1/domain_blocks")
1715 domain_blocks = json_response(conn, 200)
1717 assert "bad.site" in domain_blocks
1718 assert "even.worse.site" in domain_blocks
1721 test "unimplemented follow_requests, blocks, domain blocks" do
1722 user = insert(:user)
1724 ["blocks", "domain_blocks", "follow_requests"]
1725 |> Enum.each(fn endpoint ->
1728 |> assign(:user, user)
1729 |> get("/api/v1/#{endpoint}")
1731 assert [] = json_response(conn, 200)
1735 test "account search", %{conn: conn} do
1736 user = insert(:user)
1737 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1738 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1742 |> assign(:user, user)
1743 |> get("/api/v1/accounts/search", %{"q" => "shp"})
1744 |> json_response(200)
1746 result_ids = for result <- results, do: result["acct"]
1748 assert user_two.nickname in result_ids
1749 assert user_three.nickname in result_ids
1753 |> assign(:user, user)
1754 |> get("/api/v1/accounts/search", %{"q" => "2hu"})
1755 |> json_response(200)
1757 result_ids = for result <- results, do: result["acct"]
1759 assert user_three.nickname in result_ids
1762 test "search", %{conn: conn} do
1763 user = insert(:user)
1764 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1765 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1767 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1770 CommonAPI.post(user, %{
1771 "status" => "This is about 2hu, but private",
1772 "visibility" => "private"
1775 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1779 |> get("/api/v1/search", %{"q" => "2hu"})
1781 assert results = json_response(conn, 200)
1783 [account | _] = results["accounts"]
1784 assert account["id"] == to_string(user_three.id)
1786 assert results["hashtags"] == []
1788 [status] = results["statuses"]
1789 assert status["id"] == to_string(activity.id)
1792 test "search fetches remote statuses", %{conn: conn} do
1796 |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
1798 assert results = json_response(conn, 200)
1800 [status] = results["statuses"]
1801 assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
1805 test "search doesn't show statuses that it shouldn't", %{conn: conn} do
1807 CommonAPI.post(insert(:user), %{
1808 "status" => "This is about 2hu, but private",
1809 "visibility" => "private"
1815 |> get("/api/v1/search", %{"q" => activity.data["object"]["id"]})
1817 assert results = json_response(conn, 200)
1819 [] = results["statuses"]
1823 test "search fetches remote accounts", %{conn: conn} do
1826 |> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"})
1828 assert results = json_response(conn, 200)
1829 [account] = results["accounts"]
1830 assert account["acct"] == "shp@social.heldscal.la"
1833 test "returns the favorites of a user", %{conn: conn} do
1834 user = insert(:user)
1835 other_user = insert(:user)
1837 {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
1838 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
1840 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1844 |> assign(:user, user)
1845 |> get("/api/v1/favourites")
1847 assert [status] = json_response(first_conn, 200)
1848 assert status["id"] == to_string(activity.id)
1850 assert [{"link", _link_header}] =
1851 Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
1853 # Honours query params
1854 {:ok, second_activity} =
1855 CommonAPI.post(other_user, %{
1857 "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
1860 {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
1862 last_like = status["id"]
1866 |> assign(:user, user)
1867 |> get("/api/v1/favourites?since_id=#{last_like}")
1869 assert [second_status] = json_response(second_conn, 200)
1870 assert second_status["id"] == to_string(second_activity.id)
1874 |> assign(:user, user)
1875 |> get("/api/v1/favourites?limit=0")
1877 assert [] = json_response(third_conn, 200)
1880 describe "updating credentials" do
1881 test "updates the user's bio", %{conn: conn} do
1882 user = insert(:user)
1883 user2 = insert(:user)
1887 |> assign(:user, user)
1888 |> patch("/api/v1/accounts/update_credentials", %{
1889 "note" => "I drink #cofe with @#{user2.nickname}"
1892 assert user = json_response(conn, 200)
1894 assert user["note"] ==
1895 ~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=") <>
1897 ~s(" class="u-url mention" href=") <>
1898 user2.ap_id <> ~s(">@<span>) <> user2.nickname <> ~s(</span></a></span>)
1901 test "updates the user's locking status", %{conn: conn} do
1902 user = insert(:user)
1906 |> assign(:user, user)
1907 |> patch("/api/v1/accounts/update_credentials", %{locked: "true"})
1909 assert user = json_response(conn, 200)
1910 assert user["locked"] == true
1913 test "updates the user's name", %{conn: conn} do
1914 user = insert(:user)
1918 |> assign(:user, user)
1919 |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
1921 assert user = json_response(conn, 200)
1922 assert user["display_name"] == "markorepairs"
1925 test "updates the user's avatar", %{conn: conn} do
1926 user = insert(:user)
1928 new_avatar = %Plug.Upload{
1929 content_type: "image/jpg",
1930 path: Path.absname("test/fixtures/image.jpg"),
1931 filename: "an_image.jpg"
1936 |> assign(:user, user)
1937 |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
1939 assert user_response = json_response(conn, 200)
1940 assert user_response["avatar"] != User.avatar_url(user)
1943 test "updates the user's banner", %{conn: conn} do
1944 user = insert(:user)
1946 new_header = %Plug.Upload{
1947 content_type: "image/jpg",
1948 path: Path.absname("test/fixtures/image.jpg"),
1949 filename: "an_image.jpg"
1954 |> assign(:user, user)
1955 |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
1957 assert user_response = json_response(conn, 200)
1958 assert user_response["header"] != User.banner_url(user)
1961 test "requires 'write' permission", %{conn: conn} do
1962 token1 = insert(:oauth_token, scopes: ["read"])
1963 token2 = insert(:oauth_token, scopes: ["write", "follow"])
1965 for token <- [token1, token2] do
1968 |> put_req_header("authorization", "Bearer #{token.token}")
1969 |> patch("/api/v1/accounts/update_credentials", %{})
1971 if token == token1 do
1972 assert %{"error" => "Insufficient permissions: write."} == json_response(conn, 403)
1974 assert json_response(conn, 200)
1980 test "get instance information", %{conn: conn} do
1981 conn = get(conn, "/api/v1/instance")
1982 assert result = json_response(conn, 200)
1984 # Note: not checking for "max_toot_chars" since it's optional
1992 "streaming_api" => _
1997 "registrations" => _
2001 test "get instance stats", %{conn: conn} do
2002 user = insert(:user, %{local: true})
2004 user2 = insert(:user, %{local: true})
2005 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
2007 insert(:user, %{local: false, nickname: "u@peer1.com"})
2008 insert(:user, %{local: false, nickname: "u@peer2.com"})
2010 {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
2012 # Stats should count users with missing or nil `info.deactivated` value
2013 user = User.get_by_id(user.id)
2014 info_change = Changeset.change(user.info, %{deactivated: nil})
2018 |> Changeset.change()
2019 |> Changeset.put_embed(:info, info_change)
2020 |> User.update_and_set_cache()
2022 Pleroma.Stats.update_stats()
2024 conn = get(conn, "/api/v1/instance")
2026 assert result = json_response(conn, 200)
2028 stats = result["stats"]
2031 assert stats["user_count"] == 1
2032 assert stats["status_count"] == 1
2033 assert stats["domain_count"] == 2
2036 test "get peers", %{conn: conn} do
2037 insert(:user, %{local: false, nickname: "u@peer1.com"})
2038 insert(:user, %{local: false, nickname: "u@peer2.com"})
2040 Pleroma.Stats.update_stats()
2042 conn = get(conn, "/api/v1/instance/peers")
2044 assert result = json_response(conn, 200)
2046 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
2049 test "put settings", %{conn: conn} do
2050 user = insert(:user)
2054 |> assign(:user, user)
2055 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
2057 assert _result = json_response(conn, 200)
2059 user = User.get_cached_by_ap_id(user.ap_id)
2060 assert user.info.settings == %{"programming" => "socks"}
2063 describe "pinned statuses" do
2065 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2067 user = insert(:user)
2068 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
2070 [user: user, activity: activity]
2073 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
2074 {:ok, _} = CommonAPI.pin(activity.id, user)
2078 |> assign(:user, user)
2079 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2080 |> json_response(200)
2082 id_str = to_string(activity.id)
2084 assert [%{"id" => ^id_str, "pinned" => true}] = result
2087 test "pin status", %{conn: conn, user: user, activity: activity} do
2088 id_str = to_string(activity.id)
2090 assert %{"id" => ^id_str, "pinned" => true} =
2092 |> assign(:user, user)
2093 |> post("/api/v1/statuses/#{activity.id}/pin")
2094 |> json_response(200)
2096 assert [%{"id" => ^id_str, "pinned" => true}] =
2098 |> assign(:user, user)
2099 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2100 |> json_response(200)
2103 test "unpin status", %{conn: conn, user: user, activity: activity} do
2104 {:ok, _} = CommonAPI.pin(activity.id, user)
2106 id_str = to_string(activity.id)
2107 user = refresh_record(user)
2109 assert %{"id" => ^id_str, "pinned" => false} =
2111 |> assign(:user, user)
2112 |> post("/api/v1/statuses/#{activity.id}/unpin")
2113 |> json_response(200)
2117 |> assign(:user, user)
2118 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2119 |> json_response(200)
2122 test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
2123 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
2125 id_str_one = to_string(activity_one.id)
2127 assert %{"id" => ^id_str_one, "pinned" => true} =
2129 |> assign(:user, user)
2130 |> post("/api/v1/statuses/#{id_str_one}/pin")
2131 |> json_response(200)
2133 user = refresh_record(user)
2135 assert %{"error" => "You have already pinned the maximum number of statuses"} =
2137 |> assign(:user, user)
2138 |> post("/api/v1/statuses/#{activity_two.id}/pin")
2139 |> json_response(400)
2142 test "Status rich-media Card", %{conn: conn, user: user} do
2143 Pleroma.Config.put([:rich_media, :enabled], true)
2144 {:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp"})
2148 |> get("/api/v1/statuses/#{activity.id}/card")
2149 |> json_response(200)
2151 assert response == %{
2152 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2153 "provider_name" => "www.imdb.com",
2154 "provider_url" => "http://www.imdb.com",
2155 "title" => "The Rock",
2157 "url" => "http://www.imdb.com/title/tt0117500/",
2158 "description" => nil,
2161 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2162 "title" => "The Rock",
2163 "type" => "video.movie",
2164 "url" => "http://www.imdb.com/title/tt0117500/"
2169 # works with private posts
2171 CommonAPI.post(user, %{"status" => "http://example.com/ogp", "visibility" => "direct"})
2175 |> assign(:user, user)
2176 |> get("/api/v1/statuses/#{activity.id}/card")
2177 |> json_response(200)
2179 assert response_two == response
2181 Pleroma.Config.put([:rich_media, :enabled], false)
2186 user = insert(:user)
2187 for_user = insert(:user)
2190 CommonAPI.post(user, %{
2191 "status" => "heweoo?"
2195 CommonAPI.post(user, %{
2196 "status" => "heweoo!"
2201 |> assign(:user, for_user)
2202 |> post("/api/v1/statuses/#{activity1.id}/bookmark")
2204 assert json_response(response1, 200)["bookmarked"] == true
2208 |> assign(:user, for_user)
2209 |> post("/api/v1/statuses/#{activity2.id}/bookmark")
2211 assert json_response(response2, 200)["bookmarked"] == true
2215 |> assign(:user, for_user)
2216 |> get("/api/v1/bookmarks")
2218 assert [json_response(response2, 200), json_response(response1, 200)] ==
2219 json_response(bookmarks, 200)
2223 |> assign(:user, for_user)
2224 |> post("/api/v1/statuses/#{activity1.id}/unbookmark")
2226 assert json_response(response1, 200)["bookmarked"] == false
2230 |> assign(:user, for_user)
2231 |> get("/api/v1/bookmarks")
2233 assert [json_response(response2, 200)] == json_response(bookmarks, 200)
2236 describe "conversation muting" do
2238 user = insert(:user)
2239 {:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
2241 [user: user, activity: activity]
2244 test "mute conversation", %{conn: conn, user: user, activity: activity} do
2245 id_str = to_string(activity.id)
2247 assert %{"id" => ^id_str, "muted" => true} =
2249 |> assign(:user, user)
2250 |> post("/api/v1/statuses/#{activity.id}/mute")
2251 |> json_response(200)
2254 test "unmute conversation", %{conn: conn, user: user, activity: activity} do
2255 {:ok, _} = CommonAPI.add_mute(user, activity)
2257 id_str = to_string(activity.id)
2258 user = refresh_record(user)
2260 assert %{"id" => ^id_str, "muted" => false} =
2262 |> assign(:user, user)
2263 |> post("/api/v1/statuses/#{activity.id}/unmute")
2264 |> json_response(200)
2268 test "flavours switching (Pleroma Extension)", %{conn: conn} do
2269 user = insert(:user)
2273 |> assign(:user, user)
2274 |> get("/api/v1/pleroma/flavour")
2276 assert "glitch" == json_response(get_old_flavour, 200)
2280 |> assign(:user, user)
2281 |> post("/api/v1/pleroma/flavour/vanilla")
2283 assert "vanilla" == json_response(set_flavour, 200)
2287 |> assign(:user, user)
2288 |> post("/api/v1/pleroma/flavour/vanilla")
2290 assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
2293 describe "reports" do
2295 reporter = insert(:user)
2296 target_user = insert(:user)
2298 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
2300 [reporter: reporter, target_user: target_user, activity: activity]
2303 test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
2304 assert %{"action_taken" => false, "id" => _} =
2306 |> assign(:user, reporter)
2307 |> post("/api/v1/reports", %{"account_id" => target_user.id})
2308 |> json_response(200)
2311 test "submit a report with statuses and comment", %{
2314 target_user: target_user,
2317 assert %{"action_taken" => false, "id" => _} =
2319 |> assign(:user, reporter)
2320 |> post("/api/v1/reports", %{
2321 "account_id" => target_user.id,
2322 "status_ids" => [activity.id],
2323 "comment" => "bad status!"
2325 |> json_response(200)
2328 test "account_id is required", %{
2333 assert %{"error" => "Valid `account_id` required"} =
2335 |> assign(:user, reporter)
2336 |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
2337 |> json_response(400)
2340 test "comment must be up to the size specified in the config", %{
2343 target_user: target_user
2345 max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
2346 comment = String.pad_trailing("a", max_size + 1, "a")
2348 error = %{"error" => "Comment must be up to #{max_size} characters"}
2352 |> assign(:user, reporter)
2353 |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
2354 |> json_response(400)
2358 describe "link headers" do
2359 test "preserves parameters in link headers", %{conn: conn} do
2360 user = insert(:user)
2361 other_user = insert(:user)
2364 CommonAPI.post(other_user, %{
2365 "status" => "hi @#{user.nickname}",
2366 "visibility" => "public"
2370 CommonAPI.post(other_user, %{
2371 "status" => "hi @#{user.nickname}",
2372 "visibility" => "public"
2375 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
2376 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
2380 |> assign(:user, user)
2381 |> get("/api/v1/notifications", %{media_only: true})
2383 assert [link_header] = get_resp_header(conn, "link")
2384 assert link_header =~ ~r/media_only=true/
2385 assert link_header =~ ~r/min_id=#{notification2.id}/
2386 assert link_header =~ ~r/max_id=#{notification1.id}/
2390 test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
2391 # Need to set an old-style integer ID to reproduce the problem
2392 # (these are no longer assigned to new accounts but were preserved
2393 # for existing accounts during the migration to flakeIDs)
2394 user_one = insert(:user, %{id: 1212})
2395 user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
2399 |> get("/api/v1/accounts/#{user_one.id}")
2403 |> get("/api/v1/accounts/#{user_two.nickname}")
2407 |> get("/api/v1/accounts/#{user_two.id}")
2409 acc_one = json_response(resp_one, 200)
2410 acc_two = json_response(resp_two, 200)
2411 acc_three = json_response(resp_three, 200)
2412 refute acc_one == acc_two
2413 assert acc_two == acc_three
2416 describe "custom emoji" do
2417 test "with tags", %{conn: conn} do
2420 |> get("/api/v1/custom_emojis")
2421 |> json_response(200)
2423 assert Map.has_key?(emoji, "shortcode")
2424 assert Map.has_key?(emoji, "static_url")
2425 assert Map.has_key?(emoji, "tags")
2426 assert is_list(emoji["tags"])
2427 assert Map.has_key?(emoji, "url")
2428 assert Map.has_key?(emoji, "visible_in_picker")
2432 describe "index/2 redirections" do
2433 setup %{conn: conn} do
2437 signing_salt: "cooldude"
2442 |> Plug.Session.call(Plug.Session.init(session_opts))
2445 test_path = "/web/statuses/test"
2446 %{conn: conn, path: test_path}
2449 test "redirects not logged-in users to the login page", %{conn: conn, path: path} do
2450 conn = get(conn, path)
2452 assert conn.status == 302
2453 assert redirected_to(conn) == "/web/login"
2456 test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
2457 token = insert(:oauth_token)
2461 |> assign(:user, token.user)
2462 |> put_session(:oauth_token, token.token)
2465 assert conn.status == 200
2468 test "saves referer path to session", %{conn: conn, path: path} do
2469 conn = get(conn, path)
2470 return_to = Plug.Conn.get_session(conn, :return_to)
2472 assert return_to == path
2475 test "redirects to the saved path after log in", %{conn: conn, path: path} do
2476 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
2477 auth = insert(:oauth_authorization, app: app)
2481 |> put_session(:return_to, path)
2482 |> get("/web/login", %{code: auth.token})
2484 assert conn.status == 302
2485 assert redirected_to(conn) == path
2488 test "redirects to the getting-started page when referer is not present", %{conn: conn} do
2489 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
2490 auth = insert(:oauth_authorization, app: app)
2492 conn = get(conn, "/web/login", %{code: auth.token})
2494 assert conn.status == 302
2495 assert redirected_to(conn) == "/web/getting-started"
2499 describe "scheduled activities" do
2500 test "creates a scheduled activity", %{conn: conn} do
2501 user = insert(:user)
2502 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2506 |> assign(:user, user)
2507 |> post("/api/v1/statuses", %{
2508 "status" => "scheduled",
2509 "scheduled_at" => scheduled_at
2512 assert %{"scheduled_at" => expected_scheduled_at} = json_response(conn, 200)
2513 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(scheduled_at)
2514 assert [] == Repo.all(Activity)
2517 test "creates a scheduled activity with a media attachment", %{conn: conn} do
2518 user = insert(:user)
2519 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2521 file = %Plug.Upload{
2522 content_type: "image/jpg",
2523 path: Path.absname("test/fixtures/image.jpg"),
2524 filename: "an_image.jpg"
2527 {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
2531 |> assign(:user, user)
2532 |> post("/api/v1/statuses", %{
2533 "media_ids" => [to_string(upload.id)],
2534 "status" => "scheduled",
2535 "scheduled_at" => scheduled_at
2538 assert %{"media_attachments" => [media_attachment]} = json_response(conn, 200)
2539 assert %{"type" => "image"} = media_attachment
2542 test "skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now",
2544 user = insert(:user)
2547 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(5) - 1, :millisecond)
2551 |> assign(:user, user)
2552 |> post("/api/v1/statuses", %{
2553 "status" => "not scheduled",
2554 "scheduled_at" => scheduled_at
2557 assert %{"content" => "not scheduled"} = json_response(conn, 200)
2558 assert [] == Repo.all(ScheduledActivity)
2561 test "returns error when daily user limit is exceeded", %{conn: conn} do
2562 user = insert(:user)
2565 NaiveDateTime.utc_now()
2566 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
2567 |> NaiveDateTime.to_iso8601()
2569 attrs = %{params: %{}, scheduled_at: today}
2570 {:ok, _} = ScheduledActivity.create(user, attrs)
2571 {:ok, _} = ScheduledActivity.create(user, attrs)
2575 |> assign(:user, user)
2576 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today})
2578 assert %{"error" => "daily limit exceeded"} == json_response(conn, 422)
2581 test "returns error when total user limit is exceeded", %{conn: conn} do
2582 user = insert(:user)
2585 NaiveDateTime.utc_now()
2586 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
2587 |> NaiveDateTime.to_iso8601()
2590 NaiveDateTime.utc_now()
2591 |> NaiveDateTime.add(:timer.hours(36), :millisecond)
2592 |> NaiveDateTime.to_iso8601()
2594 attrs = %{params: %{}, scheduled_at: today}
2595 {:ok, _} = ScheduledActivity.create(user, attrs)
2596 {:ok, _} = ScheduledActivity.create(user, attrs)
2597 {:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow})
2601 |> assign(:user, user)
2602 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow})
2604 assert %{"error" => "total limit exceeded"} == json_response(conn, 422)
2607 test "shows scheduled activities", %{conn: conn} do
2608 user = insert(:user)
2609 scheduled_activity_id1 = insert(:scheduled_activity, user: user).id |> to_string()
2610 scheduled_activity_id2 = insert(:scheduled_activity, user: user).id |> to_string()
2611 scheduled_activity_id3 = insert(:scheduled_activity, user: user).id |> to_string()
2612 scheduled_activity_id4 = insert(:scheduled_activity, user: user).id |> to_string()
2616 |> assign(:user, user)
2621 |> get("/api/v1/scheduled_statuses?limit=2&min_id=#{scheduled_activity_id1}")
2623 result = json_response(conn_res, 200)
2624 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
2629 |> get("/api/v1/scheduled_statuses?limit=2&since_id=#{scheduled_activity_id1}")
2631 result = json_response(conn_res, 200)
2632 assert [%{"id" => ^scheduled_activity_id4}, %{"id" => ^scheduled_activity_id3}] = result
2637 |> get("/api/v1/scheduled_statuses?limit=2&max_id=#{scheduled_activity_id4}")
2639 result = json_response(conn_res, 200)
2640 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
2643 test "shows a scheduled activity", %{conn: conn} do
2644 user = insert(:user)
2645 scheduled_activity = insert(:scheduled_activity, user: user)
2649 |> assign(:user, user)
2650 |> get("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
2652 assert %{"id" => scheduled_activity_id} = json_response(res_conn, 200)
2653 assert scheduled_activity_id == scheduled_activity.id |> to_string()
2657 |> assign(:user, user)
2658 |> get("/api/v1/scheduled_statuses/404")
2660 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
2663 test "updates a scheduled activity", %{conn: conn} do
2664 user = insert(:user)
2665 scheduled_activity = insert(:scheduled_activity, user: user)
2668 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2672 |> assign(:user, user)
2673 |> put("/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{
2674 scheduled_at: new_scheduled_at
2677 assert %{"scheduled_at" => expected_scheduled_at} = json_response(res_conn, 200)
2678 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(new_scheduled_at)
2682 |> assign(:user, user)
2683 |> put("/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at})
2685 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
2688 test "deletes a scheduled activity", %{conn: conn} do
2689 user = insert(:user)
2690 scheduled_activity = insert(:scheduled_activity, user: user)
2694 |> assign(:user, user)
2695 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
2697 assert %{} = json_response(res_conn, 200)
2698 assert nil == Repo.get(ScheduledActivity, scheduled_activity.id)
2702 |> assign(:user, user)
2703 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
2705 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
2709 test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{conn: conn} do
2710 user1 = insert(:user)
2711 user2 = insert(:user)
2712 user3 = insert(:user)
2714 {:ok, replied_to} = TwitterAPI.create_status(user1, %{"status" => "cofe"})
2716 # Reply to status from another user
2719 |> assign(:user, user2)
2720 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
2722 assert %{"content" => "xD", "id" => id} = json_response(conn1, 200)
2724 activity = Activity.get_by_id(id)
2726 assert activity.data["object"]["inReplyTo"] == replied_to.data["object"]["id"]
2727 assert activity.data["object"]["inReplyToStatusId"] == replied_to.id
2729 # Reblog from the third user
2732 |> assign(:user, user3)
2733 |> post("/api/v1/statuses/#{activity.id}/reblog")
2735 assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
2736 json_response(conn2, 200)
2738 assert to_string(activity.id) == id
2740 # Getting third user status
2743 |> assign(:user, user3)
2744 |> get("api/v1/timelines/home")
2746 [reblogged_activity] = json_response(conn3, 200)
2748 assert reblogged_activity["reblog"]["in_reply_to_id"] == replied_to.id
2750 replied_to_user = User.get_by_ap_id(replied_to.data["actor"])
2751 assert reblogged_activity["reblog"]["in_reply_to_account_id"] == replied_to_user.id