Apply suggestion to test/web/mastodon_api/mastodon_api_controller_test.exs
[akkoma] / test / web / mastodon_api / mastodon_api_controller_test.exs
index c05c39db6df72d4dc3988d29230c0c43ec179d4a..7b337044c7a6ec4b40d80010dabaab9bc02427e5 100644 (file)
@@ -21,7 +21,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
   alias Pleroma.Web.OAuth.Token
   alias Pleroma.Web.OStatus
   alias Pleroma.Web.Push
-  alias Pleroma.Web.TwitterAPI.TwitterAPI
   import Pleroma.Factory
   import ExUnit.CaptureLog
   import Tesla.Mock
@@ -153,7 +152,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
       refute id == third_id
 
       # An activity that will expire:
-      expires_in = 120
+      # 2 hours
+      expires_in = 120 * 60
 
       conn_four =
         conn
@@ -168,12 +168,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
 
       estimated_expires_at =
         NaiveDateTime.utc_now()
-        |> NaiveDateTime.add(:timer.minutes(expires_in), :millisecond)
+        |> NaiveDateTime.add(expires_in)
         |> NaiveDateTime.truncate(:second)
 
       # This assert will fail if the test takes longer than a minute. I sure hope it never does:
       assert abs(NaiveDateTime.diff(expiration.scheduled_at, estimated_expires_at, :second)) < 60
-      assert fourth_response["pleroma"]["expires_at"] == NaiveDateTime.to_iso8601(expiration.scheduled_at)
+
+      assert fourth_response["pleroma"]["expires_at"] ==
+               NaiveDateTime.to_iso8601(expiration.scheduled_at)
     end
 
     test "replying to a status", %{conn: conn} do
@@ -924,106 +926,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     end
   end
 
-  describe "lists" do
-    test "creating a list", %{conn: conn} do
-      user = insert(:user)
-
-      conn =
-        conn
-        |> assign(:user, user)
-        |> post("/api/v1/lists", %{"title" => "cuties"})
-
-      assert %{"title" => title} = json_response(conn, 200)
-      assert title == "cuties"
-    end
-
-    test "adding users to a list", %{conn: conn} do
-      user = insert(:user)
-      other_user = insert(:user)
-      {:ok, list} = Pleroma.List.create("name", user)
-
-      conn =
-        conn
-        |> assign(:user, user)
-        |> post("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
-
-      assert %{} == json_response(conn, 200)
-      %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
-      assert following == [other_user.follower_address]
-    end
-
-    test "removing users from a list", %{conn: conn} do
-      user = insert(:user)
-      other_user = insert(:user)
-      third_user = insert(:user)
-      {:ok, list} = Pleroma.List.create("name", user)
-      {:ok, list} = Pleroma.List.follow(list, other_user)
-      {:ok, list} = Pleroma.List.follow(list, third_user)
-
-      conn =
-        conn
-        |> assign(:user, user)
-        |> delete("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
-
-      assert %{} == json_response(conn, 200)
-      %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
-      assert following == [third_user.follower_address]
-    end
-
-    test "listing users in a list", %{conn: conn} do
-      user = insert(:user)
-      other_user = insert(:user)
-      {:ok, list} = Pleroma.List.create("name", user)
-      {:ok, list} = Pleroma.List.follow(list, other_user)
-
-      conn =
-        conn
-        |> assign(:user, user)
-        |> get("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
-
-      assert [%{"id" => id}] = json_response(conn, 200)
-      assert id == to_string(other_user.id)
-    end
-
-    test "retrieving a list", %{conn: conn} do
-      user = insert(:user)
-      {:ok, list} = Pleroma.List.create("name", user)
-
-      conn =
-        conn
-        |> assign(:user, user)
-        |> get("/api/v1/lists/#{list.id}")
-
-      assert %{"id" => id} = json_response(conn, 200)
-      assert id == to_string(list.id)
-    end
-
-    test "renaming a list", %{conn: conn} do
-      user = insert(:user)
-      {:ok, list} = Pleroma.List.create("name", user)
-
-      conn =
-        conn
-        |> assign(:user, user)
-        |> put("/api/v1/lists/#{list.id}", %{"title" => "newname"})
-
-      assert %{"title" => name} = json_response(conn, 200)
-      assert name == "newname"
-    end
-
-    test "deleting a list", %{conn: conn} do
-      user = insert(:user)
-      {:ok, list} = Pleroma.List.create("name", user)
-
-      conn =
-        conn
-        |> assign(:user, user)
-        |> delete("/api/v1/lists/#{list.id}")
-
-      assert %{} = json_response(conn, 200)
-      assert is_nil(Repo.get(Pleroma.List, list.id))
-    end
-
+  describe "list timelines" do
     test "list timeline", %{conn: conn} do
       user = insert(:user)
       other_user = insert(:user)
@@ -1580,12 +1483,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
         filename: "an_image.jpg"
       }
 
-      media =
-        TwitterAPI.upload(file, user, "json")
-        |> Jason.decode!()
+      {:ok, %{id: media_id}} = ActivityPub.upload(file, actor: user.ap_id)
 
-      {:ok, image_post} =
-        CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media["media_id"]]})
+      {:ok, image_post} = CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media_id]})
 
       conn =
         conn
