1 defmodule Pleroma.Web.TwitterAPI.ControllerTest do
2 use Pleroma.Web.ConnCase
3 alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
4 alias Pleroma.Builders.{ActivityBuilder, UserBuilder}
5 alias Pleroma.{Repo, Activity, User, Object, Notification}
6 alias Pleroma.Web.ActivityPub.ActivityPub
7 alias Pleroma.Web.TwitterAPI.UserView
8 alias Pleroma.Web.TwitterAPI.NotificationView
9 alias Pleroma.Web.CommonAPI
10 alias Pleroma.Web.TwitterAPI.TwitterAPI
13 import Pleroma.Factory
15 @banner "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
17 describe "POST /api/account/update_profile_banner" do
18 test "it updates the banner", %{conn: conn} do
22 |> assign(:user, user)
23 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => @banner})
26 user = refresh_record(user)
27 assert user.info.banner["type"] == "Image"
31 describe "POST /api/qvitter/update_background_image" do
32 test "it updates the background", %{conn: conn} do
36 |> assign(:user, user)
37 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => @banner})
40 user = refresh_record(user)
41 assert user.info.background["type"] == "Image"
45 describe "POST /api/account/verify_credentials" do
48 test "without valid credentials", %{conn: conn} do
49 conn = post(conn, "/api/account/verify_credentials.json")
50 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
53 test "with credentials", %{conn: conn, user: user} do
56 |> with_credentials(user.nickname, "test")
57 |> post("/api/account/verify_credentials.json")
60 assert response == UserView.render("show.json", %{user: user, token: response["token"]})
64 describe "POST /statuses/update.json" do
67 test "without valid credentials", %{conn: conn} do
68 conn = post(conn, "/api/statuses/update.json")
69 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
72 test "with credentials", %{conn: conn, user: user} do
73 conn_with_creds = conn |> with_credentials(user.nickname, "test")
74 request_path = "/api/statuses/update.json"
77 "request" => request_path,
78 "error" => "Client must provide a 'status' parameter with a value."
85 assert json_response(conn, 400) == error_response
89 |> post(request_path, %{status: ""})
91 assert json_response(conn, 400) == error_response
95 |> post(request_path, %{status: " "})
97 assert json_response(conn, 400) == error_response
99 # we post with visibility private in order to avoid triggering relay
102 |> post(request_path, %{status: "Nice meme.", visibility: "private"})
104 assert json_response(conn, 200) ==
105 ActivityRepresenter.to_map(Repo.one(Activity), %{user: user})
109 describe "GET /statuses/public_timeline.json" do
110 test "returns statuses", %{conn: conn} do
112 activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
113 ActivityBuilder.insert_list(10, %{}, %{user: user})
114 since_id = List.last(activities).id
118 |> get("/api/statuses/public_timeline.json", %{since_id: since_id})
120 response = json_response(conn, 200)
122 assert length(response) == 10
125 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
127 Application.get_env(:pleroma, :instance)
128 |> Keyword.put(:public, false)
130 Application.put_env(:pleroma, :instance, instance)
133 |> get("/api/statuses/public_timeline.json")
134 |> json_response(403)
137 Application.get_env(:pleroma, :instance)
138 |> Keyword.put(:public, true)
140 Application.put_env(:pleroma, :instance, instance)
143 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
145 |> get("/api/statuses/public_timeline.json")
146 |> json_response(200)
150 describe "GET /statuses/public_and_external_timeline.json" do
151 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
153 Application.get_env(:pleroma, :instance)
154 |> Keyword.put(:public, false)
156 Application.put_env(:pleroma, :instance, instance)
159 |> get("/api/statuses/public_and_external_timeline.json")
160 |> json_response(403)
163 Application.get_env(:pleroma, :instance)
164 |> Keyword.put(:public, true)
166 Application.put_env(:pleroma, :instance, instance)
169 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
171 |> get("/api/statuses/public_and_external_timeline.json")
172 |> json_response(200)
176 describe "GET /statuses/show/:id.json" do
177 test "returns one status", %{conn: conn} do
179 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
180 actor = Repo.get_by!(User, ap_id: activity.data["actor"])
184 |> get("/api/statuses/show/#{activity.id}.json")
186 response = json_response(conn, 200)
188 assert response == ActivityRepresenter.to_map(activity, %{user: actor})
192 describe "GET /users/show.json" do
193 test "gets user with screen_name", %{conn: conn} do
198 |> get("/api/users/show.json", %{"screen_name" => user.nickname})
200 response = json_response(conn, 200)
202 assert response["id"] == user.id
205 test "gets user with user_id", %{conn: conn} do
210 |> get("/api/users/show.json", %{"user_id" => user.id})
212 response = json_response(conn, 200)
214 assert response["id"] == user.id
217 test "gets a user for a logged in user", %{conn: conn} do
219 logged_in = insert(:user)
221 {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})
225 |> with_credentials(logged_in.nickname, "test")
226 |> get("/api/users/show.json", %{"user_id" => user.id})
228 response = json_response(conn, 200)
230 assert response["following"] == true
234 describe "GET /statusnet/conversation/:id.json" do
235 test "returns the statuses in the conversation", %{conn: conn} do
236 {:ok, _user} = UserBuilder.insert()
237 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
238 {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
239 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
243 |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
245 response = json_response(conn, 200)
247 assert length(response) == 2
251 describe "GET /statuses/friends_timeline.json" do
254 test "without valid credentials", %{conn: conn} do
255 conn = get(conn, "/api/statuses/friends_timeline.json")
256 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
259 test "with credentials", %{conn: conn, user: current_user} do
263 ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
265 returned_activities =
266 ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
268 other_user = insert(:user)
269 ActivityBuilder.insert_list(10, %{}, %{user: other_user})
270 since_id = List.last(activities).id
273 Ecto.Changeset.change(current_user, following: [User.ap_followers(user)])
278 |> with_credentials(current_user.nickname, "test")
279 |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
281 response = json_response(conn, 200)
283 assert length(response) == 10
286 Enum.map(returned_activities, fn activity ->
287 ActivityRepresenter.to_map(activity, %{
288 user: User.get_cached_by_ap_id(activity.data["actor"]),
295 describe "GET /statuses/dm_timeline.json" do
296 test "it show direct messages", %{conn: conn} do
297 user_one = insert(:user)
298 user_two = insert(:user)
300 {:ok, user_two} = User.follow(user_two, user_one)
303 CommonAPI.post(user_one, %{
304 "status" => "Hi @#{user_two.nickname}!",
305 "visibility" => "direct"
309 CommonAPI.post(user_two, %{
310 "status" => "Hi @#{user_one.nickname}!",
311 "visibility" => "direct"
314 {:ok, _follower_only} =
315 CommonAPI.post(user_one, %{
316 "status" => "Hi @#{user_two.nickname}!",
317 "visibility" => "private"
320 # Only direct should be visible here
323 |> assign(:user, user_two)
324 |> get("/api/statuses/dm_timeline.json")
326 [status, status_two] = json_response(res_conn, 200)
327 assert status["id"] == direct_two.id
328 assert status_two["id"] == direct.id
332 describe "GET /statuses/mentions.json" do
335 test "without valid credentials", %{conn: conn} do
336 conn = get(conn, "/api/statuses/mentions.json")
337 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
340 test "with credentials", %{conn: conn, user: current_user} do
342 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: current_user})
346 |> with_credentials(current_user.nickname, "test")
347 |> get("/api/statuses/mentions.json")
349 response = json_response(conn, 200)
351 assert length(response) == 1
353 assert Enum.at(response, 0) ==
354 ActivityRepresenter.to_map(activity, %{
356 mentioned: [current_user]
361 describe "GET /api/qvitter/statuses/notifications.json" do
364 test "without valid credentials", %{conn: conn} do
365 conn = get(conn, "/api/qvitter/statuses/notifications.json")
366 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
369 test "with credentials", %{conn: conn, user: current_user} do
370 other_user = insert(:user)
373 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
377 |> with_credentials(current_user.nickname, "test")
378 |> get("/api/qvitter/statuses/notifications.json")
380 response = json_response(conn, 200)
382 assert length(response) == 1
385 NotificationView.render("notification.json", %{
386 notifications: Notification.for_user(current_user),
392 describe "POST /api/qvitter/statuses/notifications/read" do
395 test "without valid credentials", %{conn: conn} do
396 conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567})
397 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
400 test "with credentials, without any params", %{conn: conn, user: current_user} do
403 |> with_credentials(current_user.nickname, "test")
404 |> post("/api/qvitter/statuses/notifications/read")
406 assert json_response(conn, 400) == %{
407 "error" => "You need to specify latest_id",
408 "request" => "/api/qvitter/statuses/notifications/read"
412 test "with credentials, with params", %{conn: conn, user: current_user} do
413 other_user = insert(:user)
416 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
420 |> with_credentials(current_user.nickname, "test")
421 |> get("/api/qvitter/statuses/notifications.json")
423 [notification] = response = json_response(response_conn, 200)
425 assert length(response) == 1
427 assert notification["is_seen"] == 0
431 |> with_credentials(current_user.nickname, "test")
432 |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]})
434 [notification] = response = json_response(response_conn, 200)
436 assert length(response) == 1
438 assert notification["is_seen"] == 1
442 describe "GET /statuses/user_timeline.json" do
445 test "without any params", %{conn: conn} do
446 conn = get(conn, "/api/statuses/user_timeline.json")
448 assert json_response(conn, 400) == %{
449 "error" => "You need to specify screen_name or user_id",
450 "request" => "/api/statuses/user_timeline.json"
454 test "with user_id", %{conn: conn} do
456 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
458 conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
459 response = json_response(conn, 200)
460 assert length(response) == 1
461 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
464 test "with screen_name", %{conn: conn} do
466 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
468 conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
469 response = json_response(conn, 200)
470 assert length(response) == 1
471 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
474 test "with credentials", %{conn: conn, user: current_user} do
475 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
479 |> with_credentials(current_user.nickname, "test")
480 |> get("/api/statuses/user_timeline.json")
482 response = json_response(conn, 200)
484 assert length(response) == 1
485 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: current_user})
488 test "with credentials with user_id", %{conn: conn, user: current_user} do
490 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
494 |> with_credentials(current_user.nickname, "test")
495 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
497 response = json_response(conn, 200)
499 assert length(response) == 1
500 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
503 test "with credentials screen_name", %{conn: conn, user: current_user} do
505 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
509 |> with_credentials(current_user.nickname, "test")
510 |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
512 response = json_response(conn, 200)
514 assert length(response) == 1
515 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
519 describe "POST /friendships/create.json" do
522 test "without valid credentials", %{conn: conn} do
523 conn = post(conn, "/api/friendships/create.json")
524 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
527 test "with credentials", %{conn: conn, user: current_user} do
528 followed = insert(:user)
532 |> with_credentials(current_user.nickname, "test")
533 |> post("/api/friendships/create.json", %{user_id: followed.id})
535 current_user = Repo.get(User, current_user.id)
536 assert User.ap_followers(followed) in current_user.following
538 assert json_response(conn, 200) ==
539 UserView.render("show.json", %{user: followed, for: current_user})
543 describe "POST /friendships/destroy.json" do
546 test "without valid credentials", %{conn: conn} do
547 conn = post(conn, "/api/friendships/destroy.json")
548 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
551 test "with credentials", %{conn: conn, user: current_user} do
552 followed = insert(:user)
554 {:ok, current_user} = User.follow(current_user, followed)
555 assert User.ap_followers(followed) in current_user.following
556 ActivityPub.follow(current_user, followed)
560 |> with_credentials(current_user.nickname, "test")
561 |> post("/api/friendships/destroy.json", %{user_id: followed.id})
563 current_user = Repo.get(User, current_user.id)
564 assert current_user.following == [current_user.ap_id]
566 assert json_response(conn, 200) ==
567 UserView.render("show.json", %{user: followed, for: current_user})
571 describe "POST /blocks/create.json" do
574 test "without valid credentials", %{conn: conn} do
575 conn = post(conn, "/api/blocks/create.json")
576 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
579 test "with credentials", %{conn: conn, user: current_user} do
580 blocked = insert(:user)
584 |> with_credentials(current_user.nickname, "test")
585 |> post("/api/blocks/create.json", %{user_id: blocked.id})
587 current_user = Repo.get(User, current_user.id)
588 assert User.blocks?(current_user, blocked)
590 assert json_response(conn, 200) ==
591 UserView.render("show.json", %{user: blocked, for: current_user})
595 describe "POST /blocks/destroy.json" do
598 test "without valid credentials", %{conn: conn} do
599 conn = post(conn, "/api/blocks/destroy.json")
600 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
603 test "with credentials", %{conn: conn, user: current_user} do
604 blocked = insert(:user)
606 {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
607 assert User.blocks?(current_user, blocked)
611 |> with_credentials(current_user.nickname, "test")
612 |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
614 current_user = Repo.get(User, current_user.id)
615 assert current_user.info.blocks == []
617 assert json_response(conn, 200) ==
618 UserView.render("show.json", %{user: blocked, for: current_user})
622 describe "GET /help/test.json" do
623 test "returns \"ok\"", %{conn: conn} do
624 conn = get(conn, "/api/help/test.json")
625 assert json_response(conn, 200) == "ok"
629 describe "POST /api/qvitter/update_avatar.json" do
632 test "without valid credentials", %{conn: conn} do
633 conn = post(conn, "/api/qvitter/update_avatar.json")
634 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
637 test "with credentials", %{conn: conn, user: current_user} do
638 avatar_image = File.read!("test/fixtures/avatar_data_uri")
642 |> with_credentials(current_user.nickname, "test")
643 |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
645 current_user = Repo.get(User, current_user.id)
646 assert is_map(current_user.avatar)
648 assert json_response(conn, 200) ==
649 UserView.render("show.json", %{user: current_user, for: current_user})
653 describe "GET /api/qvitter/mutes.json" do
656 test "unimplemented mutes without valid credentials", %{conn: conn} do
657 conn = get(conn, "/api/qvitter/mutes.json")
658 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
661 test "unimplemented mutes with credentials", %{conn: conn, user: current_user} do
664 |> with_credentials(current_user.nickname, "test")
665 |> get("/api/qvitter/mutes.json")
666 |> json_response(200)
672 describe "POST /api/favorites/create/:id" do
675 test "without valid credentials", %{conn: conn} do
676 note_activity = insert(:note_activity)
677 conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
678 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
681 test "with credentials", %{conn: conn, user: current_user} do
682 note_activity = insert(:note_activity)
686 |> with_credentials(current_user.nickname, "test")
687 |> post("/api/favorites/create/#{note_activity.id}.json")
689 assert json_response(conn, 200)
692 test "with credentials, invalid param", %{conn: conn, user: current_user} do
695 |> with_credentials(current_user.nickname, "test")
696 |> post("/api/favorites/create/wrong.json")
698 assert json_response(conn, 400)
701 test "with credentials, invalid activity", %{conn: conn, user: current_user} do
704 |> with_credentials(current_user.nickname, "test")
705 |> post("/api/favorites/create/1.json")
707 assert json_response(conn, 500)
711 describe "POST /api/favorites/destroy/:id" do
714 test "without valid credentials", %{conn: conn} do
715 note_activity = insert(:note_activity)
716 conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
717 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
720 test "with credentials", %{conn: conn, user: current_user} do
721 note_activity = insert(:note_activity)
722 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
723 ActivityPub.like(current_user, object)
727 |> with_credentials(current_user.nickname, "test")
728 |> post("/api/favorites/destroy/#{note_activity.id}.json")
730 assert json_response(conn, 200)
734 describe "POST /api/statuses/retweet/:id" do
737 test "without valid credentials", %{conn: conn} do
738 note_activity = insert(:note_activity)
739 conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
740 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
743 test "with credentials", %{conn: conn, user: current_user} do
744 note_activity = insert(:note_activity)
746 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
750 |> with_credentials(current_user.nickname, "test")
751 |> post(request_path)
753 activity = Repo.get(Activity, note_activity.id)
754 activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
756 assert json_response(response, 200) ==
757 ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
761 describe "POST /api/statuses/unretweet/:id" do
764 test "without valid credentials", %{conn: conn} do
765 note_activity = insert(:note_activity)
766 conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
767 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
770 test "with credentials", %{conn: conn, user: current_user} do
771 note_activity = insert(:note_activity)
773 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
777 |> with_credentials(current_user.nickname, "test")
778 |> post(request_path)
780 request_path = String.replace(request_path, "retweet", "unretweet")
784 |> with_credentials(current_user.nickname, "test")
785 |> post(request_path)
787 activity = Repo.get(Activity, note_activity.id)
788 activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
790 assert json_response(response, 200) ==
791 ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
795 describe "POST /api/account/register" do
796 test "it creates a new user", %{conn: conn} do
798 "nickname" => "lain",
799 "email" => "lain@wired.jp",
800 "fullname" => "lain iwakura",
801 "bio" => "close the world.",
802 "password" => "bear",
808 |> post("/api/account/register", data)
810 user = json_response(conn, 200)
812 fetched_user = Repo.get_by(User, nickname: "lain")
813 assert user == UserView.render("show.json", %{user: fetched_user})
816 test "it returns errors on a problem", %{conn: conn} do
818 "email" => "lain@wired.jp",
819 "fullname" => "lain iwakura",
820 "bio" => "close the world.",
821 "password" => "bear",
827 |> post("/api/account/register", data)
829 errors = json_response(conn, 400)
831 assert is_binary(errors["error"])
835 describe "GET /api/externalprofile/show" do
836 test "it returns the user", %{conn: conn} do
838 other_user = insert(:user)
842 |> assign(:user, user)
843 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
845 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
849 describe "GET /api/statuses/followers" do
850 test "it returns a user's followers", %{conn: conn} do
852 follower_one = insert(:user)
853 follower_two = insert(:user)
854 _not_follower = insert(:user)
856 {:ok, follower_one} = User.follow(follower_one, user)
857 {:ok, follower_two} = User.follow(follower_two, user)
861 |> assign(:user, user)
862 |> get("/api/statuses/followers")
864 expected = UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
865 result = json_response(conn, 200)
866 assert Enum.sort(expected) == Enum.sort(result)
869 test "it returns a given user's followers with user_id", %{conn: conn} do
871 follower_one = insert(:user)
872 follower_two = insert(:user)
873 not_follower = insert(:user)
875 {:ok, follower_one} = User.follow(follower_one, user)
876 {:ok, follower_two} = User.follow(follower_two, user)
880 |> assign(:user, not_follower)
881 |> get("/api/statuses/followers", %{"user_id" => user.id})
883 assert MapSet.equal?(
884 MapSet.new(json_response(conn, 200)),
886 UserView.render("index.json", %{
887 users: [follower_one, follower_two],
894 test "it returns empty for a hidden network", %{conn: conn} do
895 user = insert(:user, %{info: %{hide_network: true}})
896 follower_one = insert(:user)
897 follower_two = insert(:user)
898 not_follower = insert(:user)
900 {:ok, _follower_one} = User.follow(follower_one, user)
901 {:ok, _follower_two} = User.follow(follower_two, user)
905 |> assign(:user, not_follower)
906 |> get("/api/statuses/followers", %{"user_id" => user.id})
907 |> json_response(200)
909 assert [] == response
912 test "it returns the followers for a hidden network if requested by the user themselves", %{
915 user = insert(:user, %{info: %{hide_network: true}})
916 follower_one = insert(:user)
917 follower_two = insert(:user)
918 _not_follower = insert(:user)
920 {:ok, _follower_one} = User.follow(follower_one, user)
921 {:ok, _follower_two} = User.follow(follower_two, user)
925 |> assign(:user, user)
926 |> get("/api/statuses/followers", %{"user_id" => user.id})
928 refute [] == json_response(conn, 200)
932 describe "GET /api/statuses/friends" do
933 test "it returns the logged in user's friends", %{conn: conn} do
935 followed_one = insert(:user)
936 followed_two = insert(:user)
937 _not_followed = insert(:user)
939 {:ok, user} = User.follow(user, followed_one)
940 {:ok, user} = User.follow(user, followed_two)
944 |> assign(:user, user)
945 |> get("/api/statuses/friends")
947 expected = UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
948 result = json_response(conn, 200)
949 assert Enum.sort(expected) == Enum.sort(result)
952 test "it returns a given user's friends with user_id", %{conn: conn} do
954 followed_one = insert(:user)
955 followed_two = insert(:user)
956 _not_followed = insert(:user)
958 {:ok, user} = User.follow(user, followed_one)
959 {:ok, user} = User.follow(user, followed_two)
963 |> assign(:user, user)
964 |> get("/api/statuses/friends", %{"user_id" => user.id})
966 assert MapSet.equal?(
967 MapSet.new(json_response(conn, 200)),
969 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
974 test "it returns empty for a hidden network", %{conn: conn} do
975 user = insert(:user, %{info: %{hide_network: true}})
976 followed_one = insert(:user)
977 followed_two = insert(:user)
978 not_followed = insert(:user)
980 {:ok, user} = User.follow(user, followed_one)
981 {:ok, user} = User.follow(user, followed_two)
985 |> assign(:user, not_followed)
986 |> get("/api/statuses/friends", %{"user_id" => user.id})
988 assert [] == json_response(conn, 200)
991 test "it returns friends for a hidden network if the user themselves request it", %{
994 user = insert(:user, %{info: %{hide_network: true}})
995 followed_one = insert(:user)
996 followed_two = insert(:user)
997 _not_followed = insert(:user)
999 {:ok, _user} = User.follow(user, followed_one)
1000 {:ok, _user} = User.follow(user, followed_two)
1004 |> assign(:user, user)
1005 |> get("/api/statuses/friends", %{"user_id" => user.id})
1006 |> json_response(200)
1008 refute [] == response
1011 test "it returns a given user's friends with screen_name", %{conn: conn} do
1012 user = insert(:user)
1013 followed_one = insert(:user)
1014 followed_two = insert(:user)
1015 _not_followed = insert(:user)
1017 {:ok, user} = User.follow(user, followed_one)
1018 {:ok, user} = User.follow(user, followed_two)
1022 |> assign(:user, user)
1023 |> get("/api/statuses/friends", %{"screen_name" => user.nickname})
1025 assert MapSet.equal?(
1026 MapSet.new(json_response(conn, 200)),
1028 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1034 describe "GET /friends/ids" do
1035 test "it returns a user's friends", %{conn: conn} do
1036 user = insert(:user)
1037 followed_one = insert(:user)
1038 followed_two = insert(:user)
1039 _not_followed = insert(:user)
1041 {:ok, user} = User.follow(user, followed_one)
1042 {:ok, user} = User.follow(user, followed_two)
1046 |> assign(:user, user)
1047 |> get("/api/friends/ids")
1049 expected = [followed_one.id, followed_two.id]
1051 assert MapSet.equal?(
1052 MapSet.new(Poison.decode!(json_response(conn, 200))),
1053 MapSet.new(expected)
1058 describe "POST /api/account/update_profile.json" do
1059 test "it updates a user's profile", %{conn: conn} do
1060 user = insert(:user)
1061 user2 = insert(:user)
1065 |> assign(:user, user)
1066 |> post("/api/account/update_profile.json", %{
1067 "name" => "new name",
1068 "description" => "hi @#{user2.nickname}"
1071 user = Repo.get!(User, user.id)
1072 assert user.name == "new name"
1075 "hi <span><a data-user='#{user2.id}' class='mention' href='#{user2.ap_id}'>@<span>#{
1077 }</span></a></span>"
1079 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1082 test "it sets and un-sets hide_network", %{conn: conn} do
1083 user = insert(:user)
1086 |> assign(:user, user)
1087 |> post("/api/account/update_profile.json", %{
1088 "hide_network" => "true"
1091 user = Repo.get!(User, user.id)
1092 assert user.info.hide_network == true
1096 |> assign(:user, user)
1097 |> post("/api/account/update_profile.json", %{
1098 "hide_network" => "false"
1101 user = Repo.get!(User, user.id)
1102 assert user.info.hide_network == false
1103 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1106 test "it locks an account", %{conn: conn} do
1107 user = insert(:user)
1111 |> assign(:user, user)
1112 |> post("/api/account/update_profile.json", %{
1116 user = Repo.get!(User, user.id)
1117 assert user.info.locked == true
1119 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1122 test "it unlocks an account", %{conn: conn} do
1123 user = insert(:user)
1127 |> assign(:user, user)
1128 |> post("/api/account/update_profile.json", %{
1132 user = Repo.get!(User, user.id)
1133 assert user.info.locked == false
1135 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1139 defp valid_user(_context) do
1140 user = insert(:user)
1144 defp with_credentials(conn, username, password) do
1145 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
1146 put_req_header(conn, "authorization", header_content)
1149 describe "GET /api/search.json" do
1150 test "it returns search results", %{conn: conn} do
1151 user = insert(:user)
1152 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1154 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1155 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1159 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
1161 assert [status] = json_response(conn, 200)
1162 assert status["id"] == activity.id
1166 describe "GET /api/statusnet/tags/timeline/:tag.json" do
1167 test "it returns the tags timeline", %{conn: conn} do
1168 user = insert(:user)
1169 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1171 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
1172 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1176 |> get("/api/statusnet/tags/timeline/2hu.json")
1178 assert [status] = json_response(conn, 200)
1179 assert status["id"] == activity.id
1183 test "Convert newlines to <br> in bio", %{conn: conn} do
1184 user = insert(:user)
1188 |> assign(:user, user)
1189 |> post("/api/account/update_profile.json", %{
1190 "description" => "Hello,\r\nWorld! I\n am a test."
1193 user = Repo.get!(User, user.id)
1194 assert user.bio == "Hello,<br>World! I<br> am a test."
1197 describe "POST /api/pleroma/change_password" do
1200 test "without credentials", %{conn: conn} do
1201 conn = post(conn, "/api/pleroma/change_password")
1202 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1205 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1208 |> with_credentials(current_user.nickname, "test")
1209 |> post("/api/pleroma/change_password", %{
1211 "new_password" => "newpass",
1212 "new_password_confirmation" => "newpass"
1215 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1218 test "with credentials, valid password and new password and confirmation not matching", %{
1224 |> with_credentials(current_user.nickname, "test")
1225 |> post("/api/pleroma/change_password", %{
1226 "password" => "test",
1227 "new_password" => "newpass",
1228 "new_password_confirmation" => "notnewpass"
1231 assert json_response(conn, 200) == %{
1232 "error" => "New password does not match confirmation."
1236 test "with credentials, valid password and invalid new password", %{
1242 |> with_credentials(current_user.nickname, "test")
1243 |> post("/api/pleroma/change_password", %{
1244 "password" => "test",
1245 "new_password" => "",
1246 "new_password_confirmation" => ""
1249 assert json_response(conn, 200) == %{
1250 "error" => "New password can't be blank."
1254 test "with credentials, valid password and matching new password and confirmation", %{
1260 |> with_credentials(current_user.nickname, "test")
1261 |> post("/api/pleroma/change_password", %{
1262 "password" => "test",
1263 "new_password" => "newpass",
1264 "new_password_confirmation" => "newpass"
1267 assert json_response(conn, 200) == %{"status" => "success"}
1268 fetched_user = Repo.get(User, current_user.id)
1269 assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
1273 describe "POST /api/pleroma/delete_account" do
1276 test "without credentials", %{conn: conn} do
1277 conn = post(conn, "/api/pleroma/delete_account")
1278 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1281 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1284 |> with_credentials(current_user.nickname, "test")
1285 |> post("/api/pleroma/delete_account", %{"password" => "hi"})
1287 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1290 test "with credentials and valid password", %{conn: conn, user: current_user} do
1293 |> with_credentials(current_user.nickname, "test")
1294 |> post("/api/pleroma/delete_account", %{"password" => "test"})
1296 assert json_response(conn, 200) == %{"status" => "success"}
1297 # Wait a second for the started task to end
1302 describe "GET /api/pleroma/friend_requests" do
1303 test "it lists friend requests" do
1304 user = insert(:user)
1305 other_user = insert(:user)
1307 {:ok, _activity} = ActivityPub.follow(other_user, user)
1309 user = Repo.get(User, user.id)
1310 other_user = Repo.get(User, other_user.id)
1312 assert User.following?(other_user, user) == false
1316 |> assign(:user, user)
1317 |> get("/api/pleroma/friend_requests")
1319 assert [relationship] = json_response(conn, 200)
1320 assert other_user.id == relationship["id"]
1324 describe "POST /api/pleroma/friendships/approve" do
1325 test "it approves a friend request" do
1326 user = insert(:user)
1327 other_user = insert(:user)
1329 {:ok, _activity} = ActivityPub.follow(other_user, user)
1331 user = Repo.get(User, user.id)
1332 other_user = Repo.get(User, other_user.id)
1334 assert User.following?(other_user, user) == false
1338 |> assign(:user, user)
1339 |> post("/api/pleroma/friendships/approve", %{"user_id" => to_string(other_user.id)})
1341 assert relationship = json_response(conn, 200)
1342 assert other_user.id == relationship["id"]
1343 assert relationship["follows_you"] == true
1347 describe "POST /api/pleroma/friendships/deny" do
1348 test "it denies a friend request" do
1349 user = insert(:user)
1350 other_user = insert(:user)
1352 {:ok, _activity} = ActivityPub.follow(other_user, user)
1354 user = Repo.get(User, user.id)
1355 other_user = Repo.get(User, other_user.id)
1357 assert User.following?(other_user, user) == false
1361 |> assign(:user, user)
1362 |> post("/api/pleroma/friendships/deny", %{"user_id" => to_string(other_user.id)})
1364 assert relationship = json_response(conn, 200)
1365 assert other_user.id == relationship["id"]
1366 assert relationship["follows_you"] == false
1370 describe "GET /api/pleroma/search_user" do
1371 test "it returns users, ordered by similarity", %{conn: conn} do
1372 user = insert(:user, %{name: "eal"})
1373 user_two = insert(:user, %{name: "ean"})
1374 user_three = insert(:user, %{name: "ebn"})
1378 |> get(twitter_api_search__path(conn, :search_user), query: "eal")
1379 |> json_response(200)
1381 assert length(resp) == 3
1382 assert [user.id, user_two.id, user_three.id] == Enum.map(resp, fn %{"id" => id} -> id end)
1386 describe "POST /api/media/upload" do
1388 Pleroma.DataCase.ensure_local_uploader(context)
1391 test "it performs the upload and sets `data[actor]` with AP id of uploader user", %{
1394 user = insert(:user)
1396 upload_filename = "test/fixtures/image_tmp.jpg"
1397 File.cp!("test/fixtures/image.jpg", upload_filename)
1399 file = %Plug.Upload{
1400 content_type: "image/jpg",
1401 path: Path.absname(upload_filename),
1402 filename: "image.jpg"
1407 |> assign(:user, user)
1408 |> put_req_header("content-type", "application/octet-stream")
1409 |> post("/api/media/upload", %{
1412 |> json_response(:ok)
1414 assert response["media_id"]
1415 object = Repo.get(Object, response["media_id"])
1417 assert object.data["actor"] == User.ap_id(user)
1421 describe "POST /api/media/metadata/create" do
1423 object = insert(:note)
1424 user = User.get_by_ap_id(object.data["actor"])
1425 %{object: object, user: user}
1428 test "it returns :forbidden status on attempt to modify someone else's upload", %{
1432 initial_description = object.data["name"]
1433 another_user = insert(:user)
1436 |> assign(:user, another_user)
1437 |> post("/api/media/metadata/create", %{"media_id" => object.id})
1438 |> json_response(:forbidden)
1440 object = Repo.get(Object, object.id)
1441 assert object.data["name"] == initial_description
1444 test "it updates `data[name]` of referenced Object with provided value", %{
1449 description = "Informative description of the image. Initial value: #{object.data["name"]}}"
1452 |> assign(:user, user)
1453 |> post("/api/media/metadata/create", %{
1454 "media_id" => object.id,
1455 "alt_text" => %{"text" => description}
1457 |> json_response(:no_content)
1459 object = Repo.get(Object, object.id)
1460 assert object.data["name"] == description