airbrake-ruby 5.2.0 → 5.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby.rb +3 -2
  3. data/lib/airbrake-ruby/async_sender.rb +3 -1
  4. data/lib/airbrake-ruby/context.rb +51 -0
  5. data/lib/airbrake-ruby/filter_chain.rb +2 -0
  6. data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
  7. data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +1 -1
  8. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +1 -1
  9. data/lib/airbrake-ruby/filters/git_revision_filter.rb +1 -1
  10. data/lib/airbrake-ruby/filters/keys_filter.rb +2 -2
  11. data/lib/airbrake-ruby/filters/sql_filter.rb +2 -2
  12. data/lib/airbrake-ruby/filters/thread_filter.rb +1 -1
  13. data/lib/airbrake-ruby/ignorable.rb +0 -2
  14. data/lib/airbrake-ruby/notice_notifier.rb +3 -4
  15. data/lib/airbrake-ruby/performance_notifier.rb +1 -2
  16. data/lib/airbrake-ruby/remote_settings/settings_data.rb +1 -1
  17. data/lib/airbrake-ruby/tdigest.rb +7 -6
  18. data/lib/airbrake-ruby/thread_pool.rb +5 -3
  19. data/lib/airbrake-ruby/timed_trace.rb +1 -3
  20. data/lib/airbrake-ruby/version.rb +1 -1
  21. data/spec/airbrake_spec.rb +139 -76
  22. data/spec/async_sender_spec.rb +10 -8
  23. data/spec/backtrace_spec.rb +13 -10
  24. data/spec/benchmark_spec.rb +5 -3
  25. data/spec/code_hunk_spec.rb +24 -15
  26. data/spec/config/processor_spec.rb +12 -4
  27. data/spec/config/validator_spec.rb +5 -2
  28. data/spec/config_spec.rb +24 -16
  29. data/spec/context_spec.rb +54 -0
  30. data/spec/deploy_notifier_spec.rb +6 -4
  31. data/spec/file_cache_spec.rb +1 -0
  32. data/spec/filter_chain_spec.rb +29 -24
  33. data/spec/filters/context_filter_spec.rb +14 -5
  34. data/spec/filters/dependency_filter_spec.rb +3 -1
  35. data/spec/filters/exception_attributes_filter_spec.rb +5 -3
  36. data/spec/filters/gem_root_filter_spec.rb +5 -2
  37. data/spec/filters/git_last_checkout_filter_spec.rb +10 -12
  38. data/spec/filters/git_repository_filter.rb +9 -9
  39. data/spec/filters/git_revision_filter_spec.rb +19 -19
  40. data/spec/filters/keys_allowlist_spec.rb +25 -16
  41. data/spec/filters/keys_blocklist_spec.rb +25 -18
  42. data/spec/filters/root_directory_filter_spec.rb +3 -3
  43. data/spec/filters/sql_filter_spec.rb +26 -26
  44. data/spec/filters/system_exit_filter_spec.rb +4 -2
  45. data/spec/filters/thread_filter_spec.rb +15 -13
  46. data/spec/loggable_spec.rb +2 -2
  47. data/spec/monotonic_time_spec.rb +8 -6
  48. data/spec/nested_exception_spec.rb +46 -46
  49. data/spec/notice_notifier/options_spec.rb +23 -13
  50. data/spec/notice_notifier_spec.rb +52 -47
  51. data/spec/notice_spec.rb +6 -2
  52. data/spec/performance_notifier_spec.rb +67 -60
  53. data/spec/promise_spec.rb +38 -32
  54. data/spec/remote_settings/callback_spec.rb +27 -8
  55. data/spec/remote_settings/settings_data_spec.rb +4 -4
  56. data/spec/remote_settings_spec.rb +18 -8
  57. data/spec/response_spec.rb +34 -12
  58. data/spec/stashable_spec.rb +5 -5
  59. data/spec/stat_spec.rb +7 -5
  60. data/spec/sync_sender_spec.rb +49 -16
  61. data/spec/tdigest_spec.rb +60 -55
  62. data/spec/thread_pool_spec.rb +65 -55
  63. data/spec/time_truncate_spec.rb +4 -2
  64. data/spec/timed_trace_spec.rb +32 -30
  65. data/spec/truncator_spec.rb +72 -43
  66. metadata +51 -48
@@ -1,4 +1,6 @@
1
1
  RSpec.describe Airbrake::Filters::ThreadFilter do
2
+ subject(:thread_filter) { described_class.new }
3
+
2
4
  let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
3
5
 
4
6
  def new_thread
@@ -17,7 +19,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
17
19
  it "attaches the thread variable" do