@@ -1651,6 +1551,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
 
       assert to_string(other_user.id) == relationship["id"]
     end
+
+    test "returns an empty list on a bad request", %{conn: conn} do
+      user = insert(:user)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/accounts/relationships", %{})
+
+      assert [] = json_response(conn, 200)
+    end
   end
 
   describe "media upload" do
@@ -1771,98 +1682,153 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     end
   end
 
-  test "account fetching", %{conn: conn} do
-    user = insert(:user)
+  describe "account fetching" do
+    test "works by id" do
+      user = insert(:user)
 
-    conn =
-      conn
-      |> get("/api/v1/accounts/#{user.id}")
+      conn =
+        build_conn()
+        |> get("/api/v1/accounts/#{user.id}")
 
-    assert %{"id" => id} = json_response(conn, 200)
-    assert id == to_string(user.id)
+      assert %{"id" => id} = json_response(conn, 200)
+      assert id == to_string(user.id)
 
-    conn =
-      build_conn()
-      |> get("/api/v1/accounts/-1")
+      conn =
+        build_conn()
+        |> get("/api/v1/accounts/-1")
 
-    assert %{"error" => "Can't find user"} = json_response(conn, 404)
-  end
+      assert %{"error" => "Can't find user"} = json_response(conn, 404)
+    end
 
-  test "account fetching also works nickname", %{conn: conn} do
-    user = insert(:user)
+    test "works by nickname" do
+      user = insert(:user)
 
-    conn =
-      conn
-      |> get("/api/v1/accounts/#{user.nickname}")
+      conn =
+        build_conn()
+        |> get("/api/v1/accounts/#{user.nickname}")
 
-    assert %{"id" => id} = json_response(conn, 200)
-    assert id == user.id
-  end
+      assert %{"id" => id} = json_response(conn, 200)
+      assert id == user.id
+    end
 
-  test "mascot upload", %{conn: conn} do
-    user = insert(:user)
+    test "works by nickname for remote users" do
+      limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
+      Pleroma.Config.put([:instance, :limit_to_local_content], false)
+      user = insert(:user, nickname: "user@example.com", local: false)
 
-    non_image_file = %Plug.Upload{
-      content_type: "audio/mpeg",
-      path: Path.absname("test/fixtures/sound.mp3"),
-      filename: "sound.mp3"
-    }
+      conn =
+        build_conn()
+        |> get("/api/v1/accounts/#{user.nickname}")
 
-    conn =
-      conn
-      |> assign(:user, user)
-      |> put("/api/v1/pleroma/mascot", %{"file" => non_image_file})
+      Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
+      assert %{"id" => id} = json_response(conn, 200)
+      assert id == user.id
+    end
 
-    assert json_response(conn, 415)
+    test "respects limit_to_local_content == :all for remote user nicknames" do
+      limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
+      Pleroma.Config.put([:instance, :limit_to_local_content], :all)
 
-    file = %Plug.Upload{
-      content_type: "image/jpg",
-      path: Path.absname("test/fixtures/image.jpg"),
-      filename: "an_image.jpg"
-    }
+      user = insert(:user, nickname: "user@example.com", local: false)
 
