summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksei Magusev <lexmag@me.com>2016-03-31 00:55:31 +0200
committerAleksei Magusev <lexmag@me.com>2016-03-31 01:31:08 +0200
commit3cdcd867923755272ee09b86a20ebb484cc851a9 (patch)
tree850212c2b235b194ae87e9c48bc01095ef9a84f7
parente1e49dfb9728a0522af5f7175273dc0574ed17f8 (diff)
downloadelixir-am-ex_unit-difference-highlighting.tar.gz
-rw-r--r--lib/ex_unit/lib/ex_unit/formatter.ex42
1 files changed, 39 insertions, 3 deletions
diff --git a/lib/ex_unit/lib/ex_unit/formatter.ex b/lib/ex_unit/lib/ex_unit/formatter.ex
index eb3a92854..2c2df5eba 100644
--- a/lib/ex_unit/lib/ex_unit/formatter.ex
+++ b/lib/ex_unit/lib/ex_unit/formatter.ex
@@ -226,9 +226,7 @@ defmodule ExUnit.Formatter do
if_value(struct.left, fn left ->
if_value(struct.right, fn right ->
if same_data_type?(left, right) do
- String.difference(inspect(left), inspect(right))
- |> Enum.map_join(&format_diff_fragment(&1, formatter))
- |> String.replace("\n", "\n" <> @inspect_padding)
+ format_diff(left, right, formatter)
else
ExUnit.AssertionError.no_value
end
@@ -236,6 +234,44 @@ defmodule ExUnit.Formatter do
end)
end
+ defp format_diff(left, right, formatter) when is_binary(left) and is_binary(right) do
+ String.difference(left, right)
+ |> Enum.map_join(&format_diff_fragment(&1, formatter))
+ |> String.replace("\n", "\n" <> @inspect_padding)
+ end
+
+ defp format_diff(left, right, formatter) when is_map(left) and is_map(right) do
+ {surplus, altered} =
+ Enum.reduce(left, {[], []}, fn({key, val1}, {surplus, altered} = acc) ->
+ case Map.fetch(right, key) do
+ {:ok, ^val1} ->
+ acc
+ {:ok, val2} ->
+ {surplus, [{key, {val1, val2}} | altered]}
+ :error ->
+ {[{key, val1} | surplus], altered}
+ end
+ end)
+ missing = Enum.reject(right, fn {key, _} -> Map.has_key?(left, key) end)
+ result = Enum.reduce(missing, [], fn({key, val}, acc) ->
+ [formatter.(:diff_insert, inspect(key) <> " => " <> inspect(val)) | acc]
+ end)
+ result = Enum.reduce(surplus, result, fn({key, val}, acc) ->
+ [formatter.(:diff_delete, inspect(key) <> " => " <> inspect(val)) | acc]
+ end)
+ result = Enum.reduce(altered, result, fn({key, {val1, val2}}, acc) ->
+ delete = formatter.(:diff_delete, inspect(val1))
+ insert = formatter.(:diff_insert, inspect(val2))
+ [inspect(key) <> " => " <> delete <> insert | acc]
+ end)
+ result = Enum.intersperse(result, ", ") |> IO.iodata_to_binary
+ "%{" <> result <> "}"
+ end
+
+ defp format_diff(left, right, formatter) do
+ format_diff(inspect(left), inspect(right), formatter)
+ end
+
defp format_diff_fragment({:eq, <<ch1::utf8, ch2::utf8, ch3::utf8>> <> rest}, _) do
slice = String.slice(rest, -2, 2)
fill = if slice != rest, do: "...", else: <<ch3::utf8>>