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 email = Pleroma.Config.get([:instance, :email])
1985 # Note: not checking for "max_toot_chars" since it's optional
1991 "email" => from_config_email,
1993 "streaming_api" => _
1998 "registrations" => _
2001 assert email == from_config_email
2004 test "get instance stats", %{conn: conn} do
2005 user = insert(:user, %{local: true})
2007 user2 = insert(:user, %{local: true})
2008 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
2010 insert(:user, %{local: false, nickname: "u@peer1.com"})
2011 insert(:user, %{local: false, nickname: "u@peer2.com"})
2013 {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
2015 # Stats should count users with missing or nil `info.deactivated` value
2016 user = User.get_by_id(user.id)
2017 info_change = Changeset.change(user.info, %{deactivated: nil})
2021 |> Changeset.change()
2022 |> Changeset.put_embed(:info, info_change)
2023 |> User.update_and_set_cache()
2025 Pleroma.Stats.update_stats()
2027 conn = get(conn, "/api/v1/instance")
2029 assert result = json_response(conn, 200)
2031 stats = result["stats"]
2034 assert stats["user_count"] == 1
2035 assert stats["status_count"] == 1
2036 assert stats["domain_count"] == 2
2039 test "get peers", %{conn: conn} do
2040 insert(:user, %{local: false, nickname: "u@peer1.com"})
2041 insert(:user, %{local: false, nickname: "u@peer2.com"})
2043 Pleroma.Stats.update_stats()
2045 conn = get(conn, "/api/v1/instance/peers")
2047 assert result = json_response(conn, 200)
2049 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
2052 test "put settings", %{conn: conn} do
2053 user = insert(:user)
2057 |> assign(:user, user)
2058 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
2060 assert _result = json_response(conn, 200)
2062 user = User.get_cached_by_ap_id(user.ap_id)
2063 assert user.info.settings == %{"programming" => "socks"}
2066 describe "pinned statuses" do
2068 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2070 user = insert(:user)
2071 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
2073 [user: user, activity: activity]
2076 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
2077 {:ok, _} = CommonAPI.pin(activity.id, user)
2081 |> assign(:user, user)
2082 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2083 |> json_response(200)
2085 id_str = to_string(activity.id)
2087 assert [%{"id" => ^id_str, "pinned" => true}] = result
2090 test "pin status", %{conn: conn, user: user, activity: activity} do
2091 id_str = to_string(activity.id)
2093 assert %{"id" => ^id_str, "pinned" => true} =
2095 |> assign(:user, user)
2096 |> post("/api/v1/statuses/#{activity.id}/pin")
2097 |> json_response(200)
2099 assert [%{"id" => ^id_str, "pinned" => true}] =
2101 |> assign(:user, user)
2102 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2103 |> json_response(200)
2106 test "unpin status", %{conn: conn, user: user, activity: activity} do
2107 {:ok, _} = CommonAPI.pin(activity.id, user)
2109 id_str = to_string(activity.id)
2110 user = refresh_record(user)
2112 assert %{"id" => ^id_str, "pinned" => false} =
2114 |> assign(:user, user)
2115 |> post("/api/v1/statuses/#{activity.id}/unpin")
2116 |> json_response(200)
2120 |> assign(:user, user)
2121 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2122 |> json_response(200)
2125 test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
2126 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
2128 id_str_one = to_string(activity_one.id)
2130 assert %{"id" => ^id_str_one, "pinned" => true} =
2132 |> assign(:user, user)
2133 |> post("/api/v1/statuses/#{id_str_one}/pin")
2134 |> json_response(200)
2136 user = refresh_record(user)
2138 assert %{"error" => "You have already pinned the maximum number of statuses"} =
2140 |> assign(:user, user)
2141 |> post("/api/v1/statuses/#{activity_two.id}/pin")
2142 |> json_response(400)
2145 test "Status rich-media Card", %{conn: conn, user: user} do
2146 Pleroma.Config.put([:rich_media, :enabled], true)
2147 {:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp"})
2151 |> get("/api/v1/statuses/#{activity.id}/card")
2152 |> json_response(200)
2154 assert response == %{
2155 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2156 "provider_name" => "www.imdb.com",
2157 "provider_url" => "http://www.imdb.com",
2158 "title" => "The Rock",
2160 "url" => "http://www.imdb.com/title/tt0117500/",
2161 "description" => nil,
2164 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2165 "title" => "The Rock",
2166 "type" => "video.movie",
2167 "url" => "http://www.imdb.com/title/tt0117500/"
2172 # works with private posts
2174 CommonAPI.post(user, %{"status" => "http://example.com/ogp", "visibility" => "direct"})
2178 |> assign(:user, user)
2179 |> get("/api/v1/statuses/#{activity.id}/card")
2180 |> json_response(200)
2182 assert response_two == response
2184 Pleroma.Config.put([:rich_media, :enabled], false)
2189 user = insert(:user)
2190 for_user = insert(:user)
2193 CommonAPI.post(user, %{
2194 "status" => "heweoo?"
2198 CommonAPI.post(user, %{
2199 "status" => "heweoo!"
2204 |> assign(:user, for_user)
2205 |> post("/api/v1/statuses/#{activity1.id}/bookmark")
2207 assert json_response(response1, 200)["bookmarked"] == true
2211 |> assign(:user, for_user)
2212 |> post("/api/v1/statuses/#{activity2.id}/bookmark")
2214 assert json_response(response2, 200)["bookmarked"] == true
2218 |> assign(:user, for_user)
2219 |> get("/api/v1/bookmarks")
2221 assert [json_response(response2, 200), json_response(response1, 200)] ==
2222 json_response(bookmarks, 200)
2226 |> assign(:user, for_user)
2227 |> post("/api/v1/statuses/#{activity1.id}/unbookmark")
2229 assert json_response(response1, 200)["bookmarked"] == false
2233 |> assign(:user, for_user)
2234 |> get("/api/v1/bookmarks")
2236 assert [json_response(response2, 200)] == json_response(bookmarks, 200)
2239 describe "conversation muting" do
2241 user = insert(:user)
2242 {:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
2244 [user: user, activity: activity]
2247 test "mute conversation", %{conn: conn, user: user, activity: activity} do
2248 id_str = to_string(activity.id)
2250 assert %{"id" => ^id_str, "muted" => true} =
2252 |> assign(:user, user)
2253 |> post("/api/v1/statuses/#{activity.id}/mute")
2254 |> json_response(200)
2257 test "unmute conversation", %{conn: conn, user: user, activity: activity} do
2258 {:ok, _} = CommonAPI.add_mute(user, activity)
2260 id_str = to_string(activity.id)
2261 user = refresh_record(user)
2263 assert %{"id" => ^id_str, "muted" => false} =
2265 |> assign(:user, user)
2266 |> post("/api/v1/statuses/#{activity.id}/unmute")
2267 |> json_response(200)
2271 test "flavours switching (Pleroma Extension)", %{conn: conn} do
2272 user = insert(:user)
2276 |> assign(:user, user)
2277 |> get("/api/v1/pleroma/flavour")
2279 assert "glitch" == json_response(get_old_flavour, 200)
2283 |> assign(:user, user)
2284 |> post("/api/v1/pleroma/flavour/vanilla")
2286 assert "vanilla" == json_response(set_flavour, 200)
2290 |> assign(:user, user)
2291 |> post("/api/v1/pleroma/flavour/vanilla")
2293 assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
2296 describe "reports" do
2298 reporter = insert(:user)
2299 target_user = insert(:user)
2301 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
2303 [reporter: reporter, target_user: target_user, activity: activity]
2306 test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
2307 assert %{"action_taken" => false, "id" => _} =
2309 |> assign(:user, reporter)
2310 |> post("/api/v1/reports", %{"account_id" => target_user.id})
2311 |> json_response(200)
2314 test "submit a report with statuses and comment", %{
2317 target_user: target_user,
2320 assert %{"action_taken" => false, "id" => _} =
2322 |> assign(:user, reporter)
2323 |> post("/api/v1/reports", %{
2324 "account_id" => target_user.id,
2325 "status_ids" => [activity.id],
2326 "comment" => "bad status!"
2328 |> json_response(200)
2331 test "account_id is required", %{
2336 assert %{"error" => "Valid `account_id` required"} =
2338 |> assign(:user, reporter)
2339 |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
2340 |> json_response(400)
2343 test "comment must be up to the size specified in the config", %{
2346 target_user: target_user
2348 max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
2349 comment = String.pad_trailing("a", max_size + 1, "a")
2351 error = %{"error" => "Comment must be up to #{max_size} characters"}
2355 |> assign(:user, reporter)
2356 |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
2357 |> json_response(400)
2361 describe "link headers" do
2362 test "preserves parameters in link headers", %{conn: conn} do
2363 user = insert(:user)
2364 other_user = insert(:user)
2367 CommonAPI.post(other_user, %{
2368 "status" => "hi @#{user.nickname}",
2369 "visibility" => "public"
2373 CommonAPI.post(other_user, %{
2374 "status" => "hi @#{user.nickname}",
2375 "visibility" => "public"
2378 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
2379 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
2383 |> assign(:user, user)
2384 |> get("/api/v1/notifications", %{media_only: true})
2386 assert [link_header] = get_resp_header(conn, "link")
2387 assert link_header =~ ~r/media_only=true/
2388 assert link_header =~ ~r/min_id=#{notification2.id}/
2389 assert link_header =~ ~r/max_id=#{notification1.id}/
2393 test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
2394 # Need to set an old-style integer ID to reproduce the problem
2395 # (these are no longer assigned to new accounts but were preserved
2396 # for existing accounts during the migration to flakeIDs)
2397 user_one = insert(:user, %{id: 1212})
2398 user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
2402 |> get("/api/v1/accounts/#{user_one.id}")
2406 |> get("/api/v1/accounts/#{user_two.nickname}")
2410 |> get("/api/v1/accounts/#{user_two.id}")
2412 acc_one = json_response(resp_one, 200)
2413 acc_two = json_response(resp_two, 200)
2414 acc_three = json_response(resp_three, 200)
2415 refute acc_one == acc_two
2416 assert acc_two == acc_three
2419 describe "custom emoji" do
2420 test "with tags", %{conn: conn} do
2423 |> get("/api/v1/custom_emojis")
2424 |> json_response(200)
2426 assert Map.has_key?(emoji, "shortcode")
2427 assert Map.has_key?(emoji, "static_url")
2428 assert Map.has_key?(emoji, "tags")
2429 assert is_list(emoji["tags"])
2430 assert Map.has_key?(emoji, "url")
2431 assert Map.has_key?(emoji, "visible_in_picker")
2435 describe "index/2 redirections" do
2436 setup %{conn: conn} do
2440 signing_salt: "cooldude"
2445 |> Plug.Session.call(Plug.Session.init(session_opts))
2448 test_path = "/web/statuses/test"
2449 %{conn: conn, path: test_path}
2452 test "redirects not logged-in users to the login page", %{conn: conn, path: path} do
2453 conn = get(conn, path)
2455 assert conn.status == 302
2456 assert redirected_to(conn) == "/web/login"
2459 test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
2460 token = insert(:oauth_token)
2464 |> assign(:user, token.user)
2465 |> put_session(:oauth_token, token.token)
2468 assert conn.status == 200
2471 test "saves referer path to session", %{conn: conn, path: path} do
2472 conn = get(conn, path)
2473 return_to = Plug.Conn.get_session(conn, :return_to)
2475 assert return_to == path
2478 test "redirects to the saved path after log in", %{conn: conn, path: path} do
2479 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
2480 auth = insert(:oauth_authorization, app: app)
2484 |> put_session(:return_to, path)
2485 |> get("/web/login", %{code: auth.token})
2487 assert conn.status == 302
2488 assert redirected_to(conn) == path
2491 test "redirects to the getting-started page when referer is not present", %{conn: conn} do
2492 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
2493 auth = insert(:oauth_authorization, app: app)
2495 conn = get(conn, "/web/login", %{code: auth.token})
2497 assert conn.status == 302
2498 assert redirected_to(conn) == "/web/getting-started"
2502 describe "scheduled activities" do
2503 test "creates a scheduled activity", %{conn: conn} do
2504 user = insert(:user)
2505 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2509 |> assign(:user, user)
2510 |> post("/api/v1/statuses", %{
2511 "status" => "scheduled",
2512 "scheduled_at" => scheduled_at
2515 assert %{"scheduled_at" => expected_scheduled_at} = json_response(conn, 200)
2516 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(scheduled_at)
2517 assert [] == Repo.all(Activity)
2520 test "creates a scheduled activity with a media attachment", %{conn: conn} do
2521 user = insert(:user)
2522 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2524 file = %Plug.Upload{
2525 content_type: "image/jpg",
2526 path: Path.absname("test/fixtures/image.jpg"),
2527 filename: "an_image.jpg"
2530 {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
2534 |> assign(:user, user)
2535 |> post("/api/v1/statuses", %{
2536 "media_ids" => [to_string(upload.id)],
2537 "status" => "scheduled",
2538 "scheduled_at" => scheduled_at
2541 assert %{"media_attachments" => [media_attachment]} = json_response(conn, 200)
2542 assert %{"type" => "image"} = media_attachment
2545 test "skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now",
2547 user = insert(:user)
2550 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(5) - 1, :millisecond)
2554 |> assign(:user, user)
2555 |> post("/api/v1/statuses", %{
2556 "status" => "not scheduled",
2557 "scheduled_at" => scheduled_at
2560 assert %{"content" => "not scheduled"} = json_response(conn, 200)
2561 assert [] == Repo.all(ScheduledActivity)
2564 test "returns error when daily user limit is exceeded", %{conn: conn} do
2565 user = insert(:user)
2568 NaiveDateTime.utc_now()
2569 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
2570 |> NaiveDateTime.to_iso8601()
2572 attrs = %{params: %{}, scheduled_at: today}
2573 {:ok, _} = ScheduledActivity.create(user, attrs)
2574 {:ok, _} = ScheduledActivity.create(user, attrs)
2578 |> assign(:user, user)
2579 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today})
2581 assert %{"error" => "daily limit exceeded"} == json_response(conn, 422)
2584 test "returns error when total user limit is exceeded", %{conn: conn} do
2585 user = insert(:user)
2588 NaiveDateTime.utc_now()
2589 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
2590 |> NaiveDateTime.to_iso8601()
2593 NaiveDateTime.utc_now()
2594 |> NaiveDateTime.add(:timer.hours(36), :millisecond)
2595 |> NaiveDateTime.to_iso8601()
2597 attrs = %{params: %{}, scheduled_at: today}
2598 {:ok, _} = ScheduledActivity.create(user, attrs)
2599 {:ok, _} = ScheduledActivity.create(user, attrs)
2600 {:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow})
2604 |> assign(:user, user)
2605 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow})
2607 assert %{"error" => "total limit exceeded"} == json_response(conn, 422)
2610 test "shows scheduled activities", %{conn: conn} do
2611 user = insert(:user)
2612 scheduled_activity_id1 = insert(:scheduled_activity, user: user).id |> to_string()
2613 scheduled_activity_id2 = insert(:scheduled_activity, user: user).id |> to_string()
2614 scheduled_activity_id3 = insert(:scheduled_activity, user: user).id |> to_string()
2615 scheduled_activity_id4 = insert(:scheduled_activity, user: user).id |> to_string()
2619 |> assign(:user, user)
2624 |> get("/api/v1/scheduled_statuses?limit=2&min_id=#{scheduled_activity_id1}")
2626 result = json_response(conn_res, 200)
2627 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
2632 |> get("/api/v1/scheduled_statuses?limit=2&since_id=#{scheduled_activity_id1}")
2634 result = json_response(conn_res, 200)
2635 assert [%{"id" => ^scheduled_activity_id4}, %{"id" => ^scheduled_activity_id3}] = result
2640 |> get("/api/v1/scheduled_statuses?limit=2&max_id=#{scheduled_activity_id4}")
2642 result = json_response(conn_res, 200)
2643 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
2646 test "shows a scheduled activity", %{conn: conn} do
2647 user = insert(:user)
2648 scheduled_activity = insert(:scheduled_activity, user: user)
2652 |> assign(:user, user)
2653 |> get("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
2655 assert %{"id" => scheduled_activity_id} = json_response(res_conn, 200)
2656 assert scheduled_activity_id == scheduled_activity.id |> to_string()
2660 |> assign(:user, user)
2661 |> get("/api/v1/scheduled_statuses/404")
2663 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
2666 test "updates a scheduled activity", %{conn: conn} do
2667 user = insert(:user)
2668 scheduled_activity = insert(:scheduled_activity, user: user)
2671 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2675 |> assign(:user, user)
2676 |> put("/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{
2677 scheduled_at: new_scheduled_at
2680 assert %{"scheduled_at" => expected_scheduled_at} = json_response(res_conn, 200)
2681 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(new_scheduled_at)
2685 |> assign(:user, user)
2686 |> put("/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at})
2688 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
2691 test "deletes a scheduled activity", %{conn: conn} do
2692 user = insert(:user)
2693 scheduled_activity = insert(:scheduled_activity, user: user)
2697 |> assign(:user, user)
2698 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
2700 assert %{} = json_response(res_conn, 200)
2701 assert nil == Repo.get(ScheduledActivity, scheduled_activity.id)
2705 |> assign(:user, user)
2706 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
2708 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
2712 test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{conn: conn} do
2713 user1 = insert(:user)
2714 user2 = insert(:user)
2715 user3 = insert(:user)
2717 {:ok, replied_to} = TwitterAPI.create_status(user1, %{"status" => "cofe"})
2719 # Reply to status from another user
2722 |> assign(:user, user2)
2723 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
2725 assert %{"content" => "xD", "id" => id} = json_response(conn1, 200)
2727 activity = Activity.get_by_id(id)
2729 assert activity.data["object"]["inReplyTo"] == replied_to.data["object"]["id"]
2730 assert activity.data["object"]["inReplyToStatusId"] == replied_to.id
2732 # Reblog from the third user
2735 |> assign(:user, user3)
2736 |> post("/api/v1/statuses/#{activity.id}/reblog")
2738 assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
2739 json_response(conn2, 200)
2741 assert to_string(activity.id) == id
2743 # Getting third user status
2746 |> assign(:user, user3)
2747 |> get("api/v1/timelines/home")
2749 [reblogged_activity] = json_response(conn3, 200)
2751 assert reblogged_activity["reblog"]["in_reply_to_id"] == replied_to.id
2753 replied_to_user = User.get_by_ap_id(replied_to.data["actor"])
2754 assert reblogged_activity["reblog"]["in_reply_to_account_id"] == replied_to_user.id