airbrake-ruby 6.0.2 → 6.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby/config/processor.rb +6 -0
  3. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +1 -1
  4. data/lib/airbrake-ruby/filters/git_repository_filter.rb +7 -1
  5. data/lib/airbrake-ruby/nested_exception.rb +22 -1
  6. data/lib/airbrake-ruby/notice.rb +5 -3
  7. data/lib/airbrake-ruby/sync_sender.rb +2 -2
  8. data/lib/airbrake-ruby/version.rb +1 -1
  9. metadata +4 -122
  10. data/spec/airbrake_spec.rb +0 -522
  11. data/spec/async_sender_spec.rb +0 -65
  12. data/spec/backtrace_spec.rb +0 -430
  13. data/spec/benchmark_spec.rb +0 -35
  14. data/spec/code_hunk_spec.rb +0 -124
  15. data/spec/config/processor_spec.rb +0 -151
  16. data/spec/config/validator_spec.rb +0 -204
  17. data/spec/config_spec.rb +0 -188
  18. data/spec/context_spec.rb +0 -54
  19. data/spec/deploy_notifier_spec.rb +0 -50
  20. data/spec/file_cache_spec.rb +0 -35
  21. data/spec/filter_chain_spec.rb +0 -124
  22. data/spec/filters/context_filter_spec.rb +0 -32
  23. data/spec/filters/dependency_filter_spec.rb +0 -14
  24. data/spec/filters/exception_attributes_filter_spec.rb +0 -52
  25. data/spec/filters/gem_root_filter_spec.rb +0 -44
  26. data/spec/filters/git_last_checkout_filter_spec.rb +0 -61
  27. data/spec/filters/git_repository_filter.rb +0 -61
  28. data/spec/filters/git_revision_filter_spec.rb +0 -126
  29. data/spec/filters/keys_allowlist_spec.rb +0 -204
  30. data/spec/filters/keys_blocklist_spec.rb +0 -242
  31. data/spec/filters/root_directory_filter_spec.rb +0 -39
  32. data/spec/filters/sql_filter_spec.rb +0 -274
  33. data/spec/filters/system_exit_filter_spec.rb +0 -16
  34. data/spec/filters/thread_filter_spec.rb +0 -281
  35. data/spec/fixtures/notroot.txt +0 -7
  36. data/spec/fixtures/project_root/code.rb +0 -221
  37. data/spec/fixtures/project_root/empty_file.rb +0 -0
  38. data/spec/fixtures/project_root/long_line.txt +0 -1
  39. data/spec/fixtures/project_root/short_file.rb +0 -3
  40. data/spec/fixtures/project_root/vendor/bundle/ignored_file.rb +0 -5
  41. data/spec/helpers.rb +0 -9
  42. data/spec/ignorable_spec.rb +0 -14
  43. data/spec/inspectable_spec.rb +0 -45
  44. data/spec/loggable_spec.rb +0 -17
  45. data/spec/monotonic_time_spec.rb +0 -25
  46. data/spec/nested_exception_spec.rb +0 -73
  47. data/spec/notice_notifier/options_spec.rb +0 -269
  48. data/spec/notice_notifier_spec.rb +0 -361
  49. data/spec/notice_spec.rb +0 -300
  50. data/spec/performance_breakdown_spec.rb +0 -11
  51. data/spec/performance_notifier_spec.rb +0 -645
  52. data/spec/promise_spec.rb +0 -203
  53. data/spec/query_spec.rb +0 -11
  54. data/spec/queue_spec.rb +0 -18
  55. data/spec/remote_settings/callback_spec.rb +0 -162
  56. data/spec/remote_settings/settings_data_spec.rb +0 -348
  57. data/spec/remote_settings_spec.rb +0 -201
  58. data/spec/request_spec.rb +0 -9
  59. data/spec/response_spec.rb +0 -110
  60. data/spec/spec_helper.rb +0 -100
  61. data/spec/stashable_spec.rb +0 -23
  62. data/spec/stat_spec.rb +0 -39
  63. data/spec/sync_sender_spec.rb +0 -168
  64. data/spec/tdigest_spec.rb +0 -235
  65. data/spec/thread_pool_spec.rb +0 -196
  66. data/spec/time_truncate_spec.rb +0 -30
  67. data/spec/timed_trace_spec.rb +0 -127
  68. data/spec/truncator_spec.rb +0 -267
