Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions lib/open_api_spex/cast.ex
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,12 @@
@spec cast(t()) :: {:ok, term()} | {:error, [Error.t()]}

# Custom validator
def cast(%__MODULE__{schema: %{"x-validate": module}} = ctx) when module != nil,
do: module.cast(ctx)
def cast(%__MODULE__{schema: %{"x-validate": module}} = ctx)
when is_atom(module) and module != nil,
do: module.cast(ctx)

def cast(%__MODULE__{schema: %{"x-validate": module}} = ctx) when is_binary(module),
do: module |> Elixir.String.split(".") |> Module.concat() |> apply(:cast, [ctx])

Check warning on line 127 in lib/open_api_spex/cast.ex

View workflow job for this annotation

GitHub Actions / Lint (OTP 26 / Elixir 1.16)

Avoid `apply/2` and `apply/3` when the number of arguments is known.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's fix this warning, otherwise LGTM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zorbash pinging you case you don't get the workflow approval notification :)


# nil schema
def cast(%__MODULE__{value: value, schema: nil}),
Expand Down
51 changes: 33 additions & 18 deletions test/cast_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ defmodule OpenApiSpec.CastTest do
def cast(ctx), do: Cast.cast(ctx)

describe "cast/1" do
defmodule CustomValidator.EvenInt do
require OpenApiSpex

alias OpenApiSpex.Cast

OpenApiSpex.schema(%{
description: "An even integer",
type: :integer,
"x-validate": __MODULE__
})

def cast(context = %Cast{value: value}) when is_integer(value) and rem(value, 2) == 0,
do: Cast.ok(context)

def cast(context), do: Cast.error(context, {:custom, "Must be an even integer"})
end

test "unknown schema type" do
assert {:error, [error]} = cast(value: "string", schema: %Schema{type: :nope})
assert error.reason == :invalid_schema_type
Expand Down Expand Up @@ -223,24 +240,7 @@ defmodule OpenApiSpec.CastTest do
end

test "cast custom error with custom validator" do
defmodule EvenInt do
require OpenApiSpex

alias OpenApiSpex.Cast

OpenApiSpex.schema(%{
description: "An even integer",
type: :integer,
"x-validate": __MODULE__
})

def cast(context = %Cast{value: value}) when is_integer(value) and rem(value, 2) == 0,
do: Cast.ok(context)

def cast(context), do: Cast.error(context, {:custom, "Must be an even integer"})
end

schema = %Schema{type: :object, properties: %{even_number: EvenInt.schema()}}
schema = %Schema{type: :object, properties: %{even_number: CustomValidator.EvenInt.schema()}}

assert {:error, errors} = cast(value: %{"even_number" => 1}, schema: schema)
assert [error] = errors
Expand All @@ -250,6 +250,21 @@ defmodule OpenApiSpec.CastTest do
assert Error.message_with_path(error) == "#/even_number: Must be an even integer"
end

test "cast with custom validator from decoded schema" do
spec =
"./test/support/encoded_schema.json"
|> File.read!()
|> Jason.decode!()
|> OpenApiSpex.OpenApi.Decode.decode()

%{
components: %{schemas: %{"CustomValidationDecoded" => custom_validation_schema}}
} = spec

assert {:ok, %{even_num: 2}} =
cast(value: %{"even_num" => 2}, schema: custom_validation_schema)
end

test "nil value with xxxOf" do
schema = %Schema{anyOf: [%Schema{nullable: true, type: :string}]}
assert {:ok, nil} = cast(value: nil, schema: schema)
Expand Down
9 changes: 9 additions & 0 deletions test/support/encoded_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,15 @@
"not": {
"type": "string"
}
},
"CustomValidationDecoded": {
"type": "object",
"properties": {
"even_num": {
"type": "integer",
"x-validate": "OpenApiSpec.CastTest.CustomValidator.EvenInt"
}
}
}
},
"links": {
Expand Down
Loading