-    conn =
-      build_conn()
-      |> assign(:user, user)
-      |> put("/api/v1/pleroma/mascot", %{"file" => file})
+      conn =
+        build_conn()
+        |> get("/api/v1/accounts/#{user.nickname}")
+
+      Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
+      assert json_response(conn, 404)
+    end
+
+    test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
+      limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
+      Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
+
+      user = insert(:user, nickname: "user@example.com", local: false)
+      reading_user = insert(:user)
+
+      conn =
+        build_conn()
+        |> get("/api/v1/accounts/#{user.nickname}")
+
+      assert json_response(conn, 404)
 
-    assert %{"id" => _, "type" => image} = json_response(conn, 200)
+      conn =
+        build_conn()
+        |> assign(:user, reading_user)
+        |> get("/api/v1/accounts/#{user.nickname}")
+
+      Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
+      assert %{"id" => id} = json_response(conn, 200)
+      assert id == user.id
+    end
   end
 
-  test "mascot retrieving", %{conn: conn} do
-    user = insert(:user)
-    # When user hasn't set a mascot, we should just get pleroma tan back
-    conn =
-      conn
-      |> assign(:user, user)
-      |> get("/api/v1/pleroma/mascot")
+  describe "/api/v1/pleroma/mascot" do
+    test "mascot upload", %{conn: conn} do
+      user = insert(:user)
 
-    assert %{"url" => url} = json_response(conn, 200)
-    assert url =~ "pleroma-fox-tan-smol"
+      non_image_file = %Plug.Upload{
+        content_type: "audio/mpeg",
+        path: Path.absname("test/fixtures/sound.mp3"),
+        filename: "sound.mp3"
+      }
 
-    # When a user sets their mascot, we should get that back
-    file = %Plug.Upload{
-      content_type: "image/jpg",
-      path: Path.absname("test/fixtures/image.jpg"),
-      filename: "an_image.jpg"
-    }
+      conn =
+        conn
+        |> assign(:user, user)
+        |> put("/api/v1/pleroma/mascot", %{"file" => non_image_file})
 
-    conn =
-      build_conn()
-      |> assign(:user, user)
-      |> put("/api/v1/pleroma/mascot", %{"file" => file})
+      assert json_response(conn, 415)
 
-    assert json_response(conn, 200)
+      file = %Plug.Upload{
+        content_type: "image/jpg",
+        path: Path.absname("test/fixtures/image.jpg"),
+        filename: "an_image.jpg"
+      }
 
-    user = User.get_cached_by_id(user.id)
+      conn =
+        build_conn()
+        |> assign(:user, user)
+        |> put("/api/v1/pleroma/mascot", %{"file" => file})
 
-    conn =
-      build_conn()
-      |> assign(:user, user)
-      |> get("/api/v1/pleroma/mascot")
+      assert %{"id" => _, "type" => image} = json_response(conn, 200)
+    end
+
+    test "mascot retrieving", %{conn: conn} do
+      user = insert(:user)
+      # When user hasn't set a mascot, we should just get pleroma tan back
+      conn =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/pleroma/mascot")
+
+      assert %{"url" => url} = json_response(conn, 200)
+      assert url =~ "pleroma-fox-tan-smol"
+
+      # When a user sets their mascot, we should get that back
+      file = %Plug.Upload{
+        content_type: "image/jpg",
+        path: Path.absname("test/fixtures/image.jpg"),
+        filename: "an_image.jpg"
+      }
 
-    assert %{"url" => url, "type" => "image"} = json_response(conn, 200)
-    assert url =~ "an_image"
+      conn =
+        build_conn()
+        |> assign(:user, user)
+        |> put("/api/v1/pleroma/mascot", %{"file" => file})
+
+      assert json_response(conn, 200)
+
+      user = User.get_cached_by_id(user.id)
+
+      conn =
+        build_conn()
+        |> assign(:user, user)
+        |> get("/api/v1/pleroma/mascot")
+
+      assert %{"url" => url, "type" => "image"} = json_response(conn, 200)
+      assert url =~ "an_image"
+    end
   end
 
   test "hashtag timeline", %{conn: conn} do
