defmodule Matcher.Utils.Maps do import Matcher.Errors def compare_maps(expected, actual, context, 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} -> Matcher.Utils.matched?(match) end) and (Enum.empty?(unexpected) or allow_unexpected?) do {:ok, nil} else {:error, error(context, [])} end end def compare_maps(e, a, context, _) do error(context, message: "expected #{expected(e)}, but got #{mismatched(a)}") end 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 end