Skip to content

Commit

Permalink
Merge branch 'error-if-selection-specifies-key-not-in-schema'
Browse files Browse the repository at this point in the history
  • Loading branch information
keathley committed Jan 31, 2020
2 parents 5be61af + 6bf487d commit 6a5c8b2
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 4 deletions.
42 changes: 38 additions & 4 deletions lib/norm/errors.ex
Expand Up @@ -34,6 +34,9 @@ defmodule Norm.SpecError do
defexception [:message]
alias Norm.Spec
alias Norm.Schema
alias Norm.Spec.Collection
alias Norm.Spec.Alt
alias Norm.Spec.Union

def exception(details) do
%__MODULE__{message: msg(details)}
Expand All @@ -49,22 +52,53 @@ defmodule Norm.SpecError do
defp format(val, indentation \\ 0)

defp format({key, spec_or_schema}, i) do
format(key, i) <> " => " <> format(spec_or_schema, i + 1)
"{" <> format(key, i) <> ", " <> format(spec_or_schema, i + 1) <> "}"
end

defp format(atom, _) when is_atom(atom), do: ":#{atom}"
defp format(str, _) when is_binary(str), do: ~s|"#{str}"|
defp format(%Spec{predicate: pred}, _), do: "spec(#{pred})"

defp format(%Schema{specs: specs}, i) do
f = fn {key, spec_or_schema}, i ->
format(key, i) <> " => " <> format(spec_or_schema, i + 1)
end

specs =
specs
|> Enum.map(&format(&1, i))
|> Enum.map(& f.(&1, i))
|> Enum.map(&pad(&1, (i + 1) * 2))
|> Enum.join("\n")

"%{\n" <> specs <> "\n" <> pad("}", i * 2)
end
defp format(%Collection{spec: spec}, i) do
"coll_of(#{format(spec, i)})"
end
defp format(%Alt{specs: specs}, i) do
formatted =
specs
|> Enum.map(&format(&1, i))
|> Enum.map(&pad(&1, (i + 1) * 2))
|> Enum.join("\n")

if length(specs) > 0 do
"alt([\n#{formatted}\n" <> pad("])", i * 2)
else
"alt([])"
end
end
defp format(%Union{specs: specs}, i) do
formatted =
specs
|> Enum.map(&format(&1, i))
|> Enum.map(&pad(&1, (i + 1) * 2))
|> Enum.join("\n")

if length(specs) > 0 do
"one_of([\n#{formatted}\n" <> pad("])", i * 2)
else
"one_of([])"
end
end

defp pad(str, 0), do: str
defp pad(str, i), do: " " <> pad(str, i - 1)
Expand Down
10 changes: 10 additions & 0 deletions test/norm/selection_test.exs
Expand Up @@ -89,6 +89,16 @@ defmodule Norm.SelectionTest do
assert_raise Norm.SpecError, fn ->
selection(schema(%{user: schema(%{age: spec(is_integer())})}), foo: [:name])
end

assert_raise Norm.SpecError, fn ->
users = schema(%{
users: coll_of(schema(%{age: spec(is_integer)})),
alts: alt([foo: :foo, bar: :bar]),
one_of: one_of([:foo, :bar]),
map_of: map_of(spec(is_atom), spec(is_atom))
})
selection(users, [:other])
end
end

test "works with structs" do
Expand Down

0 comments on commit 6a5c8b2

Please sign in to comment.