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"
45 describe "POST /api/qvitter/update_background_image" do
46 test "it updates the background", %{conn: conn} do
50 |> assign(:user, user)
51 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => @banner})
54 user = refresh_record(user)
55 assert user.info.background["type"] == "Image"
59 describe "POST /api/account/verify_credentials" do
62 test "without valid credentials", %{conn: conn} do
63 conn = post(conn, "/api/account/verify_credentials.json")
64 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
67 test "with credentials", %{conn: conn, user: user} do
70 |> with_credentials(user.nickname, "test")
71 |> post("/api/account/verify_credentials.json")
75 UserView.render("show.json", %{user: user, token: response["token"], for: user})
79 describe "POST /statuses/update.json" do
82 test "without valid credentials", %{conn: conn} do
83 conn = post(conn, "/api/statuses/update.json")
84 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
87 test "with credentials", %{conn: conn, user: user} do
88 conn_with_creds = conn |> with_credentials(user.nickname, "test")
89 request_path = "/api/statuses/update.json"
92 "request" => request_path,
93 "error" => "Client must provide a 'status' parameter with a value."
100 assert json_response(conn, 400) == error_response
104 |> post(request_path, %{status: ""})
106 assert json_response(conn, 400) == error_response
110 |> post(request_path, %{status: " "})
112 assert json_response(conn, 400) == error_response
114 # we post with visibility private in order to avoid triggering relay
117 |> post(request_path, %{status: "Nice meme.", visibility: "private"})
119 assert json_response(conn, 200) ==
120 ActivityView.render("activity.json", %{
121 activity: Repo.one(Activity),
128 describe "GET /statuses/public_timeline.json" do
131 test "returns statuses", %{conn: conn} do
133 activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
134 ActivityBuilder.insert_list(10, %{}, %{user: user})
135 since_id = List.last(activities).id
139 |> get("/api/statuses/public_timeline.json", %{since_id: since_id})
141 response = json_response(conn, 200)
143 assert length(response) == 10
146 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
147 Pleroma.Config.put([:instance, :public], false)
150 |> get("/api/statuses/public_timeline.json")
151 |> json_response(403)
153 Pleroma.Config.put([:instance, :public], true)
156 test "returns 200 to authenticated request when the instance is not public",
157 %{conn: conn, user: user} do
158 Pleroma.Config.put([:instance, :public], false)
161 |> with_credentials(user.nickname, "test")
162 |> get("/api/statuses/public_timeline.json")
163 |> json_response(200)
165 Pleroma.Config.put([:instance, :public], true)
168 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
170 |> get("/api/statuses/public_timeline.json")
171 |> json_response(200)
174 test "returns 200 to authenticated request when the instance is public",
175 %{conn: conn, user: user} do
177 |> with_credentials(user.nickname, "test")
178 |> get("/api/statuses/public_timeline.json")
179 |> json_response(200)
182 test_with_mock "treats user as unauthenticated if `assigns[:token]` is present but lacks `read` permission",
186 token = insert(:oauth_token, scopes: ["write"])
189 |> put_req_header("authorization", "Bearer #{token.token}")
190 |> get("/api/statuses/public_timeline.json")
191 |> json_response(200)
193 assert called(Controller.public_timeline(%{assigns: %{user: nil}}, :_))
197 describe "GET /statuses/public_and_external_timeline.json" do
200 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
201 Pleroma.Config.put([:instance, :public], false)
204 |> get("/api/statuses/public_and_external_timeline.json")
205 |> json_response(403)
207 Pleroma.Config.put([:instance, :public], true)
210 test "returns 200 to authenticated request when the instance is not public",
211 %{conn: conn, user: user} do
212 Pleroma.Config.put([:instance, :public], false)
215 |> with_credentials(user.nickname, "test")
216 |> get("/api/statuses/public_and_external_timeline.json")
217 |> json_response(200)
219 Pleroma.Config.put([:instance, :public], true)
222 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
224 |> get("/api/statuses/public_and_external_timeline.json")
225 |> json_response(200)
228 test "returns 200 to authenticated request when the instance is public",
229 %{conn: conn, user: user} do
231 |> with_credentials(user.nickname, "test")
232 |> get("/api/statuses/public_and_external_timeline.json")
233 |> json_response(200)
237 describe "GET /statuses/show/:id.json" do
238 test "returns one status", %{conn: conn} do
240 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
241 actor = User.get_cached_by_ap_id(activity.data["actor"])
245 |> get("/api/statuses/show/#{activity.id}.json")
247 response = json_response(conn, 200)
249 assert response == ActivityView.render("activity.json", %{activity: activity, user: actor})
253 describe "GET /users/show.json" do
254 test "gets user with screen_name", %{conn: conn} do
259 |> get("/api/users/show.json", %{"screen_name" => user.nickname})
261 response = json_response(conn, 200)
263 assert response["id"] == user.id
266 test "gets user with user_id", %{conn: conn} do
271 |> get("/api/users/show.json", %{"user_id" => user.id})
273 response = json_response(conn, 200)
275 assert response["id"] == user.id
278 test "gets a user for a logged in user", %{conn: conn} do
280 logged_in = insert(:user)
282 {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})
286 |> with_credentials(logged_in.nickname, "test")
287 |> get("/api/users/show.json", %{"user_id" => user.id})
289 response = json_response(conn, 200)
291 assert response["following"] == true
295 describe "GET /statusnet/conversation/:id.json" do
296 test "returns the statuses in the conversation", %{conn: conn} do
297 {:ok, _user} = UserBuilder.insert()
298 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
299 {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
300 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
304 |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
306 response = json_response(conn, 200)
308 assert length(response) == 2
312 describe "GET /statuses/friends_timeline.json" do
315 test "without valid credentials", %{conn: conn} do
316 conn = get(conn, "/api/statuses/friends_timeline.json")
317 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
320 test "with credentials", %{conn: conn, user: current_user} do
324 ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
326 returned_activities =
327 ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
329 other_user = insert(:user)
330 ActivityBuilder.insert_list(10, %{}, %{user: other_user})
331 since_id = List.last(activities).id
334 Changeset.change(current_user, following: [User.ap_followers(user)])
339 |> with_credentials(current_user.nickname, "test")
340 |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
342 response = json_response(conn, 200)
344 assert length(response) == 10
347 Enum.map(returned_activities, fn activity ->
348 ActivityView.render("activity.json", %{
350 user: User.get_cached_by_ap_id(activity.data["actor"]),
357 describe "GET /statuses/dm_timeline.json" do
358 test "it show direct messages", %{conn: conn} do
359 user_one = insert(:user)
360 user_two = insert(:user)
362 {:ok, user_two} = User.follow(user_two, user_one)
365 CommonAPI.post(user_one, %{
366 "status" => "Hi @#{user_two.nickname}!",
367 "visibility" => "direct"
371 CommonAPI.post(user_two, %{
372 "status" => "Hi @#{user_one.nickname}!",
373 "visibility" => "direct"
376 {:ok, _follower_only} =
377 CommonAPI.post(user_one, %{
378 "status" => "Hi @#{user_two.nickname}!",
379 "visibility" => "private"
382 # Only direct should be visible here
385 |> assign(:user, user_two)
386 |> get("/api/statuses/dm_timeline.json")
388 [status, status_two] = json_response(res_conn, 200)
389 assert status["id"] == direct_two.id
390 assert status_two["id"] == direct.id
393 test "doesn't include DMs from blocked users", %{conn: conn} do
394 blocker = insert(:user)
395 blocked = insert(:user)
397 {:ok, blocker} = User.block(blocker, blocked)
399 {:ok, _blocked_direct} =
400 CommonAPI.post(blocked, %{
401 "status" => "Hi @#{blocker.nickname}!",
402 "visibility" => "direct"
406 CommonAPI.post(user, %{
407 "status" => "Hi @#{blocker.nickname}!",
408 "visibility" => "direct"
413 |> assign(:user, blocker)
414 |> get("/api/statuses/dm_timeline.json")
416 [status] = json_response(res_conn, 200)
417 assert status["id"] == direct.id
421 describe "GET /statuses/mentions.json" do
424 test "without valid credentials", %{conn: conn} do
425 conn = get(conn, "/api/statuses/mentions.json")
426 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
429 test "with credentials", %{conn: conn, user: current_user} do
431 CommonAPI.post(current_user, %{
432 "status" => "why is tenshi eating a corndog so cute?",
433 "visibility" => "public"
438 |> with_credentials(current_user.nickname, "test")
439 |> get("/api/statuses/mentions.json")
441 response = json_response(conn, 200)
443 assert length(response) == 1
445 assert Enum.at(response, 0) ==
446 ActivityView.render("activity.json", %{
453 test "does not show DMs in mentions timeline", %{conn: conn, user: current_user} do
455 CommonAPI.post(current_user, %{
456 "status" => "Have you guys ever seen how cute tenshi eating a corndog is?",
457 "visibility" => "direct"
462 |> with_credentials(current_user.nickname, "test")
463 |> get("/api/statuses/mentions.json")
465 response = json_response(conn, 200)
467 assert Enum.empty?(response)
471 describe "GET /api/qvitter/statuses/notifications.json" do
474 test "without valid credentials", %{conn: conn} do
475 conn = get(conn, "/api/qvitter/statuses/notifications.json")
476 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
479 test "with credentials", %{conn: conn, user: current_user} do
480 other_user = insert(:user)
483 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
487 |> with_credentials(current_user.nickname, "test")
488 |> get("/api/qvitter/statuses/notifications.json")
490 response = json_response(conn, 200)
492 assert length(response) == 1
495 NotificationView.render("notification.json", %{
496 notifications: Notification.for_user(current_user),
502 describe "POST /api/qvitter/statuses/notifications/read" do
505 test "without valid credentials", %{conn: conn} do
506 conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567})
507 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
510 test "with credentials, without any params", %{conn: conn, user: current_user} do
513 |> with_credentials(current_user.nickname, "test")
514 |> post("/api/qvitter/statuses/notifications/read")
516 assert json_response(conn, 400) == %{
517 "error" => "You need to specify latest_id",
518 "request" => "/api/qvitter/statuses/notifications/read"
522 test "with credentials, with params", %{conn: conn, user: current_user} do
523 other_user = insert(:user)
526 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
530 |> with_credentials(current_user.nickname, "test")
531 |> get("/api/qvitter/statuses/notifications.json")
533 [notification] = response = json_response(response_conn, 200)
535 assert length(response) == 1
537 assert notification["is_seen"] == 0
541 |> with_credentials(current_user.nickname, "test")
542 |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]})
544 [notification] = response = json_response(response_conn, 200)
546 assert length(response) == 1
548 assert notification["is_seen"] == 1
552 describe "GET /statuses/user_timeline.json" do
555 test "without any params", %{conn: conn} do
556 conn = get(conn, "/api/statuses/user_timeline.json")
558 assert json_response(conn, 400) == %{
559 "error" => "You need to specify screen_name or user_id",
560 "request" => "/api/statuses/user_timeline.json"
564 test "with user_id", %{conn: conn} do
566 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
568 conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
569 response = json_response(conn, 200)
570 assert length(response) == 1
572 assert Enum.at(response, 0) ==
573 ActivityView.render("activity.json", %{user: user, activity: activity})
576 test "with screen_name", %{conn: conn} do
578 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
580 conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
581 response = json_response(conn, 200)
582 assert length(response) == 1
584 assert Enum.at(response, 0) ==
585 ActivityView.render("activity.json", %{user: user, activity: activity})
588 test "with credentials", %{conn: conn, user: current_user} do
589 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
593 |> with_credentials(current_user.nickname, "test")
594 |> get("/api/statuses/user_timeline.json")
596 response = json_response(conn, 200)
598 assert length(response) == 1
600 assert Enum.at(response, 0) ==
601 ActivityView.render("activity.json", %{
608 test "with credentials with user_id", %{conn: conn, user: current_user} do
610 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
614 |> with_credentials(current_user.nickname, "test")
615 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
617 response = json_response(conn, 200)
619 assert length(response) == 1
621 assert Enum.at(response, 0) ==
622 ActivityView.render("activity.json", %{user: user, activity: activity})
625 test "with credentials screen_name", %{conn: conn, user: current_user} do
627 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
631 |> with_credentials(current_user.nickname, "test")
632 |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
634 response = json_response(conn, 200)
636 assert length(response) == 1
638 assert Enum.at(response, 0) ==
639 ActivityView.render("activity.json", %{user: user, activity: activity})
642 test "with credentials with user_id, excluding RTs", %{conn: conn, user: current_user} do
644 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1, "type" => "Create"}, %{user: user})
645 {:ok, _} = ActivityBuilder.insert(%{"id" => 2, "type" => "Announce"}, %{user: user})
649 |> with_credentials(current_user.nickname, "test")
650 |> get("/api/statuses/user_timeline.json", %{
651 "user_id" => user.id,
652 "include_rts" => "false"
655 response = json_response(conn, 200)
657 assert length(response) == 1
659 assert Enum.at(response, 0) ==
660 ActivityView.render("activity.json", %{user: user, activity: activity})
664 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id, "include_rts" => "0"})
666 response = json_response(conn, 200)
668 assert length(response) == 1
670 assert Enum.at(response, 0) ==
671 ActivityView.render("activity.json", %{user: user, activity: activity})
675 describe "POST /friendships/create.json" do
678 test "without valid credentials", %{conn: conn} do
679 conn = post(conn, "/api/friendships/create.json")
680 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
683 test "with credentials", %{conn: conn, user: current_user} do
684 followed = insert(:user)
688 |> with_credentials(current_user.nickname, "test")
689 |> post("/api/friendships/create.json", %{user_id: followed.id})
691 current_user = User.get_cached_by_id(current_user.id)
692 assert User.ap_followers(followed) in current_user.following
694 assert json_response(conn, 200) ==
695 UserView.render("show.json", %{user: followed, for: current_user})
698 test "for restricted account", %{conn: conn, user: current_user} do
699 followed = insert(:user, info: %User.Info{locked: true})
703 |> with_credentials(current_user.nickname, "test")
704 |> post("/api/friendships/create.json", %{user_id: followed.id})
706 current_user = User.get_cached_by_id(current_user.id)
707 followed = User.get_cached_by_id(followed.id)
709 refute User.ap_followers(followed) in current_user.following
711 assert json_response(conn, 200) ==
712 UserView.render("show.json", %{user: followed, for: current_user})
716 describe "POST /friendships/destroy.json" do
719 test "without valid credentials", %{conn: conn} do
720 conn = post(conn, "/api/friendships/destroy.json")
721 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
724 test "with credentials", %{conn: conn, user: current_user} do
725 followed = insert(:user)
727 {:ok, current_user} = User.follow(current_user, followed)
728 assert User.ap_followers(followed) in current_user.following
729 ActivityPub.follow(current_user, followed)
733 |> with_credentials(current_user.nickname, "test")
734 |> post("/api/friendships/destroy.json", %{user_id: followed.id})
736 current_user = User.get_cached_by_id(current_user.id)
737 assert current_user.following == [current_user.ap_id]
739 assert json_response(conn, 200) ==
740 UserView.render("show.json", %{user: followed, for: current_user})
744 describe "POST /blocks/create.json" do
747 test "without valid credentials", %{conn: conn} do
748 conn = post(conn, "/api/blocks/create.json")
749 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
752 test "with credentials", %{conn: conn, user: current_user} do
753 blocked = insert(:user)
757 |> with_credentials(current_user.nickname, "test")
758 |> post("/api/blocks/create.json", %{user_id: blocked.id})
760 current_user = User.get_cached_by_id(current_user.id)
761 assert User.blocks?(current_user, blocked)
763 assert json_response(conn, 200) ==
764 UserView.render("show.json", %{user: blocked, for: current_user})
768 describe "POST /blocks/destroy.json" do
771 test "without valid credentials", %{conn: conn} do
772 conn = post(conn, "/api/blocks/destroy.json")
773 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
776 test "with credentials", %{conn: conn, user: current_user} do
777 blocked = insert(:user)
779 {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
780 assert User.blocks?(current_user, blocked)
784 |> with_credentials(current_user.nickname, "test")
785 |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
787 current_user = User.get_cached_by_id(current_user.id)
788 assert current_user.info.blocks == []
790 assert json_response(conn, 200) ==
791 UserView.render("show.json", %{user: blocked, for: current_user})
795 describe "GET /help/test.json" do
796 test "returns \"ok\"", %{conn: conn} do
797 conn = get(conn, "/api/help/test.json")
798 assert json_response(conn, 200) == "ok"
802 describe "POST /api/qvitter/update_avatar.json" do
805 test "without valid credentials", %{conn: conn} do
806 conn = post(conn, "/api/qvitter/update_avatar.json")
807 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
810 test "with credentials", %{conn: conn, user: current_user} do
811 avatar_image = File.read!("test/fixtures/avatar_data_uri")
815 |> with_credentials(current_user.nickname, "test")
816 |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
818 current_user = User.get_cached_by_id(current_user.id)
819 assert is_map(current_user.avatar)
821 assert json_response(conn, 200) ==
822 UserView.render("show.json", %{user: current_user, for: current_user})
826 describe "GET /api/qvitter/mutes.json" do
829 test "unimplemented mutes without valid credentials", %{conn: conn} do
830 conn = get(conn, "/api/qvitter/mutes.json")
831 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
834 test "unimplemented mutes with credentials", %{conn: conn, user: current_user} do
837 |> with_credentials(current_user.nickname, "test")
838 |> get("/api/qvitter/mutes.json")
839 |> json_response(200)
845 describe "POST /api/favorites/create/:id" do
848 test "without valid credentials", %{conn: conn} do
849 note_activity = insert(:note_activity)
850 conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
851 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
854 test "with credentials", %{conn: conn, user: current_user} do
855 note_activity = insert(:note_activity)
859 |> with_credentials(current_user.nickname, "test")
860 |> post("/api/favorites/create/#{note_activity.id}.json")
862 assert json_response(conn, 200)
865 test "with credentials, invalid param", %{conn: conn, user: current_user} do
868 |> with_credentials(current_user.nickname, "test")
869 |> post("/api/favorites/create/wrong.json")
871 assert json_response(conn, 400)
874 test "with credentials, invalid activity", %{conn: conn, user: current_user} do
877 |> with_credentials(current_user.nickname, "test")
878 |> post("/api/favorites/create/1.json")
880 assert json_response(conn, 400)
884 describe "POST /api/favorites/destroy/:id" do
887 test "without valid credentials", %{conn: conn} do
888 note_activity = insert(:note_activity)
889 conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
890 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
893 test "with credentials", %{conn: conn, user: current_user} do
894 note_activity = insert(:note_activity)
895 object = Object.normalize(note_activity)
896 ActivityPub.like(current_user, object)
900 |> with_credentials(current_user.nickname, "test")
901 |> post("/api/favorites/destroy/#{note_activity.id}.json")
903 assert json_response(conn, 200)
907 describe "POST /api/statuses/retweet/:id" do
910 test "without valid credentials", %{conn: conn} do
911 note_activity = insert(:note_activity)
912 conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
913 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
916 test "with credentials", %{conn: conn, user: current_user} do
917 note_activity = insert(:note_activity)
919 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
923 |> with_credentials(current_user.nickname, "test")
924 |> post(request_path)
926 activity = Activity.get_by_id(note_activity.id)
927 activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
929 assert json_response(response, 200) ==
930 ActivityView.render("activity.json", %{
938 describe "POST /api/statuses/unretweet/:id" do
941 test "without valid credentials", %{conn: conn} do
942 note_activity = insert(:note_activity)
943 conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
944 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
947 test "with credentials", %{conn: conn, user: current_user} do
948 note_activity = insert(:note_activity)
950 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
954 |> with_credentials(current_user.nickname, "test")
955 |> post(request_path)
957 request_path = String.replace(request_path, "retweet", "unretweet")
961 |> with_credentials(current_user.nickname, "test")
962 |> post(request_path)
964 activity = Activity.get_by_id(note_activity.id)
965 activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
967 assert json_response(response, 200) ==
968 ActivityView.render("activity.json", %{
976 describe "POST /api/account/register" do
977 test "it creates a new user", %{conn: conn} do
979 "nickname" => "lain",
980 "email" => "lain@wired.jp",
981 "fullname" => "lain iwakura",
982 "bio" => "close the world.",
983 "password" => "bear",
989 |> post("/api/account/register", data)
991 user = json_response(conn, 200)
993 fetched_user = User.get_cached_by_nickname("lain")
994 assert user == UserView.render("show.json", %{user: fetched_user})
997 test "it returns errors on a problem", %{conn: conn} do
999 "email" => "lain@wired.jp",
1000 "fullname" => "lain iwakura",
1001 "bio" => "close the world.",
1002 "password" => "bear",
1008 |> post("/api/account/register", data)
1010 errors = json_response(conn, 400)
1012 assert is_binary(errors["error"])
1016 describe "POST /api/account/password_reset, with valid parameters" do
1017 setup %{conn: conn} do
1018 user = insert(:user)
1019 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1020 %{conn: conn, user: user}
1023 test "it returns 204", %{conn: conn} do
1024 assert json_response(conn, :no_content)
1027 test "it creates a PasswordResetToken record for user", %{user: user} do
1028 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1032 test "it sends an email to user", %{user: user} do
1033 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1035 email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
1036 notify_email = Pleroma.Config.get([:instance, :notify_email])
1037 instance_name = Pleroma.Config.get([:instance, :name])
1040 from: {instance_name, notify_email},
1041 to: {user.name, user.email},
1042 html_body: email.html_body
1047 describe "POST /api/account/password_reset, with invalid parameters" do
1050 test "it returns 500 when user is not found", %{conn: conn, user: user} do
1051 conn = post(conn, "/api/account/password_reset?email=nonexisting_#{user.email}")
1052 assert json_response(conn, :internal_server_error)
1055 test "it returns 500 when user is not local", %{conn: conn, user: user} do
1056 {:ok, user} = Repo.update(Changeset.change(user, local: false))
1057 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1058 assert json_response(conn, :internal_server_error)
1062 describe "GET /api/account/confirm_email/:id/:token" do
1064 user = insert(:user)
1065 info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
1069 |> Changeset.change()
1070 |> Changeset.put_embed(:info, info_change)
1073 assert user.info.confirmation_pending
1078 test "it redirects to root url", %{conn: conn, user: user} do
1079 conn = get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1081 assert 302 == conn.status
1084 test "it confirms the user account", %{conn: conn, user: user} do
1085 get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1087 user = User.get_cached_by_id(user.id)
1089 refute user.info.confirmation_pending
1090 refute user.info.confirmation_token
1093 test "it returns 500 if user cannot be found by id", %{conn: conn, user: user} do
1094 conn = get(conn, "/api/account/confirm_email/0/#{user.info.confirmation_token}")
1096 assert 500 == conn.status
1099 test "it returns 500 if token is invalid", %{conn: conn, user: user} do
1100 conn = get(conn, "/api/account/confirm_email/#{user.id}/wrong_token")
1102 assert 500 == conn.status
1106 describe "POST /api/account/resend_confirmation_email" do
1108 setting = Pleroma.Config.get([:instance, :account_activation_required])
1111 Pleroma.Config.put([:instance, :account_activation_required], true)
1112 on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
1115 user = insert(:user)
1116 info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
1120 |> Changeset.change()
1121 |> Changeset.put_embed(:info, info_change)
1124 assert user.info.confirmation_pending
1129 test "it returns 204 No Content", %{conn: conn, user: user} do
1131 |> assign(:user, user)
1132 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1133 |> json_response(:no_content)
1136 test "it sends confirmation email", %{conn: conn, user: user} do
1138 |> assign(:user, user)
1139 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1141 email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
1142 notify_email = Pleroma.Config.get([:instance, :notify_email])
1143 instance_name = Pleroma.Config.get([:instance, :name])
1146 from: {instance_name, notify_email},
1147 to: {user.name, user.email},
1148 html_body: email.html_body
1153 describe "GET /api/externalprofile/show" do
1154 test "it returns the user", %{conn: conn} do
1155 user = insert(:user)
1156 other_user = insert(:user)
1160 |> assign(:user, user)
1161 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
1163 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
1167 describe "GET /api/statuses/followers" do
1168 test "it returns a user's followers", %{conn: conn} do
1169 user = insert(:user)
1170 follower_one = insert(:user)
1171 follower_two = insert(:user)
1172 _not_follower = insert(:user)
1174 {:ok, follower_one} = User.follow(follower_one, user)
1175 {:ok, follower_two} = User.follow(follower_two, user)
1179 |> assign(:user, user)
1180 |> get("/api/statuses/followers")
1182 expected = UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
1183 result = json_response(conn, 200)
1184 assert Enum.sort(expected) == Enum.sort(result)
1187 test "it returns 20 followers per page", %{conn: conn} do
1188 user = insert(:user)
1189 followers = insert_list(21, :user)
1191 Enum.each(followers, fn follower ->
1192 User.follow(follower, user)
1197 |> assign(:user, user)
1198 |> get("/api/statuses/followers")
1200 result = json_response(res_conn, 200)
1201 assert length(result) == 20
1205 |> assign(:user, user)
1206 |> get("/api/statuses/followers?page=2")
1208 result = json_response(res_conn, 200)
1209 assert length(result) == 1
1212 test "it returns a given user's followers with user_id", %{conn: conn} do
1213 user = insert(:user)
1214 follower_one = insert(:user)
1215 follower_two = insert(:user)
1216 not_follower = insert(:user)
1218 {:ok, follower_one} = User.follow(follower_one, user)
1219 {:ok, follower_two} = User.follow(follower_two, user)
1223 |> assign(:user, not_follower)
1224 |> get("/api/statuses/followers", %{"user_id" => user.id})
1226 assert MapSet.equal?(
1227 MapSet.new(json_response(conn, 200)),
1229 UserView.render("index.json", %{
1230 users: [follower_one, follower_two],
1237 test "it returns empty when hide_followers is set to true", %{conn: conn} do
1238 user = insert(:user, %{info: %{hide_followers: true}})
1239 follower_one = insert(:user)
1240 follower_two = insert(:user)
1241 not_follower = insert(:user)
1243 {:ok, _follower_one} = User.follow(follower_one, user)
1244 {:ok, _follower_two} = User.follow(follower_two, user)
1248 |> assign(:user, not_follower)
1249 |> get("/api/statuses/followers", %{"user_id" => user.id})
1250 |> json_response(200)
1252 assert [] == response
1255 test "it returns the followers when hide_followers is set to true if requested by the user themselves",
1259 user = insert(:user, %{info: %{hide_followers: true}})
1260 follower_one = insert(:user)
1261 follower_two = insert(:user)
1262 _not_follower = insert(:user)
1264 {:ok, _follower_one} = User.follow(follower_one, user)
1265 {:ok, _follower_two} = User.follow(follower_two, user)
1269 |> assign(:user, user)
1270 |> get("/api/statuses/followers", %{"user_id" => user.id})
1272 refute [] == json_response(conn, 200)
1276 describe "GET /api/statuses/blocks" do
1277 test "it returns the list of users blocked by requester", %{conn: conn} do
1278 user = insert(:user)
1279 other_user = insert(:user)
1281 {:ok, user} = User.block(user, other_user)
1285 |> assign(:user, user)
1286 |> get("/api/statuses/blocks")
1288 expected = UserView.render("index.json", %{users: [other_user], for: user})
1289 result = json_response(conn, 200)
1290 assert Enum.sort(expected) == Enum.sort(result)
1294 describe "GET /api/statuses/friends" do
1295 test "it returns the logged in user's friends", %{conn: conn} do
1296 user = insert(:user)
1297 followed_one = insert(:user)
1298 followed_two = insert(:user)
1299 _not_followed = insert(:user)
1301 {:ok, user} = User.follow(user, followed_one)
1302 {:ok, user} = User.follow(user, followed_two)
1306 |> assign(:user, user)
1307 |> get("/api/statuses/friends")
1309 expected = UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1310 result = json_response(conn, 200)
1311 assert Enum.sort(expected) == Enum.sort(result)
1314 test "it returns 20 friends per page, except if 'export' is set to true", %{conn: conn} do
1315 user = insert(:user)
1316 followeds = insert_list(21, :user)
1319 Enum.reduce(followeds, {:ok, user}, fn followed, {:ok, user} ->
1320 User.follow(user, followed)
1325 |> assign(:user, user)
1326 |> get("/api/statuses/friends")
1328 result = json_response(res_conn, 200)
1329 assert length(result) == 20
1333 |> assign(:user, user)
1334 |> get("/api/statuses/friends", %{page: 2})
1336 result = json_response(res_conn, 200)
1337 assert length(result) == 1
1341 |> assign(:user, user)
1342 |> get("/api/statuses/friends", %{all: true})
1344 result = json_response(res_conn, 200)
1345 assert length(result) == 21
1348 test "it returns a given user's friends with user_id", %{conn: conn} do
1349 user = insert(:user)
1350 followed_one = insert(:user)
1351 followed_two = insert(:user)
1352 _not_followed = insert(:user)
1354 {:ok, user} = User.follow(user, followed_one)
1355 {:ok, user} = User.follow(user, followed_two)
1359 |> assign(:user, user)
1360 |> get("/api/statuses/friends", %{"user_id" => user.id})
1362 assert MapSet.equal?(
1363 MapSet.new(json_response(conn, 200)),
1365 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1370 test "it returns empty when hide_follows is set to true", %{conn: conn} do
1371 user = insert(:user, %{info: %{hide_follows: true}})
1372 followed_one = insert(:user)
1373 followed_two = insert(:user)
1374 not_followed = insert(:user)
1376 {:ok, user} = User.follow(user, followed_one)
1377 {:ok, user} = User.follow(user, followed_two)
1381 |> assign(:user, not_followed)
1382 |> get("/api/statuses/friends", %{"user_id" => user.id})
1384 assert [] == json_response(conn, 200)
1387 test "it returns friends when hide_follows is set to true if the user themselves request it",
1391 user = insert(:user, %{info: %{hide_follows: true}})
1392 followed_one = insert(:user)
1393 followed_two = insert(:user)
1394 _not_followed = insert(:user)
1396 {:ok, _user} = User.follow(user, followed_one)
1397 {:ok, _user} = User.follow(user, followed_two)
1401 |> assign(:user, user)
1402 |> get("/api/statuses/friends", %{"user_id" => user.id})
1403 |> json_response(200)
1405 refute [] == response
1408 test "it returns a given user's friends with screen_name", %{conn: conn} do
1409 user = insert(:user)
1410 followed_one = insert(:user)
1411 followed_two = insert(:user)
1412 _not_followed = insert(:user)
1414 {:ok, user} = User.follow(user, followed_one)
1415 {:ok, user} = User.follow(user, followed_two)
1419 |> assign(:user, user)
1420 |> get("/api/statuses/friends", %{"screen_name" => user.nickname})
1422 assert MapSet.equal?(
1423 MapSet.new(json_response(conn, 200)),
1425 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1431 describe "GET /friends/ids" do
1432 test "it returns a user's friends", %{conn: conn} do
1433 user = insert(:user)
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, user)
1444 |> get("/api/friends/ids")
1446 expected = [followed_one.id, followed_two.id]
1448 assert MapSet.equal?(
1449 MapSet.new(Poison.decode!(json_response(conn, 200))),
1450 MapSet.new(expected)
1455 describe "POST /api/account/update_profile.json" do
1456 test "it updates a user's profile", %{conn: conn} do
1457 user = insert(:user)
1458 user2 = insert(:user)
1462 |> assign(:user, user)
1463 |> post("/api/account/update_profile.json", %{
1464 "name" => "new name",
1465 "description" => "hi @#{user2.nickname}"
1468 user = Repo.get!(User, user.id)
1469 assert user.name == "new name"
1472 "hi <span class='h-card'><a data-user='#{user2.id}' class='u-url mention' href='#{
1474 }'>@<span>#{user2.nickname}</span></a></span>"
1476 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1479 test "it sets and un-sets hide_follows", %{conn: conn} do
1480 user = insert(:user)
1483 |> assign(:user, user)
1484 |> post("/api/account/update_profile.json", %{
1485 "hide_follows" => "true"
1488 user = Repo.get!(User, user.id)
1489 assert user.info.hide_follows == true
1493 |> assign(:user, user)
1494 |> post("/api/account/update_profile.json", %{
1495 "hide_follows" => "false"
1498 user = refresh_record(user)
1499 assert user.info.hide_follows == false
1500 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1503 test "it sets and un-sets hide_followers", %{conn: conn} do
1504 user = insert(:user)
1507 |> assign(:user, user)
1508 |> post("/api/account/update_profile.json", %{
1509 "hide_followers" => "true"
1512 user = Repo.get!(User, user.id)
1513 assert user.info.hide_followers == true
1517 |> assign(:user, user)
1518 |> post("/api/account/update_profile.json", %{
1519 "hide_followers" => "false"
1522 user = Repo.get!(User, user.id)
1523 assert user.info.hide_followers == false
1524 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1527 test "it sets and un-sets show_role", %{conn: conn} do
1528 user = insert(:user)
1531 |> assign(:user, user)
1532 |> post("/api/account/update_profile.json", %{
1533 "show_role" => "true"
1536 user = Repo.get!(User, user.id)
1537 assert user.info.show_role == true
1541 |> assign(:user, user)
1542 |> post("/api/account/update_profile.json", %{
1543 "show_role" => "false"
1546 user = Repo.get!(User, user.id)
1547 assert user.info.show_role == false
1548 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1551 test "it sets and un-sets skip_thread_containment", %{conn: conn} do
1552 user = insert(:user)
1556 |> assign(:user, user)
1557 |> post("/api/account/update_profile.json", %{"skip_thread_containment" => "true"})
1558 |> json_response(200)
1560 assert response["pleroma"]["skip_thread_containment"] == true
1561 user = refresh_record(user)
1562 assert user.info.skip_thread_containment
1566 |> assign(:user, user)
1567 |> post("/api/account/update_profile.json", %{"skip_thread_containment" => "false"})
1568 |> json_response(200)
1570 assert response["pleroma"]["skip_thread_containment"] == false
1571 refute refresh_record(user).info.skip_thread_containment
1574 test "it locks an account", %{conn: conn} do
1575 user = insert(:user)
1579 |> assign(:user, user)
1580 |> post("/api/account/update_profile.json", %{
1584 user = Repo.get!(User, user.id)
1585 assert user.info.locked == true
1587 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1590 test "it unlocks an account", %{conn: conn} do
1591 user = insert(:user)
1595 |> assign(:user, user)
1596 |> post("/api/account/update_profile.json", %{
1600 user = Repo.get!(User, user.id)
1601 assert user.info.locked == false
1603 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1606 # Broken before the change to class="emoji" and non-<img/> in the DB
1608 test "it formats emojos", %{conn: conn} do
1609 user = insert(:user)
1613 |> assign(:user, user)
1614 |> post("/api/account/update_profile.json", %{
1615 "bio" => "I love our :moominmamma:"
1618 assert response = json_response(conn, 200)
1621 "description" => "I love our :moominmamma:",
1622 "description_html" =>
1623 ~s{I love our <img class="emoji" alt="moominmamma" title="moominmamma" src="} <>
1629 |> get("/api/users/show.json?user_id=#{user.nickname}")
1631 assert response == json_response(conn, 200)
1635 defp valid_user(_context) do
1636 user = insert(:user)
1640 defp with_credentials(conn, username, password) do
1641 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
1642 put_req_header(conn, "authorization", header_content)
1645 describe "GET /api/search.json" do
1646 test "it returns search results", %{conn: conn} do
1647 user = insert(:user)
1648 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1650 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1651 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1655 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
1657 assert [status] = json_response(conn, 200)
1658 assert status["id"] == activity.id
1662 describe "GET /api/statusnet/tags/timeline/:tag.json" do
1663 test "it returns the tags timeline", %{conn: conn} do
1664 user = insert(:user)
1665 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1667 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
1668 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1672 |> get("/api/statusnet/tags/timeline/2hu.json")
1674 assert [status] = json_response(conn, 200)
1675 assert status["id"] == activity.id
1679 test "Convert newlines to <br> in bio", %{conn: conn} do
1680 user = insert(:user)
1684 |> assign(:user, user)
1685 |> post("/api/account/update_profile.json", %{
1686 "description" => "Hello,\r\nWorld! I\n am a test."
1689 user = Repo.get!(User, user.id)
1690 assert user.bio == "Hello,<br>World! I<br> am a test."
1693 describe "POST /api/pleroma/change_password" do
1696 test "without credentials", %{conn: conn} do
1697 conn = post(conn, "/api/pleroma/change_password")
1698 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1701 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1704 |> with_credentials(current_user.nickname, "test")
1705 |> post("/api/pleroma/change_password", %{
1707 "new_password" => "newpass",
1708 "new_password_confirmation" => "newpass"
1711 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1714 test "with credentials, valid password and new password and confirmation not matching", %{
1720 |> with_credentials(current_user.nickname, "test")
1721 |> post("/api/pleroma/change_password", %{
1722 "password" => "test",
1723 "new_password" => "newpass",
1724 "new_password_confirmation" => "notnewpass"
1727 assert json_response(conn, 200) == %{
1728 "error" => "New password does not match confirmation."
1732 test "with credentials, valid password and invalid new password", %{
1738 |> with_credentials(current_user.nickname, "test")
1739 |> post("/api/pleroma/change_password", %{
1740 "password" => "test",
1741 "new_password" => "",
1742 "new_password_confirmation" => ""
1745 assert json_response(conn, 200) == %{
1746 "error" => "New password can't be blank."
1750 test "with credentials, valid password and matching new password and confirmation", %{
1756 |> with_credentials(current_user.nickname, "test")
1757 |> post("/api/pleroma/change_password", %{
1758 "password" => "test",
1759 "new_password" => "newpass",
1760 "new_password_confirmation" => "newpass"
1763 assert json_response(conn, 200) == %{"status" => "success"}
1764 fetched_user = User.get_cached_by_id(current_user.id)
1765 assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
1769 describe "POST /api/pleroma/delete_account" do
1772 test "without credentials", %{conn: conn} do
1773 conn = post(conn, "/api/pleroma/delete_account")
1774 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1777 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1780 |> with_credentials(current_user.nickname, "test")
1781 |> post("/api/pleroma/delete_account", %{"password" => "hi"})
1783 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1786 test "with credentials and valid password", %{conn: conn, user: current_user} do
1789 |> with_credentials(current_user.nickname, "test")
1790 |> post("/api/pleroma/delete_account", %{"password" => "test"})
1792 assert json_response(conn, 200) == %{"status" => "success"}
1793 # Wait a second for the started task to end
1798 describe "GET /api/pleroma/friend_requests" do
1799 test "it lists friend requests" do
1800 user = insert(:user)
1801 other_user = insert(:user)
1803 {:ok, _activity} = ActivityPub.follow(other_user, user)
1805 user = User.get_cached_by_id(user.id)
1806 other_user = User.get_cached_by_id(other_user.id)
1808 assert User.following?(other_user, user) == false
1812 |> assign(:user, user)
1813 |> get("/api/pleroma/friend_requests")
1815 assert [relationship] = json_response(conn, 200)
1816 assert other_user.id == relationship["id"]
1819 test "requires 'read' permission", %{conn: conn} do
1820 token1 = insert(:oauth_token, scopes: ["write"])
1821 token2 = insert(:oauth_token, scopes: ["read"])
1823 for token <- [token1, token2] do
1826 |> put_req_header("authorization", "Bearer #{token.token}")
1827 |> get("/api/pleroma/friend_requests")
1829 if token == token1 do
1830 assert %{"error" => "Insufficient permissions: read."} == json_response(conn, 403)
1832 assert json_response(conn, 200)
1838 describe "POST /api/pleroma/friendships/approve" do
1839 test "it approves a friend request" do
1840 user = insert(:user)
1841 other_user = insert(:user)
1843 {:ok, _activity} = ActivityPub.follow(other_user, user)
1845 user = User.get_cached_by_id(user.id)
1846 other_user = User.get_cached_by_id(other_user.id)
1848 assert User.following?(other_user, user) == false
1852 |> assign(:user, user)
1853 |> post("/api/pleroma/friendships/approve", %{"user_id" => other_user.id})
1855 assert relationship = json_response(conn, 200)
1856 assert other_user.id == relationship["id"]
1857 assert relationship["follows_you"] == true
1861 describe "POST /api/pleroma/friendships/deny" do
1862 test "it denies a friend request" do
1863 user = insert(:user)
1864 other_user = insert(:user)
1866 {:ok, _activity} = ActivityPub.follow(other_user, user)
1868 user = User.get_cached_by_id(user.id)
1869 other_user = User.get_cached_by_id(other_user.id)
1871 assert User.following?(other_user, user) == false
1875 |> assign(:user, user)
1876 |> post("/api/pleroma/friendships/deny", %{"user_id" => other_user.id})
1878 assert relationship = json_response(conn, 200)
1879 assert other_user.id == relationship["id"]
1880 assert relationship["follows_you"] == false
1884 describe "GET /api/pleroma/search_user" do
1885 test "it returns users, ordered by similarity", %{conn: conn} do
1886 user = insert(:user, %{name: "eal"})
1887 user_two = insert(:user, %{name: "eal me"})
1888 _user_three = insert(:user, %{name: "zzz"})
1892 |> get(twitter_api_search__path(conn, :search_user), query: "eal me")
1893 |> json_response(200)
1895 assert length(resp) == 2
1896 assert [user_two.id, user.id] == Enum.map(resp, fn %{"id" => id} -> id end)
1900 describe "POST /api/media/upload" do
1902 Pleroma.DataCase.ensure_local_uploader(context)
1905 test "it performs the upload and sets `data[actor]` with AP id of uploader user", %{
1908 user = insert(:user)
1910 upload_filename = "test/fixtures/image_tmp.jpg"
1911 File.cp!("test/fixtures/image.jpg", upload_filename)
1913 file = %Plug.Upload{
1914 content_type: "image/jpg",
1915 path: Path.absname(upload_filename),
1916 filename: "image.jpg"
1921 |> assign(:user, user)
1922 |> put_req_header("content-type", "application/octet-stream")
1923 |> post("/api/media/upload", %{
1926 |> json_response(:ok)
1928 assert response["media_id"]
1929 object = Repo.get(Object, response["media_id"])
1931 assert object.data["actor"] == User.ap_id(user)
1935 describe "POST /api/media/metadata/create" do
1937 object = insert(:note)
1938 user = User.get_cached_by_ap_id(object.data["actor"])
1939 %{object: object, user: user}
1942 test "it returns :forbidden status on attempt to modify someone else's upload", %{
1946 initial_description = object.data["name"]
1947 another_user = insert(:user)
1950 |> assign(:user, another_user)
1951 |> post("/api/media/metadata/create", %{"media_id" => object.id})
1952 |> json_response(:forbidden)
1954 object = Repo.get(Object, object.id)
1955 assert object.data["name"] == initial_description
1958 test "it updates `data[name]` of referenced Object with provided value", %{
1963 description = "Informative description of the image. Initial value: #{object.data["name"]}}"
1966 |> assign(:user, user)
1967 |> post("/api/media/metadata/create", %{
1968 "media_id" => object.id,
1969 "alt_text" => %{"text" => description}
1971 |> json_response(:no_content)
1973 object = Repo.get(Object, object.id)
1974 assert object.data["name"] == description
1978 describe "POST /api/statuses/user_timeline.json?user_id=:user_id&pinned=true" do
1979 test "it returns a list of pinned statuses", %{conn: conn} do
1980 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1982 user = insert(:user, %{name: "egor"})
1983 {:ok, %{id: activity_id}} = CommonAPI.post(user, %{"status" => "HI!!!"})
1984 {:ok, _} = CommonAPI.pin(activity_id, user)
1988 |> get("/api/statuses/user_timeline.json", %{user_id: user.id, pinned: true})
1989 |> json_response(200)
1991 assert length(resp) == 1
1992 assert [%{"id" => ^activity_id, "pinned" => true}] = resp
1996 describe "POST /api/statuses/pin/:id" do
1998 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1999 [user: insert(:user)]
2002 test "without valid credentials", %{conn: conn} do
2003 note_activity = insert(:note_activity)
2004 conn = post(conn, "/api/statuses/pin/#{note_activity.id}.json")
2005 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2008 test "with credentials", %{conn: conn, user: user} do
2009 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2011 request_path = "/api/statuses/pin/#{activity.id}.json"
2015 |> with_credentials(user.nickname, "test")
2016 |> post(request_path)
2018 user = refresh_record(user)
2020 assert json_response(response, 200) ==
2021 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2025 describe "POST /api/statuses/unpin/:id" do
2027 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2028 [user: insert(:user)]
2031 test "without valid credentials", %{conn: conn} do
2032 note_activity = insert(:note_activity)
2033 conn = post(conn, "/api/statuses/unpin/#{note_activity.id}.json")
2034 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2037 test "with credentials", %{conn: conn, user: user} do
2038 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2039 {:ok, activity} = CommonAPI.pin(activity.id, user)
2041 request_path = "/api/statuses/unpin/#{activity.id}.json"
2045 |> with_credentials(user.nickname, "test")
2046 |> post(request_path)
2048 user = refresh_record(user)
2050 assert json_response(response, 200) ==
2051 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2055 describe "GET /api/oauth_tokens" do
2057 token = insert(:oauth_token) |> Repo.preload(:user)
2062 test "renders list", %{token: token} do
2065 |> assign(:user, token.user)
2066 |> get("/api/oauth_tokens")
2069 json_response(response, 200)
2073 assert keys -- ["id", "app_name", "valid_until"] == []
2076 test "revoke token", %{token: token} do
2079 |> assign(:user, token.user)
2080 |> delete("/api/oauth_tokens/#{token.id}")
2082 tokens = Token.get_user_tokens(token.user)
2085 assert response.status == 201