Page MenuHomePhorge

No OneTemporary

Size
4 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/open_api_spex/cast/array.ex b/lib/open_api_spex/cast/array.ex
index 83dc113..4dd07af 100644
--- a/lib/open_api_spex/cast/array.ex
+++ b/lib/open_api_spex/cast/array.ex
@@ -1,70 +1,72 @@
defmodule OpenApiSpex.Cast.Array do
@moduledoc false
alias OpenApiSpex.Cast
- def cast(%{value: []}), do: {:ok, []}
+ def cast(%{value: [], schema: %{minItems: nil}}) do
+ {:ok, []}
+ end
def cast(%{value: items} = ctx) when is_list(items) do
case cast_array(ctx) do
{:cast, ctx} -> cast(ctx)
{items, []} -> Cast.ok(%{ctx | value: items})
{_, errors} -> {:error, errors}
end
end
def cast(ctx),
do: Cast.error(ctx, {:invalid_type, :array})
## Private functions
defp cast_array(%{value: value, schema: %{minItems: minimum}} = ctx) when is_integer(minimum) do
item_count = Enum.count(value)
if item_count < minimum do
Cast.error(ctx, {:min_items, minimum, item_count})
else
Cast.success(ctx, :minItems)
end
end
defp cast_array(%{value: value, schema: %{maxItems: maximum}} = ctx) when is_integer(maximum) do
item_count = Enum.count(value)
if item_count > maximum do
Cast.error(ctx, {:max_items, maximum, item_count})
else
Cast.success(ctx, :maxItems)
end
end
defp cast_array(%{value: value, schema: %{uniqueItems: true}} = ctx) do
unique_size =
value
|> MapSet.new()
|> MapSet.size()
if unique_size != Enum.count(value) do
Cast.error(ctx, {:unique_items})
else
Cast.success(ctx, :uniqueItems)
end
end
defp cast_array(%{value: items} = ctx) do
cast_results =
items
|> Enum.with_index()
|> Enum.map(fn {item, index} ->
path = [index | ctx.path]
Cast.cast(%{ctx | value: item, schema: ctx.schema.items, path: path})
end)
errors =
for({:error, errors} <- cast_results, do: errors)
|> Enum.concat()
items = for {:ok, item} <- cast_results, do: item
{items, errors}
end
end
diff --git a/test/cast/array_test.exs b/test/cast/array_test.exs
index ac0721f..a5f300c 100644
--- a/test/cast/array_test.exs
+++ b/test/cast/array_test.exs
@@ -1,65 +1,70 @@
defmodule OpenApiSpec.Cast.ArrayTest do
use ExUnit.Case
alias OpenApiSpex.Cast.{Array, Error}
alias OpenApiSpex.{Cast, Schema}
defp cast(map), do: Array.cast(struct(Cast, map))
describe "cast/4" do
test "array" do
schema = %Schema{type: :array}
assert cast(value: [], schema: schema) == {:ok, []}
assert cast(value: [1, 2, 3], schema: schema) == {:ok, [1, 2, 3]}
assert cast(value: ["1", "2", "3"], schema: schema) == {:ok, ["1", "2", "3"]}
assert {:error, [error]} = cast(value: %{}, schema: schema)
assert %Error{} = error
assert error.reason == :invalid_type
assert error.value == %{}
end
test "with maxItems" do
schema = %Schema{type: :array, maxItems: 2}
assert cast(value: [1, 2], schema: schema) == {:ok, [1, 2]}
assert {:error, [error]} = cast(value: [1, 2, 3], schema: schema)
assert %Error{} = error
assert error.reason == :max_items
assert error.value == [1, 2, 3]
end
test "with minItems" do
schema = %Schema{type: :array, minItems: 2}
assert cast(value: [1, 2], schema: schema) == {:ok, [1, 2]}
assert {:error, [error]} = cast(value: [1], schema: schema)
assert %Error{} = error
assert error.reason == :min_items
assert error.value == [1]
+
+ # Test for #179, "minLength validation ignores empty array"
+ assert {:error, [%Error{reason: :min_items, value: []}]} = cast(value: [], schema: schema)
+ # Negative test, check that minItems: 0 allows an empty array
+ assert cast(value: [], schema: %Schema{type: :array, minItems: 0}) == {:ok, []}
end
test "with uniqueItems" do
schema = %Schema{type: :array, uniqueItems: true}
assert cast(value: [1, 2], schema: schema) == {:ok, [1, 2]}
assert {:error, [error]} = cast(value: [1, 1], schema: schema)
assert %Error{} = error
assert error.reason == :unique_items
assert error.value == [1, 1]
end
test "array with items schema" do
items_schema = %Schema{type: :integer}
schema = %Schema{type: :array, items: items_schema}
assert cast(value: [], schema: schema) == {:ok, []}
assert cast(value: [1, 2, 3], schema: schema) == {:ok, [1, 2, 3]}
assert cast(value: ["1", "2", "3"], schema: schema) == {:ok, [1, 2, 3]}
assert {:error, [error]} = cast(value: [1, "two"], schema: schema)
assert %Error{} = error
assert error.reason == :invalid_type
assert error.value == "two"
assert error.path == [1]
end
end
end

File Metadata

Mime Type
text/x-diff
Expires
Wed, Nov 27, 12:53 AM (1 d, 12 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40529
Default Alt Text
(4 KB)

Event Timeline