18
20
  new_thread do |th|
19
21
  th.thread_variable_set(:bingo, var)
20
- subject.call(notice)
22
+ thread_filter.call(notice)
21
23
  end
22
24
 
23
25
  expect(notice[:params][:thread][:thread_variables][:bingo]).to eq(var)
@@ -60,7 +62,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
60
62
  it "converts it to a String and attaches" do
61
63
  new_thread do |th|
62
64
  th.thread_variable_set(:bingo, Object.new)
63
- subject.call(notice)
65
+ thread_filter.call(notice)
64
66
  end
65
67
 
66
68
  vars = notice[:params][:thread][:thread_variables]
@@ -90,7 +92,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
90
92
  it "converts objects to a safe objects" do
91
93
  new_thread do |th|
92
94
  th.thread_variable_set(:bingo, var)
93
- subject.call(notice)
95
+ thread_filter.call(notice)
94
96
  end
95
97
 
96
98
  vars = notice[:params][:thread][:thread_variables]
@@ -121,7 +123,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
121
123
 
122
124
  new_thread do |th|
123
125
  th.thread_variable_set(var, :bingo)
124
- subject.call(notice)
126
+ thread_filter.call(notice)
125
127
  end
126
128
 
127
129
  thread_variables = notice[:params][:thread][:thread_variables]
@@ -134,7 +136,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
134
136
  it "attaches the fiber variable" do
135
137
  new_thread do |th|
136
138
  th[:bingo] = var
137
- subject.call(notice)
139
+ thread_filter.call(notice)
138
140
  end
139
141
 
140
142
  expect(notice[:params][:thread][:fiber_variables][:bingo]).to eq(var)
@@ -177,7 +179,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
177
179
  it "converts it to a String and attaches" do
178
180
  new_thread do |th|
179
181
  th[:bingo] = Object.new
180
- subject.call(notice)
182
+ thread_filter.call(notice)
181
183
  end
182
184
 
183
185
  vars = notice[:params][:thread][:fiber_variables]
@@ -207,7 +209,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
207
209
  it "converts objects to a safe objects" do
208
210
  new_thread do |th|
209
211
  th[:bingo] = var
210
- subject.call(notice)
212
+ thread_filter.call(notice)
211
213
  end
212
214
 
213
215
  vars = notice[:params][:thread][:fiber_variables]
@@ -237,31 +239,31 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
237
239
  it "appends name" do
238
240
  new_thread do |th|
239
241
  th.name = 'bingo'
240
- subject.call(notice)
242
+ thread_filter.call(notice)
241
243
  end
242
244
 
243
245
  expect(notice[:params][:thread][:name]).to eq('bingo')
244
246
  end
245
247
 
246
248
  it "appends thread inspect (self)" do