@@ -2230,23 +2196,51 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     end
   end
 
-  test "subscribing / unsubscribing to a user", %{conn: conn} do
-    user = insert(:user)
-    subscription_target = insert(:user)
+  describe "subscribing / unsubscribing" do
+    test "subscribing / unsubscribing to a user", %{conn: conn} do
+      user = insert(:user)
+      subscription_target = insert(:user)
 
-    conn =
-      conn
-      |> assign(:user, user)
-      |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
+      conn =
+        conn
+        |> assign(:user, user)
+        |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
 
-    assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
+      assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
 
-    conn =
-      build_conn()
-      |> assign(:user, user)
-      |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
+      conn =
+        build_conn()
+        |> assign(:user, user)
+        |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
+
+      assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
+    end
+  end
+
+  describe "subscribing" do
+    test "returns 404 when subscription_target not found", %{conn: conn} do
+      user = insert(:user)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> post("/api/v1/pleroma/accounts/target_id/subscribe")
+
+      assert %{"error" => "Record not found"} = json_response(conn, 404)
+    end
+  end
+
+  describe "unsubscribing" do
+    test "returns 404 when subscription_target not found", %{conn: conn} do
+      user = insert(:user)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> post("/api/v1/pleroma/accounts/target_id/unsubscribe")
 
-    assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
+      assert %{"error" => "Record not found"} = json_response(conn, 404)
+    end
   end
 
   test "getting a list of mutes", %{conn: conn} do
@@ -2861,6 +2855,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
                }
              }
     end
+
+    test "returns empty object when id invalid", %{conn: conn} do
+      response =
+        conn
+        |> get("/api/v1/statuses/9eoozpwTul5mjSEDRI/card")
+        |> json_response(200)
+
+      assert response == %{}
+    end
   end
 
   test "bookmarks" do
@@ -3180,6 +3183,18 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
       assert conn.status == 302
       assert redirected_to(conn) == path
     end
+  end
+
+  describe "GET /web/login" do
+    test "redirects to /oauth/authorize", %{conn: conn} do
+      app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
+      conn = get(conn, "/web/login", %{})
+
+      assert conn.status == 302
+
+      assert redirected_to(conn) ==
+               "/oauth/authorize?response_type=code&client_id=#{app.client_id}&redirect_uri=.&scope=read+write+follow+push"
+    end
 
     test "redirects to the getting-started page when referer is not present", %{conn: conn} do
       app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
@@ -3190,6 +3205,18 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
       assert conn.status == 302
       assert redirected_to(conn) == "/web/getting-started"
     end
+
+    test "redirects to the getting-started page when user assigned", %{conn: conn} do
+      user = insert(:user)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> get("/web/login", %{})
+
+      assert conn.status == 302
+      assert redirected_to(conn) == "/web/getting-started"
+    end
   end
 
   describe "scheduled activities" do
@@ -3448,6 +3475,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
   end
 
   describe "create account by app" do
+    setup do
+      valid_params = %{
+        username: "lain",
+        email: "lain@example.org",
+        password: "PlzDontHackLain",
+        agreement: true
+      }
+
+      [valid_params: valid_params]
+    end
+
     test "Account registration via Application", %{conn: conn} do
       conn =
         conn
@@ -3491,6 +3529,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
           username: "lain",
           email: "lain@example.org",
           password: "PlzDontHackLain",
+          bio: "Test Bio",
           agreement: true
         })
 
@@ -3509,6 +3548,18 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
       assert token_from_db.user.info.confirmation_pending
     end
 
+    test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
+      _user = insert(:user, email: "lain@example.org")
+      app_token = insert(:oauth_token, user: nil)
+
+      conn =
+        conn
+        |> put_req_header("authorization", "Bearer " <> app_token.token)
+
+      res = post(conn, "/api/v1/accounts", valid_params)
+      assert json_response(res, 400) == %{"error" => "{\"email\":[\"has already been taken\"]}"}
+    end
+
     test "rate limit", %{conn: conn} do
       app_token = insert(:oauth_token, user: nil)
 
