From cdb4461540844b344ad118797d06b132066830a2 Mon Sep 17 00:00:00 2001 From: Luca Corti Date: Mon, 23 May 2022 08:16:21 +0200 Subject: [PATCH] Improve CI pipeline (#377) * Improve test matrix * Run Dialyzer in CI * Run in CI * Only enforce formatting on latest elixir version Co-authored-by: Luca Corti Co-authored-by: Luca Corti --- .credo.exs | 19 ++++ .github/workflows/elixir.yml | 72 +++++++++----- .gitignore | 2 + .travis.yml | 32 ------- config/config.exs | 2 +- config/test.exs | 2 +- examples/phoenix_app/mix.exs | 2 +- lib/open_api_spex.ex | 4 +- lib/open_api_spex/cast.ex | 2 + lib/open_api_spex/cast/all_of.ex | 18 ++-- lib/open_api_spex/cast/discriminator.ex | 14 ++- lib/open_api_spex/cast/error.ex | 2 + lib/open_api_spex/cast/number.ex | 5 +- lib/open_api_spex/cast/string.ex | 1 + lib/open_api_spex/cast_parameters.ex | 2 +- lib/open_api_spex/components.ex | 16 ++-- lib/open_api_spex/controller.ex | 95 ++++++++++--------- lib/open_api_spex/deprecated_cast.ex | 47 ++++----- lib/open_api_spex/discriminator.ex | 12 ++- lib/open_api_spex/encoding.ex | 2 +- lib/open_api_spex/header.ex | 3 +- lib/open_api_spex/media_type.ex | 2 +- lib/open_api_spex/open_api.ex | 16 ++-- lib/open_api_spex/open_api/decode.ex | 13 ++- lib/open_api_spex/operation.ex | 9 +- lib/open_api_spex/operation2.ex | 6 +- lib/open_api_spex/operation_builder.ex | 5 +- lib/open_api_spex/parameter.ex | 6 +- lib/open_api_spex/path_item.ex | 2 +- lib/open_api_spex/paths.ex | 9 +- lib/open_api_spex/plug/app_env_cache.ex | 2 + lib/open_api_spex/plug/cache.ex | 2 +- lib/open_api_spex/plug/cast.ex | 4 +- lib/open_api_spex/plug/cast2.ex | 2 + lib/open_api_spex/plug/cast_and_validate.ex | 10 +- .../plug/default_render_error.ex | 2 + lib/open_api_spex/plug/json_render_error.ex | 2 +- .../plug/json_render_error_v2.ex | 2 +- lib/open_api_spex/plug/none_cache.ex | 2 + .../plug/persistent_term_cache.ex | 2 + lib/open_api_spex/plug/put_api_spec.ex | 3 +- lib/open_api_spex/plug/swagger_ui.ex | 2 +- lib/open_api_spex/plug/validate.ex | 8 +- lib/open_api_spex/reference.ex | 2 +- lib/open_api_spex/response.ex | 3 +- lib/open_api_spex/responses.ex | 2 +- lib/open_api_spex/schema.ex | 20 ++-- lib/open_api_spex/schema_consistency.ex | 2 +- lib/open_api_spex/schema_resolver.ex | 10 +- lib/open_api_spex/server.ex | 4 +- lib/open_api_spex/term_type.ex | 2 + lib/open_api_spex/test/assertions2.ex | 2 + mix.exs | 13 ++- mix.lock | 31 +++--- test/plug/cast_test.exs | 2 +- 55 files changed, 305 insertions(+), 253 deletions(-) create mode 100644 .credo.exs delete mode 100644 .travis.yml diff --git a/.credo.exs b/.credo.exs new file mode 100644 index 00000000..c3a518b6 --- /dev/null +++ b/.credo.exs @@ -0,0 +1,19 @@ +%{ + configs: [ + %{ + name: "default", + files: %{ + included: ["lib/"], + excluded: [] + }, + plugins: [], + requires: [], + strict: true, + parse_timeout: 5000, + color: true, + checks: [ + {Credo.Check.Consistency.ParameterPatternMatching, false} + ] + } + ] +} diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index 8a9c6558..e2811b31 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -7,35 +7,59 @@ on: branches: [master] jobs: - build: - name: Build and test - runs-on: ubuntu-18.04 + lint: + name: Lint (OTP ${{matrix.otp}} / Elixir ${{matrix.elixir}}) + runs-on: ubuntu-latest strategy: matrix: - elixir: [1.9, 1.12] - otp: [23.0] - + otp: ['25'] + elixir: ['1.13'] steps: - uses: actions/checkout@v2 - - name: Set up Elixir - uses: actions/setup-elixir@v1 + - uses: erlef/setup-beam@v1 + id: beam with: - elixir-version: ${{ matrix.elixir }} # Define the elixir version [required] - otp-version: ${{ matrix.otp }} # Define the OTP version [required] - - name: Restore dependencies cache + otp-version: ${{matrix.otp}} + elixir-version: ${{matrix.elixir}} + - name: PLT cache uses: actions/cache@v2 with: + key: | + ${{ runner.os }}-${{ steps.beam.outputs.elixir-version }}-${{ steps.beam.outputs.otp-version }}-plt + restore-keys: | + ${{ runner.os }}-${{ steps.beam.outputs.elixir-version }}-${{ steps.beam.outputs.otp-version }}-plt + path: | + priv/plts + - run: mix deps.get + - run: mix compile --warnings-as-errors + - run: mix format --check-formatted + - run: mix credo --strict --all + - run: mix dialyzer + test: + runs-on: ubuntu-latest + name: Test (OTP ${{matrix.otp}} / Elixir ${{matrix.elixir}}) + strategy: + matrix: + otp: ['22', '23', '24', '25'] + elixir: ['1.10', '1.11', '1.12', '1.13'] + exclude: + - {otp: '24', elixir: '1.10'} + - {otp: '25', elixir: '1.10'} + - {otp: '25', elixir: '1.11'} + - {otp: '25', elixir: '1.12'} + steps: + - uses: actions/checkout@v2 + - uses: erlef/setup-beam@v1 + with: + otp-version: ${{matrix.otp}} + elixir-version: ${{matrix.elixir}} + - uses: actions/cache@v2 + with: + key: | + ${{ runner.os }}-${{ steps.beam.outputs.elixir-version }}-${{ steps.beam.outputs.otp-version }}-build + restore-keys: | + ${{ runner.os }}-${{ steps.beam.outputs.elixir-version }}-${{ steps.beam.outputs.otp-version }}-build path: | - deps - _build/test - key: ${{ runner.os }}-deps-${{ hashFiles('**/mix.lock', '**/config/*.exs') }} - restore-keys: ${{ runner.os }}-deps- - - name: Install and compile dependencies - run: MIX_ENV=test mix do deps.get, deps.compile - - name: Compile application - run: MIX_ENV=test mix compile --warnings-as-errors - - name: Check formatting - if: ${{ matrix.elixir == '1.12' }} - run: mix format --check-formatted - - name: Run tests - run: mix test + _build + - run: mix deps.get + - run: mix test diff --git a/.gitignore b/.gitignore index 9e28806f..9ca9b3b1 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ open_api_spex-*.tar .vscode/ .idea *.iml + +/priv/plts diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index dcf932f9..00000000 --- a/.travis.yml +++ /dev/null @@ -1,32 +0,0 @@ -language: elixir - -elixir: - - 1.8 - - 1.9 - - 1.10 - -otp_release: - - 20.3 - - 21.3 - - 22.3 - - 23.0 - -jobs: - exclude: - - elixir: 1.8 - otp_release: 23.0 - - elixir: 1.9 - otp_release: 23.0 - - elixir: 1.10 - otp_release: 20.3 - -script: - - mix compile --warnings-as-errors - - mix test - - mix format --check-formatted - - mix dialyzer --halt-exit-status - -cache: - directories: - - _build - - deps diff --git a/config/config.exs b/config/config.exs index 9c0a0c0d..dafa9905 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,6 +1,6 @@ # This file is responsible for configuring your application # and its dependencies with the aid of the Mix.Config module. -use Mix.Config +import Config # This configuration is loaded before any dependency and is restricted # to this project. If another project depends on this project, this diff --git a/config/test.exs b/config/test.exs index 96d9fcc8..477c9079 100644 --- a/config/test.exs +++ b/config/test.exs @@ -1,3 +1,3 @@ -use Mix.Config +import Config config :logger, level: :info diff --git a/examples/phoenix_app/mix.exs b/examples/phoenix_app/mix.exs index 4c555267..8971eb8e 100644 --- a/examples/phoenix_app/mix.exs +++ b/examples/phoenix_app/mix.exs @@ -42,11 +42,11 @@ defmodule PhoenixApp.Mixfile do [ {:open_api_spex, path: "../../"}, {:ecto, "~> 2.2"}, + {:httpoison, "~> 1.7"}, {:sqlite_ecto2, "~> 2.4"}, {:phoenix, "~> 1.4"}, {:plug_cowboy, "~> 2.0"}, {:jason, "~> 1.0"}, - {:httpoison, "~> 1.7"}, {:dialyxir, "1.0.0-rc.6", only: [:dev], runtime: false} ] end diff --git a/lib/open_api_spex.ex b/lib/open_api_spex.ex index 384844f9..a88c56bd 100644 --- a/lib/open_api_spex.ex +++ b/lib/open_api_spex.ex @@ -10,9 +10,9 @@ defmodule OpenApiSpex do Operation2, Reference, Schema, + SchemaConsistency, SchemaException, - SchemaResolver, - SchemaConsistency + SchemaResolver } alias OpenApiSpex.Cast.Error diff --git a/lib/open_api_spex/cast.ex b/lib/open_api_spex/cast.ex index 7d24e524..b80d058a 100644 --- a/lib/open_api_spex/cast.ex +++ b/lib/open_api_spex/cast.ex @@ -1,4 +1,6 @@ defmodule OpenApiSpex.Cast do + @moduledoc "Cast and validate a value against an OpenApiSpex schema" + alias OpenApiSpex.{Reference, Schema} alias OpenApiSpex.Reference diff --git a/lib/open_api_spex/cast/all_of.ex b/lib/open_api_spex/cast/all_of.ex index 591e7f85..d3cd2030 100644 --- a/lib/open_api_spex/cast/all_of.ex +++ b/lib/open_api_spex/cast/all_of.ex @@ -17,13 +17,11 @@ defmodule OpenApiSpex.Cast.AllOf do {:ok, Enum.concat(acc, value)} {:error, errors} -> - with {:ok, cleaned_ctx} <- reject_error_values(ctx, errors) do - case Cast.cast(cleaned_ctx) do - {:ok, cleaned_values} -> - new_ctx = put_in(ctx.schema.allOf, remaining) - new_ctx = update_in(new_ctx.value, fn values -> values -- cleaned_ctx.value end) - cast_all_of(new_ctx, Enum.concat(acc, cleaned_values)) - end + with {:ok, cleaned_ctx} <- reject_error_values(ctx, errors), + {:ok, cleaned_values} <- Cast.cast(cleaned_ctx) do + new_ctx = put_in(ctx.schema.allOf, remaining) + new_ctx = update_in(new_ctx.value, fn values -> values -- cleaned_ctx.value end) + cast_all_of(new_ctx, Enum.concat(acc, cleaned_values)) else _ -> Cast.error(ctx, {:all_of, to_string(schema.title || schema.type)}) end @@ -48,8 +46,10 @@ defmodule OpenApiSpex.Cast.AllOf do cast_all_of(new_ctx, acc) {:ok, value} -> - # allOf definitions with primitives are a little bit strange..., we just return the cast for the first Schema, - # but validate the values against every other schema as well, since the value must be compatible with all Schemas + # allOf definitions with primitives are a little bit strange. + # we just return the cast for the first Schema, but validate + # the values against every other schema as well, since the value + # must be compatible with all Schemas cast_all_of(new_ctx, acc || value) {:error, _} -> diff --git a/lib/open_api_spex/cast/discriminator.ex b/lib/open_api_spex/cast/discriminator.ex index 17c325d3..2c8e6900 100644 --- a/lib/open_api_spex/cast/discriminator.ex +++ b/lib/open_api_spex/cast/discriminator.ex @@ -81,11 +81,15 @@ defmodule OpenApiSpex.Cast.Discriminator do do: {locate_schemas(schemas, ctx.schemas), Cast.cast(ctx)} defp find_discriminator_schema(discriminator, mappings = %{}, schemas) do - with {:ok, "#/components/schemas/" <> name} <- Map.fetch(mappings, discriminator) do - find_discriminator_schema(name, nil, schemas) - else - {:ok, name} -> find_discriminator_schema(name, nil, schemas) - :error -> find_discriminator_schema(discriminator, nil, schemas) + case Map.fetch(mappings, discriminator) do + {:ok, "#/components/schemas/" <> name} -> + find_discriminator_schema(name, nil, schemas) + + {:ok, name} -> + find_discriminator_schema(name, nil, schemas) + + :error -> + find_discriminator_schema(discriminator, nil, schemas) end end diff --git a/lib/open_api_spex/cast/error.ex b/lib/open_api_spex/cast/error.ex index 426a9b27..4182d994 100644 --- a/lib/open_api_spex/cast/error.ex +++ b/lib/open_api_spex/cast/error.ex @@ -1,4 +1,6 @@ defmodule OpenApiSpex.Cast.Error do + @moduledoc "OpenApiSpex Cast Error" + alias OpenApiSpex.TermType @type all_of_error :: {:all_of, [String.t()]} diff --git a/lib/open_api_spex/cast/number.ex b/lib/open_api_spex/cast/number.ex index c7810a0b..51e606e2 100644 --- a/lib/open_api_spex/cast/number.ex +++ b/lib/open_api_spex/cast/number.ex @@ -2,6 +2,9 @@ defmodule OpenApiSpex.Cast.Number do @moduledoc false alias OpenApiSpex.Cast + # credo:disable-for-next-line + # TODO We need a way to distinguish numbers in (JSON) body vs in request parameters + # so we can reject strings values for properties of `type: :number` @spec cast(ctx :: Cast.t()) :: {:ok, Cast.t()} | Cast.Error.t() def cast(%{value: value} = ctx) when is_number(value) do case cast_number(ctx) do @@ -10,8 +13,6 @@ defmodule OpenApiSpex.Cast.Number do end end - # TODO We need a way to distinguish numbers in (JSON) body vs in request parameters - # so we can reject strings values for properties of `type: :number` def cast(%{value: value} = ctx) when is_binary(value) do case Float.parse(value) do {value, ""} -> cast(%{ctx | value: value}) diff --git a/lib/open_api_spex/cast/string.ex b/lib/open_api_spex/cast/string.ex index 9defb74e..b3ba4220 100644 --- a/lib/open_api_spex/cast/string.ex +++ b/lib/open_api_spex/cast/string.ex @@ -54,6 +54,7 @@ defmodule OpenApiSpex.Cast.String do ?e, ?f ] + # credo:disable-for-next-line def cast(%{ value: < nil + case get_docs(mod, name) do + {:ok, {mod_meta, summary, description, meta}} -> + %Operation{ + summary: summary, + externalDocs: OperationBuilder.build_external_docs(meta, mod_meta), + description: description || "", + operationId: OperationBuilder.build_operation_id(meta, mod, name), + parameters: OperationBuilder.build_parameters(meta), + requestBody: OperationBuilder.build_request_body(meta), + responses: OperationBuilder.build_responses(meta), + security: OperationBuilder.build_security(meta, mod_meta), + tags: OperationBuilder.build_tags(meta, mod_meta) + } + + _ -> + nil end end defp get_docs(module, name) do {:docs_v1, _anno, _lang, _format, _module_doc, mod_meta, mod_docs} = Code.fetch_docs(module) - doc_for_function = - Enum.find(mod_docs, fn - {{:function, ^name, _}, _, _, _, _} -> true - _ -> false - end) + mod_docs + |> Enum.find(mod_docs, fn + {{:function, ^name, _}, _, _, _, _} -> true + _ -> false + end) + |> doc_for_function(module, name, mod_meta) + end - case doc_for_function do - {_, _, _, :hidden, _} -> - nil + defp doc_for_function({_, _, _, :hidden, _}, _module, _name, _mod_meta), do: nil - {_, _, _, docs, meta} when is_map(meta) -> - cond do - Enum.empty?(meta) -> - IO.warn("No docs found for function #{module}.#{name}/2") - nil - - not Map.has_key?(meta, :responses) -> - IO.warn("No responses declaration found for function #{module}.#{name}/2") - nil - - true -> - {summary, description} = - with %{"en" => contents} <- docs, - [summary | maybe_description] = String.split(contents, ~r/\n\s*\n/, parts: 2) do - {summary, List.first(maybe_description) || ""} - else - _ -> - {"", ""} - end - - {:ok, {mod_meta, summary, description, meta}} - end + defp doc_for_function({_, _, _, docs, meta}, module, name, mod_meta) when is_map(meta) do + cond do + Enum.empty?(meta) -> + IO.warn("No docs found for function #{module}.#{name}/2") + nil - _ -> - IO.warn("Invalid docs declaration found for function #{module}.#{name}/2") + not Map.has_key?(meta, :responses) -> + IO.warn("No responses declaration found for function #{module}.#{name}/2") nil + + true -> + {summary, description} = + case docs do + %{"en" => contents} -> + [summary | maybe_description] = String.split(contents, ~r/\n\s*\n/, parts: 2) + {summary, List.first(maybe_description) || ""} + + _ -> + {"", ""} + end + + {:ok, {mod_meta, summary, description, meta}} end end + + defp doc_for_function(_doc_for_function, module, name, _mod_meta) do + IO.warn("Invalid docs declaration found for function #{module}.#{name}/2") + nil + end end diff --git a/lib/open_api_spex/deprecated_cast.ex b/lib/open_api_spex/deprecated_cast.ex index 46adb8fb..7606b11e 100644 --- a/lib/open_api_spex/deprecated_cast.ex +++ b/lib/open_api_spex/deprecated_cast.ex @@ -138,20 +138,19 @@ defmodule OpenApiSpex.DeprecatedCast do |> no_struct() |> Enum.split_with(fn {k, _v} -> is_binary(k) end) - with {:ok, props} <- cast_properties(schema, regular_properties, schemas), - {:ok, struct} <- Map.new(others ++ props) |> make_struct(schema) do - {:ok, struct} + with {:ok, props} <- cast_properties(schema, regular_properties, schemas) do + make_struct(Map.new(others ++ props), schema) end end def cast(ref = %Reference{}, val, schemas), do: cast(Reference.resolve_schema(ref, schemas), val, schemas) - def cast(_additionalProperties = false, val, _schemas) do + def cast(_additional_properties = false, val, _schemas) do {:error, "Unexpected field with value #{inspect(val)}"} end - def cast(_additionalProperties, val, _schemas), do: {:ok, val} + def cast(_additional_properties, val, _schemas), do: {:ok, val} defp make_struct(val = %_{}, _), do: {:ok, val} defp make_struct(val, %{"x-struct": nil}), do: {:ok, val} @@ -285,9 +284,8 @@ defmodule OpenApiSpex.DeprecatedCast do def validate(schema = %Schema{type: :array}, value, path, schemas) when is_list(value) do with :ok <- validate_max_items(schema, value, path), :ok <- validate_min_items(schema, value, path), - :ok <- validate_unique_items(schema, value, path), - :ok <- validate_array_items(schema, value, {path, 0}, schemas) do - :ok + :ok <- validate_unique_items(schema, value, path) do + validate_array_items(schema, value, {path, 0}, schemas) end end @@ -296,16 +294,14 @@ defmodule OpenApiSpex.DeprecatedCast do with :ok <- validate_required_properties(schema, value, path), :ok <- validate_max_properties(schema, value, path), - :ok <- validate_min_properties(schema, value, path), - :ok <- - validate_object_properties( - schema.properties, - MapSet.new(schema.required), - value, - path, - schemas - ) do - :ok + :ok <- validate_min_properties(schema, value, path) do + validate_object_properties( + schema.properties, + MapSet.new(schema.required), + value, + path, + schemas + ) end end @@ -332,18 +328,16 @@ defmodule OpenApiSpex.DeprecatedCast do @spec validate_number_types(Schema.t(), number, String.t()) :: :ok | {:error, String.t()} defp validate_number_types(schema, value, path) do with :ok <- validate_multiple(schema, value, path), - :ok <- validate_maximum(schema, value, path), - :ok <- validate_minimum(schema, value, path) do - :ok + :ok <- validate_maximum(schema, value, path) do + validate_minimum(schema, value, path) end end @spec validate_string_types(Schema.t(), String.t(), String.t()) :: :ok | {:error, String.t()} defp validate_string_types(schema, value, path) do with :ok <- validate_max_length(schema, value, path), - :ok <- validate_min_length(schema, value, path), - :ok <- validate_pattern(schema, value, path) do - :ok + :ok <- validate_min_length(schema, value, path) do + validate_pattern(schema, value, path) end end @@ -531,9 +525,8 @@ defmodule OpenApiSpex.DeprecatedCast do property_value, property_path, schemas - ), - :ok <- validate_object_properties(rest, required, value, path, schemas) do - :ok + ) do + validate_object_properties(rest, required, value, path, schemas) end end diff --git a/lib/open_api_spex/discriminator.ex b/lib/open_api_spex/discriminator.ex index bd179d66..85352bc8 100644 --- a/lib/open_api_spex/discriminator.ex +++ b/lib/open_api_spex/discriminator.ex @@ -29,11 +29,13 @@ defmodule OpenApiSpex.Discriminator do """ @spec resolve(t, map, %{String.t() => Schema.t()}) :: {:ok, Schema.t()} | {:error, String.t()} def resolve(%{propertyName: name, mapping: mapping}, value = %{}, schemas = %{}) do - with {:ok, val} <- get_property_value(value, name) do - mapped = map_property_value(mapping, val) - lookup_schema(schemas, mapped) - else - {:error, reason} -> {:error, reason} + case get_property_value(value, name) do + {:ok, val} -> + mapped = map_property_value(mapping, val) + lookup_schema(schemas, mapped) + + {:error, reason} -> + {:error, reason} end end diff --git a/lib/open_api_spex/encoding.ex b/lib/open_api_spex/encoding.ex index 6e73d3e5..45b26cd1 100644 --- a/lib/open_api_spex/encoding.ex +++ b/lib/open_api_spex/encoding.ex @@ -2,7 +2,7 @@ defmodule OpenApiSpex.Encoding do @moduledoc """ Defines the `OpenApiSpex.Encoding.t` type. """ - alias OpenApiSpex.{Header, Reference, Parameter} + alias OpenApiSpex.{Header, Parameter, Reference} defstruct [ :contentType, diff --git a/lib/open_api_spex/header.ex b/lib/open_api_spex/header.ex index fce1fa90..a69bb522 100644 --- a/lib/open_api_spex/header.ex +++ b/lib/open_api_spex/header.ex @@ -2,7 +2,8 @@ defmodule OpenApiSpex.Header do @moduledoc """ Defines the `OpenApiSpex.Header.t` type. """ - alias OpenApiSpex.{Schema, Reference, Example} + + alias OpenApiSpex.{Example, Reference, Schema} defstruct [ :description, diff --git a/lib/open_api_spex/media_type.ex b/lib/open_api_spex/media_type.ex index 1d60d5ff..8e199c50 100644 --- a/lib/open_api_spex/media_type.ex +++ b/lib/open_api_spex/media_type.ex @@ -2,7 +2,7 @@ defmodule OpenApiSpex.MediaType do @moduledoc """ Defines the `OpenApiSpex.MediaType.t` type. """ - alias OpenApiSpex.{Schema, Reference, Example, Encoding} + alias OpenApiSpex.{Encoding, Example, Reference, Schema} defstruct [ :schema, diff --git a/lib/open_api_spex/open_api.ex b/lib/open_api_spex/open_api.ex index 977239cf..21069627 100644 --- a/lib/open_api_spex/open_api.ex +++ b/lib/open_api_spex/open_api.ex @@ -4,18 +4,18 @@ defmodule OpenApiSpex.OpenApi do construct an `OpenApiSpex.OpenApi.t` at runtime. """ alias OpenApiSpex.{ - Extendable, - Info, - Server, - Paths, Components, - SecurityRequirement, - Tag, + Example, + Extendable, ExternalDocumentation, - OpenApi, + Info, MediaType, + OpenApi, + Paths, Schema, - Example + SecurityRequirement, + Server, + Tag } @enforce_keys [:info, :paths] diff --git a/lib/open_api_spex/open_api/decode.ex b/lib/open_api_spex/open_api/decode.ex index 8524e2e0..343b665c 100644 --- a/lib/open_api_spex/open_api/decode.ex +++ b/lib/open_api_spex/open_api/decode.ex @@ -1,5 +1,6 @@ defmodule OpenApiSpex.OpenApi.Decode do - # This module exposes functionality to convert an arbitrary map into a OpenApi struct. + @moduledoc "This module exposes functionality to convert an arbitrary map into a OpenApi struct." + alias OpenApiSpex.{ Components, Contact, @@ -57,10 +58,12 @@ defmodule OpenApiSpex.OpenApi.Decode do end defp map_get(map, atom_key) when is_atom(atom_key) do - with %{^atom_key => value} <- map do - {atom_key, value} - else - _ -> map_get(map, to_string(atom_key)) + case map do + %{^atom_key => value} -> + {atom_key, value} + + _ -> + map_get(map, to_string(atom_key)) end end diff --git a/lib/open_api_spex/operation.ex b/lib/open_api_spex/operation.ex index f880def6..a2c2caf2 100644 --- a/lib/open_api_spex/operation.ex +++ b/lib/open_api_spex/operation.ex @@ -8,6 +8,7 @@ defmodule OpenApiSpex.Operation do MediaType, Operation, Parameter, + PathItem, Reference, RequestBody, Response, @@ -17,6 +18,8 @@ defmodule OpenApiSpex.Operation do Server } + alias Plug.Conn + @enforce_keys :responses defstruct tags: [], summary: nil, @@ -249,10 +252,8 @@ defmodule OpenApiSpex.Operation do with :ok <- validate_required_parameters(operation.parameters || [], conn.params), parameters <- Enum.filter(operation.parameters || [], &Map.has_key?(conn.params, &1.name)), - :ok <- validate_parameter_schemas(parameters, conn.params, schemas), - :ok <- - validate_body_schema(operation.requestBody, conn.body_params, content_type, schemas) do - :ok + :ok <- validate_parameter_schemas(parameters, conn.params, schemas) do + validate_body_schema(operation.requestBody, conn.body_params, content_type, schemas) end end diff --git a/lib/open_api_spex/operation2.ex b/lib/open_api_spex/operation2.ex index 2affadc8..755cd0bb 100644 --- a/lib/open_api_spex/operation2.ex +++ b/lib/open_api_spex/operation2.ex @@ -5,10 +5,10 @@ defmodule OpenApiSpex.Operation2 do alias OpenApiSpex.{ Cast, CastParameters, - Operation, - RequestBody, Components, - Reference + Operation, + Reference, + RequestBody } alias OpenApiSpex.Cast.Error diff --git a/lib/open_api_spex/operation_builder.ex b/lib/open_api_spex/operation_builder.ex index 204f3666..cc3412d3 100644 --- a/lib/open_api_spex/operation_builder.ex +++ b/lib/open_api_spex/operation_builder.ex @@ -1,7 +1,8 @@ defmodule OpenApiSpex.OperationBuilder do @moduledoc false - alias OpenApiSpex.{ExternalDocumentation, Operation, Parameter, Response, Reference} + alias OpenApiSpex.{ExternalDocumentation, Operation, Parameter, Reference, Response} + alias Plug.Conn.Status def ensure_type_and_schema_exclusive!(name, type, schema) do if type != nil && schema != nil do @@ -107,7 +108,7 @@ defmodule OpenApiSpex.OperationBuilder do def build_responses(_), do: [] defp status_to_code(:default), do: :default - defp status_to_code(status), do: Plug.Conn.Status.code(status) + defp status_to_code(status), do: Status.code(status) def build_request_body(%{body: {description, media_type, schema}}) do Operation.request_body(description, media_type, schema) diff --git a/lib/open_api_spex/parameter.ex b/lib/open_api_spex/parameter.ex index 437f78dc..336068a2 100644 --- a/lib/open_api_spex/parameter.ex +++ b/lib/open_api_spex/parameter.ex @@ -3,11 +3,11 @@ defmodule OpenApiSpex.Parameter do Defines the `OpenApiSpex.Parameter.t` type. """ alias OpenApiSpex.{ - Schema, - Reference, Example, MediaType, - Parameter + Parameter, + Reference, + Schema } @enforce_keys [:name, :in] diff --git a/lib/open_api_spex/path_item.ex b/lib/open_api_spex/path_item.ex index 0b73b9ba..39457018 100644 --- a/lib/open_api_spex/path_item.ex +++ b/lib/open_api_spex/path_item.ex @@ -3,7 +3,7 @@ defmodule OpenApiSpex.PathItem do Defines the `OpenApiSpex.PathItem.t` type. """ - alias OpenApiSpex.{Operation, Server, Parameter, PathItem, Reference} + alias OpenApiSpex.{Operation, Parameter, PathItem, Reference, Server} defstruct [ :"$ref", diff --git a/lib/open_api_spex/paths.ex b/lib/open_api_spex/paths.ex index 1a90e253..bb259d1d 100644 --- a/lib/open_api_spex/paths.ex +++ b/lib/open_api_spex/paths.ex @@ -2,7 +2,7 @@ defmodule OpenApiSpex.Paths do @moduledoc """ Defines the `OpenApiSpex.Paths.t` type. """ - alias OpenApiSpex.{PathItem, Operation} + alias OpenApiSpex.{Operation, PathItem} @typedoc """ [Paths Object](https://swagger.io/specification/#pathsObject) @@ -26,7 +26,7 @@ defmodule OpenApiSpex.Paths do @doc """ Create a Paths map from a list of routes. """ - @spec from_routes([Phoenix.Route.t()]) :: t + @spec from_routes([Phoenix.Router.Route.t()]) :: t def from_routes(routes) do paths = routes @@ -49,11 +49,10 @@ defmodule OpenApiSpex.Paths do defp open_api_path(path) do path |> String.split("/") - |> Enum.map(fn + |> Enum.map_join("/", fn ":" <> segment -> "{#{segment}}" segment -> segment end) - |> Enum.join("/") end @spec find_duplicate_operations(paths :: t) :: [{operation_id, [{path, verb, Operation.t()}]}] @@ -66,7 +65,7 @@ defmodule OpenApiSpex.Paths do all_operations |> Enum.group_by(fn {_path, _verb, operation} -> operation.operationId end) |> Enum.filter(fn - {_operationId, [_item]} -> false + {_operation_id, [_item]} -> false _ -> true end) end diff --git a/lib/open_api_spex/plug/app_env_cache.ex b/lib/open_api_spex/plug/app_env_cache.ex index 0647f78a..c0006057 100644 --- a/lib/open_api_spex/plug/app_env_cache.ex +++ b/lib/open_api_spex/plug/app_env_cache.ex @@ -1,4 +1,6 @@ defmodule OpenApiSpex.Plug.AppEnvCache do + @moduledoc "OpenApiSpex AppEnvCache" + @behaviour OpenApiSpex.Plug.Cache @impl true diff --git a/lib/open_api_spex/plug/cache.ex b/lib/open_api_spex/plug/cache.ex index f54c4916..c99130c1 100644 --- a/lib/open_api_spex/plug/cache.ex +++ b/lib/open_api_spex/plug/cache.ex @@ -24,7 +24,7 @@ defmodule OpenApiSpex.Plug.Cache do alias OpenApiSpex.OpenApi default_adapter = - if(function_exported?(:persistent_term, :info, 0)) do + if function_exported?(:persistent_term, :info, 0) do OpenApiSpex.Plug.PersistentTermCache else OpenApiSpex.Plug.AppEnvCache diff --git a/lib/open_api_spex/plug/cast.ex b/lib/open_api_spex/plug/cast.ex index 73ab31b2..16f765c0 100644 --- a/lib/open_api_spex/plug/cast.ex +++ b/lib/open_api_spex/plug/cast.ex @@ -44,6 +44,7 @@ defmodule OpenApiSpex.Plug.Cast do @behaviour Plug + alias OpenApiSpex.Plug.PutApiSpec alias Plug.Conn @impl Plug @@ -60,7 +61,7 @@ defmodule OpenApiSpex.Plug.Cast do operation_id: operation_id, render_error: render_error }) do - {spec, operation_lookup} = OpenApiSpex.Plug.PutApiSpec.get_spec_and_operation_lookup(conn) + {spec, operation_lookup} = PutApiSpec.get_spec_and_operation_lookup(conn) operation = operation_lookup[operation_id] content_type = @@ -69,6 +70,7 @@ defmodule OpenApiSpex.Plug.Cast do |> String.split(";") |> Enum.at(0) + # credo:disable-for-next-line case apply(OpenApiSpex, :cast, [spec, operation, conn, content_type]) do {:ok, conn} -> conn diff --git a/lib/open_api_spex/plug/cast2.ex b/lib/open_api_spex/plug/cast2.ex index d44014cd..99162c95 100644 --- a/lib/open_api_spex/plug/cast2.ex +++ b/lib/open_api_spex/plug/cast2.ex @@ -1,4 +1,6 @@ defmodule OpenApiSpex.Plug.Cast2 do + @moduledoc false + @behaviour Plug @impl Plug diff --git a/lib/open_api_spex/plug/cast_and_validate.ex b/lib/open_api_spex/plug/cast_and_validate.ex index 8aa667fe..d8d82838 100644 --- a/lib/open_api_spex/plug/cast_and_validate.ex +++ b/lib/open_api_spex/plug/cast_and_validate.ex @@ -52,6 +52,7 @@ defmodule OpenApiSpex.Plug.CastAndValidate do @behaviour Plug alias OpenApiSpex.Plug.PutApiSpec + alias Plug.Conn @impl Plug def init(opts) do @@ -78,15 +79,16 @@ defmodule OpenApiSpex.Plug.CastAndValidate do cast_opts = opts |> Map.take([:replace_params]) |> Map.to_list() - with {:ok, conn} <- OpenApiSpex.cast_and_validate(spec, operation, conn, nil, cast_opts) do - conn - else + case OpenApiSpex.cast_and_validate(spec, operation, conn, nil, cast_opts) do + {:ok, conn} -> + conn + {:error, errors} -> errors = render_error.init(errors) conn |> render_error.call(errors) - |> Plug.Conn.halt() + |> Conn.halt() end end diff --git a/lib/open_api_spex/plug/default_render_error.ex b/lib/open_api_spex/plug/default_render_error.ex index 4ea52e99..ae3385da 100644 --- a/lib/open_api_spex/plug/default_render_error.ex +++ b/lib/open_api_spex/plug/default_render_error.ex @@ -1,4 +1,6 @@ defmodule OpenApiSpex.Plug.DefaultRenderError do + @moduledoc false + @deprecated "#{__MODULE__} is no longer the default error renderer" @behaviour Plug diff --git a/lib/open_api_spex/plug/json_render_error.ex b/lib/open_api_spex/plug/json_render_error.ex index 52ab9883..06bc16d1 100644 --- a/lib/open_api_spex/plug/json_render_error.ex +++ b/lib/open_api_spex/plug/json_render_error.ex @@ -6,8 +6,8 @@ defmodule OpenApiSpex.Plug.JsonRenderError do @behaviour Plug - alias Plug.Conn alias OpenApiSpex.OpenApi + alias Plug.Conn @impl Plug def init(errors), do: errors diff --git a/lib/open_api_spex/plug/json_render_error_v2.ex b/lib/open_api_spex/plug/json_render_error_v2.ex index 09871c6f..c71c41d7 100644 --- a/lib/open_api_spex/plug/json_render_error_v2.ex +++ b/lib/open_api_spex/plug/json_render_error_v2.ex @@ -9,8 +9,8 @@ defmodule OpenApiSpex.Plug.JsonRenderErrorV2 do """ @behaviour Plug - alias Plug.Conn alias OpenApiSpex.OpenApi + alias Plug.Conn @impl Plug def init(errors), do: errors diff --git a/lib/open_api_spex/plug/none_cache.ex b/lib/open_api_spex/plug/none_cache.ex index d7d71193..01adc50e 100644 --- a/lib/open_api_spex/plug/none_cache.ex +++ b/lib/open_api_spex/plug/none_cache.ex @@ -1,4 +1,6 @@ defmodule OpenApiSpex.Plug.NoneCache do + @moduledoc false + @behaviour OpenApiSpex.Plug.Cache @impl true diff --git a/lib/open_api_spex/plug/persistent_term_cache.ex b/lib/open_api_spex/plug/persistent_term_cache.ex index 00f89cef..f52604ba 100644 --- a/lib/open_api_spex/plug/persistent_term_cache.ex +++ b/lib/open_api_spex/plug/persistent_term_cache.ex @@ -1,5 +1,7 @@ if function_exported?(:persistent_term, :info, 0) do defmodule OpenApiSpex.Plug.PersistentTermCache do + @moduledoc false + @behaviour OpenApiSpex.Plug.Cache @impl true diff --git a/lib/open_api_spex/plug/put_api_spec.ex b/lib/open_api_spex/plug/put_api_spec.ex index 5cc6be3b..6415d026 100644 --- a/lib/open_api_spex/plug/put_api_spec.ex +++ b/lib/open_api_spex/plug/put_api_spec.ex @@ -12,7 +12,8 @@ defmodule OpenApiSpex.Plug.PutApiSpec do plug OpenApiSpex.Plug.PutApiSpec, module: MyAppWeb.ApiSpec """ - alias OpenApiSpex.OpenApi + alias OpenApiSpex.{OpenApi, Operation} + alias Plug.Conn @behaviour Plug diff --git a/lib/open_api_spex/plug/swagger_ui.ex b/lib/open_api_spex/plug/swagger_ui.ex index 39e91d05..1b807810 100644 --- a/lib/open_api_spex/plug/swagger_ui.ex +++ b/lib/open_api_spex/plug/swagger_ui.ex @@ -193,7 +193,7 @@ defmodule OpenApiSpex.Plug.SwaggerUI do end defp supplement_config(%{oauth2_redirect_url: {:endpoint_url, path}} = config, conn) do - endpoint_module = apply(Phoenix.Controller, :endpoint_module, [conn]) + endpoint_module = Phoenix.Controller.endpoint_module(conn) url = Path.join(endpoint_module.url(), path) Map.put(config, :oauth2_redirect_url, url) end diff --git a/lib/open_api_spex/plug/validate.ex b/lib/open_api_spex/plug/validate.ex index bde10ca3..0a9c9d12 100644 --- a/lib/open_api_spex/plug/validate.ex +++ b/lib/open_api_spex/plug/validate.ex @@ -70,9 +70,11 @@ defmodule OpenApiSpex.Plug.Validate do |> String.split(";", parts: 2) |> Enum.at(0) - with :ok <- apply(OpenApiSpex, :validate, [spec, operation, conn, content_type]) do - conn - else + # credo:disable-for-next-line + case apply(OpenApiSpex, :validate, [spec, operation, conn, content_type]) do + :ok -> + conn + {:error, reason} -> opts = render_error.init(reason) diff --git a/lib/open_api_spex/reference.ex b/lib/open_api_spex/reference.ex index 00ce415a..971c9ed8 100644 --- a/lib/open_api_spex/reference.ex +++ b/lib/open_api_spex/reference.ex @@ -3,7 +3,7 @@ defmodule OpenApiSpex.Reference do Defines the `OpenApiSpex.Reference.t` type. """ - alias OpenApiSpex.{Components, Reference, RequestBody} + alias OpenApiSpex.{Components, Parameter, Reference, RequestBody, Schema} @enforce_keys :"$ref" defstruct [ diff --git a/lib/open_api_spex/response.ex b/lib/open_api_spex/response.ex index 7432f5ba..e12f5e92 100644 --- a/lib/open_api_spex/response.ex +++ b/lib/open_api_spex/response.ex @@ -2,7 +2,8 @@ defmodule OpenApiSpex.Response do @moduledoc """ Defines the `OpenApiSpex.Response.t` type. """ - alias OpenApiSpex.{Header, Reference, MediaType, Link, Response} + + alias OpenApiSpex.{Components, Header, Link, MediaType, Reference, Response} @enforce_keys :description defstruct [ diff --git a/lib/open_api_spex/responses.ex b/lib/open_api_spex/responses.ex index f0e4f3fc..f5086714 100644 --- a/lib/open_api_spex/responses.ex +++ b/lib/open_api_spex/responses.ex @@ -2,7 +2,7 @@ defmodule OpenApiSpex.Responses do @moduledoc """ Defines the `OpenApiSpex.Responses.t` type. """ - alias OpenApiSpex.{Response, Reference} + alias OpenApiSpex.{Reference, Response} @typedoc """ [Responses Object](https://swagger.io/specification/#responsesObject) diff --git a/lib/open_api_spex/schema.ex b/lib/open_api_spex/schema.ex index 59e9fa4a..7eecf391 100644 --- a/lib/open_api_spex/schema.ex +++ b/lib/open_api_spex/schema.ex @@ -133,12 +133,12 @@ defmodule OpenApiSpex.Schema do """ alias OpenApiSpex.{ - Schema, - Reference, DeprecatedCast, Discriminator, - Xml, - ExternalDocumentation + ExternalDocumentation, + Reference, + Schema, + Xml } @doc """ @@ -304,14 +304,14 @@ defmodule OpenApiSpex.Schema do ## Examples - iex> OpenApiSpex.Schema.validate(%OpenApiSpex.Schema{type: :integer, minimum: 5}, 3, %{}) - {:error, "#: 3 is smaller than minimum 5"} + iex> OpenApiSpex.Schema.validate(%OpenApiSpex.Schema{type: :integer, minimum: 5}, 3, %{}) + {:error, "#: 3 is smaller than minimum 5"} - iex> OpenApiSpex.Schema.validate(%OpenApiSpex.Schema{type: :string, pattern: "(.*)@(.*)"}, "joe@gmail.com", %{}) - :ok + iex> OpenApiSpex.Schema.validate(%OpenApiSpex.Schema{type: :string, pattern: "(.*)@(.*)"}, "joe@gmail.com", %{}) + :ok - iex> OpenApiSpex.Schema.validate(%OpenApiSpex.Schema{type: :string, pattern: "(.*)@(.*)"}, "joegmail.com", %{}) - {:error, "#: Value \"joegmail.com\" does not match pattern: (.*)@(.*)"} + iex> OpenApiSpex.Schema.validate(%OpenApiSpex.Schema{type: :string, pattern: "(.*)@(.*)"}, "joegmail.com", %{}) + {:error, "#: Value \"joegmail.com\" does not match pattern: (.*)@(.*)"} """ @spec validate(Schema.t() | Reference.t(), any, %{String.t() => Schema.t() | Reference.t()}) :: :ok | {:error, String.t()} diff --git a/lib/open_api_spex/schema_consistency.ex b/lib/open_api_spex/schema_consistency.ex index a4ebc9ed..e501a5d1 100644 --- a/lib/open_api_spex/schema_consistency.ex +++ b/lib/open_api_spex/schema_consistency.ex @@ -14,7 +14,7 @@ defmodule OpenApiSpex.SchemaConsistency do &validate_type_key/1 ] |> Enum.reduce([], fn validator, acc -> - case apply(validator, [schema]) do + case validator.(schema) do :ok -> acc {:error, message} -> [message | acc] end diff --git a/lib/open_api_spex/schema_resolver.ex b/lib/open_api_spex/schema_resolver.ex index 41a5c4e2..88f9dca2 100644 --- a/lib/open_api_spex/schema_resolver.ex +++ b/lib/open_api_spex/schema_resolver.ex @@ -3,16 +3,16 @@ defmodule OpenApiSpex.SchemaResolver do Internal module used to resolve `OpenApiSpex.Schema` structs from atoms. """ alias OpenApiSpex.{ - OpenApi, Components, - PathItem, + MediaType, + OpenApi, Operation, Parameter, + PathItem, Reference, - MediaType, - Schema, RequestBody, - Response + Response, + Schema } @doc """ diff --git a/lib/open_api_spex/server.ex b/lib/open_api_spex/server.ex index 913ef29b..9dc20298 100644 --- a/lib/open_api_spex/server.ex +++ b/lib/open_api_spex/server.ex @@ -36,8 +36,8 @@ defmodule OpenApiSpex.Server do """ @spec from_endpoint(module) :: t def from_endpoint(endpoint) do - uri = apply(endpoint, :struct_url, []) - path = apply(endpoint, :path, [""]) || "/" + uri = endpoint.struct_url() + path = endpoint.path("") || "/" uri = %{uri | path: path} %Server{ diff --git a/lib/open_api_spex/term_type.ex b/lib/open_api_spex/term_type.ex index 0b409147..fa10ea7c 100644 --- a/lib/open_api_spex/term_type.ex +++ b/lib/open_api_spex/term_type.ex @@ -1,4 +1,6 @@ defmodule OpenApiSpex.TermType do + @moduledoc false + alias OpenApiSpex.Schema @spec type(term) :: Schema.data_type() | nil | String.t() diff --git a/lib/open_api_spex/test/assertions2.ex b/lib/open_api_spex/test/assertions2.ex index 9ef82f96..52d81c47 100644 --- a/lib/open_api_spex/test/assertions2.ex +++ b/lib/open_api_spex/test/assertions2.ex @@ -3,6 +3,8 @@ defmodule OpenApiSpex.Test.Assertions2 do Defines helpers for testing API responses and examples against API spec schemas. """ + alias OpenApiSpex.OpenApi + @doc """ Asserts that `value` conforms to the schema with title `schema_title` in `api_spec`. """ diff --git a/mix.exs b/mix.exs index 86a9f357..80904964 100644 --- a/mix.exs +++ b/mix.exs @@ -8,7 +8,7 @@ defmodule OpenApiSpex.Mixfile do [ app: :open_api_spex, version: @version, - elixir: "~> 1.7", + elixir: "~> 1.10", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, consolidate_protocols: Mix.env() != :test, @@ -55,12 +55,13 @@ defmodule OpenApiSpex.Mixfile do defp deps do [ - {:dialyxir, "~> 0.5", only: [:dev, :test], runtime: false}, + {:credo, "~> 1.0", only: [:dev], runtime: false}, + {:dialyxir, "~> 1.0", only: [:dev], runtime: false}, {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, {:jason, "~> 1.0", optional: true}, {:phoenix, "~> 1.3", only: [:dev, :test]}, {:plug, "~> 1.7"}, - {:poison, "~> 3.1 or ~> 4.0", optional: true} + {:poison, "~> 4.0 or ~> 5.0", optional: true} ] end @@ -83,10 +84,8 @@ defmodule OpenApiSpex.Mixfile do defp dialyzer do [ - plt_add_apps: [:mix, :jason, :poison], - plt_add_deps: :apps_direct, - flags: ["-Werror_handling", "-Wno_unused", "-Wunmatched_returns", "-Wunderspecs"], - remove_defaults: [:unknown] + plt_file: {:no_warn, "priv/plts/dialyzer.plt"}, + plt_add_apps: [:ex_unit, :mix, :jason, :poison] ] end end diff --git a/mix.lock b/mix.lock index 9d02dad7..0fdc0dcd 100644 --- a/mix.lock +++ b/mix.lock @@ -1,17 +1,22 @@ %{ - "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm", "6c32a70ed5d452c6650916555b1f96c79af5fc4bf286997f8b15f213de786f73"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"}, - "ex_doc": {:hex, :ex_doc, "0.24.2", "e4c26603830c1a2286dae45f4412a4d1980e1e89dc779fcd0181ed1d5a05c8d9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "e134e1d9e821b8d9e4244687fb2ace58d479b67b282de5158333b0d57c6fb7da"}, - "jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"}, - "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"}, + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, + "credo": {:hex, :credo, "1.6.4", "ddd474afb6e8c240313f3a7b0d025cc3213f0d171879429bf8535d7021d9ad78", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "c28f910b61e1ff829bffa056ef7293a8db50e87f2c57a9b5c3f57eee124536b7"}, + "dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.25", "2024618731c55ebfcc5439d756852ec4e85978a39d0d58593763924d9a15916f", [:mix], [], "hexpm", "56749c5e1c59447f7b7a23ddb235e4b3defe276afc220a6227237f3efe83f51e"}, + "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, + "ex_doc": {:hex, :ex_doc, "0.28.3", "6eea2f69995f5fba94cd6dd398df369fe4e777a47cd887714a0976930615c9e6", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "05387a6a2655b5f9820f3f627450ed20b4325c25977b2ee69bed90af6688e718"}, + "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, + "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"}, + "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, - "mime": {:hex, :mime, "1.5.0", "203ef35ef3389aae6d361918bf3f952fa17a09e8e43b5aa592b93eba05d0fb8d", [:mix], [], "hexpm", "55a94c0f552249fc1a3dd9cd2d3ab9de9d3c89b559c2bd01121f824834f24746"}, - "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, - "phoenix": {:hex, :phoenix, "1.5.7", "2923bb3af924f184459fe4fa4b100bd25fa6468e69b2803dfae82698269aa5e0", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "774cd64417c5a3788414fdbb2be2eb9bcd0c048d9e6ad11a0c1fd67b7c0d0978"}, + "mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, + "phoenix": {:hex, :phoenix, "1.6.6", "281c8ce8dccc9f60607346b72cdfc597c3dde134dd9df28dff08282f0b751754", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "807bd646e64cd9dc83db016199715faba72758e6db1de0707eef0a2da4924364"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, - "plug": {:hex, :plug, "1.11.0", "f17217525597628298998bc3baed9f8ea1fa3f1160aa9871aee6df47a6e4d38e", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2d9c633f0499f9dc5c2fd069161af4e2e7756890b81adcbb2ceaa074e8308876"}, - "plug_crypto": {:hex, :plug_crypto, "1.2.0", "1cb20793aa63a6c619dd18bb33d7a3aa94818e5fd39ad357051a67f26dfa2df6", [:mix], [], "hexpm", "a48b538ae8bf381ffac344520755f3007cc10bd8e90b240af98ea29b69683fc2"}, - "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm", "ba8836feea4b394bb718a161fc59a288fe0109b5006d6bdf97b6badfcf6f0f25"}, - "telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"} + "phoenix_view": {:hex, :phoenix_view, "1.1.2", "1b82764a065fb41051637872c7bd07ed2fdb6f5c3bd89684d4dca6e10115c95a", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "7ae90ad27b09091266f6adbb61e1d2516a7c3d7062c6789d46a7554ec40f3a56"}, + "plug": {:hex, :plug, "1.13.4", "addb6e125347226e3b11489e23d22a60f7ab74786befb86c14f94fb5f23ca9a4", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "06114c1f2a334212fe3ae567dbb3b1d29fd492c1a09783d52f3d489c1a6f4cf2"}, + "plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"}, + "poison": {:hex, :poison, "5.0.0", "d2b54589ab4157bbb82ec2050757779bfed724463a544b6e20d79855a9e43b24", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "11dc6117c501b80c62a7594f941d043982a1bd05a1184280c0d9166eb4d8d3fc"}, + "telemetry": {:hex, :telemetry, "1.0.0", "0f453a102cdf13d506b7c0ab158324c337c41f1cc7548f0bc0e130bbf0ae9452", [:rebar3], [], "hexpm", "73bc09fa59b4a0284efb4624335583c528e07ec9ae76aca96ea0673850aec57a"}, } diff --git a/test/plug/cast_test.exs b/test/plug/cast_test.exs index 6960b6a4..1c54bdf7 100644 --- a/test/plug/cast_test.exs +++ b/test/plug/cast_test.exs @@ -398,7 +398,7 @@ defmodule OpenApiSpex.Plug.CastTest do conn = :post - |> Plug.Test.conn("api/utility/echo/body_params", Jason.encode!(request_body)) + |> Plug.Test.conn("/api/utility/echo/body_params", Jason.encode!(request_body)) |> Plug.Conn.put_req_header("content-type", "application/json") |> OpenApiSpexTest.Router.call([])