defmodule Matcher.Utils do
def matched?({:ok, _}), do: true
def matched?(_), do: false
def is_enumerable(value) do
Enumerable.impl_for(value) != nil
end
def compare_maps(expected, actual, allow_unexpected?: allow_unexpected?)
when is_map(expected) and is_map(actual) do
expected_results =
Enum.map(expected, fn {key, matcher} ->
find_value(key, matcher, actual)
end)
unexpected = Map.keys(actual) -- Map.keys(expected)
if Enum.all?(expected_results, fn {_, _, _, match} ->
matched?(match)
end) and (Enum.empty?(unexpected) or allow_unexpected?) do
{:ok, nil}
else
{:error, %{}}
end
end
def compare_maps(e, a, _),
do: {:error, %{error: "expected #{inspect(e)}, but got #{inspect(a)}"}}
defp find_value(key, matcher, actual_map) do
actual_value = Map.get(actual_map, key)
match = Matcher.match(matcher, actual_value)
{key, matcher, actual_value, match}
end
def permutations([]), do: [[]]
def permutations(list),
do: for(elem <- list, rest <- permutations(list -- [elem]), do: [elem | rest])
def compare_lists([], []), do: {:ok, %{}}
def compare_lists([_ | _], []), do: {:error, %{}}
def compare_lists([], [_ | _]), do: {:error, %{}}
def compare_lists([eh | et], [ah | at]) do
case Matcher.match(eh, ah) do
{:ok, _} -> Matcher.match(et, at)
error -> error
end
end
def compare_lists(e, a), do: {:error, %{error: "expected #{inspect(e)}, but got #{inspect(a)}"}}
end