diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/support/api_spec_helpers.ex | 57 | ||||
-rw-r--r-- | test/support/conn_case.ex | 36 | ||||
-rw-r--r-- | test/web/api_spec/app_operation_test.exs | 45 | ||||
-rw-r--r-- | test/web/api_spec/schema_examples_test.exs | 43 | ||||
-rw-r--r-- | test/web/mastodon_api/controllers/app_controller_test.exs | 4 | ||||
-rw-r--r-- | test/web/mastodon_api/controllers/custom_emoji_controller_test.exs | 17 | ||||
-rw-r--r-- | test/web/mastodon_api/controllers/domain_block_controller_test.exs | 28 |
7 files changed, 146 insertions, 84 deletions
diff --git a/test/support/api_spec_helpers.ex b/test/support/api_spec_helpers.ex new file mode 100644 index 000000000..80c69c788 --- /dev/null +++ b/test/support/api_spec_helpers.ex @@ -0,0 +1,57 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Tests.ApiSpecHelpers do + @moduledoc """ + OpenAPI spec test helpers + """ + + import ExUnit.Assertions + + alias OpenApiSpex.Cast.Error + alias OpenApiSpex.Reference + alias OpenApiSpex.Schema + + def assert_schema(value, schema) do + api_spec = Pleroma.Web.ApiSpec.spec() + + case OpenApiSpex.cast_value(value, schema, api_spec) do + {:ok, data} -> + data + + {:error, errors} -> + errors = + Enum.map(errors, fn error -> + message = Error.message(error) + path = Error.path_to_string(error) + "#{message} at #{path}" + end) + + flunk( + "Value does not conform to schema #{schema.title}: #{Enum.join(errors, "\n")}\n#{ + inspect(value) + }" + ) + end + end + + def resolve_schema(%Schema{} = schema), do: schema + + def resolve_schema(%Reference{} = ref) do + schemas = Pleroma.Web.ApiSpec.spec().components.schemas + Reference.resolve_schema(ref, schemas) + end + + def api_operations do + paths = Pleroma.Web.ApiSpec.spec().paths + + Enum.flat_map(paths, fn {_, path_item} -> + path_item + |> Map.take([:delete, :get, :head, :options, :patch, :post, :put, :trace]) + |> Map.values() + |> Enum.reject(&is_nil/1) + |> Enum.uniq() + end) + end +end diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index 064874201..781622476 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -51,6 +51,42 @@ defmodule Pleroma.Web.ConnCase do %{user: user, token: token, conn: conn} end + defp json_response_and_validate_schema(conn, status \\ nil) do + content_type = + conn + |> Plug.Conn.get_resp_header("content-type") + |> List.first() + |> String.split(";") + |> List.first() + + status = status || conn.status + + %{private: %{open_api_spex: %{operation_id: op_id, operation_lookup: lookup, spec: spec}}} = + conn + + schema = lookup[op_id].responses[status].content[content_type].schema + json = json_response(conn, status) + + case OpenApiSpex.cast_value(json, schema, spec) do + {:ok, _data} -> + json + + {:error, errors} -> + errors = + Enum.map(errors, fn error -> + message = OpenApiSpex.Cast.Error.message(error) + path = OpenApiSpex.Cast.Error.path_to_string(error) + "#{message} at #{path}" + end) + + flunk( + "Response does not conform to schema of #{op_id} operation: #{ + Enum.join(errors, "\n") + }\n#{inspect(json)}" + ) + end + end + defp ensure_federating_or_authenticated(conn, url, user) do initial_setting = Config.get([:instance, :federating]) on_exit(fn -> Config.put([:instance, :federating], initial_setting) end) diff --git a/test/web/api_spec/app_operation_test.exs b/test/web/api_spec/app_operation_test.exs deleted file mode 100644 index 5b96abb44..000000000 --- a/test/web/api_spec/app_operation_test.exs +++ /dev/null @@ -1,45 +0,0 @@ -# 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.AppOperationTest do - use Pleroma.Web.ConnCase, async: true - - alias Pleroma.Web.ApiSpec - alias Pleroma.Web.ApiSpec.Schemas.AppCreateRequest - alias Pleroma.Web.ApiSpec.Schemas.AppCreateResponse - - import OpenApiSpex.TestAssertions - import Pleroma.Factory - - test "AppCreateRequest example matches schema" do - api_spec = ApiSpec.spec() - schema = AppCreateRequest.schema() - assert_schema(schema.example, "AppCreateRequest", api_spec) - end - - test "AppCreateResponse example matches schema" do - api_spec = ApiSpec.spec() - schema = AppCreateResponse.schema() - assert_schema(schema.example, "AppCreateResponse", api_spec) - end - - test "AppController produces a AppCreateResponse", %{conn: conn} do - api_spec = ApiSpec.spec() - app_attrs = build(:oauth_app) - - json = - conn - |> put_req_header("content-type", "application/json") - |> post( - "/api/v1/apps", - Jason.encode!(%{ - client_name: app_attrs.client_name, - redirect_uris: app_attrs.redirect_uris - }) - ) - |> json_response(200) - - assert_schema(json, "AppCreateResponse", api_spec) - end -end diff --git a/test/web/api_spec/schema_examples_test.exs b/test/web/api_spec/schema_examples_test.exs new file mode 100644 index 000000000..88b6f07cb --- /dev/null +++ b/test/web/api_spec/schema_examples_test.exs @@ -0,0 +1,43 @@ +# 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.SchemaExamplesTest do + use ExUnit.Case, async: true + import Pleroma.Tests.ApiSpecHelpers + + @content_type "application/json" + + for operation <- api_operations() do + describe operation.operationId <> " Request Body" do + if operation.requestBody do + @media_type operation.requestBody.content[@content_type] + @schema resolve_schema(@media_type.schema) + + if @media_type.example do + test "request body media type example matches schema" do + assert_schema(@media_type.example, @schema) + end + end + + if @schema.example do + test "request body schema example matches schema" do + assert_schema(@schema.example, @schema) + end + end + end + end + + for {status, response} <- operation.responses do + describe "#{operation.operationId} - #{status} Response" do + @schema resolve_schema(response.content[@content_type].schema) + + if @schema.example do + test "example matches schema" do + assert_schema(@schema.example, @schema) + end + end + end + end + end +end diff --git a/test/web/mastodon_api/controllers/app_controller_test.exs b/test/web/mastodon_api/controllers/app_controller_test.exs index e7b11d14e..a0b8b126c 100644 --- a/test/web/mastodon_api/controllers/app_controller_test.exs +++ b/test/web/mastodon_api/controllers/app_controller_test.exs @@ -27,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.AppControllerTest do "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key) } - assert expected == json_response(conn, 200) + assert expected == json_response_and_validate_schema(conn, 200) end test "creates an oauth app", %{conn: conn} do @@ -55,6 +55,6 @@ defmodule Pleroma.Web.MastodonAPI.AppControllerTest do "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key) } - assert expected == json_response(conn, 200) + assert expected == json_response_and_validate_schema(conn, 200) end end diff --git a/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs b/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs index 0b2ffa470..4222556a4 100644 --- a/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs +++ b/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs @@ -5,15 +5,13 @@ defmodule Pleroma.Web.MastodonAPI.CustomEmojiControllerTest do use Pleroma.Web.ConnCase, async: true alias Pleroma.Web.ApiSpec - alias Pleroma.Web.ApiSpec.Schemas.CustomEmoji - alias Pleroma.Web.ApiSpec.Schemas.CustomEmojisResponse import OpenApiSpex.TestAssertions test "with tags", %{conn: conn} do assert resp = conn |> get("/api/v1/custom_emojis") - |> json_response(200) + |> json_response_and_validate_schema(200) assert [emoji | _body] = resp assert Map.has_key?(emoji, "shortcode") @@ -23,19 +21,6 @@ defmodule Pleroma.Web.MastodonAPI.CustomEmojiControllerTest do assert Map.has_key?(emoji, "category") assert Map.has_key?(emoji, "url") assert Map.has_key?(emoji, "visible_in_picker") - assert_schema(resp, "CustomEmojisResponse", ApiSpec.spec()) assert_schema(emoji, "CustomEmoji", ApiSpec.spec()) end - - test "CustomEmoji example matches schema" do - api_spec = ApiSpec.spec() - schema = CustomEmoji.schema() - assert_schema(schema.example, "CustomEmoji", api_spec) - end - - test "CustomEmojisResponse example matches schema" do - api_spec = ApiSpec.spec() - schema = CustomEmojisResponse.schema() - assert_schema(schema.example, "CustomEmojisResponse", api_spec) - end end diff --git a/test/web/mastodon_api/controllers/domain_block_controller_test.exs b/test/web/mastodon_api/controllers/domain_block_controller_test.exs index d66190c90..01a24afcf 100644 --- a/test/web/mastodon_api/controllers/domain_block_controller_test.exs +++ b/test/web/mastodon_api/controllers/domain_block_controller_test.exs @@ -6,11 +6,8 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do use Pleroma.Web.ConnCase alias Pleroma.User - alias Pleroma.Web.ApiSpec - alias Pleroma.Web.ApiSpec.Schemas.DomainBlocksResponse import Pleroma.Factory - import OpenApiSpex.TestAssertions test "blocking / unblocking a domain" do %{user: user, conn: conn} = oauth_access(["write:blocks"]) @@ -21,7 +18,7 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do |> put_req_header("content-type", "application/json") |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"}) - assert %{} = json_response(ret_conn, 200) + assert %{} == json_response_and_validate_schema(ret_conn, 200) user = User.get_cached_by_ap_id(user.ap_id) assert User.blocks?(user, other_user) @@ -30,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do |> put_req_header("content-type", "application/json") |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"}) - assert %{} = json_response(ret_conn, 200) + assert %{} == json_response_and_validate_schema(ret_conn, 200) user = User.get_cached_by_ap_id(user.ap_id) refute User.blocks?(user, other_user) end @@ -41,21 +38,10 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do {: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 - assert_schema(domain_blocks, "DomainBlocksResponse", ApiSpec.spec()) - end - - test "DomainBlocksResponse example matches schema" do - api_spec = ApiSpec.spec() - schema = DomainBlocksResponse.schema() - assert_schema(schema.example, "DomainBlocksResponse", api_spec) + assert ["even.worse.site", "bad.site"] == + conn + |> assign(:user, user) + |> get("/api/v1/domain_blocks") + |> json_response_and_validate_schema(200) end end |