Skip to content

Commit

Permalink
Always return selection errors
Browse files Browse the repository at this point in the history
  • Loading branch information
keathley committed Feb 1, 2020
1 parent ee46655 commit 1c950e1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 15 deletions.
32 changes: 17 additions & 15 deletions lib/norm/spec/selection.ex
Expand Up @@ -73,21 +73,23 @@ defmodule Norm.Spec.Selection do
alias Norm.Conformer
alias Norm.Conformer.Conformable

def conform(_, input, path) when not is_map(input) do
{:error, [Conformer.error(path, input, "not a map")]}
end

def conform(%{required: required, schema: schema}, input, path) do
with {:ok, conformed} <- Conformable.conform(schema, input, path) do
errors = ensure_keys(required, conformed, path, [])

if Enum.any?(errors) do
errors =
errors
|> Enum.flat_map(fn {_, errors} -> errors end)

{:error, errors}
else
# We can just return the conformed values here because we know that
# everything is in there.
{:ok, conformed}
end
case Conformable.conform(schema, input, path) do
{:ok, conformed} ->
errors = ensure_keys(required, conformed, path, [])
if Enum.any?(errors) do
{:error, errors}
else
{:ok, conformed}
end

{:error, conforming_errors} ->
errors = ensure_keys(required, input, path, [])
{:error, conforming_errors ++ errors}
end
end

Expand Down Expand Up @@ -117,7 +119,7 @@ defmodule Norm.Spec.Selection do
if Map.has_key?(conformed, key) do
:ok
else
{:error, [Conformer.error(path ++ [key], conformed, ":required")]}
Conformer.error(path ++ [key], conformed, ":required")
end
end
end
Expand Down
12 changes: 12 additions & 0 deletions test/norm/selection_test.exs
Expand Up @@ -77,6 +77,18 @@ defmodule Norm.SelectionTest do
refute valid?(%{name: "chris", age: 31}, selection(user_schema()))
end

test "always returns missing keys even if the schema errors" do
s = schema(%{
a: coll_of(selection(schema(%{b: spec(is_boolean())}))),
c: spec(is_boolean())
})
assert {:error, errors} = conform(%{a: [%{b: "no_bool"}]}, selection(s, [:c]))
assert errors == [
%{input: "no_bool", path: [:a, 0, :b], spec: "is_boolean()"},
%{input: %{a: [%{b: "no_bool"}]}, path: [:c], spec: ":required"},
]
end

test "errors if there are keys that aren't specified in a schema" do
assert_raise Norm.SpecError, fn ->
selection(schema(%{age: spec(is_integer())}), [:name])
Expand Down

0 comments on commit 1c950e1

Please sign in to comment.