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.TwitterAPI.ControllerTest do
6 use Pleroma.Web.ConnCase
10 alias Pleroma.Builders.ActivityBuilder
11 alias Pleroma.Builders.UserBuilder
12 alias Pleroma.Notification
16 alias Pleroma.Web.ActivityPub.ActivityPub
17 alias Pleroma.Web.CommonAPI
18 alias Pleroma.Web.OAuth.Token
19 alias Pleroma.Web.TwitterAPI.ActivityView
20 alias Pleroma.Web.TwitterAPI.Controller
21 alias Pleroma.Web.TwitterAPI.NotificationView
22 alias Pleroma.Web.TwitterAPI.TwitterAPI
23 alias Pleroma.Web.TwitterAPI.UserView
26 import Pleroma.Factory
27 import Swoosh.TestAssertions
29 @banner "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
31 describe "POST /api/account/update_profile_banner" do
32 test "it updates the banner", %{conn: conn} do
36 |> assign(:user, user)
37 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => @banner})
40 user = refresh_record(user)
41 assert user.info.banner["type"] == "Image"
44 test "profile banner can be reset", %{conn: conn} do
48 |> assign(:user, user)
49 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => ""})
52 user = refresh_record(user)
53 assert user.info.banner == %{}
57 describe "POST /api/qvitter/update_background_image" do
58 test "it updates the background", %{conn: conn} do
62 |> assign(:user, user)
63 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => @banner})
66 user = refresh_record(user)
67 assert user.info.background["type"] == "Image"
70 test "background can be reset", %{conn: conn} do
74 |> assign(:user, user)
75 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => ""})
78 user = refresh_record(user)
79 assert user.info.background == %{}
83 describe "POST /api/account/verify_credentials" do
86 test "without valid credentials", %{conn: conn} do
87 conn = post(conn, "/api/account/verify_credentials.json")
88 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
91 test "with credentials", %{conn: conn, user: user} do
94 |> with_credentials(user.nickname, "test")
95 |> post("/api/account/verify_credentials.json")
99 UserView.render("show.json", %{user: user, token: response["token"], for: user})
103 describe "POST /statuses/update.json" do
106 test "without valid credentials", %{conn: conn} do
107 conn = post(conn, "/api/statuses/update.json")
108 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
111 test "with credentials", %{conn: conn, user: user} do
112 conn_with_creds = conn |> with_credentials(user.nickname, "test")
113 request_path = "/api/statuses/update.json"
116 "request" => request_path,
117 "error" => "Client must provide a 'status' parameter with a value."
122 |> post(request_path)
124 assert json_response(conn, 400) == error_response
128 |> post(request_path, %{status: ""})
130 assert json_response(conn, 400) == error_response
134 |> post(request_path, %{status: " "})
136 assert json_response(conn, 400) == error_response
138 # we post with visibility private in order to avoid triggering relay
141 |> post(request_path, %{status: "Nice meme.", visibility: "private"})
143 assert json_response(conn, 200) ==
144 ActivityView.render("activity.json", %{
145 activity: Repo.one(Activity),
152 describe "GET /statuses/public_timeline.json" do
154 clear_config([:instance, :public])
156 test "returns statuses", %{conn: conn} do
158 activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
159 ActivityBuilder.insert_list(10, %{}, %{user: user})
160 since_id = List.last(activities).id
164 |> get("/api/statuses/public_timeline.json", %{since_id: since_id})
166 response = json_response(conn, 200)
168 assert length(response) == 10
171 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
172 Pleroma.Config.put([:instance, :public], false)
175 |> get("/api/statuses/public_timeline.json")
176 |> json_response(403)
179 test "returns 200 to authenticated request when the instance is not public",
180 %{conn: conn, user: user} do
181 Pleroma.Config.put([:instance, :public], false)
184 |> with_credentials(user.nickname, "test")
185 |> get("/api/statuses/public_timeline.json")
186 |> json_response(200)
189 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
191 |> get("/api/statuses/public_timeline.json")
192 |> json_response(200)
195 test "returns 200 to authenticated request when the instance is public",
196 %{conn: conn, user: user} do
198 |> with_credentials(user.nickname, "test")
199 |> get("/api/statuses/public_timeline.json")
200 |> json_response(200)
203 test_with_mock "treats user as unauthenticated if `assigns[:token]` is present but lacks `read` permission",
207 token = insert(:oauth_token, scopes: ["write"])
210 |> put_req_header("authorization", "Bearer #{token.token}")
211 |> get("/api/statuses/public_timeline.json")
212 |> json_response(200)
214 assert called(Controller.public_timeline(%{assigns: %{user: nil}}, :_))
218 describe "GET /statuses/public_and_external_timeline.json" do
220 clear_config([:instance, :public])
222 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
223 Pleroma.Config.put([:instance, :public], false)
226 |> get("/api/statuses/public_and_external_timeline.json")
227 |> json_response(403)
230 test "returns 200 to authenticated request when the instance is not public",
231 %{conn: conn, user: user} do
232 Pleroma.Config.put([:instance, :public], false)
235 |> with_credentials(user.nickname, "test")
236 |> get("/api/statuses/public_and_external_timeline.json")
237 |> json_response(200)
240 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
242 |> get("/api/statuses/public_and_external_timeline.json")
243 |> json_response(200)
246 test "returns 200 to authenticated request when the instance is public",
247 %{conn: conn, user: user} do
249 |> with_credentials(user.nickname, "test")
250 |> get("/api/statuses/public_and_external_timeline.json")
251 |> json_response(200)
255 describe "GET /statuses/show/:id.json" do
256 test "returns one status", %{conn: conn} do
258 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
259 actor = User.get_cached_by_ap_id(activity.data["actor"])
263 |> get("/api/statuses/show/#{activity.id}.json")
265 response = json_response(conn, 200)
267 assert response == ActivityView.render("activity.json", %{activity: activity, user: actor})
271 describe "GET /users/show.json" do
272 test "gets user with screen_name", %{conn: conn} do
277 |> get("/api/users/show.json", %{"screen_name" => user.nickname})
279 response = json_response(conn, 200)
281 assert response["id"] == user.id
284 test "gets user with user_id", %{conn: conn} do
289 |> get("/api/users/show.json", %{"user_id" => user.id})
291 response = json_response(conn, 200)
293 assert response["id"] == user.id
296 test "gets a user for a logged in user", %{conn: conn} do
298 logged_in = insert(:user)
300 {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})
304 |> with_credentials(logged_in.nickname, "test")
305 |> get("/api/users/show.json", %{"user_id" => user.id})
307 response = json_response(conn, 200)
309 assert response["following"] == true
313 describe "GET /statusnet/conversation/:id.json" do
314 test "returns the statuses in the conversation", %{conn: conn} do
315 {:ok, _user} = UserBuilder.insert()
316 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
317 {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
318 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
322 |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
324 response = json_response(conn, 200)
326 assert length(response) == 2
330 describe "GET /statuses/friends_timeline.json" do
333 test "without valid credentials", %{conn: conn} do
334 conn = get(conn, "/api/statuses/friends_timeline.json")
335 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
338 test "with credentials", %{conn: conn, user: current_user} do
342 ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
344 returned_activities =
345 ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
347 other_user = insert(:user)
348 ActivityBuilder.insert_list(10, %{}, %{user: other_user})
349 since_id = List.last(activities).id
352 Changeset.change(current_user, following: [User.ap_followers(user)])
357 |> with_credentials(current_user.nickname, "test")
358 |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
360 response = json_response(conn, 200)
362 assert length(response) == 10
365 Enum.map(returned_activities, fn activity ->
366 ActivityView.render("activity.json", %{
368 user: User.get_cached_by_ap_id(activity.data["actor"]),
375 describe "GET /statuses/dm_timeline.json" do
376 test "it show direct messages", %{conn: conn} do
377 user_one = insert(:user)
378 user_two = insert(:user)
380 {:ok, user_two} = User.follow(user_two, user_one)
383 CommonAPI.post(user_one, %{
384 "status" => "Hi @#{user_two.nickname}!",
385 "visibility" => "direct"
389 CommonAPI.post(user_two, %{
390 "status" => "Hi @#{user_one.nickname}!",
391 "visibility" => "direct"
394 {:ok, _follower_only} =
395 CommonAPI.post(user_one, %{
396 "status" => "Hi @#{user_two.nickname}!",
397 "visibility" => "private"
400 # Only direct should be visible here
403 |> assign(:user, user_two)
404 |> get("/api/statuses/dm_timeline.json")
406 [status, status_two] = json_response(res_conn, 200)
407 assert status["id"] == direct_two.id
408 assert status_two["id"] == direct.id
411 test "doesn't include DMs from blocked users", %{conn: conn} do
412 blocker = insert(:user)
413 blocked = insert(:user)
415 {:ok, blocker} = User.block(blocker, blocked)
417 {:ok, _blocked_direct} =
418 CommonAPI.post(blocked, %{
419 "status" => "Hi @#{blocker.nickname}!",
420 "visibility" => "direct"
424 CommonAPI.post(user, %{
425 "status" => "Hi @#{blocker.nickname}!",
426 "visibility" => "direct"
431 |> assign(:user, blocker)
432 |> get("/api/statuses/dm_timeline.json")
434 [status] = json_response(res_conn, 200)
435 assert status["id"] == direct.id
439 describe "GET /statuses/mentions.json" do
442 test "without valid credentials", %{conn: conn} do
443 conn = get(conn, "/api/statuses/mentions.json")
444 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
447 test "with credentials", %{conn: conn, user: current_user} do
449 CommonAPI.post(current_user, %{
450 "status" => "why is tenshi eating a corndog so cute?",
451 "visibility" => "public"
456 |> with_credentials(current_user.nickname, "test")
457 |> get("/api/statuses/mentions.json")
459 response = json_response(conn, 200)
461 assert length(response) == 1
463 assert Enum.at(response, 0) ==
464 ActivityView.render("activity.json", %{
471 test "does not show DMs in mentions timeline", %{conn: conn, user: current_user} do
473 CommonAPI.post(current_user, %{
474 "status" => "Have you guys ever seen how cute tenshi eating a corndog is?",
475 "visibility" => "direct"
480 |> with_credentials(current_user.nickname, "test")
481 |> get("/api/statuses/mentions.json")
483 response = json_response(conn, 200)
485 assert Enum.empty?(response)
489 describe "GET /api/qvitter/statuses/notifications.json" do
492 test "without valid credentials", %{conn: conn} do
493 conn = get(conn, "/api/qvitter/statuses/notifications.json")
494 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
497 test "with credentials", %{conn: conn, user: current_user} do
498 other_user = insert(:user)
501 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
505 |> with_credentials(current_user.nickname, "test")
506 |> get("/api/qvitter/statuses/notifications.json")
508 response = json_response(conn, 200)
510 assert length(response) == 1
513 NotificationView.render("notification.json", %{
514 notifications: Notification.for_user(current_user),
519 test "muted user", %{conn: conn, user: current_user} do
520 other_user = insert(:user)
522 {:ok, current_user} = User.mute(current_user, other_user)
525 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
529 |> with_credentials(current_user.nickname, "test")
530 |> get("/api/qvitter/statuses/notifications.json")
532 assert json_response(conn, 200) == []
535 test "muted user with with_muted parameter", %{conn: conn, user: current_user} do
536 other_user = insert(:user)
538 {:ok, current_user} = User.mute(current_user, other_user)
541 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
545 |> with_credentials(current_user.nickname, "test")
546 |> get("/api/qvitter/statuses/notifications.json", %{"with_muted" => "true"})
548 assert length(json_response(conn, 200)) == 1
552 describe "POST /api/qvitter/statuses/notifications/read" do
555 test "without valid credentials", %{conn: conn} do
556 conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567})
557 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
560 test "with credentials, without any params", %{conn: conn, user: current_user} do
563 |> with_credentials(current_user.nickname, "test")
564 |> post("/api/qvitter/statuses/notifications/read")
566 assert json_response(conn, 400) == %{
567 "error" => "You need to specify latest_id",
568 "request" => "/api/qvitter/statuses/notifications/read"
572 test "with credentials, with params", %{conn: conn, user: current_user} do
573 other_user = insert(:user)
576 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
580 |> with_credentials(current_user.nickname, "test")
581 |> get("/api/qvitter/statuses/notifications.json")
583 [notification] = response = json_response(response_conn, 200)
585 assert length(response) == 1
587 assert notification["is_seen"] == 0
591 |> with_credentials(current_user.nickname, "test")
592 |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]})
594 [notification] = response = json_response(response_conn, 200)
596 assert length(response) == 1
598 assert notification["is_seen"] == 1
602 describe "GET /statuses/user_timeline.json" do
605 test "without any params", %{conn: conn} do
606 conn = get(conn, "/api/statuses/user_timeline.json")
608 assert json_response(conn, 400) == %{
609 "error" => "You need to specify screen_name or user_id",
610 "request" => "/api/statuses/user_timeline.json"
614 test "with user_id", %{conn: conn} do
616 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
618 conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
619 response = json_response(conn, 200)
620 assert length(response) == 1
622 assert Enum.at(response, 0) ==
623 ActivityView.render("activity.json", %{user: user, activity: activity})
626 test "with screen_name", %{conn: conn} do
628 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
630 conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
631 response = json_response(conn, 200)
632 assert length(response) == 1
634 assert Enum.at(response, 0) ==
635 ActivityView.render("activity.json", %{user: user, activity: activity})
638 test "with credentials", %{conn: conn, user: current_user} do
639 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
643 |> with_credentials(current_user.nickname, "test")
644 |> get("/api/statuses/user_timeline.json")
646 response = json_response(conn, 200)
648 assert length(response) == 1
650 assert Enum.at(response, 0) ==
651 ActivityView.render("activity.json", %{
658 test "with credentials with user_id", %{conn: conn, user: current_user} do
660 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
664 |> with_credentials(current_user.nickname, "test")
665 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
667 response = json_response(conn, 200)
669 assert length(response) == 1
671 assert Enum.at(response, 0) ==
672 ActivityView.render("activity.json", %{user: user, activity: activity})
675 test "with credentials screen_name", %{conn: conn, user: current_user} do
677 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
681 |> with_credentials(current_user.nickname, "test")
682 |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
684 response = json_response(conn, 200)
686 assert length(response) == 1
688 assert Enum.at(response, 0) ==
689 ActivityView.render("activity.json", %{user: user, activity: activity})
692 test "with credentials with user_id, excluding RTs", %{conn: conn, user: current_user} do
694 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1, "type" => "Create"}, %{user: user})
695 {:ok, _} = ActivityBuilder.insert(%{"id" => 2, "type" => "Announce"}, %{user: user})
699 |> with_credentials(current_user.nickname, "test")
700 |> get("/api/statuses/user_timeline.json", %{
701 "user_id" => user.id,
702 "include_rts" => "false"
705 response = json_response(conn, 200)
707 assert length(response) == 1
709 assert Enum.at(response, 0) ==
710 ActivityView.render("activity.json", %{user: user, activity: activity})
714 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id, "include_rts" => "0"})
716 response = json_response(conn, 200)
718 assert length(response) == 1
720 assert Enum.at(response, 0) ==
721 ActivityView.render("activity.json", %{user: user, activity: activity})
725 describe "POST /friendships/create.json" do
728 test "without valid credentials", %{conn: conn} do
729 conn = post(conn, "/api/friendships/create.json")
730 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
733 test "with credentials", %{conn: conn, user: current_user} do
734 followed = insert(:user)
738 |> with_credentials(current_user.nickname, "test")
739 |> post("/api/friendships/create.json", %{user_id: followed.id})
741 current_user = User.get_cached_by_id(current_user.id)
742 assert User.ap_followers(followed) in current_user.following
744 assert json_response(conn, 200) ==
745 UserView.render("show.json", %{user: followed, for: current_user})
748 test "for restricted account", %{conn: conn, user: current_user} do
749 followed = insert(:user, info: %User.Info{locked: true})
753 |> with_credentials(current_user.nickname, "test")
754 |> post("/api/friendships/create.json", %{user_id: followed.id})
756 current_user = User.get_cached_by_id(current_user.id)
757 followed = User.get_cached_by_id(followed.id)
759 refute User.ap_followers(followed) in current_user.following
761 assert json_response(conn, 200) ==
762 UserView.render("show.json", %{user: followed, for: current_user})
766 describe "POST /friendships/destroy.json" do
769 test "without valid credentials", %{conn: conn} do
770 conn = post(conn, "/api/friendships/destroy.json")
771 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
774 test "with credentials", %{conn: conn, user: current_user} do
775 followed = insert(:user)
777 {:ok, current_user} = User.follow(current_user, followed)
778 assert User.ap_followers(followed) in current_user.following
779 ActivityPub.follow(current_user, followed)
783 |> with_credentials(current_user.nickname, "test")
784 |> post("/api/friendships/destroy.json", %{user_id: followed.id})
786 current_user = User.get_cached_by_id(current_user.id)
787 assert current_user.following == [current_user.ap_id]
789 assert json_response(conn, 200) ==
790 UserView.render("show.json", %{user: followed, for: current_user})
794 describe "POST /blocks/create.json" do
797 test "without valid credentials", %{conn: conn} do
798 conn = post(conn, "/api/blocks/create.json")
799 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
802 test "with credentials", %{conn: conn, user: current_user} do
803 blocked = insert(:user)
807 |> with_credentials(current_user.nickname, "test")
808 |> post("/api/blocks/create.json", %{user_id: blocked.id})
810 current_user = User.get_cached_by_id(current_user.id)
811 assert User.blocks?(current_user, blocked)
813 assert json_response(conn, 200) ==
814 UserView.render("show.json", %{user: blocked, for: current_user})
818 describe "POST /blocks/destroy.json" do
821 test "without valid credentials", %{conn: conn} do
822 conn = post(conn, "/api/blocks/destroy.json")
823 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
826 test "with credentials", %{conn: conn, user: current_user} do
827 blocked = insert(:user)
829 {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
830 assert User.blocks?(current_user, blocked)
834 |> with_credentials(current_user.nickname, "test")
835 |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
837 current_user = User.get_cached_by_id(current_user.id)
838 assert current_user.info.blocks == []
840 assert json_response(conn, 200) ==
841 UserView.render("show.json", %{user: blocked, for: current_user})
845 describe "GET /help/test.json" do
846 test "returns \"ok\"", %{conn: conn} do
847 conn = get(conn, "/api/help/test.json")
848 assert json_response(conn, 200) == "ok"
852 describe "POST /api/qvitter/update_avatar.json" do
855 test "without valid credentials", %{conn: conn} do
856 conn = post(conn, "/api/qvitter/update_avatar.json")
857 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
860 test "with credentials", %{conn: conn, user: current_user} do
861 avatar_image = File.read!("test/fixtures/avatar_data_uri")
865 |> with_credentials(current_user.nickname, "test")
866 |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
868 current_user = User.get_cached_by_id(current_user.id)
869 assert is_map(current_user.avatar)
871 assert json_response(conn, 200) ==
872 UserView.render("show.json", %{user: current_user, for: current_user})
875 test "user avatar can be reset", %{conn: conn, user: current_user} do
878 |> with_credentials(current_user.nickname, "test")
879 |> post("/api/qvitter/update_avatar.json", %{img: ""})
881 current_user = User.get_cached_by_id(current_user.id)
882 assert current_user.avatar == nil
884 assert json_response(conn, 200) ==
885 UserView.render("show.json", %{user: current_user, for: current_user})
889 describe "GET /api/qvitter/mutes.json" do
892 test "unimplemented mutes without valid credentials", %{conn: conn} do
893 conn = get(conn, "/api/qvitter/mutes.json")
894 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
897 test "unimplemented mutes with credentials", %{conn: conn, user: current_user} do
900 |> with_credentials(current_user.nickname, "test")
901 |> get("/api/qvitter/mutes.json")
902 |> json_response(200)
908 describe "POST /api/favorites/create/:id" do
911 test "without valid credentials", %{conn: conn} do
912 note_activity = insert(:note_activity)
913 conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
914 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
917 test "with credentials", %{conn: conn, user: current_user} do
918 note_activity = insert(:note_activity)
922 |> with_credentials(current_user.nickname, "test")
923 |> post("/api/favorites/create/#{note_activity.id}.json")
925 assert json_response(conn, 200)
928 test "with credentials, invalid param", %{conn: conn, user: current_user} do
931 |> with_credentials(current_user.nickname, "test")
932 |> post("/api/favorites/create/wrong.json")
934 assert json_response(conn, 400)
937 test "with credentials, invalid activity", %{conn: conn, user: current_user} do
940 |> with_credentials(current_user.nickname, "test")
941 |> post("/api/favorites/create/1.json")
943 assert json_response(conn, 400)
947 describe "POST /api/favorites/destroy/:id" do
950 test "without valid credentials", %{conn: conn} do
951 note_activity = insert(:note_activity)
952 conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
953 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
956 test "with credentials", %{conn: conn, user: current_user} do
957 note_activity = insert(:note_activity)
958 object = Object.normalize(note_activity)
959 ActivityPub.like(current_user, object)
963 |> with_credentials(current_user.nickname, "test")
964 |> post("/api/favorites/destroy/#{note_activity.id}.json")
966 assert json_response(conn, 200)
970 describe "POST /api/statuses/retweet/:id" do
973 test "without valid credentials", %{conn: conn} do
974 note_activity = insert(:note_activity)
975 conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
976 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
979 test "with credentials", %{conn: conn, user: current_user} do
980 note_activity = insert(:note_activity)
982 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
986 |> with_credentials(current_user.nickname, "test")
987 |> post(request_path)
989 activity = Activity.get_by_id(note_activity.id)
990 activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
992 assert json_response(response, 200) ==
993 ActivityView.render("activity.json", %{
1001 describe "POST /api/statuses/unretweet/:id" do
1004 test "without valid credentials", %{conn: conn} do
1005 note_activity = insert(:note_activity)
1006 conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
1007 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1010 test "with credentials", %{conn: conn, user: current_user} do
1011 note_activity = insert(:note_activity)
1013 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
1017 |> with_credentials(current_user.nickname, "test")
1018 |> post(request_path)
1020 request_path = String.replace(request_path, "retweet", "unretweet")
1024 |> with_credentials(current_user.nickname, "test")
1025 |> post(request_path)
1027 activity = Activity.get_by_id(note_activity.id)
1028 activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
1030 assert json_response(response, 200) ==
1031 ActivityView.render("activity.json", %{
1032 user: activity_user,
1039 describe "POST /api/account/register" do
1040 test "it creates a new user", %{conn: conn} do
1042 "nickname" => "lain",
1043 "email" => "lain@wired.jp",
1044 "fullname" => "lain iwakura",
1045 "bio" => "close the world.",
1046 "password" => "bear",
1052 |> post("/api/account/register", data)
1054 user = json_response(conn, 200)
1056 fetched_user = User.get_cached_by_nickname("lain")
1057 assert user == UserView.render("show.json", %{user: fetched_user})
1060 test "it returns errors on a problem", %{conn: conn} do
1062 "email" => "lain@wired.jp",
1063 "fullname" => "lain iwakura",
1064 "bio" => "close the world.",
1065 "password" => "bear",
1071 |> post("/api/account/register", data)
1073 errors = json_response(conn, 400)
1075 assert is_binary(errors["error"])
1079 describe "POST /api/account/password_reset, with valid parameters" do
1080 setup %{conn: conn} do
1081 user = insert(:user)
1082 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1083 %{conn: conn, user: user}
1086 test "it returns 204", %{conn: conn} do
1087 assert json_response(conn, :no_content)
1090 test "it creates a PasswordResetToken record for user", %{user: user} do
1091 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1095 test "it sends an email to user", %{user: user} do
1096 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1098 email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
1099 notify_email = Pleroma.Config.get([:instance, :notify_email])
1100 instance_name = Pleroma.Config.get([:instance, :name])
1103 from: {instance_name, notify_email},
1104 to: {user.name, user.email},
1105 html_body: email.html_body
1110 describe "POST /api/account/password_reset, with invalid parameters" do
1113 test "it returns 404 when user is not found", %{conn: conn, user: user} do
1114 conn = post(conn, "/api/account/password_reset?email=nonexisting_#{user.email}")
1115 assert conn.status == 404
1116 assert conn.resp_body == ""
1119 test "it returns 400 when user is not local", %{conn: conn, user: user} do
1120 {:ok, user} = Repo.update(Changeset.change(user, local: false))
1121 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1122 assert conn.status == 400
1123 assert conn.resp_body == ""
1127 describe "GET /api/account/confirm_email/:id/:token" do
1129 user = insert(:user)
1130 info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
1134 |> Changeset.change()
1135 |> Changeset.put_embed(:info, info_change)
1138 assert user.info.confirmation_pending
1143 test "it redirects to root url", %{conn: conn, user: user} do
1144 conn = get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1146 assert 302 == conn.status
1149 test "it confirms the user account", %{conn: conn, user: user} do
1150 get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1152 user = User.get_cached_by_id(user.id)
1154 refute user.info.confirmation_pending
1155 refute user.info.confirmation_token
1158 test "it returns 500 if user cannot be found by id", %{conn: conn, user: user} do
1159 conn = get(conn, "/api/account/confirm_email/0/#{user.info.confirmation_token}")
1161 assert 500 == conn.status
1164 test "it returns 500 if token is invalid", %{conn: conn, user: user} do
1165 conn = get(conn, "/api/account/confirm_email/#{user.id}/wrong_token")
1167 assert 500 == conn.status
1171 describe "POST /api/account/resend_confirmation_email" do
1173 user = insert(:user)
1174 info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
1178 |> Changeset.change()
1179 |> Changeset.put_embed(:info, info_change)
1182 assert user.info.confirmation_pending
1187 clear_config([:instance, :account_activation_required]) do
1188 Pleroma.Config.put([:instance, :account_activation_required], true)
1191 test "it returns 204 No Content", %{conn: conn, user: user} do
1193 |> assign(:user, user)
1194 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1195 |> json_response(:no_content)
1198 test "it sends confirmation email", %{conn: conn, user: user} do
1200 |> assign(:user, user)
1201 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1203 email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
1204 notify_email = Pleroma.Config.get([:instance, :notify_email])
1205 instance_name = Pleroma.Config.get([:instance, :name])
1208 from: {instance_name, notify_email},
1209 to: {user.name, user.email},
1210 html_body: email.html_body
1215 describe "GET /api/externalprofile/show" do
1216 test "it returns the user", %{conn: conn} do
1217 user = insert(:user)
1218 other_user = insert(:user)
1222 |> assign(:user, user)
1223 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
1225 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
1229 describe "GET /api/statuses/followers" do
1230 test "it returns a user's followers", %{conn: conn} do
1231 user = insert(:user)
1232 follower_one = insert(:user)
1233 follower_two = insert(:user)
1234 _not_follower = insert(:user)
1236 {:ok, follower_one} = User.follow(follower_one, user)
1237 {:ok, follower_two} = User.follow(follower_two, user)
1241 |> assign(:user, user)
1242 |> get("/api/statuses/followers")
1244 expected = UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
1245 result = json_response(conn, 200)
1246 assert Enum.sort(expected) == Enum.sort(result)
1249 test "it returns 20 followers per page", %{conn: conn} do
1250 user = insert(:user)
1251 followers = insert_list(21, :user)
1253 Enum.each(followers, fn follower ->
1254 User.follow(follower, user)
1259 |> assign(:user, user)
1260 |> get("/api/statuses/followers")
1262 result = json_response(res_conn, 200)
1263 assert length(result) == 20
1267 |> assign(:user, user)
1268 |> get("/api/statuses/followers?page=2")
1270 result = json_response(res_conn, 200)
1271 assert length(result) == 1
1274 test "it returns a given user's followers with user_id", %{conn: conn} do
1275 user = insert(:user)
1276 follower_one = insert(:user)
1277 follower_two = insert(:user)
1278 not_follower = insert(:user)
1280 {:ok, follower_one} = User.follow(follower_one, user)
1281 {:ok, follower_two} = User.follow(follower_two, user)
1285 |> assign(:user, not_follower)
1286 |> get("/api/statuses/followers", %{"user_id" => user.id})
1288 assert MapSet.equal?(
1289 MapSet.new(json_response(conn, 200)),
1291 UserView.render("index.json", %{
1292 users: [follower_one, follower_two],
1299 test "it returns empty when hide_followers is set to true", %{conn: conn} do
1300 user = insert(:user, %{info: %{hide_followers: true}})
1301 follower_one = insert(:user)
1302 follower_two = insert(:user)
1303 not_follower = insert(:user)
1305 {:ok, _follower_one} = User.follow(follower_one, user)
1306 {:ok, _follower_two} = User.follow(follower_two, user)
1310 |> assign(:user, not_follower)
1311 |> get("/api/statuses/followers", %{"user_id" => user.id})
1312 |> json_response(200)
1314 assert [] == response
1317 test "it returns the followers when hide_followers is set to true if requested by the user themselves",
1321 user = insert(:user, %{info: %{hide_followers: true}})
1322 follower_one = insert(:user)
1323 follower_two = insert(:user)
1324 _not_follower = insert(:user)
1326 {:ok, _follower_one} = User.follow(follower_one, user)
1327 {:ok, _follower_two} = User.follow(follower_two, user)
1331 |> assign(:user, user)
1332 |> get("/api/statuses/followers", %{"user_id" => user.id})
1334 refute [] == json_response(conn, 200)
1338 describe "GET /api/statuses/blocks" do
1339 test "it returns the list of users blocked by requester", %{conn: conn} do
1340 user = insert(:user)
1341 other_user = insert(:user)
1343 {:ok, user} = User.block(user, other_user)
1347 |> assign(:user, user)
1348 |> get("/api/statuses/blocks")
1350 expected = UserView.render("index.json", %{users: [other_user], for: user})
1351 result = json_response(conn, 200)
1352 assert Enum.sort(expected) == Enum.sort(result)
1356 describe "GET /api/statuses/friends" do
1357 test "it returns the logged in user's friends", %{conn: conn} do
1358 user = insert(:user)
1359 followed_one = insert(:user)
1360 followed_two = insert(:user)
1361 _not_followed = insert(:user)
1363 {:ok, user} = User.follow(user, followed_one)
1364 {:ok, user} = User.follow(user, followed_two)
1368 |> assign(:user, user)
1369 |> get("/api/statuses/friends")
1371 expected = UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1372 result = json_response(conn, 200)
1373 assert Enum.sort(expected) == Enum.sort(result)
1376 test "it returns 20 friends per page, except if 'export' is set to true", %{conn: conn} do
1377 user = insert(:user)
1378 followeds = insert_list(21, :user)
1381 Enum.reduce(followeds, {:ok, user}, fn followed, {:ok, user} ->
1382 User.follow(user, followed)
1387 |> assign(:user, user)
1388 |> get("/api/statuses/friends")
1390 result = json_response(res_conn, 200)
1391 assert length(result) == 20
1395 |> assign(:user, user)
1396 |> get("/api/statuses/friends", %{page: 2})
1398 result = json_response(res_conn, 200)
1399 assert length(result) == 1
1403 |> assign(:user, user)
1404 |> get("/api/statuses/friends", %{all: true})
1406 result = json_response(res_conn, 200)
1407 assert length(result) == 21
1410 test "it returns a given user's friends with user_id", %{conn: conn} do
1411 user = insert(:user)
1412 followed_one = insert(:user)
1413 followed_two = insert(:user)
1414 _not_followed = insert(:user)
1416 {:ok, user} = User.follow(user, followed_one)
1417 {:ok, user} = User.follow(user, followed_two)
1421 |> assign(:user, user)
1422 |> get("/api/statuses/friends", %{"user_id" => user.id})
1424 assert MapSet.equal?(
1425 MapSet.new(json_response(conn, 200)),
1427 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1432 test "it returns empty when hide_follows is set to true", %{conn: conn} do
1433 user = insert(:user, %{info: %{hide_follows: true}})
1434 followed_one = insert(:user)
1435 followed_two = insert(:user)
1436 not_followed = insert(:user)
1438 {:ok, user} = User.follow(user, followed_one)
1439 {:ok, user} = User.follow(user, followed_two)
1443 |> assign(:user, not_followed)
1444 |> get("/api/statuses/friends", %{"user_id" => user.id})
1446 assert [] == json_response(conn, 200)
1449 test "it returns friends when hide_follows is set to true if the user themselves request it",
1453 user = insert(:user, %{info: %{hide_follows: true}})
1454 followed_one = insert(:user)
1455 followed_two = insert(:user)
1456 _not_followed = insert(:user)
1458 {:ok, _user} = User.follow(user, followed_one)
1459 {:ok, _user} = User.follow(user, followed_two)
1463 |> assign(:user, user)
1464 |> get("/api/statuses/friends", %{"user_id" => user.id})
1465 |> json_response(200)
1467 refute [] == response
1470 test "it returns a given user's friends with screen_name", %{conn: conn} do
1471 user = insert(:user)
1472 followed_one = insert(:user)
1473 followed_two = insert(:user)
1474 _not_followed = insert(:user)
1476 {:ok, user} = User.follow(user, followed_one)
1477 {:ok, user} = User.follow(user, followed_two)
1481 |> assign(:user, user)
1482 |> get("/api/statuses/friends", %{"screen_name" => user.nickname})
1484 assert MapSet.equal?(
1485 MapSet.new(json_response(conn, 200)),
1487 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1493 describe "GET /friends/ids" do
1494 test "it returns a user's friends", %{conn: conn} do
1495 user = insert(:user)
1496 followed_one = insert(:user)
1497 followed_two = insert(:user)
1498 _not_followed = insert(:user)
1500 {:ok, user} = User.follow(user, followed_one)
1501 {:ok, user} = User.follow(user, followed_two)
1505 |> assign(:user, user)
1506 |> get("/api/friends/ids")
1508 expected = [followed_one.id, followed_two.id]
1510 assert MapSet.equal?(
1511 MapSet.new(Poison.decode!(json_response(conn, 200))),
1512 MapSet.new(expected)
1517 describe "POST /api/account/update_profile.json" do
1518 test "it updates a user's profile", %{conn: conn} do
1519 user = insert(:user)
1520 user2 = insert(:user)
1524 |> assign(:user, user)
1525 |> post("/api/account/update_profile.json", %{
1526 "name" => "new name",
1527 "description" => "hi @#{user2.nickname}"
1530 user = Repo.get!(User, user.id)
1531 assert user.name == "new name"
1534 "hi <span class='h-card'><a data-user='#{user2.id}' class='u-url mention' href='#{
1536 }'>@<span>#{user2.nickname}</span></a></span>"
1538 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1541 test "it sets and un-sets hide_follows", %{conn: conn} do
1542 user = insert(:user)
1545 |> assign(:user, user)
1546 |> post("/api/account/update_profile.json", %{
1547 "hide_follows" => "true"
1550 user = Repo.get!(User, user.id)
1551 assert user.info.hide_follows == true
1555 |> assign(:user, user)
1556 |> post("/api/account/update_profile.json", %{
1557 "hide_follows" => "false"
1560 user = refresh_record(user)
1561 assert user.info.hide_follows == false
1562 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1565 test "it sets and un-sets hide_followers", %{conn: conn} do
1566 user = insert(:user)
1569 |> assign(:user, user)
1570 |> post("/api/account/update_profile.json", %{
1571 "hide_followers" => "true"
1574 user = Repo.get!(User, user.id)
1575 assert user.info.hide_followers == true
1579 |> assign(:user, user)
1580 |> post("/api/account/update_profile.json", %{
1581 "hide_followers" => "false"
1584 user = Repo.get!(User, user.id)
1585 assert user.info.hide_followers == false
1586 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1589 test "it sets and un-sets show_role", %{conn: conn} do
1590 user = insert(:user)
1593 |> assign(:user, user)
1594 |> post("/api/account/update_profile.json", %{
1595 "show_role" => "true"
1598 user = Repo.get!(User, user.id)
1599 assert user.info.show_role == true
1603 |> assign(:user, user)
1604 |> post("/api/account/update_profile.json", %{
1605 "show_role" => "false"
1608 user = Repo.get!(User, user.id)
1609 assert user.info.show_role == false
1610 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1613 test "it sets and un-sets skip_thread_containment", %{conn: conn} do
1614 user = insert(:user)
1618 |> assign(:user, user)
1619 |> post("/api/account/update_profile.json", %{"skip_thread_containment" => "true"})
1620 |> json_response(200)
1622 assert response["pleroma"]["skip_thread_containment"] == true
1623 user = refresh_record(user)
1624 assert user.info.skip_thread_containment
1628 |> assign(:user, user)
1629 |> post("/api/account/update_profile.json", %{"skip_thread_containment" => "false"})
1630 |> json_response(200)
1632 assert response["pleroma"]["skip_thread_containment"] == false
1633 refute refresh_record(user).info.skip_thread_containment
1636 test "it locks an account", %{conn: conn} do
1637 user = insert(:user)
1641 |> assign(:user, user)
1642 |> post("/api/account/update_profile.json", %{
1646 user = Repo.get!(User, user.id)
1647 assert user.info.locked == true
1649 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1652 test "it unlocks an account", %{conn: conn} do
1653 user = insert(:user)
1657 |> assign(:user, user)
1658 |> post("/api/account/update_profile.json", %{
1662 user = Repo.get!(User, user.id)
1663 assert user.info.locked == false
1665 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1668 # Broken before the change to class="emoji" and non-<img/> in the DB
1670 test "it formats emojos", %{conn: conn} do
1671 user = insert(:user)
1675 |> assign(:user, user)
1676 |> post("/api/account/update_profile.json", %{
1677 "bio" => "I love our :moominmamma:"
1680 assert response = json_response(conn, 200)
1683 "description" => "I love our :moominmamma:",
1684 "description_html" =>
1685 ~s{I love our <img class="emoji" alt="moominmamma" title="moominmamma" src="} <>
1691 |> get("/api/users/show.json?user_id=#{user.nickname}")
1693 assert response == json_response(conn, 200)
1697 defp valid_user(_context) do
1698 user = insert(:user)
1702 defp with_credentials(conn, username, password) do
1703 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
1704 put_req_header(conn, "authorization", header_content)
1707 describe "GET /api/search.json" do
1708 test "it returns search results", %{conn: conn} do
1709 user = insert(:user)
1710 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1712 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1713 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1717 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
1719 assert [status] = json_response(conn, 200)
1720 assert status["id"] == activity.id
1724 describe "GET /api/statusnet/tags/timeline/:tag.json" do
1725 test "it returns the tags timeline", %{conn: conn} do
1726 user = insert(:user)
1727 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1729 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
1730 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1734 |> get("/api/statusnet/tags/timeline/2hu.json")
1736 assert [status] = json_response(conn, 200)
1737 assert status["id"] == activity.id
1741 test "Convert newlines to <br> in bio", %{conn: conn} do
1742 user = insert(:user)
1746 |> assign(:user, user)
1747 |> post("/api/account/update_profile.json", %{
1748 "description" => "Hello,\r\nWorld! I\n am a test."
1751 user = Repo.get!(User, user.id)
1752 assert user.bio == "Hello,<br>World! I<br> am a test."
1755 describe "POST /api/pleroma/change_password" do
1758 test "without credentials", %{conn: conn} do
1759 conn = post(conn, "/api/pleroma/change_password")
1760 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1763 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1766 |> with_credentials(current_user.nickname, "test")
1767 |> post("/api/pleroma/change_password", %{
1769 "new_password" => "newpass",
1770 "new_password_confirmation" => "newpass"
1773 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1776 test "with credentials, valid password and new password and confirmation not matching", %{
1782 |> with_credentials(current_user.nickname, "test")
1783 |> post("/api/pleroma/change_password", %{
1784 "password" => "test",
1785 "new_password" => "newpass",
1786 "new_password_confirmation" => "notnewpass"
1789 assert json_response(conn, 200) == %{
1790 "error" => "New password does not match confirmation."
1794 test "with credentials, valid password and invalid new password", %{
1800 |> with_credentials(current_user.nickname, "test")
1801 |> post("/api/pleroma/change_password", %{
1802 "password" => "test",
1803 "new_password" => "",
1804 "new_password_confirmation" => ""
1807 assert json_response(conn, 200) == %{
1808 "error" => "New password can't be blank."
1812 test "with credentials, valid password and matching new password and confirmation", %{
1818 |> with_credentials(current_user.nickname, "test")
1819 |> post("/api/pleroma/change_password", %{
1820 "password" => "test",
1821 "new_password" => "newpass",
1822 "new_password_confirmation" => "newpass"
1825 assert json_response(conn, 200) == %{"status" => "success"}
1826 fetched_user = User.get_cached_by_id(current_user.id)
1827 assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
1831 describe "POST /api/pleroma/delete_account" do
1834 test "without credentials", %{conn: conn} do
1835 conn = post(conn, "/api/pleroma/delete_account")
1836 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1839 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1842 |> with_credentials(current_user.nickname, "test")
1843 |> post("/api/pleroma/delete_account", %{"password" => "hi"})
1845 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1848 test "with credentials and valid password", %{conn: conn, user: current_user} do
1851 |> with_credentials(current_user.nickname, "test")
1852 |> post("/api/pleroma/delete_account", %{"password" => "test"})
1854 assert json_response(conn, 200) == %{"status" => "success"}
1855 # Wait a second for the started task to end
1860 describe "GET /api/pleroma/friend_requests" do
1861 test "it lists friend requests" do
1862 user = insert(:user)
1863 other_user = insert(:user)
1865 {:ok, _activity} = ActivityPub.follow(other_user, user)
1867 user = User.get_cached_by_id(user.id)
1868 other_user = User.get_cached_by_id(other_user.id)
1870 assert User.following?(other_user, user) == false
1874 |> assign(:user, user)
1875 |> get("/api/pleroma/friend_requests")
1877 assert [relationship] = json_response(conn, 200)
1878 assert other_user.id == relationship["id"]
1881 test "requires 'read' permission", %{conn: conn} do
1882 token1 = insert(:oauth_token, scopes: ["write"])
1883 token2 = insert(:oauth_token, scopes: ["read"])
1885 for token <- [token1, token2] do
1888 |> put_req_header("authorization", "Bearer #{token.token}")
1889 |> get("/api/pleroma/friend_requests")
1891 if token == token1 do
1892 assert %{"error" => "Insufficient permissions: read."} == json_response(conn, 403)
1894 assert json_response(conn, 200)
1900 describe "POST /api/pleroma/friendships/approve" do
1901 test "it approves a friend request" do
1902 user = insert(:user)
1903 other_user = insert(:user)
1905 {:ok, _activity} = ActivityPub.follow(other_user, user)
1907 user = User.get_cached_by_id(user.id)
1908 other_user = User.get_cached_by_id(other_user.id)
1910 assert User.following?(other_user, user) == false
1914 |> assign(:user, user)
1915 |> post("/api/pleroma/friendships/approve", %{"user_id" => other_user.id})
1917 assert relationship = json_response(conn, 200)
1918 assert other_user.id == relationship["id"]
1919 assert relationship["follows_you"] == true
1923 describe "POST /api/pleroma/friendships/deny" do
1924 test "it denies a friend request" do
1925 user = insert(:user)
1926 other_user = insert(:user)
1928 {:ok, _activity} = ActivityPub.follow(other_user, user)
1930 user = User.get_cached_by_id(user.id)
1931 other_user = User.get_cached_by_id(other_user.id)
1933 assert User.following?(other_user, user) == false
1937 |> assign(:user, user)
1938 |> post("/api/pleroma/friendships/deny", %{"user_id" => other_user.id})
1940 assert relationship = json_response(conn, 200)
1941 assert other_user.id == relationship["id"]
1942 assert relationship["follows_you"] == false
1946 describe "GET /api/pleroma/search_user" do
1947 test "it returns users, ordered by similarity", %{conn: conn} do
1948 user = insert(:user, %{name: "eal"})
1949 user_two = insert(:user, %{name: "eal me"})
1950 _user_three = insert(:user, %{name: "zzz"})
1954 |> get(twitter_api_search__path(conn, :search_user), query: "eal me")
1955 |> json_response(200)
1957 assert length(resp) == 2
1958 assert [user_two.id, user.id] == Enum.map(resp, fn %{"id" => id} -> id end)
1962 describe "POST /api/media/upload" do
1964 Pleroma.DataCase.ensure_local_uploader(context)
1967 test "it performs the upload and sets `data[actor]` with AP id of uploader user", %{
1970 user = insert(:user)
1972 upload_filename = "test/fixtures/image_tmp.jpg"
1973 File.cp!("test/fixtures/image.jpg", upload_filename)
1975 file = %Plug.Upload{
1976 content_type: "image/jpg",
1977 path: Path.absname(upload_filename),
1978 filename: "image.jpg"
1983 |> assign(:user, user)
1984 |> put_req_header("content-type", "application/octet-stream")
1985 |> post("/api/media/upload", %{
1988 |> json_response(:ok)
1990 assert response["media_id"]
1991 object = Repo.get(Object, response["media_id"])
1993 assert object.data["actor"] == User.ap_id(user)
1997 describe "POST /api/media/metadata/create" do
1999 object = insert(:note)
2000 user = User.get_cached_by_ap_id(object.data["actor"])
2001 %{object: object, user: user}
2004 test "it returns :forbidden status on attempt to modify someone else's upload", %{
2008 initial_description = object.data["name"]
2009 another_user = insert(:user)
2012 |> assign(:user, another_user)
2013 |> post("/api/media/metadata/create", %{"media_id" => object.id})
2014 |> json_response(:forbidden)
2016 object = Repo.get(Object, object.id)
2017 assert object.data["name"] == initial_description
2020 test "it updates `data[name]` of referenced Object with provided value", %{
2025 description = "Informative description of the image. Initial value: #{object.data["name"]}}"
2028 |> assign(:user, user)
2029 |> post("/api/media/metadata/create", %{
2030 "media_id" => object.id,
2031 "alt_text" => %{"text" => description}
2033 |> json_response(:no_content)
2035 object = Repo.get(Object, object.id)
2036 assert object.data["name"] == description
2040 describe "POST /api/statuses/user_timeline.json?user_id=:user_id&pinned=true" do
2041 test "it returns a list of pinned statuses", %{conn: conn} do
2042 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2044 user = insert(:user, %{name: "egor"})
2045 {:ok, %{id: activity_id}} = CommonAPI.post(user, %{"status" => "HI!!!"})
2046 {:ok, _} = CommonAPI.pin(activity_id, user)
2050 |> get("/api/statuses/user_timeline.json", %{user_id: user.id, pinned: true})
2051 |> json_response(200)
2053 assert length(resp) == 1
2054 assert [%{"id" => ^activity_id, "pinned" => true}] = resp
2058 describe "POST /api/statuses/pin/:id" do
2060 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2061 [user: insert(:user)]
2064 test "without valid credentials", %{conn: conn} do
2065 note_activity = insert(:note_activity)
2066 conn = post(conn, "/api/statuses/pin/#{note_activity.id}.json")
2067 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2070 test "with credentials", %{conn: conn, user: user} do
2071 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2073 request_path = "/api/statuses/pin/#{activity.id}.json"
2077 |> with_credentials(user.nickname, "test")
2078 |> post(request_path)
2080 user = refresh_record(user)
2082 assert json_response(response, 200) ==
2083 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2087 describe "POST /api/statuses/unpin/:id" do
2089 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2090 [user: insert(:user)]
2093 test "without valid credentials", %{conn: conn} do
2094 note_activity = insert(:note_activity)
2095 conn = post(conn, "/api/statuses/unpin/#{note_activity.id}.json")
2096 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2099 test "with credentials", %{conn: conn, user: user} do
2100 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2101 {:ok, activity} = CommonAPI.pin(activity.id, user)
2103 request_path = "/api/statuses/unpin/#{activity.id}.json"
2107 |> with_credentials(user.nickname, "test")
2108 |> post(request_path)
2110 user = refresh_record(user)
2112 assert json_response(response, 200) ==
2113 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2117 describe "GET /api/oauth_tokens" do
2119 token = insert(:oauth_token) |> Repo.preload(:user)
2124 test "renders list", %{token: token} do
2127 |> assign(:user, token.user)
2128 |> get("/api/oauth_tokens")
2131 json_response(response, 200)
2135 assert keys -- ["id", "app_name", "valid_until"] == []
2138 test "revoke token", %{token: token} do
2141 |> assign(:user, token.user)
2142 |> delete("/api/oauth_tokens/#{token.id}")
2144 tokens = Token.get_user_tokens(token.user)
2147 assert response.status == 201