Skip to content

Commit

Permalink
Add 'found atom/string key, expected string/atom' mismatch detection …
Browse files Browse the repository at this point in the history
…to literal map matcher

Fixes #40
  • Loading branch information
mtrudel committed Nov 12, 2024
1 parent 3a87dc5 commit 93470d7
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 5 deletions.
30 changes: 25 additions & 5 deletions lib/machete/matchers/literal_map_matcher.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,35 @@ defmodule Machete.LiteralMapMatcher do
a_keys = a |> Map.keys() |> MapSet.new()
b_keys = b |> Map.keys() |> MapSet.new()

extra_keys = MapSet.difference(b_keys, a_keys)
missing_keys = MapSet.difference(a_keys, b_keys)

atom_keys =
extra_keys
|> Enum.filter(&(is_atom(&1) && MapSet.member?(missing_keys, to_string(&1))))
|> MapSet.new()

string_keys =
extra_keys
|> Enum.filter(
&(is_binary(&1) && MapSet.member?(missing_keys, String.to_existing_atom(&1)))
)
|> MapSet.new()

extra_keys =
MapSet.difference(b_keys, a_keys)
|> Enum.flat_map(&mismatch("Unexpected key", &1))
extra_keys
|> MapSet.difference(atom_keys)
|> MapSet.difference(string_keys)

missing_keys =
MapSet.difference(a_keys, b_keys)
|> Enum.flat_map(&mismatch("Missing key", &1))
missing_keys
|> MapSet.difference(atom_keys |> Enum.map(&Kernel.to_string/1) |> MapSet.new())
|> MapSet.difference(string_keys |> Enum.map(&String.to_existing_atom/1) |> MapSet.new())

extra_keys ++ missing_keys
Enum.flat_map(extra_keys, &mismatch("Unexpected key", &1)) ++
Enum.flat_map(missing_keys, &mismatch("Missing key", &1)) ++
Enum.flat_map(atom_keys, &mismatch("Found atom key, expected string", &1)) ++
Enum.flat_map(string_keys, &mismatch("Found string key, expected atom", &1))
end

defp mismatched_values(a, b) do
Expand Down
8 changes: 8 additions & 0 deletions test/machete/matchers/literal_map_matcher_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ defmodule LiteralMapMatcherTest do
assert %{a: 1} ~>> %{} ~> mismatch("Unexpected key", :a)
end

test "produces a useful mismatch on atom entries where strings were expected" do
assert %{a: 1} ~>> %{"a" => 1} ~> mismatch("Found atom key, expected string", :a)
end

test "produces a useful mismatch on atom entries where atoms were expected" do
assert %{"a" => 1} ~>> %{a: 1} ~> mismatch("Found string key, expected atom", "a")
end

test "produces a useful mismatch on non-maps" do
assert 1 ~>> %{} ~> mismatch("Value is not a map")
end
Expand Down

0 comments on commit 93470d7

Please sign in to comment.