-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy patherror_tracker_test.exs
176 lines (137 loc) · 5.73 KB
/
error_tracker_test.exs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
defmodule ErrorTrackerTest do
use ErrorTracker.Test.Case
alias ErrorTracker.Error
alias ErrorTracker.Occurrence
# We use this file path because for some reason the test scripts are not
# handled as part of the application, so the last line of the app executed is
# on the case module.
@relative_file_path "test/support/case.ex"
describe inspect(&ErrorTracker.report/3) do
setup context do
if Map.has_key?(context, :enabled) do
Application.put_env(:error_tracker, :enabled, context[:enabled])
# Ensure that the application env is restored after each test
on_exit(fn -> Application.delete_env(:error_tracker, :enabled) end)
end
[]
end
test "reports exceptions" do
%Occurrence{error: error = %Error{}} =
report_error(fn -> raise "This is a test" end)
assert error.kind == to_string(RuntimeError)
assert error.reason == "This is a test"
assert error.source_line =~ @relative_file_path
end
test "reports badarith errors" do
string_var = to_string(1)
%Occurrence{error: error = %Error{}, stacktrace: %{lines: [last_line | _]}} =
report_error(fn -> 1 + string_var end)
assert error.kind == to_string(ArithmeticError)
assert error.reason == "bad argument in arithmetic expression"
# Elixir 1.17.0 reports these errors differently than previous versions
if Version.compare(System.version(), "1.17.0") == :lt do
assert last_line.module == "ErrorTrackerTest"
assert last_line.function =~ "&ErrorTracker.report/3 reports badarith errors"
assert last_line.arity == 1
assert last_line.file
assert last_line.line
else
assert last_line.module == "erlang"
assert last_line.function == "+"
assert last_line.arity == 2
refute last_line.file
refute last_line.line
end
end
test "reports undefined function errors" do
# This function does not exist and will raise when called
{m, f, a} = {ErrorTracker, :invalid_fun, []}
%Occurrence{error: error = %Error{}} =
report_error(fn -> apply(m, f, a) end)
assert error.kind == to_string(UndefinedFunctionError)
assert error.reason =~ "is undefined or private"
assert error.source_function == Exception.format_mfa(m, f, Enum.count(a))
assert error.source_line == "(nofile)"
end
test "reports throws" do
%Occurrence{error: error = %Error{}} =
report_error(fn -> throw("This is a test") end)
assert error.kind == "throw"
assert error.reason == "This is a test"
assert error.source_line =~ @relative_file_path
end
test "reports exits" do
%Occurrence{error: error = %Error{}} =
report_error(fn -> exit("This is a test") end)
assert error.kind == "exit"
assert error.reason == "This is a test"
assert error.source_line =~ @relative_file_path
end
@tag capture_log: true
test "reports errors with invalid context" do
# It's invalid because cannot be serialized to JSON
invalid_context = %{foo: %ErrorTracker.Error{}}
assert %Occurrence{} = report_error(fn -> raise "test" end, invalid_context)
end
test "without enabled flag it works as expected" do
# Ensure no value is set
Application.delete_env(:error_tracker, :enabled)
assert %Occurrence{} = report_error(fn -> raise "Sample error" end)
end
@tag enabled: true
test "with enabled flag to true it works as expected" do
assert %Occurrence{} = report_error(fn -> raise "Sample error" end)
end
@tag enabled: false
test "with enabled flag to false it does not store the exception" do
assert report_error(fn -> raise "Sample error" end) == :noop
end
test "includes breadcrumbs if present" do
breadcrumbs = ["breadcrumb 1", "breadcrumb 2"]
occurrence =
report_error(fn ->
raise ErrorWithBreadcrumbs, message: "test", bread_crumbs: breadcrumbs
end)
assert occurrence.breadcrumbs == breadcrumbs
end
test "includes breadcrumbs if stored by the user" do
ErrorTracker.add_breadcrumb("breadcrumb 1")
ErrorTracker.add_breadcrumb("breadcrumb 2")
occurrence = report_error(fn -> raise "Sample error" end)
assert occurrence.breadcrumbs == ["breadcrumb 1", "breadcrumb 2"]
end
test "merges breadcrumbs stored by the user and contained on the exception" do
ErrorTracker.add_breadcrumb("breadcrumb 1")
ErrorTracker.add_breadcrumb("breadcrumb 2")
occurrence =
report_error(fn ->
raise ErrorWithBreadcrumbs, message: "test", bread_crumbs: ["breadcrumb 3"]
end)
assert occurrence.breadcrumbs == ["breadcrumb 1", "breadcrumb 2", "breadcrumb 3"]
end
end
describe inspect(&ErrorTracker.resolve/1) do
test "marks the error as resolved" do
%Occurrence{error: error} = report_error(fn -> raise "This is a test" end)
assert {:ok, %Error{status: :resolved}} = ErrorTracker.resolve(error)
end
end
describe inspect(&ErrorTracker.unresolve/1) do
test "marks the error as unresolved" do
%Occurrence{error: error} = report_error(fn -> raise "This is a test" end)
# Manually mark the error as resolved
{:ok, resolved} = ErrorTracker.resolve(error)
assert {:ok, %Error{status: :unresolved}} = ErrorTracker.unresolve(resolved)
end
end
describe inspect(&ErrorTracker.add_breadcrumb/1) do
test "adds an entry to the breadcrumbs list" do
ErrorTracker.add_breadcrumb("breadcrumb 1")
ErrorTracker.add_breadcrumb("breadcrumb 2")
assert ["breadcrumb 1", "breadcrumb 2"] = ErrorTracker.get_breadcrumbs()
end
end
end
defmodule ErrorWithBreadcrumbs do
defexception [:message, :bread_crumbs]
end