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
15 alias Pleroma.Tests.ObanHelpers
17 alias Pleroma.Web.ActivityPub.ActivityPub
18 alias Pleroma.Web.CommonAPI
19 alias Pleroma.Web.OAuth.Token
20 alias Pleroma.Web.TwitterAPI.ActivityView
21 alias Pleroma.Web.TwitterAPI.Controller
22 alias Pleroma.Web.TwitterAPI.NotificationView
23 alias Pleroma.Web.TwitterAPI.TwitterAPI
24 alias Pleroma.Web.TwitterAPI.UserView
27 import Pleroma.Factory
28 import Swoosh.TestAssertions
30 @banner "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
32 describe "POST /api/account/update_profile_banner" do
33 test "it updates the banner", %{conn: conn} do
37 |> assign(:user, user)
38 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => @banner})
41 user = refresh_record(user)
42 assert user.info.banner["type"] == "Image"
45 test "profile banner can be reset", %{conn: conn} do
49 |> assign(:user, user)
50 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => ""})
53 user = refresh_record(user)
54 assert user.info.banner == %{}
58 describe "POST /api/qvitter/update_background_image" do
59 test "it updates the background", %{conn: conn} do
63 |> assign(:user, user)
64 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => @banner})
67 user = refresh_record(user)
68 assert user.info.background["type"] == "Image"
71 test "background can be reset", %{conn: conn} do
75 |> assign(:user, user)
76 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => ""})
79 user = refresh_record(user)
80 assert user.info.background == %{}
84 describe "POST /api/account/verify_credentials" do
87 test "without valid credentials", %{conn: conn} do
88 conn = post(conn, "/api/account/verify_credentials.json")
89 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
92 test "with credentials", %{conn: conn, user: user} do
95 |> with_credentials(user.nickname, "test")
96 |> post("/api/account/verify_credentials.json")
100 UserView.render("show.json", %{user: user, token: response["token"], for: user})
104 describe "POST /statuses/update.json" do
107 test "without valid credentials", %{conn: conn} do
108 conn = post(conn, "/api/statuses/update.json")
109 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
112 test "with credentials", %{conn: conn, user: user} do
113 conn_with_creds = conn |> with_credentials(user.nickname, "test")
114 request_path = "/api/statuses/update.json"
117 "request" => request_path,
118 "error" => "Client must provide a 'status' parameter with a value."
123 |> post(request_path)
125 assert json_response(conn, 400) == error_response
129 |> post(request_path, %{status: ""})
131 assert json_response(conn, 400) == error_response
135 |> post(request_path, %{status: " "})
137 assert json_response(conn, 400) == error_response
139 # we post with visibility private in order to avoid triggering relay
142 |> post(request_path, %{status: "Nice meme.", visibility: "private"})
144 assert json_response(conn, 200) ==
145 ActivityView.render("activity.json", %{
146 activity: Repo.one(Activity),
153 describe "GET /statuses/public_timeline.json" do
155 clear_config([:instance, :public])
157 test "returns statuses", %{conn: conn} do
159 activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
160 ActivityBuilder.insert_list(10, %{}, %{user: user})
161 since_id = List.last(activities).id
165 |> get("/api/statuses/public_timeline.json", %{since_id: since_id})
167 response = json_response(conn, 200)
169 assert length(response) == 10
172 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
173 Pleroma.Config.put([:instance, :public], false)
176 |> get("/api/statuses/public_timeline.json")
177 |> json_response(403)
180 test "returns 200 to authenticated request when the instance is not public",
181 %{conn: conn, user: user} do
182 Pleroma.Config.put([:instance, :public], false)
185 |> with_credentials(user.nickname, "test")
186 |> get("/api/statuses/public_timeline.json")
187 |> json_response(200)
190 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
192 |> get("/api/statuses/public_timeline.json")
193 |> json_response(200)
196 test "returns 200 to authenticated request when the instance is public",
197 %{conn: conn, user: user} do
199 |> with_credentials(user.nickname, "test")
200 |> get("/api/statuses/public_timeline.json")
201 |> json_response(200)
204 test_with_mock "treats user as unauthenticated if `assigns[:token]` is present but lacks `read` permission",
208 token = insert(:oauth_token, scopes: ["write"])
211 |> put_req_header("authorization", "Bearer #{token.token}")
212 |> get("/api/statuses/public_timeline.json")
213 |> json_response(200)
215 assert called(Controller.public_timeline(%{assigns: %{user: nil}}, :_))
219 describe "GET /statuses/public_and_external_timeline.json" do
221 clear_config([:instance, :public])
223 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
224 Pleroma.Config.put([:instance, :public], false)
227 |> get("/api/statuses/public_and_external_timeline.json")
228 |> json_response(403)
231 test "returns 200 to authenticated request when the instance is not public",
232 %{conn: conn, user: user} do
233 Pleroma.Config.put([:instance, :public], false)
236 |> with_credentials(user.nickname, "test")
237 |> get("/api/statuses/public_and_external_timeline.json")
238 |> json_response(200)
241 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
243 |> get("/api/statuses/public_and_external_timeline.json")
244 |> json_response(200)
247 test "returns 200 to authenticated request when the instance is public",
248 %{conn: conn, user: user} do
250 |> with_credentials(user.nickname, "test")
251 |> get("/api/statuses/public_and_external_timeline.json")
252 |> json_response(200)
256 describe "GET /statuses/show/:id.json" do
257 test "returns one status", %{conn: conn} do
259 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
260 actor = User.get_cached_by_ap_id(activity.data["actor"])
264 |> get("/api/statuses/show/#{activity.id}.json")
266 response = json_response(conn, 200)
268 assert response == ActivityView.render("activity.json", %{activity: activity, user: actor})
272 describe "GET /users/show.json" do
273 test "gets user with screen_name", %{conn: conn} do
278 |> get("/api/users/show.json", %{"screen_name" => user.nickname})
280 response = json_response(conn, 200)
282 assert response["id"] == user.id
285 test "gets user with user_id", %{conn: conn} do
290 |> get("/api/users/show.json", %{"user_id" => user.id})
292 response = json_response(conn, 200)
294 assert response["id"] == user.id
297 test "gets a user for a logged in user", %{conn: conn} do
299 logged_in = insert(:user)
301 {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})
305 |> with_credentials(logged_in.nickname, "test")
306 |> get("/api/users/show.json", %{"user_id" => user.id})
308 response = json_response(conn, 200)
310 assert response["following"] == true
314 describe "GET /statusnet/conversation/:id.json" do
315 test "returns the statuses in the conversation", %{conn: conn} do
316 {:ok, _user} = UserBuilder.insert()
317 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
318 {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
319 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
323 |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
325 response = json_response(conn, 200)
327 assert length(response) == 2
331 describe "GET /statuses/friends_timeline.json" do
334 test "without valid credentials", %{conn: conn} do
335 conn = get(conn, "/api/statuses/friends_timeline.json")
336 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
339 test "with credentials", %{conn: conn, user: current_user} do
343 ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
345 returned_activities =
346 ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
348 other_user = insert(:user)
349 ActivityBuilder.insert_list(10, %{}, %{user: other_user})
350 since_id = List.last(activities).id
353 Changeset.change(current_user, following: [User.ap_followers(user)])
358 |> with_credentials(current_user.nickname, "test")
359 |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
361 response = json_response(conn, 200)
363 assert length(response) == 10
366 Enum.map(returned_activities, fn activity ->
367 ActivityView.render("activity.json", %{
369 user: User.get_cached_by_ap_id(activity.data["actor"]),
376 describe "GET /statuses/dm_timeline.json" do
377 test "it show direct messages", %{conn: conn} do
378 user_one = insert(:user)
379 user_two = insert(:user)
381 {:ok, user_two} = User.follow(user_two, user_one)
384 CommonAPI.post(user_one, %{
385 "status" => "Hi @#{user_two.nickname}!",
386 "visibility" => "direct"
390 CommonAPI.post(user_two, %{
391 "status" => "Hi @#{user_one.nickname}!",
392 "visibility" => "direct"
395 {:ok, _follower_only} =
396 CommonAPI.post(user_one, %{
397 "status" => "Hi @#{user_two.nickname}!",
398 "visibility" => "private"
401 # Only direct should be visible here
404 |> assign(:user, user_two)
405 |> get("/api/statuses/dm_timeline.json")
407 [status, status_two] = json_response(res_conn, 200)
408 assert status["id"] == direct_two.id
409 assert status_two["id"] == direct.id
412 test "doesn't include DMs from blocked users", %{conn: conn} do
413 blocker = insert(:user)
414 blocked = insert(:user)
416 {:ok, blocker} = User.block(blocker, blocked)
418 {:ok, _blocked_direct} =
419 CommonAPI.post(blocked, %{
420 "status" => "Hi @#{blocker.nickname}!",
421 "visibility" => "direct"
425 CommonAPI.post(user, %{
426 "status" => "Hi @#{blocker.nickname}!",
427 "visibility" => "direct"
432 |> assign(:user, blocker)
433 |> get("/api/statuses/dm_timeline.json")
435 [status] = json_response(res_conn, 200)
436 assert status["id"] == direct.id
440 describe "GET /statuses/mentions.json" do
443 test "without valid credentials", %{conn: conn} do
444 conn = get(conn, "/api/statuses/mentions.json")
445 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
448 test "with credentials", %{conn: conn, user: current_user} do
450 CommonAPI.post(current_user, %{
451 "status" => "why is tenshi eating a corndog so cute?",
452 "visibility" => "public"
457 |> with_credentials(current_user.nickname, "test")
458 |> get("/api/statuses/mentions.json")
460 response = json_response(conn, 200)
462 assert length(response) == 1
464 assert Enum.at(response, 0) ==
465 ActivityView.render("activity.json", %{
472 test "does not show DMs in mentions timeline", %{conn: conn, user: current_user} do
474 CommonAPI.post(current_user, %{
475 "status" => "Have you guys ever seen how cute tenshi eating a corndog is?",
476 "visibility" => "direct"
481 |> with_credentials(current_user.nickname, "test")
482 |> get("/api/statuses/mentions.json")
484 response = json_response(conn, 200)
486 assert Enum.empty?(response)
490 describe "GET /api/qvitter/statuses/notifications.json" do
493 test "without valid credentials", %{conn: conn} do
494 conn = get(conn, "/api/qvitter/statuses/notifications.json")
495 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
498 test "with credentials", %{conn: conn, user: current_user} do
499 other_user = insert(:user)
502 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
506 |> with_credentials(current_user.nickname, "test")
507 |> get("/api/qvitter/statuses/notifications.json")
509 response = json_response(conn, 200)
511 assert length(response) == 1
514 NotificationView.render("notification.json", %{
515 notifications: Notification.for_user(current_user),
520 test "muted user", %{conn: conn, user: current_user} do
521 other_user = insert(:user)
523 {:ok, current_user} = User.mute(current_user, other_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 assert json_response(conn, 200) == []
536 test "muted user with with_muted parameter", %{conn: conn, user: current_user} do
537 other_user = insert(:user)
539 {:ok, current_user} = User.mute(current_user, other_user)
542 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
546 |> with_credentials(current_user.nickname, "test")
547 |> get("/api/qvitter/statuses/notifications.json", %{"with_muted" => "true"})
549 assert length(json_response(conn, 200)) == 1
553 describe "POST /api/qvitter/statuses/notifications/read" do
556 test "without valid credentials", %{conn: conn} do
557 conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567})
558 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
561 test "with credentials, without any params", %{conn: conn, user: current_user} do
564 |> with_credentials(current_user.nickname, "test")
565 |> post("/api/qvitter/statuses/notifications/read")
567 assert json_response(conn, 400) == %{
568 "error" => "You need to specify latest_id",
569 "request" => "/api/qvitter/statuses/notifications/read"
573 test "with credentials, with params", %{conn: conn, user: current_user} do
574 other_user = insert(:user)
577 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
581 |> with_credentials(current_user.nickname, "test")
582 |> get("/api/qvitter/statuses/notifications.json")
584 [notification] = response = json_response(response_conn, 200)
586 assert length(response) == 1
588 assert notification["is_seen"] == 0
592 |> with_credentials(current_user.nickname, "test")
593 |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]})
595 [notification] = response = json_response(response_conn, 200)
597 assert length(response) == 1
599 assert notification["is_seen"] == 1
603 describe "GET /statuses/user_timeline.json" do
606 test "without any params", %{conn: conn} do
607 conn = get(conn, "/api/statuses/user_timeline.json")
609 assert json_response(conn, 400) == %{
610 "error" => "You need to specify screen_name or user_id",
611 "request" => "/api/statuses/user_timeline.json"
615 test "with user_id", %{conn: conn} do
617 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
619 conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
620 response = json_response(conn, 200)
621 assert length(response) == 1
623 assert Enum.at(response, 0) ==
624 ActivityView.render("activity.json", %{user: user, activity: activity})
627 test "with screen_name", %{conn: conn} do
629 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
631 conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
632 response = json_response(conn, 200)
633 assert length(response) == 1
635 assert Enum.at(response, 0) ==
636 ActivityView.render("activity.json", %{user: user, activity: activity})
639 test "with credentials", %{conn: conn, user: current_user} do
640 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
644 |> with_credentials(current_user.nickname, "test")
645 |> get("/api/statuses/user_timeline.json")
647 response = json_response(conn, 200)
649 assert length(response) == 1
651 assert Enum.at(response, 0) ==
652 ActivityView.render("activity.json", %{
659 test "with credentials with user_id", %{conn: conn, user: current_user} do
661 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
665 |> with_credentials(current_user.nickname, "test")
666 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
668 response = json_response(conn, 200)
670 assert length(response) == 1
672 assert Enum.at(response, 0) ==
673 ActivityView.render("activity.json", %{user: user, activity: activity})
676 test "with credentials screen_name", %{conn: conn, user: current_user} do
678 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
682 |> with_credentials(current_user.nickname, "test")
683 |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
685 response = json_response(conn, 200)
687 assert length(response) == 1
689 assert Enum.at(response, 0) ==
690 ActivityView.render("activity.json", %{user: user, activity: activity})
693 test "with credentials with user_id, excluding RTs", %{conn: conn, user: current_user} do
695 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1, "type" => "Create"}, %{user: user})
696 {:ok, _} = ActivityBuilder.insert(%{"id" => 2, "type" => "Announce"}, %{user: user})
700 |> with_credentials(current_user.nickname, "test")
701 |> get("/api/statuses/user_timeline.json", %{
702 "user_id" => user.id,
703 "include_rts" => "false"
706 response = json_response(conn, 200)
708 assert length(response) == 1
710 assert Enum.at(response, 0) ==
711 ActivityView.render("activity.json", %{user: user, activity: activity})
715 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id, "include_rts" => "0"})
717 response = json_response(conn, 200)
719 assert length(response) == 1
721 assert Enum.at(response, 0) ==
722 ActivityView.render("activity.json", %{user: user, activity: activity})
726 describe "POST /friendships/create.json" do
729 test "without valid credentials", %{conn: conn} do
730 conn = post(conn, "/api/friendships/create.json")
731 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
734 test "with credentials", %{conn: conn, user: current_user} do
735 followed = insert(:user)
739 |> with_credentials(current_user.nickname, "test")
740 |> post("/api/friendships/create.json", %{user_id: followed.id})
742 current_user = User.get_cached_by_id(current_user.id)
743 assert User.ap_followers(followed) in current_user.following
745 assert json_response(conn, 200) ==
746 UserView.render("show.json", %{user: followed, for: current_user})
749 test "for restricted account", %{conn: conn, user: current_user} do
750 followed = insert(:user, info: %User.Info{locked: true})
754 |> with_credentials(current_user.nickname, "test")
755 |> post("/api/friendships/create.json", %{user_id: followed.id})
757 current_user = User.get_cached_by_id(current_user.id)
758 followed = User.get_cached_by_id(followed.id)
760 refute User.ap_followers(followed) in current_user.following
762 assert json_response(conn, 200) ==
763 UserView.render("show.json", %{user: followed, for: current_user})
767 describe "POST /friendships/destroy.json" do
770 test "without valid credentials", %{conn: conn} do
771 conn = post(conn, "/api/friendships/destroy.json")
772 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
775 test "with credentials", %{conn: conn, user: current_user} do
776 followed = insert(:user)
778 {:ok, current_user} = User.follow(current_user, followed)
779 assert User.ap_followers(followed) in current_user.following
780 ActivityPub.follow(current_user, followed)
784 |> with_credentials(current_user.nickname, "test")
785 |> post("/api/friendships/destroy.json", %{user_id: followed.id})
787 current_user = User.get_cached_by_id(current_user.id)
788 assert current_user.following == [current_user.ap_id]
790 assert json_response(conn, 200) ==
791 UserView.render("show.json", %{user: followed, for: current_user})
795 describe "POST /blocks/create.json" do
798 test "without valid credentials", %{conn: conn} do
799 conn = post(conn, "/api/blocks/create.json")
800 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
803 test "with credentials", %{conn: conn, user: current_user} do
804 blocked = insert(:user)
808 |> with_credentials(current_user.nickname, "test")
809 |> post("/api/blocks/create.json", %{user_id: blocked.id})
811 current_user = User.get_cached_by_id(current_user.id)
812 assert User.blocks?(current_user, blocked)
814 assert json_response(conn, 200) ==
815 UserView.render("show.json", %{user: blocked, for: current_user})
819 describe "POST /blocks/destroy.json" do
822 test "without valid credentials", %{conn: conn} do
823 conn = post(conn, "/api/blocks/destroy.json")
824 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
827 test "with credentials", %{conn: conn, user: current_user} do
828 blocked = insert(:user)
830 {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
831 assert User.blocks?(current_user, blocked)
835 |> with_credentials(current_user.nickname, "test")
836 |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
838 current_user = User.get_cached_by_id(current_user.id)
839 assert current_user.info.blocks == []
841 assert json_response(conn, 200) ==
842 UserView.render("show.json", %{user: blocked, for: current_user})
846 describe "GET /help/test.json" do
847 test "returns \"ok\"", %{conn: conn} do
848 conn = get(conn, "/api/help/test.json")
849 assert json_response(conn, 200) == "ok"
853 describe "POST /api/qvitter/update_avatar.json" do
856 test "without valid credentials", %{conn: conn} do
857 conn = post(conn, "/api/qvitter/update_avatar.json")
858 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
861 test "with credentials", %{conn: conn, user: current_user} do
862 avatar_image = File.read!("test/fixtures/avatar_data_uri")
866 |> with_credentials(current_user.nickname, "test")
867 |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
869 current_user = User.get_cached_by_id(current_user.id)
870 assert is_map(current_user.avatar)
872 assert json_response(conn, 200) ==
873 UserView.render("show.json", %{user: current_user, for: current_user})
876 test "user avatar can be reset", %{conn: conn, user: current_user} do
879 |> with_credentials(current_user.nickname, "test")
880 |> post("/api/qvitter/update_avatar.json", %{img: ""})
882 current_user = User.get_cached_by_id(current_user.id)
883 assert current_user.avatar == nil
885 assert json_response(conn, 200) ==
886 UserView.render("show.json", %{user: current_user, for: current_user})
890 describe "GET /api/qvitter/mutes.json" do
893 test "unimplemented mutes without valid credentials", %{conn: conn} do
894 conn = get(conn, "/api/qvitter/mutes.json")
895 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
898 test "unimplemented mutes with credentials", %{conn: conn, user: current_user} do
901 |> with_credentials(current_user.nickname, "test")
902 |> get("/api/qvitter/mutes.json")
903 |> json_response(200)
909 describe "POST /api/favorites/create/:id" do
912 test "without valid credentials", %{conn: conn} do
913 note_activity = insert(:note_activity)
914 conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
915 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
918 test "with credentials", %{conn: conn, user: current_user} do
919 note_activity = insert(:note_activity)
923 |> with_credentials(current_user.nickname, "test")
924 |> post("/api/favorites/create/#{note_activity.id}.json")
926 assert json_response(conn, 200)
929 test "with credentials, invalid param", %{conn: conn, user: current_user} do
932 |> with_credentials(current_user.nickname, "test")
933 |> post("/api/favorites/create/wrong.json")
935 assert json_response(conn, 400)
938 test "with credentials, invalid activity", %{conn: conn, user: current_user} do
941 |> with_credentials(current_user.nickname, "test")
942 |> post("/api/favorites/create/1.json")
944 assert json_response(conn, 400)
948 describe "POST /api/favorites/destroy/:id" do
951 test "without valid credentials", %{conn: conn} do
952 note_activity = insert(:note_activity)
953 conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
954 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
957 test "with credentials", %{conn: conn, user: current_user} do
958 note_activity = insert(:note_activity)
959 object = Object.normalize(note_activity)
960 ActivityPub.like(current_user, object)
964 |> with_credentials(current_user.nickname, "test")
965 |> post("/api/favorites/destroy/#{note_activity.id}.json")
967 assert json_response(conn, 200)
971 describe "POST /api/statuses/retweet/:id" do
974 test "without valid credentials", %{conn: conn} do
975 note_activity = insert(:note_activity)
976 conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
977 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
980 test "with credentials", %{conn: conn, user: current_user} do
981 note_activity = insert(:note_activity)
983 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
987 |> with_credentials(current_user.nickname, "test")
988 |> post(request_path)
990 activity = Activity.get_by_id(note_activity.id)
991 activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
993 assert json_response(response, 200) ==
994 ActivityView.render("activity.json", %{
1002 describe "POST /api/statuses/unretweet/:id" do
1005 test "without valid credentials", %{conn: conn} do
1006 note_activity = insert(:note_activity)
1007 conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
1008 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1011 test "with credentials", %{conn: conn, user: current_user} do
1012 note_activity = insert(:note_activity)
1014 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
1018 |> with_credentials(current_user.nickname, "test")
1019 |> post(request_path)
1021 request_path = String.replace(request_path, "retweet", "unretweet")
1025 |> with_credentials(current_user.nickname, "test")
1026 |> post(request_path)
1028 activity = Activity.get_by_id(note_activity.id)
1029 activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
1031 assert json_response(response, 200) ==
1032 ActivityView.render("activity.json", %{
1033 user: activity_user,
1040 describe "POST /api/account/register" do
1041 test "it creates a new user", %{conn: conn} do
1043 "nickname" => "lain",
1044 "email" => "lain@wired.jp",
1045 "fullname" => "lain iwakura",
1046 "bio" => "close the world.",
1047 "password" => "bear",
1053 |> post("/api/account/register", data)
1055 user = json_response(conn, 200)
1057 fetched_user = User.get_cached_by_nickname("lain")
1058 assert user == UserView.render("show.json", %{user: fetched_user})
1061 test "it returns errors on a problem", %{conn: conn} do
1063 "email" => "lain@wired.jp",
1064 "fullname" => "lain iwakura",
1065 "bio" => "close the world.",
1066 "password" => "bear",
1072 |> post("/api/account/register", data)
1074 errors = json_response(conn, 400)
1076 assert is_binary(errors["error"])
1080 describe "POST /api/account/password_reset, with valid parameters" do
1081 setup %{conn: conn} do
1082 user = insert(:user)
1083 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1084 %{conn: conn, user: user}
1087 test "it returns 204", %{conn: conn} do
1088 assert json_response(conn, :no_content)
1091 test "it creates a PasswordResetToken record for user", %{user: user} do
1092 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1096 test "it sends an email to user", %{user: user} do
1097 ObanHelpers.perform_all()
1098 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1100 email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
1101 notify_email = Pleroma.Config.get([:instance, :notify_email])
1102 instance_name = Pleroma.Config.get([:instance, :name])
1105 from: {instance_name, notify_email},
1106 to: {user.name, user.email},
1107 html_body: email.html_body
1112 describe "POST /api/account/password_reset, with invalid parameters" do
1115 test "it returns 404 when user is not found", %{conn: conn, user: user} do
1116 conn = post(conn, "/api/account/password_reset?email=nonexisting_#{user.email}")
1117 assert conn.status == 404
1118 assert conn.resp_body == ""
1121 test "it returns 400 when user is not local", %{conn: conn, user: user} do
1122 {:ok, user} = Repo.update(Changeset.change(user, local: false))
1123 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1124 assert conn.status == 400
1125 assert conn.resp_body == ""
1129 describe "GET /api/account/confirm_email/:id/:token" do
1131 user = insert(:user)
1132 info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
1136 |> Changeset.change()
1137 |> Changeset.put_embed(:info, info_change)
1140 assert user.info.confirmation_pending
1145 test "it redirects to root url", %{conn: conn, user: user} do
1146 conn = get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1148 assert 302 == conn.status
1151 test "it confirms the user account", %{conn: conn, user: user} do
1152 get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1154 user = User.get_cached_by_id(user.id)
1156 refute user.info.confirmation_pending
1157 refute user.info.confirmation_token
1160 test "it returns 500 if user cannot be found by id", %{conn: conn, user: user} do
1161 conn = get(conn, "/api/account/confirm_email/0/#{user.info.confirmation_token}")
1163 assert 500 == conn.status
1166 test "it returns 500 if token is invalid", %{conn: conn, user: user} do
1167 conn = get(conn, "/api/account/confirm_email/#{user.id}/wrong_token")
1169 assert 500 == conn.status
1173 describe "POST /api/account/resend_confirmation_email" do
1175 user = insert(:user)
1176 info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
1180 |> Changeset.change()
1181 |> Changeset.put_embed(:info, info_change)
1184 assert user.info.confirmation_pending
1189 clear_config([:instance, :account_activation_required]) do
1190 Pleroma.Config.put([:instance, :account_activation_required], true)
1193 test "it returns 204 No Content", %{conn: conn, user: user} do
1195 |> assign(:user, user)
1196 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1197 |> json_response(:no_content)
1200 test "it sends confirmation email", %{conn: conn, user: user} do
1202 |> assign(:user, user)
1203 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1205 ObanHelpers.perform_all()
1207 email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
1208 notify_email = Pleroma.Config.get([:instance, :notify_email])
1209 instance_name = Pleroma.Config.get([:instance, :name])
1212 from: {instance_name, notify_email},
1213 to: {user.name, user.email},
1214 html_body: email.html_body
1219 describe "GET /api/externalprofile/show" do
1220 test "it returns the user", %{conn: conn} do
1221 user = insert(:user)
1222 other_user = insert(:user)
1226 |> assign(:user, user)
1227 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
1229 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
1233 describe "GET /api/statuses/followers" do
1234 test "it returns a user's followers", %{conn: conn} do
1235 user = insert(:user)
1236 follower_one = insert(:user)
1237 follower_two = insert(:user)
1238 _not_follower = insert(:user)
1240 {:ok, follower_one} = User.follow(follower_one, user)
1241 {:ok, follower_two} = User.follow(follower_two, user)
1245 |> assign(:user, user)
1246 |> get("/api/statuses/followers")
1248 expected = UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
1249 result = json_response(conn, 200)
1250 assert Enum.sort(expected) == Enum.sort(result)
1253 test "it returns 20 followers per page", %{conn: conn} do
1254 user = insert(:user)
1255 followers = insert_list(21, :user)
1257 Enum.each(followers, fn follower ->
1258 User.follow(follower, user)
1263 |> assign(:user, user)
1264 |> get("/api/statuses/followers")
1266 result = json_response(res_conn, 200)
1267 assert length(result) == 20
1271 |> assign(:user, user)
1272 |> get("/api/statuses/followers?page=2")
1274 result = json_response(res_conn, 200)
1275 assert length(result) == 1
1278 test "it returns a given user's followers with user_id", %{conn: conn} do
1279 user = insert(:user)
1280 follower_one = insert(:user)
1281 follower_two = insert(:user)
1282 not_follower = insert(:user)
1284 {:ok, follower_one} = User.follow(follower_one, user)
1285 {:ok, follower_two} = User.follow(follower_two, user)
1289 |> assign(:user, not_follower)
1290 |> get("/api/statuses/followers", %{"user_id" => user.id})
1292 assert MapSet.equal?(
1293 MapSet.new(json_response(conn, 200)),
1295 UserView.render("index.json", %{
1296 users: [follower_one, follower_two],
1303 test "it returns empty when hide_followers is set to true", %{conn: conn} do
1304 user = insert(:user, %{info: %{hide_followers: true}})
1305 follower_one = insert(:user)
1306 follower_two = insert(:user)
1307 not_follower = insert(:user)
1309 {:ok, _follower_one} = User.follow(follower_one, user)
1310 {:ok, _follower_two} = User.follow(follower_two, user)
1314 |> assign(:user, not_follower)
1315 |> get("/api/statuses/followers", %{"user_id" => user.id})
1316 |> json_response(200)
1318 assert [] == response
1321 test "it returns the followers when hide_followers is set to true if requested by the user themselves",
1325 user = insert(:user, %{info: %{hide_followers: true}})
1326 follower_one = insert(:user)
1327 follower_two = insert(:user)
1328 _not_follower = insert(:user)
1330 {:ok, _follower_one} = User.follow(follower_one, user)
1331 {:ok, _follower_two} = User.follow(follower_two, user)
1335 |> assign(:user, user)
1336 |> get("/api/statuses/followers", %{"user_id" => user.id})
1338 refute [] == json_response(conn, 200)
1342 describe "GET /api/statuses/blocks" do
1343 test "it returns the list of users blocked by requester", %{conn: conn} do
1344 user = insert(:user)
1345 other_user = insert(:user)
1347 {:ok, user} = User.block(user, other_user)
1351 |> assign(:user, user)
1352 |> get("/api/statuses/blocks")
1354 expected = UserView.render("index.json", %{users: [other_user], for: user})
1355 result = json_response(conn, 200)
1356 assert Enum.sort(expected) == Enum.sort(result)
1360 describe "GET /api/statuses/friends" do
1361 test "it returns the logged in user's friends", %{conn: conn} do
1362 user = insert(:user)
1363 followed_one = insert(:user)
1364 followed_two = insert(:user)
1365 _not_followed = insert(:user)
1367 {:ok, user} = User.follow(user, followed_one)
1368 {:ok, user} = User.follow(user, followed_two)
1372 |> assign(:user, user)
1373 |> get("/api/statuses/friends")
1375 expected = UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1376 result = json_response(conn, 200)
1377 assert Enum.sort(expected) == Enum.sort(result)
1380 test "it returns 20 friends per page, except if 'export' is set to true", %{conn: conn} do
1381 user = insert(:user)
1382 followeds = insert_list(21, :user)
1385 Enum.reduce(followeds, {:ok, user}, fn followed, {:ok, user} ->
1386 User.follow(user, followed)
1391 |> assign(:user, user)
1392 |> get("/api/statuses/friends")
1394 result = json_response(res_conn, 200)
1395 assert length(result) == 20
1399 |> assign(:user, user)
1400 |> get("/api/statuses/friends", %{page: 2})
1402 result = json_response(res_conn, 200)
1403 assert length(result) == 1
1407 |> assign(:user, user)
1408 |> get("/api/statuses/friends", %{all: true})
1410 result = json_response(res_conn, 200)
1411 assert length(result) == 21
1414 test "it returns a given user's friends with user_id", %{conn: conn} do
1415 user = insert(:user)
1416 followed_one = insert(:user)
1417 followed_two = insert(:user)
1418 _not_followed = insert(:user)
1420 {:ok, user} = User.follow(user, followed_one)
1421 {:ok, user} = User.follow(user, followed_two)
1425 |> assign(:user, user)
1426 |> get("/api/statuses/friends", %{"user_id" => user.id})
1428 assert MapSet.equal?(
1429 MapSet.new(json_response(conn, 200)),
1431 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1436 test "it returns empty when hide_follows is set to true", %{conn: conn} do
1437 user = insert(:user, %{info: %{hide_follows: true}})
1438 followed_one = insert(:user)
1439 followed_two = insert(:user)
1440 not_followed = insert(:user)
1442 {:ok, user} = User.follow(user, followed_one)
1443 {:ok, user} = User.follow(user, followed_two)
1447 |> assign(:user, not_followed)
1448 |> get("/api/statuses/friends", %{"user_id" => user.id})
1450 assert [] == json_response(conn, 200)
1453 test "it returns friends when hide_follows is set to true if the user themselves request it",
1457 user = insert(:user, %{info: %{hide_follows: true}})
1458 followed_one = insert(:user)
1459 followed_two = insert(:user)
1460 _not_followed = insert(:user)
1462 {:ok, _user} = User.follow(user, followed_one)
1463 {:ok, _user} = User.follow(user, followed_two)
1467 |> assign(:user, user)
1468 |> get("/api/statuses/friends", %{"user_id" => user.id})
1469 |> json_response(200)
1471 refute [] == response
1474 test "it returns a given user's friends with screen_name", %{conn: conn} do
1475 user = insert(:user)
1476 followed_one = insert(:user)
1477 followed_two = insert(:user)
1478 _not_followed = insert(:user)
1480 {:ok, user} = User.follow(user, followed_one)
1481 {:ok, user} = User.follow(user, followed_two)
1485 |> assign(:user, user)
1486 |> get("/api/statuses/friends", %{"screen_name" => user.nickname})
1488 assert MapSet.equal?(
1489 MapSet.new(json_response(conn, 200)),
1491 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1497 describe "GET /friends/ids" do
1498 test "it returns a user's friends", %{conn: conn} do
1499 user = insert(:user)
1500 followed_one = insert(:user)
1501 followed_two = insert(:user)
1502 _not_followed = insert(:user)
1504 {:ok, user} = User.follow(user, followed_one)
1505 {:ok, user} = User.follow(user, followed_two)
1509 |> assign(:user, user)
1510 |> get("/api/friends/ids")
1512 expected = [followed_one.id, followed_two.id]
1514 assert MapSet.equal?(
1515 MapSet.new(Poison.decode!(json_response(conn, 200))),
1516 MapSet.new(expected)
1521 describe "POST /api/account/update_profile.json" do
1522 test "it updates a user's profile", %{conn: conn} do
1523 user = insert(:user)
1524 user2 = insert(:user)
1528 |> assign(:user, user)
1529 |> post("/api/account/update_profile.json", %{
1530 "name" => "new name",
1531 "description" => "hi @#{user2.nickname}"
1534 user = Repo.get!(User, user.id)
1535 assert user.name == "new name"
1538 "hi <span class='h-card'><a data-user='#{user2.id}' class='u-url mention' href='#{
1540 }'>@<span>#{user2.nickname}</span></a></span>"
1542 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1545 test "it sets and un-sets hide_follows", %{conn: conn} do
1546 user = insert(:user)
1549 |> assign(:user, user)
1550 |> post("/api/account/update_profile.json", %{
1551 "hide_follows" => "true"
1554 user = Repo.get!(User, user.id)
1555 assert user.info.hide_follows == true
1559 |> assign(:user, user)
1560 |> post("/api/account/update_profile.json", %{
1561 "hide_follows" => "false"
1564 user = refresh_record(user)
1565 assert user.info.hide_follows == false
1566 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1569 test "it sets and un-sets hide_followers", %{conn: conn} do
1570 user = insert(:user)
1573 |> assign(:user, user)
1574 |> post("/api/account/update_profile.json", %{
1575 "hide_followers" => "true"
1578 user = Repo.get!(User, user.id)
1579 assert user.info.hide_followers == true
1583 |> assign(:user, user)
1584 |> post("/api/account/update_profile.json", %{
1585 "hide_followers" => "false"
1588 user = Repo.get!(User, user.id)
1589 assert user.info.hide_followers == false
1590 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1593 test "it sets and un-sets show_role", %{conn: conn} do
1594 user = insert(:user)
1597 |> assign(:user, user)
1598 |> post("/api/account/update_profile.json", %{
1599 "show_role" => "true"
1602 user = Repo.get!(User, user.id)
1603 assert user.info.show_role == true
1607 |> assign(:user, user)
1608 |> post("/api/account/update_profile.json", %{
1609 "show_role" => "false"
1612 user = Repo.get!(User, user.id)
1613 assert user.info.show_role == false
1614 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1617 test "it sets and un-sets skip_thread_containment", %{conn: conn} do
1618 user = insert(:user)
1622 |> assign(:user, user)
1623 |> post("/api/account/update_profile.json", %{"skip_thread_containment" => "true"})
1624 |> json_response(200)
1626 assert response["pleroma"]["skip_thread_containment"] == true
1627 user = refresh_record(user)
1628 assert user.info.skip_thread_containment
1632 |> assign(:user, user)
1633 |> post("/api/account/update_profile.json", %{"skip_thread_containment" => "false"})
1634 |> json_response(200)
1636 assert response["pleroma"]["skip_thread_containment"] == false
1637 refute refresh_record(user).info.skip_thread_containment
1640 test "it locks an account", %{conn: conn} do
1641 user = insert(:user)
1645 |> assign(:user, user)
1646 |> post("/api/account/update_profile.json", %{
1650 user = Repo.get!(User, user.id)
1651 assert user.info.locked == true
1653 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1656 test "it unlocks an account", %{conn: conn} do
1657 user = insert(:user)
1661 |> assign(:user, user)
1662 |> post("/api/account/update_profile.json", %{
1666 user = Repo.get!(User, user.id)
1667 assert user.info.locked == false
1669 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1672 # Broken before the change to class="emoji" and non-<img/> in the DB
1674 test "it formats emojos", %{conn: conn} do
1675 user = insert(:user)
1679 |> assign(:user, user)
1680 |> post("/api/account/update_profile.json", %{
1681 "bio" => "I love our :moominmamma:"
1684 assert response = json_response(conn, 200)
1687 "description" => "I love our :moominmamma:",
1688 "description_html" =>
1689 ~s{I love our <img class="emoji" alt="moominmamma" title="moominmamma" src="} <>
1695 |> get("/api/users/show.json?user_id=#{user.nickname}")
1697 assert response == json_response(conn, 200)
1701 defp valid_user(_context) do
1702 user = insert(:user)
1706 defp with_credentials(conn, username, password) do
1707 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
1708 put_req_header(conn, "authorization", header_content)
1711 describe "GET /api/search.json" do
1712 test "it returns search results", %{conn: conn} do
1713 user = insert(:user)
1714 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1716 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1717 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1721 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
1723 assert [status] = json_response(conn, 200)
1724 assert status["id"] == activity.id
1728 describe "GET /api/statusnet/tags/timeline/:tag.json" do
1729 test "it returns the tags timeline", %{conn: conn} do
1730 user = insert(:user)
1731 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1733 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
1734 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1738 |> get("/api/statusnet/tags/timeline/2hu.json")
1740 assert [status] = json_response(conn, 200)
1741 assert status["id"] == activity.id
1745 test "Convert newlines to <br> in bio", %{conn: conn} do
1746 user = insert(:user)
1750 |> assign(:user, user)
1751 |> post("/api/account/update_profile.json", %{
1752 "description" => "Hello,\r\nWorld! I\n am a test."
1755 user = Repo.get!(User, user.id)
1756 assert user.bio == "Hello,<br>World! I<br> am a test."
1759 describe "POST /api/pleroma/change_password" do
1762 test "without credentials", %{conn: conn} do
1763 conn = post(conn, "/api/pleroma/change_password")
1764 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1767 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1770 |> with_credentials(current_user.nickname, "test")
1771 |> post("/api/pleroma/change_password", %{
1773 "new_password" => "newpass",
1774 "new_password_confirmation" => "newpass"
1777 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1780 test "with credentials, valid password and new password and confirmation not matching", %{
1786 |> with_credentials(current_user.nickname, "test")
1787 |> post("/api/pleroma/change_password", %{
1788 "password" => "test",
1789 "new_password" => "newpass",
1790 "new_password_confirmation" => "notnewpass"
1793 assert json_response(conn, 200) == %{
1794 "error" => "New password does not match confirmation."
1798 test "with credentials, valid password and invalid new password", %{
1804 |> with_credentials(current_user.nickname, "test")
1805 |> post("/api/pleroma/change_password", %{
1806 "password" => "test",
1807 "new_password" => "",
1808 "new_password_confirmation" => ""
1811 assert json_response(conn, 200) == %{
1812 "error" => "New password can't be blank."
1816 test "with credentials, valid password and matching new password and confirmation", %{
1822 |> with_credentials(current_user.nickname, "test")
1823 |> post("/api/pleroma/change_password", %{
1824 "password" => "test",
1825 "new_password" => "newpass",
1826 "new_password_confirmation" => "newpass"
1829 assert json_response(conn, 200) == %{"status" => "success"}
1830 fetched_user = User.get_cached_by_id(current_user.id)
1831 assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
1835 describe "POST /api/pleroma/delete_account" do
1838 test "without credentials", %{conn: conn} do
1839 conn = post(conn, "/api/pleroma/delete_account")
1840 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1843 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1846 |> with_credentials(current_user.nickname, "test")
1847 |> post("/api/pleroma/delete_account", %{"password" => "hi"})
1849 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1852 test "with credentials and valid password", %{conn: conn, user: current_user} do
1855 |> with_credentials(current_user.nickname, "test")
1856 |> post("/api/pleroma/delete_account", %{"password" => "test"})
1858 assert json_response(conn, 200) == %{"status" => "success"}
1859 # Wait a second for the started task to end
1864 describe "GET /api/pleroma/friend_requests" do
1865 test "it lists friend requests" do
1866 user = insert(:user)
1867 other_user = insert(:user)
1869 {:ok, _activity} = ActivityPub.follow(other_user, user)
1871 user = User.get_cached_by_id(user.id)
1872 other_user = User.get_cached_by_id(other_user.id)
1874 assert User.following?(other_user, user) == false
1878 |> assign(:user, user)
1879 |> get("/api/pleroma/friend_requests")
1881 assert [relationship] = json_response(conn, 200)
1882 assert other_user.id == relationship["id"]
1885 test "requires 'read' permission", %{conn: conn} do
1886 token1 = insert(:oauth_token, scopes: ["write"])
1887 token2 = insert(:oauth_token, scopes: ["read"])
1889 for token <- [token1, token2] do
1892 |> put_req_header("authorization", "Bearer #{token.token}")
1893 |> get("/api/pleroma/friend_requests")
1895 if token == token1 do
1896 assert %{"error" => "Insufficient permissions: read."} == json_response(conn, 403)
1898 assert json_response(conn, 200)
1904 describe "POST /api/pleroma/friendships/approve" do
1905 test "it approves a friend request" do
1906 user = insert(:user)
1907 other_user = insert(:user)
1909 {:ok, _activity} = ActivityPub.follow(other_user, user)
1911 user = User.get_cached_by_id(user.id)
1912 other_user = User.get_cached_by_id(other_user.id)
1914 assert User.following?(other_user, user) == false
1918 |> assign(:user, user)
1919 |> post("/api/pleroma/friendships/approve", %{"user_id" => other_user.id})
1921 assert relationship = json_response(conn, 200)
1922 assert other_user.id == relationship["id"]
1923 assert relationship["follows_you"] == true
1927 describe "POST /api/pleroma/friendships/deny" do
1928 test "it denies a friend request" do
1929 user = insert(:user)
1930 other_user = insert(:user)
1932 {:ok, _activity} = ActivityPub.follow(other_user, user)
1934 user = User.get_cached_by_id(user.id)
1935 other_user = User.get_cached_by_id(other_user.id)
1937 assert User.following?(other_user, user) == false
1941 |> assign(:user, user)
1942 |> post("/api/pleroma/friendships/deny", %{"user_id" => other_user.id})
1944 assert relationship = json_response(conn, 200)
1945 assert other_user.id == relationship["id"]
1946 assert relationship["follows_you"] == false
1950 describe "GET /api/pleroma/search_user" do
1951 test "it returns users, ordered by similarity", %{conn: conn} do
1952 user = insert(:user, %{name: "eal"})
1953 user_two = insert(:user, %{name: "eal me"})
1954 _user_three = insert(:user, %{name: "zzz"})
1958 |> get(twitter_api_search__path(conn, :search_user), query: "eal me")
1959 |> json_response(200)
1961 assert length(resp) == 2
1962 assert [user_two.id, user.id] == Enum.map(resp, fn %{"id" => id} -> id end)
1966 describe "POST /api/media/upload" do
1968 Pleroma.DataCase.ensure_local_uploader(context)
1971 test "it performs the upload and sets `data[actor]` with AP id of uploader user", %{
1974 user = insert(:user)
1976 upload_filename = "test/fixtures/image_tmp.jpg"
1977 File.cp!("test/fixtures/image.jpg", upload_filename)
1979 file = %Plug.Upload{
1980 content_type: "image/jpg",
1981 path: Path.absname(upload_filename),
1982 filename: "image.jpg"
1987 |> assign(:user, user)
1988 |> put_req_header("content-type", "application/octet-stream")
1989 |> post("/api/media/upload", %{
1992 |> json_response(:ok)
1994 assert response["media_id"]
1995 object = Repo.get(Object, response["media_id"])
1997 assert object.data["actor"] == User.ap_id(user)
2001 describe "POST /api/media/metadata/create" do
2003 object = insert(:note)
2004 user = User.get_cached_by_ap_id(object.data["actor"])
2005 %{object: object, user: user}
2008 test "it returns :forbidden status on attempt to modify someone else's upload", %{
2012 initial_description = object.data["name"]
2013 another_user = insert(:user)
2016 |> assign(:user, another_user)
2017 |> post("/api/media/metadata/create", %{"media_id" => object.id})
2018 |> json_response(:forbidden)
2020 object = Repo.get(Object, object.id)
2021 assert object.data["name"] == initial_description
2024 test "it updates `data[name]` of referenced Object with provided value", %{
2029 description = "Informative description of the image. Initial value: #{object.data["name"]}}"
2032 |> assign(:user, user)
2033 |> post("/api/media/metadata/create", %{
2034 "media_id" => object.id,
2035 "alt_text" => %{"text" => description}
2037 |> json_response(:no_content)
2039 object = Repo.get(Object, object.id)
2040 assert object.data["name"] == description
2044 describe "POST /api/statuses/user_timeline.json?user_id=:user_id&pinned=true" do
2045 test "it returns a list of pinned statuses", %{conn: conn} do
2046 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2048 user = insert(:user, %{name: "egor"})
2049 {:ok, %{id: activity_id}} = CommonAPI.post(user, %{"status" => "HI!!!"})
2050 {:ok, _} = CommonAPI.pin(activity_id, user)
2054 |> get("/api/statuses/user_timeline.json", %{user_id: user.id, pinned: true})
2055 |> json_response(200)
2057 assert length(resp) == 1
2058 assert [%{"id" => ^activity_id, "pinned" => true}] = resp
2062 describe "POST /api/statuses/pin/:id" do
2064 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2065 [user: insert(:user)]
2068 test "without valid credentials", %{conn: conn} do
2069 note_activity = insert(:note_activity)
2070 conn = post(conn, "/api/statuses/pin/#{note_activity.id}.json")
2071 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2074 test "with credentials", %{conn: conn, user: user} do
2075 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2077 request_path = "/api/statuses/pin/#{activity.id}.json"
2081 |> with_credentials(user.nickname, "test")
2082 |> post(request_path)
2084 user = refresh_record(user)
2086 assert json_response(response, 200) ==
2087 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2091 describe "POST /api/statuses/unpin/:id" do
2093 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2094 [user: insert(:user)]
2097 test "without valid credentials", %{conn: conn} do
2098 note_activity = insert(:note_activity)
2099 conn = post(conn, "/api/statuses/unpin/#{note_activity.id}.json")
2100 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2103 test "with credentials", %{conn: conn, user: user} do
2104 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2105 {:ok, activity} = CommonAPI.pin(activity.id, user)
2107 request_path = "/api/statuses/unpin/#{activity.id}.json"
2111 |> with_credentials(user.nickname, "test")
2112 |> post(request_path)
2114 user = refresh_record(user)
2116 assert json_response(response, 200) ==
2117 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2121 describe "GET /api/oauth_tokens" do
2123 token = insert(:oauth_token) |> Repo.preload(:user)
2128 test "renders list", %{token: token} do
2131 |> assign(:user, token.user)
2132 |> get("/api/oauth_tokens")
2135 json_response(response, 200)
2139 assert keys -- ["id", "app_name", "valid_until"] == []
2142 test "revoke token", %{token: token} do
2145 |> assign(:user, token.user)
2146 |> delete("/api/oauth_tokens/#{token.id}")
2148 tokens = Token.get_user_tokens(token.user)
2151 assert response.status == 201