Add OpenAPI spec for NotificationController
authorEgor Kislitsyn <egor@kislitsyn.com>
Tue, 28 Apr 2020 17:27:54 +0000 (21:27 +0400)
committerEgor Kislitsyn <egor@kislitsyn.com>
Tue, 28 Apr 2020 17:27:54 +0000 (21:27 +0400)
lib/pleroma/web/api_spec/helpers.ex
lib/pleroma/web/api_spec/operations/account_operation.ex
lib/pleroma/web/api_spec/operations/domain_block_operation.ex
lib/pleroma/web/api_spec/operations/notification_operation.ex [new file with mode: 0644]
lib/pleroma/web/mastodon_api/controllers/notification_controller.ex
lib/pleroma/web/router.ex
test/web/mastodon_api/controllers/notification_controller_test.exs

index ce40fb9e800575063ea7b81db416679a5efc7fa7..df08044864d4490815c4ce4cd83aa86cf1231328 100644 (file)
@@ -46,4 +46,12 @@ defmodule Pleroma.Web.ApiSpec.Helpers do
       )
     ]
   end
+
+  def empty_object_response do
+    Operation.response("Empty object", "application/json", %Schema{type: :object, example: %{}})
+  end
+
+  def empty_array_response do
+    Operation.response("Empty array", "application/json", %Schema{type: :array, example: []})
+  end
 end
index 2efe6e9013e265d799e42547d17f79c21c95e8e9..6fb6e627b3bdfcc8d6c55583d57c18d002e38a33 100644 (file)
@@ -343,7 +343,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
       description: "Not implemented",
       security: [%{"oAuth" => ["read:accounts"]}],
       responses: %{
-        200 => Operation.response("Empry array", "application/json", %Schema{type: :array})
+        200 => empty_array_response()
       }
     }
   end
@@ -355,7 +355,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
       operationId: "AccountController.identity_proofs",
       description: "Not implemented",
       responses: %{
-        200 => Operation.response("Empry array", "application/json", %Schema{type: :array})
+        200 => empty_array_response()
       }
     }
   end
index 3b7f51cebb152f71636f49d878de2d750d8c7b24..049bcf93139c5b1005bc292159c021922269fdd5 100644 (file)
@@ -5,7 +5,7 @@
 defmodule Pleroma.Web.ApiSpec.DomainBlockOperation do
   alias OpenApiSpex.Operation
   alias OpenApiSpex.Schema
-  alias Pleroma.Web.ApiSpec.Helpers
+  import Pleroma.Web.ApiSpec.Helpers
 
   def open_api_operation(action) do
     operation = String.to_existing_atom("#{action}_operation")
@@ -46,9 +46,7 @@ defmodule Pleroma.Web.ApiSpec.DomainBlockOperation do
       operationId: "DomainBlockController.create",
       requestBody: domain_block_request(),
       security: [%{"oAuth" => ["follow", "write:blocks"]}],
-      responses: %{
-        200 => Operation.response("Empty object", "application/json", %Schema{type: :object})
-      }
+      responses: %{200 => empty_object_response()}
     }
   end
 
@@ -67,7 +65,7 @@ defmodule Pleroma.Web.ApiSpec.DomainBlockOperation do
   end
 
   defp domain_block_request do
