Skip to content

Instantly share code, notes, and snippets.

@teamon
Last active September 10, 2016 08:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save teamon/eb18047df0db665d2671a9f1c38b16cc to your computer and use it in GitHub Desktop.
Save teamon/eb18047df0db665d2671a9f1c38b16cc to your computer and use it in GitHub Desktop.
@doc """
Asserts based on pattern matching.
Example: check if collection contains element that matches the pattern
assert_match %{body: "lorem"} in messages
assert_match %{id: ^id} in response["users"]
"""
defmacro assert_match({:in, _, [left, right]} = assertion) do
code = Macro.escape(assertion)
left = Macro.expand(left, __CALLER__)
pins = collect_pins_from_pattern(left)
quote do
right = unquote(right)
assert Enum.any?(right, fn
unquote(left) -> true
_ -> false
end),
right: right,
expr: unquote(code),
message: "match (=) in collection failed" <> ExUnit.Assertions.__pins__(unquote(pins))
end
end
# stolen from ExUnit
defp collect_pins_from_pattern(expr) do
{_, pins} =
Macro.prewalk(expr, [], fn
{:^, _, [{name, _, _} = var]}, acc ->
{:ok, [{name, var} | acc]}
form, acc ->
{form, acc}
end)
Enum.uniq_by(pins, &elem(&1, 0))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment