Skip to content

Commit 69e2d39

Browse files
committed
enable pretty printing using config
1 parent 8008a80 commit 69e2d39

File tree

5 files changed

+145
-28
lines changed

5 files changed

+145
-28
lines changed

Diff for: README.md

+9
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,15 @@ Parameter types and return types are not checked.
237237

238238
Hammox now includes telemetry events! See [Telemetry Guide](https://hexdocs.pm/hammox/Telemetry.html) for more information.
239239

240+
## Configuration
241+
242+
Hammox includes experimental pretty printing of error messages.
243+
To enable it add to `config/test.exs`
244+
245+
```elixir
246+
config :hammox, pretty: true
247+
```
248+
240249
## License
241250

242251
Copyright 2019 Michał Szewczak

Diff for: lib/hammox/type_match_error.ex

+38-26
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@ defmodule Hammox.TypeMatchError do
1414
}
1515
end
1616

17+
defp message_string(reasons) when is_list(reasons) do
18+
reasons
19+
|> Enum.with_index()
20+
|> Enum.map_join("\n\n", fn {reason, index} ->
21+
padding = put_padding(index)
22+
23+
reason
24+
|> human_reason()
25+
|> String.replace_prefix("", padding)
26+
end)
27+
end
28+
29+
defp message_string(reason) when is_tuple(reason) do
30+
message_string([reason])
31+
end
32+
1733
defp human_reason({:arg_type_mismatch, index, value, type}) do
1834
"#{Ordinal.ordinalize(index + 1)} argument value #{custom_inspect(value)} does not match #{Ordinal.ordinalize(index + 1)} parameter's type #{type_to_string(type)}."
1935
end
@@ -95,22 +111,6 @@ defmodule Hammox.TypeMatchError do
95111
"Value #{custom_inspect(value)} does not implement the #{protocol_name} protocol."
96112
end
97113

98-
defp message_string(reasons) when is_list(reasons) do
99-
reasons
100-
|> Enum.with_index()
101-
|> Enum.map_join("\n\n", fn {reason, index} ->
102-
padding = put_padding(index)
103-
104-
reason
105-
|> human_reason()
106-
|> String.replace_prefix("", padding)
107-
end)
108-
end
109-
110-
defp message_string(reason) when is_tuple(reason) do
111-
message_string([reason])
112-
end
113-
114114
defp type_to_string({:type, _, :map_field_exact, [type1, type2]}) do
115115
"required(#{type_to_string(type1)}) => #{type_to_string(type2)}"
116116
end
@@ -135,19 +135,27 @@ defmodule Hammox.TypeMatchError do
135135
end
136136

137137
defp format_multiple(type_string) do
138-
padding = "\n" <> get_padding()
139-
140-
type_string
141-
|> String.replace(" | ", padding <> " | ")
142-
|> String.replace_prefix("", padding)
138+
if pretty_print() do
139+
padding = get_padding()
140+
141+
type_string
142+
|> String.replace(" | ", "\n" <> padding <> " | ")
143+
|> String.replace_prefix("", "\n" <> padding)
144+
else
145+
type_string
146+
end
143147
end
144148

145149
defp custom_inspect(value) do
146-
padding = get_padding()
147-
148-
value
149-
|> inspect(limit: :infinity, printable_limit: 500, pretty: true)
150-
|> String.replace("\n", "\n" <> padding)
150+
if pretty_print() do
151+
padding = get_padding()
152+
153+
value
154+
|> inspect(limit: :infinity, printable_limit: 500, pretty: true)
155+
|> String.replace("\n", "\n" <> padding)
156+
else
157+
inspect(value)
158+
end
151159
end
152160

153161
defp put_padding(level) when is_integer(level) do
@@ -165,4 +173,8 @@ defmodule Hammox.TypeMatchError do
165173
defp get_padding() do
166174
Process.get(:padding)
167175
end
176+
177+
defp pretty_print do
178+
Application.get_env(:hammox, :pretty)
179+
end
168180
end

Diff for: test/hammox/type_match_error_test.exs

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
defmodule Hammox.TypeMatchErrorTest do
2+
use ExUnit.Case, async: true
3+
4+
alias Hammox.TypeMatchError
5+
6+
describe "standard error" do
7+
test "reason" do
8+
error = TypeMatchError.exception({:error, reason()})
9+
10+
assert error.message ==
11+
"""
12+
13+
Returned value {:ok, %{__struct__: Post, body: "post body", post_body: "nil"}} does not match type {:ok, Post.t()} | {:error, any()}.
14+
15+
Value {:ok, %{__struct__: Post, body: "post body", post_body: "nil"}} does not match type {:ok, Post.t()} | {:error, any()}.
16+
17+
1st tuple element :ok does not match 1st element type :error.
18+
19+
Value :ok does not match type :error.
20+
"""
21+
|> String.replace_trailing("\n", "")
22+
end
23+
end
24+
25+
describe "pretty error" do
26+
setup do
27+
Application.put_env(:hammox, :pretty, true)
28+
29+
on_exit(fn ->
30+
Application.delete_env(:hammox, :pretty)
31+
end)
32+
end
33+
34+
test "reason" do
35+
error = TypeMatchError.exception({:error, reason()})
36+
37+
assert error.message ==
38+
"""
39+
40+
Returned value {:ok, %{__struct__: Post, body: \"post body\", post_body: \"nil\"}} does not match type
41+
{:ok, Post.t()}
42+
| {:error, any()}.
43+
44+
Value {:ok, %{__struct__: Post, body: \"post body\", post_body: \"nil\"}} does not match type
45+
{:ok, Post.t()}
46+
| {:error, any()}.
47+
48+
1st tuple element :ok does not match 1st element type
49+
:error.
50+
51+
Value :ok does not match type
52+
:error.
53+
"""
54+
|> String.replace_trailing("\n", "")
55+
end
56+
end
57+
58+
defp reason do
59+
[
60+
{:return_type_mismatch,
61+
{:ok,
62+
%{
63+
__struct__: Post,
64+
body: "post body",
65+
post_body: "nil"
66+
}},
67+
{:type, 49, :union,
68+
[
69+
{:type, 0, :tuple,
70+
[
71+
{:atom, 0, :ok},
72+
{:remote_type, 49, [{:atom, 0, Post}, {:atom, 0, :t}, []]}
73+
]},
74+
{:type, 0, :tuple, [{:atom, 0, :error}, {:type, 49, :any, []}]}
75+
]}},
76+
{:type_mismatch,
77+
{:ok,
78+
%{
79+
__struct__: Post,
80+
body: "post body",
81+
post_body: "nil"
82+
}},
83+
{:type, 49, :union,
84+
[
85+
{:type, 0, :tuple,
86+
[
87+
{:atom, 0, :ok},
88+
{:remote_type, 49, [{:atom, 0, Post}, {:atom, 0, :t}, []]}
89+
]},
90+
{:type, 0, :tuple, [{:atom, 0, :error}, {:type, 49, :any, []}]}
91+
]}},
92+
{:tuple_elem_type_mismatch, 0, :ok, {:atom, 0, :error}},
93+
{:type_mismatch, :ok, {:atom, 0, :error}}
94+
]
95+
end
96+
end

Diff for: test/hammox_test.exs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1198,7 +1198,7 @@ defmodule HammoxTest do
11981198

11991199
assert_raise(
12001200
Hammox.TypeMatchError,
1201-
~r/1st argument value "bar" does not match 1st parameter's type \natom()./,
1201+
~r/1st argument value "bar" does not match 1st parameter's type atom()./,
12021202
fn -> TestMock.foo_unnamed_arg("bar") end
12031203
)
12041204
end

Diff for: test/support/behaviour.ex

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ defmodule Hammox.Test.Behaviour do
2626
@callback foo_bitstring_size_literal() :: <<_::3>>
2727
@callback foo_bitstring_unit_literal() :: <<_::_*3>>
2828
@callback foo_bitstring_size_unit_literal() :: <<_::2, _::_*3>>
29-
@callback foo_nullary_function_literal() :: (-> :ok)
29+
@callback foo_nullary_function_literal() :: (() -> :ok)
3030
@callback foo_binary_function_literal() :: (:a, :b -> :ok)
3131
@callback foo_any_arity_function_literal() :: (... -> :ok)
3232
@callback foo_integer_literal() :: 1

0 commit comments

Comments
 (0)