-    Helpers.request_body(
+    request_body(
       "Parameters",
       %Schema{
         type: :object,
diff --git a/lib/pleroma/web/api_spec/operations/notification_operation.ex b/lib/pleroma/web/api_spec/operations/notification_operation.ex
new file mode 100644 (file)
index 0000000..c6514f3
--- /dev/null
@@ -0,0 +1,202 @@
+# 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.NotificationOperation do
+  alias OpenApiSpex.Operation
+  alias OpenApiSpex.Operation
+  alias OpenApiSpex.Schema
+  alias Pleroma.Web.ApiSpec.Schemas.Account
+  alias Pleroma.Web.ApiSpec.Schemas.ApiError
+  alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
+  alias Pleroma.Web.ApiSpec.Schemas.Status
+  alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
+
+  import Pleroma.Web.ApiSpec.Helpers
+
+  def open_api_operation(action) do
+    operation = String.to_existing_atom("#{action}_operation")
+    apply(__MODULE__, operation, [])
+  end
+
+  def index_operation do
+    %Operation{
+      tags: ["Notifications"],
+      summary: "Get all notifications",
+      description:
+        "Notifications concerning the user. This API returns Link headers containing links to the next/previous page. However, the links can also be constructed dynamically using query params and `id` values.",
+      operationId: "NotificationController.index",
+      security: [%{"oAuth" => ["read:notifications"]}],
+      parameters:
+        [
+          Operation.parameter(
+            :exclude_types,
+            :query,
+            %Schema{type: :array, items: notification_type()},
+            "Array of types to exclude"
+          ),
+          Operation.parameter(
+            :account_id,
+            :query,
+            %Schema{type: :string},
+            "Return only notifications received from this account"
+          ),
+          Operation.parameter(
+            :exclude_visibilities,
+            :query,
+            %Schema{type: :array, items: VisibilityScope},
+            "Exclude the notifications for activities with the given visibilities"
+          ),
+          Operation.parameter(
+            :include_types,
+            :query,
+            %Schema{type: :array, items: notification_type()},
+            "Include the notifications for activities with the given types"
+          ),
+          Operation.parameter(
+            :with_muted,
+            :query,
+            BooleanLike,
+            "Include the notifications from muted users"
+          )
+        ] ++ pagination_params(),
+      responses: %{
+        200 =>
+          Operation.response("Array of notifications", "application/json", %Schema{
+            type: :array,
+            items: notification()
+          }),
+        404 => Operation.response("Error", "application/json", ApiError)
+      }
+    }
+  end
+
+  def show_operation do
+    %Operation{
+      tags: ["Notifications"],
+      summary: "Get a single notification",
+      description: "View information about a notification with a given ID.",
+      operationId: "NotificationController.show",
+      security: [%{"oAuth" => ["read:notifications"]}],
+      parameters: [id_param()],
+      responses: %{
+        200 => Operation.response("Notification", "application/json", notification())
+      }
+    }
+  end
+
+  def clear_operation do
+    %Operation{
+      tags: ["Notifications"],
+      summary: "Dismiss all notifications",
+      description: "Clear all notifications from the server.",
+      operationId: "NotificationController.clear",
+      security: [%{"oAuth" => ["write:notifications"]}],
+      responses: %{200 => empty_object_response()}
+    }
+  end
+
+  def dismiss_operation do
+    %Operation{
+      tags: ["Notifications"],
+      summary: "Dismiss a single notification",
+      description: "Clear a single notification from the server.",
+      operationId: "NotificationController.dismiss",
+      parameters: [id_param()],
+      security: [%{"oAuth" => ["write:notifications"]}],
+      responses: %{200 => empty_object_response()}
+    }
+  end
+
+  def dismiss_via_body_operation do
+    %Operation{
+      tags: ["Notifications"],
+      summary: "Dismiss a single notification",
+      deprecated: true,
+      description: "Clear a single notification from the server.",
+      operationId: "NotificationController.dismiss_via_body",
+      requestBody:
+        request_body(
+          "Parameters",
+          %Schema{type: :object, properties: %{id: %Schema{type: :string}}},
+          required: true
+        ),
+      security: [%{"oAuth" => ["write:notifications"]}],
+      responses: %{200 => empty_object_response()}
+    }
+  end
+
+  def destroy_multiple_operation do
+    %Operation{
+      tags: ["Notifications"],
+      summary: "Dismiss multiple notifications",
+      operationId: "NotificationController.destroy_multiple",
+      security: [%{"oAuth" => ["write:notifications"]}],
+      parameters: [
+        Operation.parameter(
+          :ids,
+          :query,
+          %Schema{type: :array, items: %Schema{type: :string}},
+          "Array of notification IDs to dismiss",
+          required: true
+        )
+      ],
+      responses: %{200 => empty_object_response()}
+    }
+  end
+
+  defp notification do
+    %Schema{
+      title: "Notification",
+      description: "Response schema for a notification",
+      type: :object,
+      properties: %{
+        id: %Schema{type: :string},
+        type: notification_type(),
+        created_at: %Schema{type: :string, format: :"date-time"},
+        account: %Schema{
+          allOf: [Account],
+          description: "The account that performed the action that generated the notification."
+        },
+        status: %Schema{
+          allOf: [Status],
+          description:
+            "Status that was the object of the notification, e.g. in mentions, reblogs, favourites, or polls.",
+          nullable: true
+        }
+      },
+      example: %{
+        "id" => "34975861",
+        "type" => "mention",
+        "created_at" => "2019-11-23T07:49:02.064Z",
+        "account" => Account.schema().example,
+        "status" => Status.schema().example
+      }
+    }
+  end
+
+  defp notification_type do
+    %Schema{
+      type: :string,
+      enum: ["follow", "favourite", "reblog", "mention", "poll", "pleroma:emoji_reaction", "move"],
+      description: """
+      The type of event that resulted in the notification.
+
+      - `follow` - Someone followed you
+      - `mention` - Someone mentioned you in their status
+      - `reblog` - Someone boosted one of your statuses
+      - `favourite` - Someone favourited one of your statuses
+      - `poll` - A poll you have voted in or created has ended
+      - `move` - Someone moved their account
+      - `pleroma:emoji_reaction` - Someone reacted with emoji to your status
+      """
+    }
+  end
+
+  defp id_param do
+    Operation.parameter(:id, :path, :string, "Notification ID",
+      example: "123",
+      required: true
+    )
+  end
+end
index 7fb536b0935e7e9c69590b3724487f66700c45ce..dcb421756631931b7c4c09547c317e919170f264 100644 (file)
@@ -13,6 +13,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
 
   @oauth_read_actions [:show, :index]
 
+  plug(OpenApiSpex.Plug.CastAndValidate, render_error: Pleroma.Web.ApiSpec.RenderError)
+
   plug(
     OAuthScopesPlug,
     %{scopes: ["read:notifications"]} when action in @oauth_read_actions
@@ -22,14 +24,16 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
 
   plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
 
+  defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.NotificationOperation
+
   # GET /api/v1/notifications
-  def index(conn, %{"account_id" => account_id} = params) do
+  def index(conn, %{account_id: account_id} = params) do
     case Pleroma.User.get_cached_by_id(account_id) do
       %{ap_id: account_ap_id} ->
         params =
           params
-          |> Map.delete("account_id")
-          |> Map.put("account_ap_id", account_ap_id)
+          |> Map.delete(:account_id)
+          |> Map.put(:account_ap_id, account_ap_id)
 
         index(conn, params)
 
@@ -41,6 +45,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
   end
 
   def index(%{assigns: %{user: user}} = conn, params) do
+    params = Map.new(params, fn {k, v} -> {to_string(k), v} end)
     notifications = MastodonAPI.get_notifications(user, params)
 
     conn
@@ -53,7 +58,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
   end
 
   # GET /api/v1/notifications/:id
-  def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+  def show(%{assigns: %{user: user}} = conn, %{id: id}) do
     with {:ok, notification} <- Notification.get(user, id) do
       render(conn, "show.json", notification: notification, for: user)
     else
@@ -71,8 +76,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
   end
 
   # POST /api/v1/notifications/:id/dismiss
-  # POST /api/v1/notifications/dismiss (deprecated)
-  def dismiss(%{assigns: %{user: user}} = conn, %{"id" => id} = _params) do
+
+  def dismiss(%{assigns: %{user: user}} = conn, %{id: id} = _params) do
     with {:ok, _notif} <- Notification.dismiss(user, id) do
       json(conn, %{})
     else
@@ -83,8 +88,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
     end
   end
 
+  # POST /api/v1/notifications/dismiss (deprecated)
+  def dismiss_via_body(%{body_params: params} = conn, _) do
+    dismiss(conn, params)
+  end
+
   # DELETE /api/v1/notifications/destroy_multiple
-  def destroy_multiple(%{assigns: %{user: user}} = conn, %{"ids" => ids} = _params) do
+  def destroy_multiple(%{assigns: %{user: user}} = conn, %{ids: ids} = _params) do
     Notification.destroy_multiple(user, ids)
     json(conn, %{})
   end
index 153802a432f42ff702b0684e87bce09ceab27d93..fe984b06c46ac6357c42bcc2d87161b777c4d50a 100644 (file)
@@ -344,7 +344,7 @@ defmodule Pleroma.Web.Router do
     post("/notifications/clear", NotificationController, :clear)
     delete("/notifications/destroy_multiple", NotificationController, :destroy_multiple)
     # Deprecated: was removed in Mastodon v3, use `/notifications/:id/dismiss` instead
-    post("/notifications/dismiss", NotificationController, :dismiss)
+    post("/notifications/dismiss", NotificationController, :dismiss_via_body)
 
     get("/scheduled_statuses", ScheduledActivityController, :index)
     get("/scheduled_statuses/:id", ScheduledActivityController, :show)
index 8c815b415eff8eb0d4c61b1838b1535dfb101a1a..db380f76a5580cb888e0829e68dd7f2711871be8 100644 (file)
@@ -25,7 +25,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
       conn
       |> assign(:user, user)
       |> get("/api/v1/notifications")
-      |> json_response(200)
+      |> json_response_and_validate_schema(200)
 
     assert Enum.all?(response, fn n ->
              get_in(n, ["account", "pleroma", "relationship"]) == %{}
@@ -50,7 +50,9 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
         user.ap_id
       }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
 
-    assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
+    assert [%{"status" => %{"content" => response}} | _rest] =
+             json_response_and_validate_schema(conn, 200)
+
     assert response == expected_response
   end
 
@@ -69,7 +71,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
         user.ap_id
       }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
 
-    assert %{"status" => %{"content" => response}} = json_response(conn, 200)
+    assert %{"status" => %{"content" => response}} = json_response_and_validate_schema(conn, 200)
     assert response == expected_response
   end
 
@@ -84,9 +86,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     conn =
       conn
       |> assign(:user, user)
-      |> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
+      |> put_req_header("content-type", "application/json")
+      |> post("/api/v1/notifications/dismiss", %{"id" => to_string(notification.id)})
 
-    assert %{} = json_response(conn, 200)
+    assert %{} = json_response_and_validate_schema(conn, 200)
   end
 
   test "dismissing a single notification" do
@@ -102,7 +105,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
       |> assign(:user, user)
       |> post("/api/v1/notifications/#{notification.id}/dismiss")
 
-    assert %{} = json_response(conn, 200)
+    assert %{} = json_response_and_validate_schema(conn, 200)
   end
 
   test "clearing all notifications" do
@@ -115,11 +118,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
 
     ret_conn = post(conn, "/api/v1/notifications/clear")
 
-    assert %{} = json_response(ret_conn, 200)
+    assert %{} = json_response_and_validate_schema(ret_conn, 200)
 
     ret_conn = get(conn, "/api/v1/notifications")
 
-    assert all = json_response(ret_conn, 200)
+    assert all = json_response_and_validate_schema(ret_conn, 200)
     assert all == []
   end
 
@@ -143,7 +146,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     result =
       conn
       |> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
-      |> json_response(:ok)
+      |> json_response_and_validate_schema(:ok)
 
     assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
 
@@ -151,7 +154,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     result =
       conn
       |> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
-      |> json_response(:ok)
+      |> json_response_and_validate_schema(:ok)
 
     assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
 
@@ -159,7 +162,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     result =
       conn
       |> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
-      |> json_response(:ok)
+      |> json_response_and_validate_schema(:ok)
 
     assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
   end
@@ -181,36 +184,28 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
       {:ok, private_activity} =
         CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "private"})
 
-      conn_res =
-        get(conn, "/api/v1/notifications", %{
-          exclude_visibilities: ["public", "unlisted", "private"]
-        })
+      query = params_to_query(%{exclude_visibilities: ["public", "unlisted", "private"]})
+      conn_res = get(conn, "/api/v1/notifications?" <> query)
 
-      assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+      assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
       assert id == direct_activity.id
 
-      conn_res =
-        get(conn, "/api/v1/notifications", %{
-          exclude_visibilities: ["public", "unlisted", "direct"]
-        })
+      query = params_to_query(%{exclude_visibilities: ["public", "unlisted", "direct"]})
+      conn_res = get(conn, "/api/v1/notifications?" <> query)
 
-      assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+      assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
       assert id == private_activity.id
 
-      conn_res =
-        get(conn, "/api/v1/notifications", %{
-          exclude_visibilities: ["public", "private", "direct"]
-        })
+      query = params_to_query(%{exclude_visibilities: ["public", "private", "direct"]})
+      conn_res = get(conn, "/api/v1/notifications?" <> query)
 
-      assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+      assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
       assert id == unlisted_activity.id
 
-      conn_res =
-        get(conn, "/api/v1/notifications", %{
-          exclude_visibilities: ["unlisted", "private", "direct"]
-        })
+      query = params_to_query(%{exclude_visibilities: ["unlisted", "private", "direct"]})
+      conn_res = get(conn, "/api/v1/notifications?" <> query)
 
-      assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+      assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
       assert id == public_activity.id
     end
 
@@ -237,8 +232,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
 
       activity_ids =
         conn
-        |> get("/api/v1/notifications", %{exclude_visibilities: ["direct"]})
-        |> json_response(200)
+        |> get("/api/v1/notifications?exclude_visibilities[]=direct")
+        |> json_response_and_validate_schema(200)
         |> Enum.map(& &1["status"]["id"])
 
       assert public_activity.id in activity_ids
@@ -248,8 +243,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
 
       activity_ids =
         conn
-        |> get("/api/v1/notifications", %{exclude_visibilities: ["unlisted"]})
-        |> json_response(200)
+        |> get("/api/v1/notifications?exclude_visibilities[]=unlisted")
+        |> json_response_and_validate_schema(200)
         |> Enum.map(& &1["status"]["id"])
 
       assert public_activity.id in activity_ids
@@ -259,8 +254,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
 
       activity_ids =
         conn
-        |> get("/api/v1/notifications", %{exclude_visibilities: ["private"]})
-        |> json_response(200)
+        |> get("/api/v1/notifications?exclude_visibilities[]=private")
+        |> json_response_and_validate_schema(200)
         |> Enum.map(& &1["status"]["id"])
 
       assert public_activity.id in activity_ids
@@ -270,8 +265,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
 
       activity_ids =
         conn
-        |> get("/api/v1/notifications", %{exclude_visibilities: ["public"]})
-        |> json_response(200)
+        |> get("/api/v1/notifications?exclude_visibilities[]=public")
+        |> json_response_and_validate_schema(200)
         |> Enum.map(& &1["status"]["id"])
 
       refute public_activity.id in activity_ids
@@ -295,8 +290,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
 
       activity_ids =
         conn
-        |> get("/api/v1/notifications", %{exclude_visibilities: ["unlisted"]})
-        |> json_response(200)
+        |> get("/api/v1/notifications?exclude_visibilities[]=unlisted")
+        |> json_response_and_validate_schema(200)
         |> Enum.map(& &1["status"]["id"])
 
       assert public_activity.id in activity_ids
@@ -319,25 +314,27 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     reblog_notification_id = get_notification_id_by_activity(reblog_activity)
     follow_notification_id = get_notification_id_by_activity(follow_activity)
 
-    conn_res =
-      get(conn, "/api/v1/notifications", %{exclude_types: ["mention", "favourite", "reblog"]})
+    query = params_to_query(%{exclude_types: ["mention", "favourite", "reblog"]})
+    conn_res = get(conn, "/api/v1/notifications?" <> query)
 
-    assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
+    assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
 
-    conn_res =
-      get(conn, "/api/v1/notifications", %{exclude_types: ["favourite", "reblog", "follow"]})
+    query = params_to_query(%{exclude_types: ["favourite", "reblog", "follow"]})
+    conn_res = get(conn, "/api/v1/notifications?" <> query)
 
-    assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
+    assert [%{"id" => ^mention_notification_id}] =
+             json_response_and_validate_schema(conn_res, 200)
 
-    conn_res =
-      get(conn, "/api/v1/notifications", %{exclude_types: ["reblog", "follow", "mention"]})
+    query = params_to_query(%{exclude_types: ["reblog", "follow", "mention"]})
+    conn_res = get(conn, "/api/v1/notifications?" <> query)
 
-    assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
+    assert [%{"id" => ^favorite_notification_id}] =
+             json_response_and_validate_schema(conn_res, 200)
 
-    conn_res =
-      get(conn, "/api/v1/notifications", %{exclude_types: ["follow", "mention", "favourite"]})
+    query = params_to_query(%{exclude_types: ["follow", "mention", "favourite"]})
+    conn_res = get(conn, "/api/v1/notifications?" <> query)
 
-    assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
+    assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
   end
 
   test "filters notifications using include_types" do
@@ -355,32 +352,34 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     reblog_notification_id = get_notification_id_by_activity(reblog_activity)
     follow_notification_id = get_notification_id_by_activity(follow_activity)
 
-    conn_res = get(conn, "/api/v1/notifications", %{include_types: ["follow"]})
+    conn_res = get(conn, "/api/v1/notifications?include_types[]=follow")
 
-    assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
+    assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
 
-    conn_res = get(conn, "/api/v1/notifications", %{include_types: ["mention"]})
+    conn_res = get(conn, "/api/v1/notifications?include_types[]=mention")
 
-    assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
+    assert [%{"id" => ^mention_notification_id}] =
+             json_response_and_validate_schema(conn_res, 200)
 
-    conn_res = get(conn, "/api/v1/notifications", %{include_types: ["favourite"]})
+    conn_res = get(conn, "/api/v1/notifications?include_types[]=favourite")
 
-    assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
+    assert [%{"id" => ^favorite_notification_id}] =
+             json_response_and_validate_schema(conn_res, 200)
 
-    conn_res = get(conn, "/api/v1/notifications", %{include_types: ["reblog"]})
+    conn_res = get(conn, "/api/v1/notifications?include_types[]=reblog")
 
-    assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
+    assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
 
-    result = conn |> get("/api/v1/notifications") |> json_response(200)
+    result = conn |> get("/api/v1/notifications") |> json_response_and_validate_schema(200)
 
     assert length(result) == 4
 
+    query = params_to_query(%{include_types: ["follow", "mention", "favourite", "reblog"]})
+
     result =
       conn
-      |> get("/api/v1/notifications", %{
-        include_types: ["follow", "mention", "favourite", "reblog"]
-      })
-      |> json_response(200)
+      |> get("/api/v1/notifications?" <> query)
+      |> json_response_and_validate_schema(200)
 
     assert length(result) == 4
   end
@@ -402,7 +401,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     result =
       conn
       |> get("/api/v1/notifications")
-      |> json_response(:ok)
+      |> json_response_and_validate_schema(:ok)
 
     assert [%{"id" => ^notification2_id}, %{"id" => ^notification1_id}] = result
 
@@ -414,22 +413,19 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     result =
       conn2
       |> get("/api/v1/notifications")
-      |> json_response(:ok)
+      |> json_response_and_validate_schema(:ok)
 
     assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
 
-    conn_destroy =
-      conn
-      |> delete("/api/v1/notifications/destroy_multiple", %{
-        "ids" => [notification1_id, notification2_id]
-      })
+    query = params_to_query(%{ids: [notification1_id, notification2_id]})
+    conn_destroy = delete(conn, "/api/v1/notifications/destroy_multiple?" <> query)
 
-    assert json_response(conn_destroy, 200) == %{}
+    assert json_response_and_validate_schema(conn_destroy, 200) == %{}
 
     result =
       conn2
       |> get("/api/v1/notifications")
-      |> json_response(:ok)
+      |> json_response_and_validate_schema(:ok)
 
     assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
   end
@@ -443,13 +439,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
 
     ret_conn = get(conn, "/api/v1/notifications")
 
-    assert length(json_response(ret_conn, 200)) == 1
+    assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
 
     {:ok, _user_relationships} = User.mute(user, user2)
 
     conn = get(conn, "/api/v1/notifications")
 
-    assert json_response(conn, 200) == []
+    assert json_response_and_validate_schema(conn, 200) == []
   end
 
   test "see notifications after muting user without notifications" do
@@ -461,13 +457,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
 
     ret_conn = get(conn, "/api/v1/notifications")
 
-    assert length(json_response(ret_conn, 200)) == 1
+    assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
 
     {:ok, _user_relationships} = User.mute(user, user2, false)
 
     conn = get(conn, "/api/v1/notifications")
 
-    assert length(json_response(conn, 200)) == 1
+    assert length(json_response_and_validate_schema(conn, 200)) == 1
   end
 
   test "see notifications after muting user with notifications and with_muted parameter" do
@@ -479,13 +475,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
 
     ret_conn = get(conn, "/api/v1/notifications")
 
-    assert length(json_response(ret_conn, 200)) == 1
+    assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
 
     {:ok, _user_relationships} = User.mute(user, user2)
 
-    conn = get(conn, "/api/v1/notifications", %{"with_muted" => "true"})
+    conn = get(conn, "/api/v1/notifications?with_muted=true")
 
-    assert length(json_response(conn, 200)) == 1
+    assert length(json_response_and_validate_schema(conn, 200)) == 1
   end
 
   @tag capture_log: true
@@ -512,7 +508,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
 
     conn = get(conn, "/api/v1/notifications")
 
-    assert length(json_response(conn, 200)) == 1
+    assert length(json_response_and_validate_schema(conn, 200)) == 1
   end
 
   describe "link headers" do
@@ -538,10 +534,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
       conn =
         conn
         |> assign(:user, user)
-        |> get("/api/v1/notifications", %{media_only: true})
+        |> get("/api/v1/notifications?limit=5")
 
       assert [link_header] = get_resp_header(conn, "link")
-      assert link_header =~ ~r/media_only=true/
+      assert link_header =~ ~r/limit=5/
       assert link_header =~ ~r/min_id=#{notification2.id}/
       assert link_header =~ ~r/max_id=#{notification1.id}/
     end
@@ -560,14 +556,14 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
       assert [%{"account" => %{"id" => ^account_id}}] =
                conn
                |> assign(:user, user)
-               |> get("/api/v1/notifications", %{account_id: account_id})
-               |> json_response(200)
+               |> get("/api/v1/notifications?account_id=#{account_id}")
+               |> json_response_and_validate_schema(200)
 
       assert %{"error" => "Account is not found"} =
                conn
                |> assign(:user, user)
-               |> get("/api/v1/notifications", %{account_id: "cofe"})
-               |> json_response(404)
+               |> get("/api/v1/notifications?account_id=cofe")
+               |> json_response_and_validate_schema(404)
     end
   end
 
@@ -577,4 +573,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     |> Map.get(:id)
     |> to_string()
   end
+
+  defp params_to_query(%{} = params) do
+    Enum.map_join(params, "&", fn
+      {k, v} when is_list(v) -> Enum.map_join(v, "&", &"#{k}[]=#{&1}")
+      {k, v} -> k <> "=" <> v
+    end)
+  end
 end