+
+ test "media upload", %{conn: conn} do
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ desc = "Description of the image"
+
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/media", %{"file" => file, "description" => desc})
+
+ assert media = json_response(conn, 200)
+
+ assert media["type"] == "image"
+ assert media["description"] == desc
+ assert media["id"]
+
+ object = Repo.get(Object, media["id"])
+ assert object.data["actor"] == User.ap_id(user)
+ end
+
+ test "hashtag timeline", %{conn: conn} do
+ following = insert(:user)
+
+ capture_log(fn ->
+ {:ok, activity} = TwitterAPI.create_status(following, %{"status" => "test #2hu"})
+
+ {:ok, [_activity]} =
+ OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
+
+ nconn =
+ conn
+ |> get("/api/v1/timelines/tag/2hu")
+
+ assert [%{"id" => id}] = json_response(nconn, 200)
+
+ assert id == to_string(activity.id)
+
+ # works for different capitalization too
+ nconn =
+ conn
+ |> get("/api/v1/timelines/tag/2HU")
+
+ assert [%{"id" => id}] = json_response(nconn, 200)
+
+ assert id == to_string(activity.id)
+ end)
+ end
+
+ test "getting followers", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+ {:ok, user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{other_user.id}/followers")
+
+ assert [%{"id" => id}] = json_response(conn, 200)
+ assert id == to_string(user.id)
+ end
+
+ test "getting followers, hide_network", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user, %{info: %{hide_network: true}})
+ {:ok, _user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{other_user.id}/followers")
+
+ assert [] == json_response(conn, 200)
+ end
+
+ test "getting followers, hide_network, same user requesting", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user, %{info: %{hide_network: true}})
+ {:ok, _user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> assign(:user, other_user)
+ |> get("/api/v1/accounts/#{other_user.id}/followers")
+
+ refute [] == json_response(conn, 200)
+ end
+
+ test "getting following", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+ {:ok, user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/following")
+
+ assert [%{"id" => id}] = json_response(conn, 200)
+ assert id == to_string(other_user.id)
+ end
+
+ test "getting following, hide_network", %{conn: conn} do
+ user = insert(:user, %{info: %{hide_network: true}})
+ other_user = insert(:user)
+ {:ok, user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/following")
+
+ assert [] == json_response(conn, 200)
+ end
+
+ test "getting following, hide_network, same user requesting", %{conn: conn} do
+ user = insert(:user, %{info: %{hide_network: true}})
+ other_user = insert(:user)
+ {:ok, user} = User.follow(user, other_user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/#{user.id}/following")
+
+ refute [] == json_response(conn, 200)
+ end
+
+ test "following / unfollowing a user", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/follow")
+
+ assert %{"id" => _id, "following" => true} = json_response(conn, 200)
+
+ user = Repo.get(User, user.id)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/unfollow")
+
+ assert %{"id" => _id, "following" => false} = json_response(conn, 200)
+
+ user = Repo.get(User, user.id)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> post("/api/v1/follows", %{"uri" => other_user.nickname})
+
+ assert %{"id" => id} = json_response(conn, 200)
+ assert id == to_string(other_user.id)
+ end
+
+ test "blocking / unblocking a user", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/block")
+
+ assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
+
+ user = Repo.get(User, user.id)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/unblock")
+
+ assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
+ end
+
+ test "getting a list of blocks", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, user} = User.block(user, other_user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/blocks")
+
+ other_user_id = to_string(other_user.id)
+ assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
+ end
+
+ test "blocking / unblocking a domain", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
+
+ assert %{} = json_response(conn, 200)
+ user = User.get_cached_by_ap_id(user.ap_id)
+ assert User.blocks?(user, other_user)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
+
+ assert %{} = json_response(conn, 200)
+ user = User.get_cached_by_ap_id(user.ap_id)
+ refute User.blocks?(user, other_user)
+ end
+
+ test "getting a list of domain blocks", %{conn: conn} do
+ user = insert(:user)
+
+ {:ok, user} = User.block_domain(user, "bad.site")
+ {:ok, user} = User.block_domain(user, "even.worse.site")
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/domain_blocks")
+
+ domain_blocks = json_response(conn, 200)
+
+ assert "bad.site" in domain_blocks
+ assert "even.worse.site" in domain_blocks
+ end
+
+ test "unimplemented mute endpoints" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ ["mute", "unmute"]
+ |> Enum.each(fn endpoint ->
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> post("/api/v1/accounts/#{other_user.id}/#{endpoint}")
+
+ assert %{"id" => id} = json_response(conn, 200)
+ assert id == to_string(other_user.id)
+ end)
+ end
+
+ test "unimplemented mutes, follow_requests, blocks, domain blocks" do
+ user = insert(:user)
+
+ ["blocks", "domain_blocks", "mutes", "follow_requests"]
+ |> Enum.each(fn endpoint ->
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> get("/api/v1/#{endpoint}")
+
+ assert [] = json_response(conn, 200)
+ end)
+ end
+
+ test "account search", %{conn: conn} do
+ user = insert(:user)
+ user_two = insert(:user, %{nickname: "shp@shitposter.club"})
+ user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
+
+ results =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/search", %{"q" => "shp"})
+ |> json_response(200)
+
+ result_ids = for result <- results, do: result["acct"]
+
+ assert user_two.nickname in result_ids
+ assert user_three.nickname in result_ids
+
+ results =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/search", %{"q" => "2hu"})
+ |> json_response(200)
+
+ result_ids = for result <- results, do: result["acct"]
+
+ assert user_three.nickname in result_ids
+ end
+
+ test "search", %{conn: conn} do
+ user = insert(:user)
+ user_two = insert(:user, %{nickname: "shp@shitposter.club"})
+ user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
+
+ {:ok, _activity} =
+ CommonAPI.post(user, %{
+ "status" => "This is about 2hu, but private",
+ "visibility" => "private"
+ })
+
+ {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
+
+ conn =
+ conn
+ |> get("/api/v1/search", %{"q" => "2hu"})
+
+ assert results = json_response(conn, 200)
+
+ [account | _] = results["accounts"]
+ assert account["id"] == to_string(user_three.id)
+
+ assert results["hashtags"] == []
+
+ [status] = results["statuses"]
+ assert status["id"] == to_string(activity.id)
+ end
+
+ test "search fetches remote statuses", %{conn: conn} do
+ capture_log(fn ->
+ conn =
+ conn
+ |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
+
+ assert results = json_response(conn, 200)
+
+ [status] = results["statuses"]
+ assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
+ end)
+ end
+
+ test "search fetches remote accounts", %{conn: conn} do
+ conn =
+ conn
+ |> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"})
+
+ assert results = json_response(conn, 200)
+ [account] = results["accounts"]
+ assert account["acct"] == "shp@social.heldscal.la"
+ end
+
+ test "returns the favorites of a user", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
+ {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
+
+ {:ok, _, _} = CommonAPI.favorite(activity.id, user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/favourites")
+
+ assert [status] = json_response(conn, 200)
+ assert status["id"] == to_string(activity.id)
+ end
+
+ describe "updating credentials" do
+ test "updates the user's bio", %{conn: conn} do
+ user = insert(:user)
+ user2 = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/accounts/update_credentials", %{
+ "note" => "I drink #cofe with @#{user2.nickname}"
+ })
+
+ assert user = json_response(conn, 200)
+
+ assert user["note"] ==
+ "I drink <a data-tag=\"cofe\" href=\"http://localhost:4001/tag/cofe\">#cofe</a> with <span><a data-user=\"#{
+ user2.id
+ }\" href=\"#{user2.ap_id}\">@<span>#{user2.nickname}</span></a></span>"
+ end
+
+ test "updates the user's locking status", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/accounts/update_credentials", %{locked: "true"})
+
+ assert user = json_response(conn, 200)
+ assert user["locked"] == true
+ end
+
+ test "updates the user's name", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
+
+ assert user = json_response(conn, 200)
+ assert user["display_name"] == "markorepairs"
+ end
+
+ test "updates the user's avatar", %{conn: conn} do
+ user = insert(:user)
+
+ new_avatar = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
+
+ assert user_response = json_response(conn, 200)
+ assert user_response["avatar"] != User.avatar_url(user)
+ end
+
+ test "updates the user's banner", %{conn: conn} do
+ user = insert(:user)
+
+ new_header = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
+
+ assert user_response = json_response(conn, 200)
+ assert user_response["header"] != User.banner_url(user)
+ end
+ end
+
+ test "get instance information", %{conn: conn} do
+ insert(:user, %{local: true})
+ user = insert(:user, %{local: true})
+ insert(:user, %{local: false})
+
+ {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
+
+ Pleroma.Stats.update_stats()
+
+ conn =
+ conn
+ |> get("/api/v1/instance")
+
+ assert result = json_response(conn, 200)
+
+ assert result["stats"]["user_count"] == 2
+ assert result["stats"]["status_count"] == 1
+ end
+
+ test "put settings", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
+
+ assert result = json_response(conn, 200)
+
+ user = User.get_cached_by_ap_id(user.ap_id)
+ assert user.info.settings == %{"programming" => "socks"}
+ end