@@ -1,361 +0,0 @@
1
- RSpec.describe Airbrake::NoticeNotifier do
2
- subject(:notice_notifier) { described_class.new }
3
-
4
- before do
5
- Airbrake::Config.instance = Airbrake::Config.new(
6
- project_id: 1,
7
- project_key: 'abc',
8
- logger: Logger.new('/dev/null'),
9
- performance_stats: true,
10
- )
11
- end
12
-
13
- describe "#new" do
14
- describe "default filter addition" do
15
- before { allow_any_instance_of(Airbrake::FilterChain).to receive(:add_filter) }
16
-
17
- it "appends the context filter" do
18
- expect_any_instance_of(Airbrake::FilterChain).to receive(:add_filter)
19
- .with(instance_of(Airbrake::Filters::ContextFilter))
20
- notice_notifier
21
- end
22
-
23
- it "appends the exception attributes filter" do
24
- expect_any_instance_of(Airbrake::FilterChain).to receive(:add_filter)
25
- .with(instance_of(Airbrake::Filters::ExceptionAttributesFilter))
26
- notice_notifier
27
- end
28
- end
29
- end
30
-
31
- describe "#notify" do
32
- let(:endpoint) { 'https://api.airbrake.io/api/v3/projects/1/notices' }
33
-
34
- let(:body) do
35
- {
36
- 'id' => '00054414-b147-6ffa-85d6-1524d83362a6',
37
- 'url' => 'http://localhost/locate/00054414-b147-6ffa-85d6-1524d83362a6',
38
- }.to_json
39
- end
40
-
41
- before { stub_request(:post, endpoint).to_return(status: 201, body: body) }
42
-
43
- it "returns a promise" do
44
- expect(notice_notifier.notify('ex')).to be_an(Airbrake::Promise)
45
- sleep 1
46
- end
47
-
48
- it "refines the notice object" do
49
- notice_notifier.add_filter { |n| n[:params] = { foo: 'bar' } }
50
- notice = notice_notifier.build_notice('ex')
51
- notice_notifier.notify(notice)
52
- expect(notice[:params]).to eq(foo: 'bar')
53
- sleep 1
54
- end
55
-
56
- context "when config is invalid" do
57
- before { Airbrake::Config.instance.merge(project_id: nil) }
58
-
59
- it "returns a rejected promise" do
60
- promise = notice_notifier.notify({})
61
- expect(promise).to be_rejected
62
- end
63
- end
64
-
65
- context "when a notice is not ignored" do
66
- it "yields the notice" do
67
- expect { |b| notice_notifier.notify('ex', &b) }
68
- .to yield_with_args(Airbrake::Notice)
69
- sleep 1
70
- end
71
- end
72
-
73
- context "when a notice is ignored via a filter" do
74
- before { notice_notifier.add_filter(&:ignore!) }
75
-
76
- it "yields the notice" do
77
- expect { |b| notice_notifier.notify('ex', &b) }
78
- .to yield_with_args(Airbrake::Notice)
79
- end
80
-
81
- it "returns a rejected promise" do
82
- value = notice_notifier.notify('ex').value
83
- expect(value['error']).to match(/was marked as ignored/)
84
- end
85
- end
86
-
87
- context "when a notice is ignored via an inline filter" do
88
- before { notice_notifier.add_filter { raise AirbrakeTestError } }
89
-
90
- it "doesn't invoke regular filters" do
91
- expect { notice_notifier.notify('ex', &:ignore!) }.not_to raise_error
92
- end
93
- end
94
-
95
- context "when async sender has workers" do
96
- it "sends an exception asynchronously" do
97
- expect_any_instance_of(Airbrake::AsyncSender).to receive(:send)
98
- notice_notifier.notify('foo', bingo: 'bango')
99
- end
100
- end
101
-
102
- context "when async sender doesn't have workers" do
103
- it "sends an exception synchronously" do
104
- allow_any_instance_of(Airbrake::AsyncSender)
105
- .to receive(:has_workers?).and_return(false)
106
- expect_any_instance_of(Airbrake::SyncSender).to receive(:send)
107
-
108
- notice_notifier.notify('foo', bingo: 'bango')
109
- end
110
- end
111
-
112
- context "when the provided environment is ignored" do
113
- before do
114
- Airbrake::Config.instance.merge(
115
- environment: 'test',
116
- ignore_environments: %w[test],
117
- )
118
- end
119
-
120
- it "doesn't send an notice" do
121
- expect_any_instance_of(Airbrake::AsyncSender).not_to receive(:send)
122
- notice_notifier.notify('foo', bingo: 'bango')
123
- end
124
-
125
- it "returns a rejected promise" do
126
- promise = notice_notifier.notify('foo', bingo: 'bango')
127
- expect(promise.value).to eq('error' => "current environment 'test' is ignored")
128
- end
129
- end
130
- end
131
-
132
- describe "#notify_sync" do
133
- let(:endpoint) { 'https://api.airbrake.io/api/v3/projects/1/notices' }
134
-
135
- let(:body) do
136
- {
137
- 'id' => '00054414-b147-6ffa-85d6-1524d83362a6',
138
- 'url' => 'http://localhost/locate/00054414-b147-6ffa-85d6-1524d83362a6',
139
- }
140
- end
141
-
142
- before { stub_request(:post, endpoint).to_return(status: 201, body: body.to_json) }
143
-
144
- it "returns a reponse hash" do
145
- expect(notice_notifier.notify_sync('ex')).to eq(body)
146
- end
147
-
148
- it "refines the notice object" do
149
- notice_notifier.add_filter { |n| n[:params] = { foo: 'bar' } }
150
- notice = notice_notifier.build_notice('ex')
151
- notice_notifier.notify_sync(notice)
152
- expect(notice[:params]).to eq(foo: 'bar')
153
- end
154
-
155
- it "sends an exception synchronously" do
156
- notice_notifier.notify_sync('foo', bingo: 'bango')
157
- expect(
158
- a_request(:post, endpoint).with(
159
- body: /"params":{.*"bingo":"bango".*}/,
160
- ),
161
- ).to have_been_made.once
162
- end
163
-
164
- context "when a notice is not ignored" do
165
- it "yields the notice" do
166
- expect { |b| notice_notifier.notify_sync('ex', &b) }
167
- .to yield_with_args(Airbrake::Notice)
168
- end
169
- end
170
-
171
- context "when a notice is ignored via a filter" do
172
- before { notice_notifier.add_filter(&:ignore!) }
173
-
174
- it "yields the notice" do
175
- expect { |b| notice_notifier.notify_sync('ex', &b) }
176
- .to yield_with_args(Airbrake::Notice)
177
- end
178
-
179
- it "returns an error hash" do
180
- response = notice_notifier.notify_sync('ex')
181
- expect(response['error']).to match(/was marked as ignored/)
182
- end
183
- end
184
-
185
- context "when a notice is ignored via an inline filter" do
186
- before { notice_notifier.add_filter { raise AirbrakeTestError } }
187
-
188
- it "doesn't invoke regular filters" do
189
- expect { notice_notifier.notify('ex', &:ignore!) }.not_to raise_error
190
- end
191
- end
192
-
193
- context "when the provided environment is ignored" do
194
- before do
195
- Airbrake::Config.instance.merge(
196
- environment: 'test', ignore_environments: %w[test],
197
- )
198
- end
199
-
200
- it "doesn't send an notice" do
201
- expect_any_instance_of(Airbrake::SyncSender).not_to receive(:send)
202
- notice_notifier.notify_sync('foo', bingo: 'bango')
203
- end
204
-
205
- it "returns an error hash" do
206
- expect(notice_notifier.notify_sync('foo'))
207
- .to eq('error' => "current environment 'test' is ignored")
208
- end
209
- end
210
- end
211
-
212
- describe "#add_filter" do
213
- context "given a block" do
214
- it "appends a new filter to the filter chain" do
215
- notifier = notice_notifier
216
- b = proc {}
217
- # rubocop:disable RSpec/StubbedMock
218
- expect_any_instance_of(Airbrake::FilterChain)
219
- .to receive(:add_filter) { |*args| expect(args.last).to be(b) }
220
- # rubocop:enable RSpec/StubbedMock
221
- notifier.add_filter(&b)
222
- end
223
- end
224
-
225
- context "given a class" do
226
- it "appends a new filter to the filter chain" do
227
- notifier = notice_notifier
228
- klass = Class.new
229
- expect_any_instance_of(Airbrake::FilterChain)
230
- .to receive(:add_filter).with(klass)
231
- notifier.add_filter(klass)
232
- end
233
- end
234
- end
235
-
236
- describe "#build_notice" do
237
- context "when given exception is another notice" do
238
- it "merges params with the notice" do
239
- notice = notice_notifier.build_notice('ex')
240
- other = notice_notifier.build_notice(notice, foo: 'bar')
241
- expect(other[:params]).to eq(foo: 'bar')
242
- end
243
-
244
- it "returns the provided notice" do
245
- notice = notice_notifier.build_notice('ex')
246
- other = notice_notifier.build_notice(notice, foo: 'bar')
247
- expect(other).to eq(notice)
248
- end
249
- end
250
-
251
- context "when given exception is an Exception" do
252
- it "prevents mutation of passed-in params hash" do
253
- params = { immutable: true }
254
- notice = notice_notifier.build_notice('ex', params)
255
- notice[:params][:mutable] = true
256
- expect(params).to eq(immutable: true)
257
- end
258
-
259
- context "and also when it doesn't have own backtrace" do
260
- context "and when the generated backtrace consists only of library frames" do
261
- it "returns the full generated backtrace" do
262
- backtrace = [
263
- "/lib/airbrake-ruby/a.rb:84:in `build_notice'",
264
- "/lib/airbrake-ruby/b.rb:124:in `send_notice'",
265
- ]
266
- allow(Kernel).to receive(:caller).and_return(backtrace)
267
-
268
- notice = notice_notifier.build_notice(Exception.new)
269
-
270
- expect(notice[:errors].first[:backtrace]).to eq(
271
- [
272
- { file: '/lib/airbrake-ruby/a.rb', line: 84, function: 'build_notice' },
273
- { file: '/lib/airbrake-ruby/b.rb', line: 124, function: 'send_notice' },
274
- ],
275
- )
276
- end
277
- end
278
-
279
- context "and when the generated backtrace consists of mixed frames" do
280
- it "returns the filtered backtrace" do
281
- backtrace = [
282
- "/airbrake-ruby/lib/airbrake-ruby/a.rb:84:in `b'",
283
- "/airbrake-ruby/lib/foo/b.rb:84:in `build'",
284
- "/airbrake-ruby/lib/bar/c.rb:124:in `send'",
285
- ]
286
- allow(Kernel).to receive(:caller).and_return(backtrace)
287
-
288
- notice = notice_notifier.build_notice(Exception.new)
289
-
290
- expect(notice[:errors].first[:backtrace]).to eq(
291
- [
292
- { file: '/airbrake-ruby/lib/foo/b.rb', line: 84, function: 'build' },
293
- { file: '/airbrake-ruby/lib/bar/c.rb', line: 124, function: 'send' },
294
- ],
295
- )
296
- end
297
- end
298
- end
299
- end
300
-
301
- # TODO: this seems to be bugged. Fix later.
302
- context "when given exception is a Java exception", skip: true do
303
- before do
304
- allow(Airbrake::Backtrace).to receive(:java_exception?).and_return(true)
305
- end
306
-
307
- it "automatically generates the backtrace" do
308
- backtrace = [
309
- "org/jruby/RubyKernel.java:998:in `eval'",
310
- "/ruby/stdlib/irb/workspace.rb:87:in `evaluate'",
311
- "/ruby/stdlib/irb.rb:489:in `block in eval_input'",
312
- ]
313
- allow(Kernel).to receive(:caller).and_return(backtrace)
314
-
315
- notice = notice_notifier.build_notice(Exception.new)
316
-
317
- # rubocop:disable Layout/LineLength
318
- expect(notice[:errors].first[:backtrace]).to eq(
319
- [
320
- { file: 'org/jruby/RubyKernel.java', line: 998, function: 'eval' },
321
- { file: '/ruby/stdlib/irb/workspace.rb', line: 87, function: 'evaluate' },
322
- { file: '/ruby/stdlib/irb.rb:489', line: 489, function: 'block in eval_input' },
323
- ],
324
- )
325
- # rubocop:enable Layout/LineLength
326
- end
327
- end
328
-
329
- context "when async sender is closed" do
330
- before do
331
- allow_any_instance_of(Airbrake::AsyncSender)
332
- .to receive(:closed?).and_return(true)
333
- end
334
-
335
- it "raises error" do
336
- expect { notice_notifier.build_notice(Exception.new('oops')) }.to raise_error(
337
- Airbrake::Error,
338
- "Airbrake is closed; can't build exception: Exception: oops",
339
- )
340
- end
341
- end
342
- end
343
-
344
- describe "#close" do
345
- it "sends the close message to async sender" do
346
- expect_any_instance_of(Airbrake::AsyncSender).to receive(:close)
347
- notice_notifier.close
348
- end
349
- end
350
-
351
- describe "#configured?" do
352
- it { is_expected.to be_configured }
353
- end
354
-
355
- describe "#merge_context" do
356
- it "merges the provided context with the notice object" do
357
- expect_any_instance_of(Hash).to receive(:merge!).with(apples: 'oranges')
358
- notice_notifier.merge_context(apples: 'oranges')
359
- end
360
- end
361
- end
data/spec/notice_spec.rb DELETED
@@ -1,300 +0,0 @@
1
- RSpec.describe Airbrake::Notice do
2
- let(:notice) { described_class.new(AirbrakeTestError.new, bingo: '1') }
3
-
4
- describe "#to_json" do
5
- context "app_version" do
6
- context "when missing" do
7
- before { Airbrake::Config.instance.merge(app_version: nil) }
8
-
9
- it "doesn't include app_version" do
10
- expect(notice.to_json).not_to match(/"context":{"version":"1.2.3"/)
11
- end
12
- end
13
-
14
- context "when present" do
15
- let(:notice) { described_class.new(AirbrakeTestError.new) }
16
-
17
- before do
18
- Airbrake::Config.instance.merge(
19
- app_version: "1.2.3",
20
- root_directory: "/one/two",
21
- )
22
- end
23
-
24
- it "includes app_version" do
25
- expect(notice.to_json).to match(/"context":{"version":"1.2.3"/)
26
- end
27
-
28
- it "includes root_directory" do
29
- expect(notice.to_json).to match(%r{"rootDirectory":"/one/two"})
30
- end
31
- end
32
- end
33
-
34
- context "when versions is empty" do
35
- it "doesn't set the 'versions' payload" do
36
- expect(notice.to_json).not_to match(
37
- /"context":{"versions":{"dep":"1.2.3"}}/,
38
- )
39
- end
40
- end
41
-
42
- context "when versions is not empty" do
43
- it "sets the 'versions' payload" do
44
- notice[:context][:versions] = { 'dep' => '1.2.3' }
45
- expect(notice.to_json).to match(
46
- /"context":{.*"versions":{"dep":"1.2.3"}.*}/,
47
- )
48
- end
49
- end
50
-
51
- context "truncation" do
52
- shared_examples 'payloads' do |size, msg|
53
- it msg do
54
- ex = AirbrakeTestError.new
55
-
56
- backtrace = []
57
- size.times { backtrace << "bin/rails:3:in `<main>'" }
58
- ex.set_backtrace(backtrace)
59
-
60
- notice = described_class.new(ex)
61
-
62
- expect(notice.to_json.bytesize).to be < 64000
63
- end
64
- end
65
-
66
- max_msg = 'truncates to the max allowed size'
67
-
68
- context "with an extremely huge payload" do
69
- include_examples 'payloads', 200_000, max_msg
70
- end
71
-
72
- context "with a big payload" do
73
- include_examples 'payloads', 50_000, max_msg
74
- end
75
-
76
- small_msg = "doesn't truncate it"
77
-
78
- context "with a small payload" do
79
- include_examples 'payloads', 1000, small_msg
80
- end
81
-
82
- context "with a tiny payload" do
83
- include_examples 'payloads', 300, small_msg
84
- end
85
-
86
- context "when truncation failed" do
87
- it "returns nil" do
88
- allow_any_instance_of(Airbrake::Truncator)
89
- .to receive(:reduce_max_size).and_return(0)
90
-
91
- encoded = Base64.encode64("\xD3\xE6\xBC\x9D\xBA").encode!('ASCII-8BIT')
92
- bad_string = Base64.decode64(encoded)
93
-
94
- ex = AirbrakeTestError.new
95
-
96
- backtrace = []
97
- 10.times { backtrace << "bin/rails:3:in `<#{bad_string}>'" }
98
- ex.set_backtrace(backtrace)
99
-
100
- notice = described_class.new(ex)
101
- expect(notice.to_json).to be_nil
102
- end
103
- end
104
-
105
- describe "object replacement with its string version" do
106
- let(:klass) { Class.new }
107
- let(:ex) { AirbrakeTestError.new }
108
- let(:params) { { bingo: [Object.new, klass.new] } }
109
- let(:notice) { described_class.new(ex, params) }
110
-
111
- before do
112
- backtrace = []
113
- backtrace_size.times { backtrace << "bin/rails:3:in `<main>'" }
114
- ex.set_backtrace(backtrace)
115
- end
116
-
117
- context "with payload within the limits" do
118
- let(:backtrace_size) { 1000 }
119
-
120
- it "doesn't happen" do
121
- expect(notice.to_json)
122
- .to match(/bingo":\["#<Object:.+>","#<#<Class:.+>:.+>"/)
123
- end
124
- end
125
-
126
- context "with payload bigger than the limit" do
127
- context "with payload within the limits" do
128
- let(:backtrace_size) { 50_000 }
129
-
130
- it "happens" do
131
- expect(notice.to_json)
132
- .to match(/bingo":\[".+Object.+",".+Class.+"/)
133
- end
134
- end
135
- end
136
- end
137
- end
138
-
139
- context "given a closed IO object" do
140
- context "and when it is not monkey-patched by ActiveSupport" do
141
- it "is not getting truncated" do
142
- notice[:params] = { obj: IO.new(0).tap(&:close) }
143
- expect(notice.to_json).to match(/"obj":"#<IO:0x.+>"/)
144
- end
145
- end
146
-
147
- context "and when it is monkey-patched by ActiveSupport" do
148
- # Instances of this class contain a closed IO object assigned to an
149
- # instance variable. Normally, the JSON gem, which we depend on can
150
- # parse closed IO objects. However, because ActiveSupport monkey-patches
151
- # #to_json and calls #to_a on them, they raise IOError when we try to
152
- # serialize them.
153
- #
154
- # @see https://goo.gl/0A3xNC
155
- # rubocop:disable Lint/ConstantDefinitionInBlock, RSpec/LeakyConstantDeclaration
156
- class ObjectWithIoIvars
157
- def initialize
158
- @bongo = Tempfile.new('bongo').tap(&:close)
159
- end
160
-
161
- # @raise [NotImplementedError] when inside a Rails environment
162
- def to_json(*)
163
- raise NotImplementedError
164
- end
165
- end
166
- # rubocop:enable Lint/ConstantDefinitionInBlock, RSpec/LeakyConstantDeclaration
167
-
168
- # @see ObjectWithIoIvars
169
- # rubocop:disable Lint/ConstantDefinitionInBlock, RSpec/LeakyConstantDeclaration
170
- class ObjectWithNestedIoIvars
171
- def initialize
172
- @bish = ObjectWithIoIvars.new
173
- end
174
-
175
- # @see ObjectWithIoIvars#to_json
176
- def to_json(*)
177
- raise NotImplementedError
178
- end
179
- end
180
- # rubocop:enable Lint/ConstantDefinitionInBlock, RSpec/LeakyConstantDeclaration
181
-
182
- context "and also when it's a closed Tempfile" do
183
- it "doesn't fail" do
184
- notice[:params] = { obj: Tempfile.new('bongo').tap(&:close) }
185
- expect(notice.to_json).to match(/"obj":"#<(Temp)?file:0x.+>"/i)
186
- end
187
- end
188
-
189
- context "and also when it's an IO ivar" do
190
- it "doesn't fail" do
191
- notice[:params] = { obj: ObjectWithIoIvars.new }
192
- expect(notice.to_json).to match(/"obj":".+ObjectWithIoIvars.+"/)
193
- end
194
-
195
- context "and when it's deeply nested inside a hash" do
196
- it "doesn't fail" do
197
- notice[:params] = { a: { b: { c: ObjectWithIoIvars.new } } }
198
- expect(notice.to_json).to match(
199
- /"params":{"a":{"b":{"c":".+ObjectWithIoIvars.+"}}.*}/,
200
- )
201
- end
202
- end
203
-
204
- context "and when it's deeply nested inside an array" do
205
- it "doesn't fail" do
206
- notice[:params] = { a: [[ObjectWithIoIvars.new]] }
207
- expect(notice.to_json).to match(
208
- /"params":{"a":\[\[".+ObjectWithIoIvars.+"\]\].*}/,
209
- )
210
- end
211
- end
212
- end
213
-
214
- context "and also when it's a non-IO ivar, which contains an IO ivar itself" do
215
- it "doesn't fail" do
216
- notice[:params] = { obj: ObjectWithNestedIoIvars.new }
217
- expect(notice.to_json).to match(/"obj":".+ObjectWithNested.+"/)
218
- end
219
- end
220
- end
221
- end
222
-
223
- it "overwrites the 'notifier' payload with the default values" do
224
- notice[:notifier] = { name: 'bingo', bango: 'bongo' }
225
-
226
- expect(notice.to_json)
227
- .to match(/"notifier":{"name":"airbrake-ruby","version":".+","url":".+"}/)
228
- end
229
-
230
- it "always contains context/hostname" do
231
- expect(notice.to_json)
232
- .to match(/"context":{.*"hostname":".+".*}/)
233
- end
234
-
235
- it "defaults to the error severity" do
236
- expect(notice.to_json).to match(/"context":{.*"severity":"error".*}/)
237
- end
238
-
239
- it "always contains environment/program_name" do
240
- expect(notice.to_json)
241
- .to match(%r|"environment":{"program_name":.+/rspec.*|)
242
- end
243
-
244
- it "contains errors" do
245
- expect(notice.to_json)
246
- .to match(/"errors":\[{"type":"AirbrakeTestError","message":"App crash/)
247
- end
248
-
249
- it "contains a backtrace" do
250
- expect(notice.to_json)
251
- .to match(%r|"backtrace":\[{"file":"/home/.+/spec/spec_helper.rb"|)
252
- end
253
-
254
- it "contains params" do
255
- expect(notice.to_json).to match(/"params":{"bingo":"1"}/)
256
- end
257
- end
258
-
259
- describe "#[]" do
260
- it "accesses payload" do
261
- expect(notice[:params]).to eq(bingo: '1')
262
- end
263
-
264
- it "raises error if notice is ignored" do
265
- notice.ignore!
266
- expect { notice[:params] }
267
- .to raise_error(Airbrake::Error, 'cannot access ignored Airbrake::Notice')
268
- end
269
- end
270
-
271
- describe "#[]=" do
272
- it "sets a payload value" do
273
- hash = { bingo: 'bango' }
274
- notice[:params] = hash
275
- expect(notice[:params]).to eq(hash)
276
- end
277
-
278
- it "raises error if notice is ignored" do
279
- notice.ignore!
280
- expect { notice[:params] = {} }
281
- .to raise_error(Airbrake::Error, 'cannot access ignored Airbrake::Notice')
282
- end
283
-
284
- it "raises error when trying to assign unrecognized key" do
285
- expect { notice[:bingo] = 1 }
286
- .to raise_error(Airbrake::Error, /:bingo is not recognized among/)
287
- end
288
-
289
- it "raises when setting non-hash objects as the value" do
290
- expect { notice[:params] = Object.new }
291
- .to raise_error(Airbrake::Error, 'Got Object value, wanted a Hash')
292
- end
293
- end
294
-
295
- describe "#stash" do
296
- subject { described_class.new(AirbrakeTestError.new) }
297
-
298
- it { is_expected.to respond_to(:stash) }
299
- end
300
- end
@@ -1,11 +0,0 @@
1
- RSpec.describe Airbrake::PerformanceBreakdown do
2
- describe "#stash" do
3
- subject do
4
- described_class.new(
5
- method: 'GET', route: '/', response_type: '', groups: {},
6
- )
7
- end
8
-
9
- it { is_expected.to respond_to(:stash) }
10
- end
11
- end