247
- subject.call(notice)
249
+ thread_filter.call(notice)
248
250
  expect(notice[:params][:thread][:self]).to match(/\A#<Thread:.+>\z/)
249
251
  end
250
252
 
251
253
  it "appends thread group" do
252
- subject.call(notice)
254
+ thread_filter.call(notice)
253
255
  expect(notice[:params][:thread][:group][0]).to match(/\A#<Thread:.+>\z/)
254
256
  end
255
257
 
256
258
  it "appends priority" do
257
- subject.call(notice)
259
+ thread_filter.call(notice)
258
260
  expect(notice[:params][:thread][:priority]).to eq(0)
259
261
  end
260
262
 
261
263
  it "appends safe_level", skip: (
262
264
  "Not supported on this version of Ruby." unless Airbrake::HAS_SAFE_LEVEL
263
265
  ) do
264
- subject.call(notice)
266
+ thread_filter.call(notice)
265
267
  expect(notice[:params][:thread][:safe_level]).to eq(0)
266
268
  end
267
269
 
@@ -270,7 +272,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
270
272
 
271
273
  new_thread do |th|
272
274
  th[key] = :bingo
273
- subject.call(notice)
275
+ thread_filter.call(notice)
274
276
  end
275
277
 
276
278
  fiber_variables = notice[:params][:thread][:fiber_variables]
@@ -6,12 +6,12 @@ RSpec.describe Airbrake::Loggable do
6
6
  end
7
7
 
8
8
  describe "#logger" do
9
- let(:subject) do
9
+ subject(:class_with_logger) do
10
10
  Class.new { include Airbrake::Loggable }.new
11
11
  end
12
12
 
13
13
  it "returns a logger that has Logger::WARN severity" do
14
- expect(subject.logger.level).to eq(Logger::WARN)
14
+ expect(class_with_logger.logger.level).to eq(Logger::WARN)
15
15
  end
16
16
  end
17
17
  end
@@ -1,23 +1,25 @@
1
1
  RSpec.describe Airbrake::MonotonicTime do
2
+ subject(:monotonic_time) { described_class }
3
+
2
4
  describe ".time_in_ms" do
3
5
  it "returns monotonic time in milliseconds" do
4
- expect(subject.time_in_ms).to be_a(Float)
6
+ expect(monotonic_time.time_in_ms).to be_a(Float)
5
7
  end
6
8
 
7
9
  it "always returns time in the future" do
8
- old_time = subject.time_in_ms
9
- expect(subject.time_in_ms).to be > old_time
10
+ old_time = monotonic_time.time_in_ms
11
+ expect(monotonic_time.time_in_ms).to be > old_time
10
12
  end
11
13
  end
12
14
 
13
15
  describe ".time_in_s" do
14
16
  it "returns monotonic time in seconds" do
15
- expect(subject.time_in_s).to be_a(Float)
17
+ expect(monotonic_time.time_in_s).to be_a(Float)
16
18
  end
17
19
 
18
20
  it "always returns time in the future" do
19
- old_time = subject.time_in_s
20
- expect(subject.time_in_s).to be > old_time
21
+ old_time = monotonic_time.time_in_s
22
+ expect(monotonic_time.time_in_s).to be > old_time
21
23
  end
22
24
  end
23
25
  end
@@ -1,73 +1,73 @@
1
1
  RSpec.describe Airbrake::NestedException do
2
2
  describe "#as_json" do
3
3
  context "given exceptions with backtraces" do
4
+ # rubocop:disable RSpec/MultipleExpectations
4
5
  it "unwinds nested exceptions" do
5
6
  begin
6
- begin
7
- raise AirbrakeTestError
8
- rescue AirbrakeTestError
9
- Ruby21Error.raise_error('bingo')
10
- end
11
- rescue Ruby21Error => ex
12
- nested_exception = described_class.new(ex)
13
- exceptions = nested_exception.as_json
14
-
15
- expect(exceptions.size).to eq(2)
16
- expect(exceptions[0][:message]).to eq('bingo')
17
- expect(exceptions[1][:message]).to eq('App crashed!')
18
- expect(exceptions[0][:backtrace]).not_to be_empty
19
- expect(exceptions[1][:backtrace]).not_to be_empty
7
+ raise AirbrakeTestError
8
+ rescue AirbrakeTestError
9
+ Ruby21Error.raise_error('bingo')
20
10
  end
11
+ rescue Ruby21Error => ex
12
+ nested_exception = described_class.new(ex)
13
+ exceptions = nested_exception.as_json
14
+
15
+ expect(exceptions.size).to eq(2)
16
+ expect(exceptions[0][:message]).to eq('bingo')
17
+ expect(exceptions[1][:message]).to eq('App crashed!')
18
+ expect(exceptions[0][:backtrace]).not_to be_empty
19
+ expect(exceptions[1][:backtrace]).not_to be_empty
21
20
  end
21
+ # rubocop:enable RSpec/MultipleExpectations
22
22
 
23
+ # rubocop:disable RSpec/MultipleExpectations
23
24
  it "unwinds no more than 3 nested exceptions" do
24
25
  begin
26
+ raise AirbrakeTestError
27
+ rescue AirbrakeTestError
25
28
  begin
26
- raise AirbrakeTestError
27
- rescue AirbrakeTestError
29
+ Ruby21Error.raise_error('bongo')
30
+ rescue Ruby21Error
28
31
  begin
29
- Ruby21Error.raise_error('bongo')
32
+ Ruby21Error.raise_error('bango')
30
33
  rescue Ruby21Error
31
- begin
32
- Ruby21Error.raise_error('bango')
33
- rescue Ruby21Error
34
- Ruby21Error.raise_error('bingo')
35
- end
34
+ Ruby21Error.raise_error('bingo')
36
35
  end
37
36
  end
38
- rescue Ruby21Error => ex
39
- nested_exception = described_class.new(ex)
40
- exceptions = nested_exception.as_json
41
-
42
- expect(exceptions.size).to eq(3)
43
- expect(exceptions[0][:message]).to eq('bingo')
44
- expect(exceptions[1][:message]).to eq('bango')
45
- expect(exceptions[2][:message]).to eq('bongo')
46
- expect(exceptions[0][:backtrace]).not_to be_empty
47
- expect(exceptions[1][:backtrace]).not_to be_empty
48
37
  end
38
+ rescue Ruby21Error => ex
39
+ nested_exception = described_class.new(ex)
40
+ exceptions = nested_exception.as_json
41
+
42
+ expect(exceptions.size).to eq(3)
43
+ expect(exceptions[0][:message]).to eq('bingo')
44
+ expect(exceptions[1][:message]).to eq('bango')
45
+ expect(exceptions[2][:message]).to eq('bongo')
46
+ expect(exceptions[0][:backtrace]).not_to be_empty
47
+ expect(exceptions[1][:backtrace]).not_to be_empty
49
48
  end
49
+ # rubocop:enable RSpec/MultipleExpectations
50
50
  end
51
51
 
52
52
  context "given exceptions without backtraces" do
53
+ # rubocop:disable RSpec/MultipleExpectations
53
54
  it "sets backtrace to nil" do
54
55
  begin
55
- begin
56
- raise AirbrakeTestError
57
- rescue AirbrakeTestError => ex2
58
- ex2.set_backtrace([])
59
- Ruby21Error.raise_error('bingo')
60
- end
61
- rescue Ruby21Error => ex1
62
- ex1.set_backtrace([])
63
- nested_exception = described_class.new(ex1)
64
- exceptions = nested_exception.as_json
65
-
66
- expect(exceptions.size).to eq(2)
67
- expect(exceptions[0][:backtrace]).to be_empty
68
- expect(exceptions[1][:backtrace]).to be_empty
56
+ raise AirbrakeTestError
57
+ rescue AirbrakeTestError => ex2
58
+ ex2.set_backtrace([])
59
+ Ruby21Error.raise_error('bingo')
69
60
  end
61
+ rescue Ruby21Error => ex1
62
+ ex1.set_backtrace([])
63
+ nested_exception = described_class.new(ex1)
64
+ exceptions = nested_exception.as_json
65
+
66
+ expect(exceptions.size).to eq(2)
67
+ expect(exceptions[0][:backtrace]).to be_empty
68
+ expect(exceptions[1][:backtrace]).to be_empty
70
69
  end
70
+ # rubocop:enable RSpec/MultipleExpectations
71
71
  end
72
72
  end
73
73
  end
@@ -1,4 +1,6 @@
1
1
  RSpec.describe Airbrake::NoticeNotifier do
2
+ subject(:notice_notifier) { described_class.new }
3
+
2
4
  let(:project_id) { 105138 }
3
5
  let(:project_key) { 'fd04e13d806a90f96614ad8e529b2822' }
4
6
  let(:localhost) { 'http://localhost:8080' }
@@ -27,7 +29,7 @@ RSpec.describe Airbrake::NoticeNotifier do
27
29
 
28
30
  example(title) do
29
31
  stub_request(:post, endpoint).to_return(status: 201, body: '{}')
30
- subject.notify_sync(ex)
32
+ notice_notifier.notify_sync(ex)
31
33
 
32
34
  expect(a_request(:post, endpoint)).to have_been_made.once
33
35
  end
@@ -35,7 +37,7 @@ RSpec.describe Airbrake::NoticeNotifier do
35
37
 
36
38
  path = '/api/v3/projects/105138/notices'
37
39
 
38
- context "given a full host" do
40
+ context "given a full host with port" do
39
41
  include_examples('endpoint', localhost = 'http://localhost:8080',
40
42
  URI.join(localhost, path),
41
43
  "sends notices to the specified host's endpoint")
@@ -63,13 +65,13 @@ RSpec.describe Airbrake::NoticeNotifier do
63
65
 
64
66
  describe ":root_directory" do
65
67
  before do
66
- subject.add_filter(
68
+ notice_notifier.add_filter(
67
69
  Airbrake::Filters::RootDirectoryFilter.new('/home/kyrylo/code'),
68
70
  )
69
71
  end
70
72
 
71
73
  it "filters out frames" do
72
- subject.notify_sync(ex)
74
+ notice_notifier.notify_sync(ex)
73
75
 
74
76
  expect(
75
77
  a_request(:post, endpoint)
@@ -82,7 +84,7 @@ RSpec.describe Airbrake::NoticeNotifier do
82
84
  before { Airbrake::Config.instance.merge(root_directory: dir) }
83
85
 
84
86
  it "being included into the notice's payload" do
85
- subject.notify_sync(ex)
87
+ notice_notifier.notify_sync(ex)
86
88
  expect(
87
89
  a_request(:post, endpoint)
88
90
  .with(body: %r{"rootDirectory":"/bingo/bango"}),
@@ -100,6 +102,7 @@ RSpec.describe Airbrake::NoticeNotifier do
100
102
  end
101
103
  end
102
104
 
105
+ # rubocop:disable RSpec/MultipleMemoizedHelpers
103
106
  describe ":proxy" do
104
107
  let(:proxy) do
105
108
  WEBrick::HTTPServer.new(
@@ -142,7 +145,7 @@ RSpec.describe Airbrake::NoticeNotifier do
142
145
  "safe to run this test on 2.6+ once we upgrade to Webmock 3.5+",
143
146
  )
144
147
  end
145
- subject.notify_sync(ex)
148
+ notice_notifier.notify_sync(ex)
146
149
 
147
150
  proxied_request = requests.pop(true)
148
151
 
@@ -155,13 +158,14 @@ RSpec.describe Airbrake::NoticeNotifier do
155
158
  # rubocop:enable Layout/LineLength
156
159
  end
157
160
  end
161
+ # rubocop:enable RSpec/MultipleMemoizedHelpers
158
162
 
159
163
  describe ":environment" do
160
164
  context "when present" do
161
165
  before { Airbrake::Config.instance.merge(environment: :production) }
162
166
 
163
167
  it "being included into the notice's payload" do
164
- subject.notify_sync(ex)
168
+ notice_notifier.notify_sync(ex)
165
169
  expect(
166
170
  a_request(:post, endpoint)
167
171
  .with(body: /"context":{.*"environment":"production".*}/),
@@ -175,7 +179,7 @@ RSpec.describe Airbrake::NoticeNotifier do
175
179
  before { Airbrake::Config.instance.merge(params) }
176
180
 
177
181
  it "sends a notice" do
178
- subject.notify_sync(ex)
182
+ notice_notifier.notify_sync(ex)
179
183
  expect(a_request(:post, endpoint)).to have_been_made
180
184
  end
181
185
  end
@@ -184,7 +188,7 @@ RSpec.describe Airbrake::NoticeNotifier do
184
188
  before { Airbrake::Config.instance.merge(params) }
185
189
 
186
190
  it "ignores exceptions occurring in envs that were not configured" do
187
- subject.notify_sync(ex)
191
+ notice_notifier.notify_sync(ex)
188
192
  expect(a_request(:post, endpoint)).not_to have_been_made
189
193
  end
190
194
  end
@@ -207,9 +211,15 @@ RSpec.describe Airbrake::NoticeNotifier do
207
211
  include_examples 'ignored notice', params
208
212
 
209
213
  it "returns early and doesn't try to parse the given exception" do
210
- expect(Airbrake::Notice).not_to receive(:new)
211
- expect(subject.notify_sync(ex))
214
+ allow(Airbrake::Notice).to receive(:new)
215
+
216
+ expect(notice_notifier.notify_sync(ex))
212
217
  .to eq('error' => "current environment 'development' is ignored")
218
+
219
+ expect(Airbrake::Notice).not_to have_received(:new)
220
+ end
221
+
222
+ it "doesn't make an HTTP request" do
213
223
  expect(a_request(:post, endpoint)).not_to have_been_made
214
224
  end
215
225
  end
@@ -246,9 +256,9 @@ RSpec.describe Airbrake::NoticeNotifier do
246
256
  end
247
257
 
248
258
  it "sends a notice" do
249
- notice = subject.build_notice(ex)
259
+ notice = notice_notifier.build_notice(ex)
250
260
  notice[:context][:headers] = 'banana'
251
- subject.notify_sync(notice)
261
+ notice_notifier.notify_sync(notice)
252
262
 
253
263
  expect(a_request(:post, endpoint)).to have_been_made
254
264
  end
@@ -1,4 +1,6 @@
1
1
  RSpec.describe Airbrake::NoticeNotifier do
2
+ subject(:notice_notifier) { described_class.new }
3
+
2
4
  before do
3
5
  Airbrake::Config.instance = Airbrake::Config.new(
4
6
  project_id: 1,
@@ -15,13 +17,13 @@ RSpec.describe Airbrake::NoticeNotifier do
15
17
  it "appends the context filter" do
16
18
  expect_any_instance_of(Airbrake::FilterChain).to receive(:add_filter)
17
19
  .with(instance_of(Airbrake::Filters::ContextFilter))
18
- subject
20
+ notice_notifier
19
21
  end
20
22
 
21
23
  it "appends the exception attributes filter" do
22
24
  expect_any_instance_of(Airbrake::FilterChain).to receive(:add_filter)
23
25
  .with(instance_of(Airbrake::Filters::ExceptionAttributesFilter))
24
- subject
26
+ notice_notifier
25
27
  end
26
28
  end
27
29
  end
@@ -39,14 +41,14 @@ RSpec.describe Airbrake::NoticeNotifier do
39
41
  before { stub_request(:post, endpoint).to_return(status: 201, body: body) }
40
42
 
41
43
  it "returns a promise" do
42
- expect(subject.notify('ex')).to be_an(Airbrake::Promise)
44
+ expect(notice_notifier.notify('ex')).to be_an(Airbrake::Promise)
43
45
  sleep 1
44
46
  end
45
47
 
46
48
  it "refines the notice object" do
47
- subject.add_filter { |n| n[:params] = { foo: 'bar' } }
48
- notice = subject.build_notice('ex')
49
- subject.notify(notice)
49
+ notice_notifier.add_filter { |n| n[:params] = { foo: 'bar' } }
50
+ notice = notice_notifier.build_notice('ex')
51
+ notice_notifier.notify(notice)
50
52
  expect(notice[:params]).to eq(foo: 'bar')
51
53
  sleep 1
52
54
  end
@@ -55,54 +57,55 @@ RSpec.describe Airbrake::NoticeNotifier do
55
57
  before { Airbrake::Config.instance.merge(project_id: nil) }
56
58
 
57
59
  it "returns a rejected promise" do
58
- promise = subject.notify({})
60
+ promise = notice_notifier.notify({})
59
61
  expect(promise).to be_rejected
60
62
  end
61
63
  end
62
64
 
63
65
  context "when a notice is not ignored" do
64
66
  it "yields the notice" do
65
- expect { |b| subject.notify('ex', &b) }
67
+ expect { |b| notice_notifier.notify('ex', &b) }
66
68
  .to yield_with_args(Airbrake::Notice)
67
69
  sleep 1
68
70
  end
69
71
  end
70
72
 
71
73
  context "when a notice is ignored via a filter" do
72
- before { subject.add_filter(&:ignore!) }
74
+ before { notice_notifier.add_filter(&:ignore!) }
73
75
 
74
76
  it "yields the notice" do
75
- expect { |b| subject.notify('ex', &b) }
77
+ expect { |b| notice_notifier.notify('ex', &b) }
76
78
  .to yield_with_args(Airbrake::Notice)
77
79
  end
78
80
 
79
81
  it "returns a rejected promise" do
80
- value = subject.notify('ex').value
82
+ value = notice_notifier.notify('ex').value
81
83
  expect(value['error']).to match(/was marked as ignored/)
82
84
  end
83
85
  end
84
86
 
85
87
  context "when a notice is ignored via an inline filter" do
86
- before { subject.add_filter { raise AirbrakeTestError } }
88
+ before { notice_notifier.add_filter { raise AirbrakeTestError } }
87
89
 
88
90
  it "doesn't invoke regular filters" do
89
- expect { subject.notify('ex', &:ignore!) }.not_to raise_error
91
+ expect { notice_notifier.notify('ex', &:ignore!) }.not_to raise_error
90
92
  end
91
93
  end
92
94
 
93
95
  context "when async sender has workers" do
94
96
  it "sends an exception asynchronously" do
95
97
  expect_any_instance_of(Airbrake::AsyncSender).to receive(:send)
96
- subject.notify('foo', bingo: 'bango')
98
+ notice_notifier.notify('foo', bingo: 'bango')
97
99
  end
98
100
  end
99
101
 
100
102
  context "when async sender doesn't have workers" do
101
103
  it "sends an exception synchronously" do
102
- expect_any_instance_of(Airbrake::AsyncSender)
104
+ allow_any_instance_of(Airbrake::AsyncSender)
103
105
  .to receive(:has_workers?).and_return(false)
104
106
  expect_any_instance_of(Airbrake::SyncSender).to receive(:send)
105
- subject.notify('foo', bingo: 'bango')
107
+
108
+ notice_notifier.notify('foo', bingo: 'bango')
106
109
  end
107
110
  end
108
111
 
@@ -116,11 +119,11 @@ RSpec.describe Airbrake::NoticeNotifier do
116
119
 
117
120
  it "doesn't send an notice" do
118
121
  expect_any_instance_of(Airbrake::AsyncSender).not_to receive(:send)
119
- subject.notify('foo', bingo: 'bango')
122
+ notice_notifier.notify('foo', bingo: 'bango')
120
123
  end
121
124
 
122
125
  it "returns a rejected promise" do
123
- promise = subject.notify('foo', bingo: 'bango')
126
+ promise = notice_notifier.notify('foo', bingo: 'bango')
124
127
  expect(promise.value).to eq('error' => "current environment 'test' is ignored")
125
128
  end
126
129
  end
@@ -139,18 +142,18 @@ RSpec.describe Airbrake::NoticeNotifier do
139
142
  before { stub_request(:post, endpoint).to_return(status: 201, body: body.to_json) }
140
143
 
141
144
  it "returns a reponse hash" do
142
- expect(subject.notify_sync('ex')).to eq(body)
145
+ expect(notice_notifier.notify_sync('ex')).to eq(body)
143
146
  end
144
147
 
145
148
  it "refines the notice object" do
146
- subject.add_filter { |n| n[:params] = { foo: 'bar' } }
147
- notice = subject.build_notice('ex')
148
- subject.notify_sync(notice)
149
+ notice_notifier.add_filter { |n| n[:params] = { foo: 'bar' } }
150
+ notice = notice_notifier.build_notice('ex')
151
+ notice_notifier.notify_sync(notice)
149
152
  expect(notice[:params]).to eq(foo: 'bar')
150
153
  end
151
154
 
152
155
  it "sends an exception synchronously" do
153
- subject.notify_sync('foo', bingo: 'bango')
156
+ notice_notifier.notify_sync('foo', bingo: 'bango')
154
157
  expect(
155
158
  a_request(:post, endpoint).with(
156
159
  body: /"params":{.*"bingo":"bango".*}/,
@@ -160,30 +163,30 @@ RSpec.describe Airbrake::NoticeNotifier do
160
163
 
161
164
  context "when a notice is not ignored" do
162
165
  it "yields the notice" do
163
- expect { |b| subject.notify_sync('ex', &b) }
166
+ expect { |b| notice_notifier.notify_sync('ex', &b) }
164
167
  .to yield_with_args(Airbrake::Notice)
165
168
  end
166
169
  end
167
170
 
168
171
  context "when a notice is ignored via a filter" do
169
- before { subject.add_filter(&:ignore!) }
172
+ before { notice_notifier.add_filter(&:ignore!) }
170
173
 
171
174
  it "yields the notice" do
172
- expect { |b| subject.notify_sync('ex', &b) }
175
+ expect { |b| notice_notifier.notify_sync('ex', &b) }
173
176
  .to yield_with_args(Airbrake::Notice)
174
177
  end
175
178
 
176
179
  it "returns an error hash" do
177
- response = subject.notify_sync('ex')
180
+ response = notice_notifier.notify_sync('ex')
178
181
  expect(response['error']).to match(/was marked as ignored/)
179
182
  end
180
183
  end
181
184
 
182
185
  context "when a notice is ignored via an inline filter" do
183
- before { subject.add_filter { raise AirbrakeTestError } }
186
+ before { notice_notifier.add_filter { raise AirbrakeTestError } }
184
187
 
185
188
  it "doesn't invoke regular filters" do
186
- expect { subject.notify('ex', &:ignore!) }.not_to raise_error
189
+ expect { notice_notifier.notify('ex', &:ignore!) }.not_to raise_error
187
190
  end
188
191
  end
189
192
 
@@ -196,11 +199,11 @@ RSpec.describe Airbrake::NoticeNotifier do
196
199
 
197
200
  it "doesn't send an notice" do
198
201
  expect_any_instance_of(Airbrake::SyncSender).not_to receive(:send)
199
- subject.notify_sync('foo', bingo: 'bango')
202
+ notice_notifier.notify_sync('foo', bingo: 'bango')
200
203
  end
201
204
 
202
205
  it "returns an error hash" do
203
- expect(subject.notify_sync('foo'))
206
+ expect(notice_notifier.notify_sync('foo'))
204
207
  .to eq('error' => "current environment 'test' is ignored")
205
208
  end
206
209
  end
@@ -209,17 +212,19 @@ RSpec.describe Airbrake::NoticeNotifier do
209
212
  describe "#add_filter" do
210
213
  context "given a block" do
211
214
  it "appends a new filter to the filter chain" do
212
- notifier = subject
215
+ notifier = notice_notifier
213
216
  b = proc {}
217
+ # rubocop:disable RSpec/StubbedMock
214
218
  expect_any_instance_of(Airbrake::FilterChain)
215
219
  .to receive(:add_filter) { |*args| expect(args.last).to be(b) }
220
+ # rubocop:enable RSpec/StubbedMock
216
221
  notifier.add_filter(&b)
217
222
  end
218
223
  end
219
224
 
220
225
  context "given a class" do
221
226
  it "appends a new filter to the filter chain" do
222
- notifier = subject
227
+ notifier = notice_notifier
223
228
  klass = Class.new
224
229
  expect_any_instance_of(Airbrake::FilterChain)
225
230
  .to receive(:add_filter).with(klass)
@@ -231,14 +236,14 @@ RSpec.describe Airbrake::NoticeNotifier do
231
236
  describe "#build_notice" do
232
237
  context "when given exception is another notice" do
233
238
  it "merges params with the notice" do
234
- notice = subject.build_notice('ex')
235
- other = subject.build_notice(notice, foo: 'bar')
239
+ notice = notice_notifier.build_notice('ex')
240
+ other = notice_notifier.build_notice(notice, foo: 'bar')
236
241
  expect(other[:params]).to eq(foo: 'bar')
237
242
  end
238
243
 
239
- it "it returns the provided notice" do
240
- notice = subject.build_notice('ex')
241
- other = subject.build_notice(notice, foo: 'bar')
244
+ it "returns the provided notice" do
245
+ notice = notice_notifier.build_notice('ex')
246
+ other = notice_notifier.build_notice(notice, foo: 'bar')
242
247
  expect(other).to eq(notice)
243
248
  end
244
249
  end
@@ -246,7 +251,7 @@ RSpec.describe Airbrake::NoticeNotifier do
246
251
  context "when given exception is an Exception" do
247
252
  it "prevents mutation of passed-in params hash" do
248
253
  params = { immutable: true }
249
- notice = subject.build_notice('ex', params)
254
+ notice = notice_notifier.build_notice('ex', params)
250
255
  notice[:params][:mutable] = true
251
256
  expect(params).to eq(immutable: true)
252
257
  end
@@ -260,7 +265,7 @@ RSpec.describe Airbrake::NoticeNotifier do
260
265
  ]
261
266
  allow(Kernel).to receive(:caller).and_return(backtrace)
262
267
 
263
- notice = subject.build_notice(Exception.new)
268
+ notice = notice_notifier.build_notice(Exception.new)
264
269
 
265
270
  expect(notice[:errors].first[:backtrace]).to eq(
266
271
  [
@@ -280,7 +285,7 @@ RSpec.describe Airbrake::NoticeNotifier do
280
285
  ]
281
286
  allow(Kernel).to receive(:caller).and_return(backtrace)
282
287
 
283
- notice = subject.build_notice(Exception.new)
288
+ notice = notice_notifier.build_notice(Exception.new)
284
289
 
285
290
  expect(notice[:errors].first[:backtrace]).to eq(
286
291
  [
@@ -296,7 +301,7 @@ RSpec.describe Airbrake::NoticeNotifier do
296
301
  # TODO: this seems to be bugged. Fix later.
297
302
  context "when given exception is a Java exception", skip: true do
298
303
  before do
299
- expect(Airbrake::Backtrace).to receive(:java_exception?).and_return(true)
304
+ allow(Airbrake::Backtrace).to receive(:java_exception?).and_return(true)
300
305
  end
301
306
 
302
307
  it "automatically generates the backtrace" do
@@ -307,7 +312,7 @@ RSpec.describe Airbrake::NoticeNotifier do
307
312
  ]
308
313
  allow(Kernel).to receive(:caller).and_return(backtrace)
309
314
 
310
- notice = subject.build_notice(Exception.new)
315
+ notice = notice_notifier.build_notice(Exception.new)
311
316
 
312
317
  # rubocop:disable Layout/LineLength
313
318
  expect(notice[:errors].first[:backtrace]).to eq(
@@ -323,12 +328,12 @@ RSpec.describe Airbrake::NoticeNotifier do
323
328
 
324
329
  context "when async sender is closed" do
325
330
  before do
326
- expect_any_instance_of(Airbrake::AsyncSender)
331
+ allow_any_instance_of(Airbrake::AsyncSender)
327
332
  .to receive(:closed?).and_return(true)
328
333
  end
329
334
 
330
335
  it "raises error" do
331
- expect { subject.build_notice(Exception.new('oops')) }.to raise_error(
336
+ expect { notice_notifier.build_notice(Exception.new('oops')) }.to raise_error(
332
337
  Airbrake::Error,
333
338
  "Airbrake is closed; can't build exception: Exception: oops",
334
339
  )
@@ -339,7 +344,7 @@ RSpec.describe Airbrake::NoticeNotifier do
339
344
  describe "#close" do
340
345
  it "sends the close message to async sender" do
341
346
  expect_any_instance_of(Airbrake::AsyncSender).to receive(:close)
342
- subject.close
347
+ notice_notifier.close
343
348
  end
344
349
  end
345
350
 
@@ -350,7 +355,7 @@ RSpec.describe Airbrake::NoticeNotifier do
350
355
  describe "#merge_context" do
351
356
  it "merges the provided context with the notice object" do
352
357
  expect_any_instance_of(Hash).to receive(:merge!).with(apples: 'oranges')
353
- subject.merge_context(apples: 'oranges')
358
+ notice_notifier.merge_context(apples: 'oranges')
354
359
  end
355
360
  end
356
361
  end