@@ -3552,6 +3603,41 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
 
       assert json_response(conn, :too_many_requests) == %{"error" => "Throttled"}
     end
+
+    test "returns bad_request if missing required params", %{
+      conn: conn,
+      valid_params: valid_params
+    } do
+      app_token = insert(:oauth_token, user: nil)
+
+      conn =
+        conn
+        |> put_req_header("authorization", "Bearer " <> app_token.token)
+
+      res = post(conn, "/api/v1/accounts", valid_params)
+      assert json_response(res, 200)
+
+      Enum.each(valid_params, fn {attr, _} ->
+        res =
+          conn
+          |> Map.put(
+            :remote_ip,
+            {:rand.uniform(15), :rand.uniform(15), :rand.uniform(15), :rand.uniform(15)}
+          )
+          |> post("/api/v1/accounts", Map.delete(valid_params, attr))
+
+        assert json_response(res, 400) == %{"error" => "Missing parameters"}
+      end)
+    end
+
+    test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
+      conn =
+        conn
+        |> put_req_header("authorization", "Bearer " <> "invalid-token")
+
+      res = post(conn, "/api/v1/accounts", valid_params)
+      assert json_response(res, 403) == %{"error" => "Invalid credentials"}
+    end
   end
 
   describe "GET /api/v1/polls/:id" do
@@ -4035,4 +4121,115 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
              ]
     end
   end
+
+  describe "PUT /api/v1/media/:id" do
+    setup do
+      actor = insert(:user)
+
+      file = %Plug.Upload{
+        content_type: "image/jpg",
+        path: Path.absname("test/fixtures/image.jpg"),
+        filename: "an_image.jpg"
+      }
+
+      {:ok, %Object{} = object} =
+        ActivityPub.upload(
+          file,
+          actor: User.ap_id(actor),
+          description: "test-m"
+        )
+
+      [actor: actor, object: object]
+    end
+
+    test "updates name of media", %{conn: conn, actor: actor, object: object} do
+      media =
+        conn
+        |> assign(:user, actor)
+        |> put("/api/v1/media/#{object.id}", %{"description" => "test-media"})
+        |> json_response(:ok)
+
+      assert media["description"] == "test-media"
+      assert refresh_record(object).data["name"] == "test-media"
+    end
+
+    test "returns error wheb request is bad", %{conn: conn, actor: actor, object: object} do
+      media =
+        conn
+        |> assign(:user, actor)
+        |> put("/api/v1/media/#{object.id}", %{})
+        |> json_response(400)
+
+      assert media == %{"error" => "bad_request"}
+    end
+  end
+
+  describe "DELETE /auth/sign_out" do
+    test "redirect to root page", %{conn: conn} do
+      user = insert(:user)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> delete("/auth/sign_out")
+
+      assert conn.status == 302
+      assert redirected_to(conn) == "/"
+    end
+  end
+
+  describe "GET /api/v1/accounts/:id/lists - account_lists" do
+    test "returns lists to which the account belongs", %{conn: conn} do
+      user = insert(:user)
+      other_user = insert(:user)
+      assert {:ok, %Pleroma.List{} = list} = Pleroma.List.create("Test List", user)
+      {:ok, %{following: _following}} = Pleroma.List.follow(list, other_user)
+
+      res =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/accounts/#{other_user.id}/lists")
+        |> json_response(200)
+
+      assert res == [%{"id" => to_string(list.id), "title" => "Test List"}]
+    end
+  end
+
+  describe "empty_array, stubs for mastodon api" do
+    test "GET /api/v1/accounts/:id/identity_proofs", %{conn: conn} do
+      user = insert(:user)
+
+      res =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/accounts/#{user.id}/identity_proofs")
+        |> json_response(200)
+
+      assert res == []
+    end
+
+    test "GET /api/v1/endorsements", %{conn: conn} do
+      user = insert(:user)
+
+      res =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/endorsements")
+        |> json_response(200)
+
+      assert res == []
+    end
+
+    test "GET /api/v1/trends", %{conn: conn} do
+      user = insert(:user)
+
+      res =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/trends")
+        |> json_response(200)
+
+      assert res == []
+    end
+  end
 end