Page MenuHomePhorge

No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/open_api_spex/cast/all_of.ex b/lib/open_api_spex/cast/all_of.ex
index f4d9c24..a536f65 100644
--- a/lib/open_api_spex/cast/all_of.ex
+++ b/lib/open_api_spex/cast/all_of.ex
@@ -1,84 +1,84 @@
defmodule OpenApiSpex.Cast.AllOf do
@moduledoc false
alias OpenApiSpex.Cast
alias OpenApiSpex.Schema
def cast(ctx), do: cast_all_of(ctx, nil)
defp cast_all_of(%{schema: %{allOf: [%Schema{type: :array} = schema | remaining]}} = ctx, acc)
when is_list(acc) or acc == nil do
# Since we parse a multi-type array, acc has to be a list or nil
acc = acc || []
- case Cast.cast(%{ctx | schema: schema}) |> IO.inspect() do
+ case Cast.cast(%{ctx | schema: schema}) do
{:ok, value} when is_list(value) ->
# Since the cast for the list didn't result in a cast error,
# we do not proceed the values through the remaining schemas
{: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
else
_ -> Cast.error(ctx, {:all_of, to_string(schema.title || schema.type)})
end
end
end
defp cast_all_of(%{schema: %{allOf: [%Schema{} = schema | remaining]}} = ctx, acc) do
schema = OpenApiSpex.resolve_schema(schema, ctx.schemas)
relaxed_schema = %{schema | additionalProperties: true}
new_ctx = put_in(ctx.schema.allOf, remaining)
- case Cast.cast(%{ctx | schema: relaxed_schema}) |> IO.inspect() do
+ case Cast.cast(%{ctx | schema: relaxed_schema}) do
{:ok, value} when is_map(value) ->
cast_all_of(new_ctx, Map.merge(acc || %{}, value))
{:ok, value} when acc == nil ->
# primitive value with no previous (valid) casts -> return
{:ok, value}
{:error, _} when remaining == [] ->
# Since no schema is left to parse the remaining values, we return a error
Cast.error(ctx, {:all_of, to_string(relaxed_schema.title || relaxed_schema.type)})
{:error, _} ->
# in case the cast results in a error, we just skip this schema
cast_all_of(new_ctx, acc)
end
end
defp cast_all_of(%{schema: %{allOf: [schema | remaining]}} = ctx, result) do
schema = OpenApiSpex.resolve_schema(schema, ctx.schemas)
cast_all_of(%{ctx | schema: %{allOf: [schema | remaining]}}, result)
end
defp cast_all_of(%{schema: schema} = ctx, nil) do
Cast.error(ctx, {:all_of, to_string(schema.title || schema.type)})
end
defp cast_all_of(%{schema: %{allOf: []}}, acc) do
# All values have been casted against the allOf schemas - return accumulator
{:ok, acc}
end
defp reject_error_values(%{value: values} = ctx, [%{reason: :invalid_type} = error | tail]) do
new_values = List.delete(values, error.value)
reject_error_values(%{ctx | value: new_values}, tail)
end
defp reject_error_values(ctx, []) do
# All errors should now be resolved for the current schema
{:ok, ctx}
end
defp reject_error_values(_ctx, errors) do
# Some errors couldn't be resolved, we break and return the remaining errors
errors
end
end
diff --git a/test/cast/all_of_test.exs b/test/cast/all_of_test.exs
index 83428a4..9bb9217 100644
--- a/test/cast/all_of_test.exs
+++ b/test/cast/all_of_test.exs
@@ -1,79 +1,79 @@
defmodule OpenApiSpex.CastAllOfTest do
use ExUnit.Case
alias OpenApiSpex.{Cast, Schema}
alias OpenApiSpex.Cast.{Error, AllOf}
alias OpenApiSpex.Test.Assertions2
defp cast(ctx), do: AllOf.cast(struct(Cast, ctx))
describe "cast/1" do
test "allOf" do
schema = %Schema{allOf: [%Schema{type: :integer}, %Schema{type: :string}]}
assert {:ok, 1} = cast(value: "1", schema: schema)
end
test "allOf, uncastable schema" do
schema = %Schema{allOf: [%Schema{type: :integer}, %Schema{type: :string}]}
assert {:error, [error]} = cast(value: [:whoops], schema: schema)
assert Error.message(error) ==
"Failed to cast value as string. Value must be castable using `allOf` schemas listed."
schema_with_title = %Schema{allOf: [%Schema{title: "Age", type: :integer}]}
assert {:error, [error_with_schema_title]} =
cast(value: [:nopes], schema: schema_with_title)
assert Error.message(error_with_schema_title) ==
"Failed to cast value as Age. Value must be castable using `allOf` schemas listed."
end
test "a more sophisticated example" do
dog = %{"bark" => "woof", "pet_type" => "Dog"}
Assertions2.assert_schema(dog, "Dog", OpenApiSpexTest.ApiSpec.spec())
end
test "allOf, for inheritance schema" do
schema = %Schema{
allOf: [
%Schema{
type: :object,
additionalProperties: true,
properties: %{
id: %Schema{
type: :string
}
}
},
%Schema{
type: :object,
additionalProperties: true,
properties: %{
bar: %Schema{
type: :string
}
}
}
]
}
value = %{id: "e30aee0f-dbda-40bd-9198-6cf609b8b640", bar: "foo"}
assert {:ok, %{id: "e30aee0f-dbda-40bd-9198-6cf609b8b640", bar: "foo"}} =
cast(value: value, schema: schema)
end
end
test "allOf, for multi-type array" do
schema = %Schema{
allOf: [
%Schema{type: :array, items: %Schema{type: :integer}},
%Schema{type: :array, items: %Schema{type: :boolean}},
%Schema{type: :array, items: %Schema{type: :string}}
]
}
value = ["Test #1", "2", "3", "4", "true", "Five!"]
- assert {:ok, [2, 3, 4, true, "Test #1", "Five!"]} = cast(value: value, schema: schema)
+ assert {:ok, [2, 3, 4, true, "Test #1", "Five!"]} = cast(value: value, schema: schema)
end
end

File Metadata

Mime Type
text/x-diff
Expires
Wed, Nov 27, 10:32 PM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40762
Default Alt Text
(6 KB)

Event Timeline