From bd6e2b300f82e66afb121c2339c3cbbfb0b1a446 Mon Sep 17 00:00:00 2001
From: Egor Kislitsyn <egor@kislitsyn.com>
Date: Wed, 8 Apr 2020 23:16:20 +0400
Subject: [PATCH] Add spec for AccountController.followers

---
 .../api_spec/operations/account_operation.ex  | 19 ++++++++++++++++++-
 .../web/api_spec/schemas/accounts_response.ex | 13 +++++++++++++
 .../controllers/account_controller.ex         |  8 +++++++-
 .../controllers/account_controller_test.exs   |  4 ++++
 4 files changed, 42 insertions(+), 2 deletions(-)
 create mode 100644 lib/pleroma/web/api_spec/schemas/accounts_response.ex

diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index 09e6d24ed..070c74758 100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -11,6 +11,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
   alias Pleroma.Web.ApiSpec.Schemas.AccountCreateRequest
   alias Pleroma.Web.ApiSpec.Schemas.AccountCreateResponse
   alias Pleroma.Web.ApiSpec.Schemas.AccountRelationshipsResponse
+  alias Pleroma.Web.ApiSpec.Schemas.AccountsResponse
   alias Pleroma.Web.ApiSpec.Schemas.AccountUpdateCredentialsRequest
   alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
   alias Pleroma.Web.ApiSpec.Schemas.StatusesResponse
@@ -139,7 +140,23 @@ def statuses_operation do
   end
 
   def followers_operation do
-    :ok
+    %Operation{
+      tags: ["accounts"],
+      summary: "Followers",
+      operationId: "AccountController.followers",
+      security: [%{"oAuth" => ["read:accounts"]}],
+      description:
+        "Accounts which follow the given account, if network is not hidden by the account owner.",
+      parameters: [
+        %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
+        Operation.parameter(:max_id, :query, :string, "Max ID"),
+        Operation.parameter(:since_id, :query, :string, "Since ID"),
+        Operation.parameter(:limit, :query, :integer, "Limit")
+      ],
+      responses: %{
+        200 => Operation.response("Accounts", "application/json", AccountsResponse)
+      }
+    }
   end
 
   def following_operation, do: :ok
diff --git a/lib/pleroma/web/api_spec/schemas/accounts_response.ex b/lib/pleroma/web/api_spec/schemas/accounts_response.ex
new file mode 100644
index 000000000..b714f59e7
--- /dev/null
+++ b/lib/pleroma/web/api_spec/schemas/accounts_response.ex
@@ -0,0 +1,13 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.Schemas.AccountsResponse do
+  require OpenApiSpex
+
+  OpenApiSpex.schema(%{
+    title: "AccountsResponse",
+    type: :array,
+    items: Pleroma.Web.ApiSpec.Schemas.Account
+  })
+end
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index 208df5698..1ffccdd1d 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -89,7 +89,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
            :update_credentials,
            :relationships,
            :show,
-           :statuses
+           :statuses,
+           :followers
          ]
   )
 
@@ -284,6 +285,11 @@ def statuses(%{assigns: %{user: reading_user}} = conn, params) do
 
   @doc "GET /api/v1/accounts/:id/followers"
   def followers(%{assigns: %{user: for_user, account: user}} = conn, params) do
+    params =
+      params
+      |> Enum.map(fn {key, value} -> {to_string(key), value} end)
+      |> Enum.into(%{})
+
     followers =
       cond do
         for_user && user.id == for_user.id -> MastodonAPI.get_followers(user, params)
diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs
index 969256fa4..79b3adc69 100644
--- a/test/web/mastodon_api/controllers/account_controller_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller_test.exs
@@ -513,6 +513,7 @@ test "getting followers", %{user: user, conn: conn} do
 
       assert [%{"id" => id}] = json_response(conn, 200)
       assert id == to_string(user.id)
+      assert_schema(json_response(conn, 200), "AccountsResponse", ApiSpec.spec())
     end
 
     test "getting followers, hide_followers", %{user: user, conn: conn} do
@@ -536,6 +537,7 @@ test "getting followers, hide_followers, same user requesting" do
         |> get("/api/v1/accounts/#{other_user.id}/followers")
 
       refute [] == json_response(conn, 200)
+      assert_schema(json_response(conn, 200), "AccountsResponse", ApiSpec.spec())
     end
 
     test "getting followers, pagination", %{user: user, conn: conn} do
@@ -551,6 +553,7 @@ test "getting followers, pagination", %{user: user, conn: conn} do
       assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
       assert id3 == follower3.id
       assert id2 == follower2.id
+      assert_schema(json_response(res_conn, 200), "AccountsResponse", ApiSpec.spec())
 
       res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
 
@@ -566,6 +569,7 @@ test "getting followers, pagination", %{user: user, conn: conn} do
       assert [link_header] = get_resp_header(res_conn, "link")
       assert link_header =~ ~r/min_id=#{follower2.id}/
       assert link_header =~ ~r/max_id=#{follower2.id}/
+      assert_schema(json_response(res_conn, 200), "AccountsResponse", ApiSpec.spec())
     end
   end