rollbar 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,40 +12,786 @@ rescue LoadError
12
12
  end
13
13
 
14
14
  describe Rollbar do
15
+ let(:notifier) { Rollbar.notifier }
16
+ context 'Notifier' do
17
+ context 'log' do
18
+ let(:exception) do
19
+ begin
20
+ foo = bar
21
+ rescue => e
22
+ e
23
+ end
24
+ end
25
+
15
26
  let(:configuration) { Rollbar.configuration }
16
27
 
17
- describe '.report_exception' do
18
- before(:each) do
19
- configure
20
- Rollbar.configure do |config|
21
- config.logger = logger_mock
28
+ it 'should report a simple message' do
29
+ expect(notifier).to receive(:report).with('error', 'test message', nil, nil)
30
+ notifier.log('error', 'test message')
31
+ end
32
+
33
+ it 'should report a simple message with extra data' do
34
+ extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
35
+
36
+ expect(notifier).to receive(:report).with('error', 'test message', nil, extra_data)
37
+ notifier.log('error', 'test message', extra_data)
38
+ end
39
+
40
+ it 'should report an exception' do
41
+ expect(notifier).to receive(:report).with('error', nil, exception, nil)
42
+ notifier.log('error', exception)
43
+ end
44
+
45
+ it 'should report an exception with extra data' do
46
+ extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
47
+
48
+ expect(notifier).to receive(:report).with('error', nil, exception, extra_data)
49
+ notifier.log('error', exception, extra_data)
50
+ end
51
+
52
+ it 'should report an exception with a description' do
53
+ expect(notifier).to receive(:report).with('error', 'exception description', exception, nil)
54
+ notifier.log('error', exception, 'exception description')
55
+ end
56
+
57
+ it 'should report an exception with a description and extra data' do
58
+ extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
59
+
60
+ expect(notifier).to receive(:report).with('error', 'exception description', exception, extra_data)
61
+ notifier.log('error', exception, extra_data, 'exception description')
62
+ end
63
+ end
64
+
65
+ context 'debug/info/warning/error/critical' do
66
+ let(:exception) do
67
+ begin
68
+ foo = bar
69
+ rescue => e
70
+ e
71
+ end
72
+ end
73
+
74
+ let(:extra_data) { {:key => 'value', :hash => {:inner_key => 'inner_value'}} }
75
+
76
+ it 'should report with a debug level' do
77
+ expect(notifier).to receive(:report).with('debug', nil, exception, nil)
78
+ notifier.debug(exception)
79
+
80
+ expect(notifier).to receive(:report).with('debug', 'description', exception, nil)
81
+ notifier.debug(exception, 'description')
82
+
83
+ expect(notifier).to receive(:report).with('debug', 'description', exception, extra_data)
84
+ notifier.debug(exception, 'description', extra_data)
85
+ end
86
+
87
+ it 'should report with an info level' do
88
+ expect(notifier).to receive(:report).with('info', nil, exception, nil)
89
+ notifier.info(exception)
90
+
91
+ expect(notifier).to receive(:report).with('info', 'description', exception, nil)
92
+ notifier.info(exception, 'description')
93
+
94
+ expect(notifier).to receive(:report).with('info', 'description', exception, extra_data)
95
+ notifier.info(exception, 'description', extra_data)
96
+ end
97
+
98
+ it 'should report with a warning level' do
99
+ expect(notifier).to receive(:report).with('warning', nil, exception, nil)
100
+ notifier.warning(exception)
101
+
102
+ expect(notifier).to receive(:report).with('warning', 'description', exception, nil)
103
+ notifier.warning(exception, 'description')
104
+
105
+ expect(notifier).to receive(:report).with('warning', 'description', exception, extra_data)
106
+ notifier.warning(exception, 'description', extra_data)
107
+ end
108
+
109
+ it 'should report with an error level' do
110
+ expect(notifier).to receive(:report).with('error', nil, exception, nil)
111
+ notifier.error(exception)
112
+
113
+ expect(notifier).to receive(:report).with('error', 'description', exception, nil)
114
+ notifier.error(exception, 'description')
115
+
116
+ expect(notifier).to receive(:report).with('error', 'description', exception, extra_data)
117
+ notifier.error(exception, 'description', extra_data)
118
+ end
119
+
120
+ it 'should report with a critical level' do
121
+ expect(notifier).to receive(:report).with('critical', nil, exception, nil)
122
+ notifier.critical(exception)
123
+
124
+ expect(notifier).to receive(:report).with('critical', 'description', exception, nil)
125
+ notifier.critical(exception, 'description')
126
+
127
+ expect(notifier).to receive(:report).with('critical', 'description', exception, extra_data)
128
+ notifier.critical(exception, 'description', extra_data)
129
+ end
130
+ end
131
+
132
+ context 'scope' do
133
+ it 'should create a new notifier object' do
134
+ notifier2 = notifier.scope
135
+
136
+ notifier2.should_not eq(notifier)
137
+ notifier2.should be_instance_of(Rollbar::Notifier)
138
+ end
139
+
140
+ it 'should create a copy of the parent notifier\'s configuration' do
141
+ notifier.configure do |config|
142
+ config.code_version = '123'
143
+ config.payload_options = {
144
+ :a => 'a',
145
+ :b => {:c => 'c'}
146
+ }
147
+ end
148
+
149
+ notifier2 = notifier.scope
150
+
151
+ notifier2.configuration.code_version.should == '123'
152
+ notifier2.configuration.should_not equal(notifier.configuration)
153
+ notifier2.configuration.payload_options.should_not equal(notifier.configuration.payload_options)
154
+ notifier2.configuration.payload_options.should == notifier.configuration.payload_options
155
+ notifier2.configuration.payload_options.should == {
156
+ :a => 'a',
157
+ :b => {:c => 'c'}
158
+ }
159
+ end
160
+
161
+ it 'should not modify any parent notifier configuration' do
162
+ configure
163
+ Rollbar.configuration.code_version.should be_nil
164
+ Rollbar.configuration.payload_options.should be_empty
165
+
166
+ notifier.configure do |config|
167
+ config.code_version = '123'
168
+ config.payload_options = {
169
+ :a => 'a',
170
+ :b => {:c => 'c'}
171
+ }
172
+ end
173
+
174
+ notifier2 = notifier.scope
175
+
176
+ notifier2.configure do |config|
177
+ config.payload_options[:c] = 'c'
178
+ end
179
+
180
+ notifier.configuration.payload_options[:c].should be_nil
181
+
182
+ notifier3 = notifier2.scope({
183
+ :b => {:c => 3, :d => 'd'}
184
+ })
185
+
186
+ notifier3.configure do |config|
187
+ config.code_version = '456'
188
+ end
189
+
190
+ notifier.configuration.code_version.should == '123'
191
+ notifier.configuration.payload_options.should == {
192
+ :a => 'a',
193
+ :b => {:c => 'c'}
194
+ }
195
+ notifier2.configuration.code_version.should == '123'
196
+ notifier2.configuration.payload_options.should == {
197
+ :a => 'a',
198
+ :b => {:c => 'c'},
199
+ :c => 'c'
200
+ }
201
+ notifier3.configuration.code_version.should == '456'
202
+ notifier3.configuration.payload_options.should == {
203
+ :a => 'a',
204
+ :b => {:c => 3, :d => 'd'},
205
+ :c => 'c'
206
+ }
207
+
208
+ Rollbar.configuration.code_version.should be_nil
209
+ Rollbar.configuration.payload_options.should be_empty
210
+ end
211
+ end
212
+
213
+ context 'report' do
214
+ let(:logger_mock) { double("Rails.logger").as_null_object }
215
+
216
+ before(:each) do
217
+ configure
218
+ Rollbar.configure do |config|
219
+ config.logger = logger_mock
220
+ end
221
+ end
222
+
223
+ after(:each) do
224
+ Rollbar.unconfigure
225
+ configure
226
+ end
227
+
228
+ it 'should reject input that doesn\'t contain an exception, message or extra data' do
229
+ expect(logger_mock).to receive(:error).with('[Rollbar] Tried to send a report with no message, exception or extra data.')
230
+ expect(notifier).not_to receive(:schedule_payload)
231
+
232
+ result = notifier.send(:report, 'info', nil, nil, nil)
233
+ result.should == 'error'
234
+ end
235
+
236
+ it 'should be ignored if the person is ignored' do
237
+ person_data = {
238
+ :id => 1,
239
+ :username => "test",
240
+ :email => "test@example.com"
241
+ }
242
+
243
+ notifier.configure do |config|
244
+ config.ignored_person_ids += [1]
245
+ config.payload_options = { :person => person_data }
246
+ end
247
+
248
+ expect(notifier).not_to receive(:schedule_payload)
249
+
250
+ result = notifier.send(:report, 'info', 'message', nil, nil)
251
+ result.should == 'ignored'
252
+ end
253
+
254
+ it 'should evaluate callables in the payload' do
255
+ notifier.should receive(:schedule_payload) do |payload|
256
+ data = payload['data']
257
+ data[:body][:message][:extra][:callable].should == 2
258
+ end
259
+
260
+ callable = proc { 1 + 1 }
261
+ notifier.send(:report, 'warning', 'message', nil, { :callable => callable })
262
+ end
263
+ end
264
+
265
+ context 'build_payload' do
266
+ after(:each) do
267
+ Rollbar.unconfigure
268
+ configure
269
+ end
270
+
271
+ context 'a basic payload' do
272
+ let(:extra_data) { {:key => 'value', :hash => {:inner_key => 'inner_value'}} }
273
+ let(:payload) { notifier.send(:build_payload, 'info', 'message', nil, extra_data) }
274
+
275
+ it 'should have the correct root-level keys' do
276
+ payload.keys.should match_array(['access_token', 'data'])
277
+ end
278
+
279
+ it 'should have the correct data keys' do
280
+ payload['data'].keys.should include(:timestamp, :environment, :level, :language, :framework, :server,
281
+ :notifier, :body)
282
+ end
283
+
284
+ it 'should have the correct notifier name and version' do
285
+ payload['data'][:notifier][:name].should == 'rollbar-gem'
286
+ payload['data'][:notifier][:version].should == Rollbar::VERSION
287
+ end
288
+
289
+ it 'should have the correct language and framework' do
290
+ payload['data'][:language].should == 'ruby'
291
+ payload['data'][:framework].should == Rollbar.configuration.framework
292
+ payload['data'][:framework].should match(/^Rails/)
293
+ end
294
+
295
+ it 'should have the correct server keys' do
296
+ payload['data'][:server].keys.should match_array([:host, :root])
297
+ end
298
+
299
+ it 'should have the correct level and message body' do
300
+ payload['data'][:level].should == 'info'
301
+ payload['data'][:body][:message][:body].should == 'message'
302
+ end
303
+ end
304
+
305
+ it 'should merge in a new key from payload_options' do
306
+ notifier.configure do |config|
307
+ config.payload_options = { :some_new_key => 'some new value' }
308
+ end
309
+
310
+ payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
311
+
312
+ payload['data'][:some_new_key].should == 'some new value'
313
+ end
314
+
315
+ it 'should overwrite existing keys from payload_options' do
316
+ payload_options = {
317
+ :notifier => 'bad notifier',
318
+ :server => { :host => 'new host', :new_server_key => 'value' }
319
+ }
320
+
321
+ notifier.configure do |config|
322
+ config.payload_options = payload_options
323
+ end
324
+
325
+ payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
326
+
327
+ payload['data'][:notifier].should == 'bad notifier'
328
+ payload['data'][:server][:host].should == 'new host'
329
+ payload['data'][:server][:root].should_not be_nil
330
+ payload['data'][:server][:new_server_key].should == 'value'
331
+ end
332
+
333
+ it 'should have default environment "unspecified"' do
334
+ Rollbar.unconfigure
335
+ payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
336
+ payload['data'][:environment].should == 'unspecified'
337
+ end
338
+
339
+ it 'should have an overridden environment' do
340
+ Rollbar.configure do |config|
341
+ config.environment = 'overridden'
342
+ end
343
+
344
+ payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
345
+ payload['data'][:environment].should == 'overridden'
346
+ end
347
+
348
+ it 'should not have custom data under default configuration' do
349
+ payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
350
+ payload['data'][:body][:message][:extra].should be_nil
351
+ end
352
+
353
+ it 'should have custom message data when custom_data_method is configured' do
354
+ Rollbar.configure do |config|
355
+ config.custom_data_method = lambda { {:a => 1, :b => [2, 3, 4]} }
356
+ end
357
+
358
+ payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
359
+ payload['data'][:body][:message][:extra].should_not be_nil
360
+ payload['data'][:body][:message][:extra][:a].should == 1
361
+ payload['data'][:body][:message][:extra][:b][2].should == 4
362
+ end
363
+
364
+ it 'should merge extra data into custom message data' do
365
+ custom_method = lambda do
366
+ { :a => 1,
367
+ :b => [2, 3, 4],
368
+ :c => { :d => 'd', :e => 'e' },
369
+ :f => ['1', '2']
370
+ }
371
+ end
372
+
373
+ Rollbar.configure do |config|
374
+ config.custom_data_method = custom_method
375
+ end
376
+
377
+ payload = notifier.send(:build_payload, 'info', 'message', nil, {:c => {:e => 'g'}, :f => 'f'})
378
+ payload['data'][:body][:message][:extra].should_not be_nil
379
+ payload['data'][:body][:message][:extra][:a].should == 1
380
+ payload['data'][:body][:message][:extra][:b][2].should == 4
381
+ payload['data'][:body][:message][:extra][:c][:d].should == 'd'
382
+ payload['data'][:body][:message][:extra][:c][:e].should == 'g'
383
+ payload['data'][:body][:message][:extra][:f].should == 'f'
384
+ end
385
+
386
+ it 'should include project_gem_paths' do
387
+ notifier.configure do |config|
388
+ config.project_gems = ['rails', 'rspec']
389
+ end
390
+
391
+ payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
392
+
393
+ payload['data'][:project_package_paths].should have(2).items
394
+ end
395
+
396
+ it 'should include a code_version' do
397
+ notifier.configure do |config|
398
+ config.code_version = 'abcdef'
399
+ end
400
+
401
+ payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
402
+
403
+ payload['data'][:code_version].should == 'abcdef'
404
+ end
405
+
406
+ it 'should have the right hostname' do
407
+ payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
408
+
409
+ payload['data'][:server][:host].should == Socket.gethostname
410
+ end
411
+
412
+ it 'should have root and branch set when configured' do
413
+ configure
414
+ Rollbar.configure do |config|
415
+ config.root = '/path/to/root'
416
+ config.branch = 'master'
417
+ end
418
+
419
+ payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
420
+
421
+ payload['data'][:server][:root].should == '/path/to/root'
422
+ payload['data'][:server][:branch].should == 'master'
423
+ end
424
+ end
425
+
426
+ context 'build_payload_body' do
427
+ let(:exception) do
428
+ begin
429
+ foo = bar
430
+ rescue => e
431
+ e
432
+ end
433
+ end
434
+
435
+ it 'should build a message body when no exception is passed in' do
436
+ body = notifier.send(:build_payload_body, 'message', nil, nil)
437
+ body[:message][:body].should == 'message'
438
+ body[:message][:extra].should be_nil
439
+ body[:trace].should be_nil
440
+ end
441
+
442
+ it 'should build a message body when no exception and extra data is passed in' do
443
+ body = notifier.send(:build_payload_body, 'message', nil, {:a => 'b'})
444
+ body[:message][:body].should == 'message'
445
+ body[:message][:extra].should == {:a => 'b'}
446
+ body[:trace].should be_nil
447
+ end
448
+
449
+ it 'should build an exception body when one is passed in' do
450
+ body = notifier.send(:build_payload_body, 'message', exception, nil)
451
+ body[:message].should be_nil
452
+
453
+ trace = body[:trace]
454
+ trace.should_not be_nil
455
+ trace[:extra].should be_nil
456
+
457
+ trace[:exception][:class].should_not be_nil
458
+ trace[:exception][:message].should_not be_nil
459
+ end
460
+
461
+ it 'should build an exception body when one is passed in along with extra data' do
462
+ body = notifier.send(:build_payload_body, 'message', exception, {:a => 'b'})
463
+ body[:message].should be_nil
464
+
465
+ trace = body[:trace]
466
+ trace.should_not be_nil
467
+
468
+ trace[:exception][:class].should_not be_nil
469
+ trace[:exception][:message].should_not be_nil
470
+ trace[:extra].should == {:a => 'b'}
471
+ end
472
+ end
473
+
474
+ context 'build_payload_body_exception' do
475
+ let(:exception) do
476
+ begin
477
+ foo = bar
478
+ rescue => e
479
+ e
480
+ end
481
+ end
482
+
483
+ after(:each) do
484
+ Rollbar.unconfigure
485
+ configure
486
+ end
487
+
488
+ it 'should build valid exception data' do
489
+ body = notifier.send(:build_payload_body_exception, nil, exception, nil)
490
+ body[:message].should be_nil
491
+
492
+ trace = body[:trace]
493
+
494
+ frames = trace[:frames]
495
+ frames.should be_a_kind_of(Array)
496
+ frames.each do |frame|
497
+ frame[:filename].should be_a_kind_of(String)
498
+ frame[:lineno].should be_a_kind_of(Fixnum)
499
+ if frame[:method]
500
+ frame[:method].should be_a_kind_of(String)
501
+ end
502
+ end
503
+
504
+ # should be NameError, but can be NoMethodError sometimes on rubinius 1.8
505
+ # http://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/
506
+ trace[:exception][:class].should match(/^(NameError|NoMethodError)$/)
507
+ trace[:exception][:message].should match(/^(undefined local variable or method `bar'|undefined method `bar' on an instance of)/)
508
+ end
509
+
510
+ it 'should build exception data with a description' do
511
+ body = notifier.send(:build_payload_body_exception, 'exception description', exception, nil)
512
+
513
+ trace = body[:trace]
514
+
515
+ trace[:exception][:message].should match(/^(undefined local variable or method `bar'|undefined method `bar' on an instance of)/)
516
+ trace[:exception][:description].should == 'exception description'
517
+ end
518
+
519
+ it 'should build exception data with a description and extra data' do
520
+ extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
521
+ body = notifier.send(:build_payload_body_exception, 'exception description', exception, extra_data)
522
+
523
+ trace = body[:trace]
524
+
525
+ trace[:exception][:message].should match(/^(undefined local variable or method `bar'|undefined method `bar' on an instance of)/)
526
+ trace[:exception][:description].should == 'exception description'
527
+ trace[:extra][:key].should == 'value'
528
+ trace[:extra][:hash].should == {:inner_key => 'inner_value'}
529
+ end
530
+
531
+ it 'should build exception data with a extra data' do
532
+ extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
533
+ body = notifier.send(:build_payload_body_exception, nil, exception, extra_data)
534
+
535
+ trace = body[:trace]
536
+
537
+ trace[:exception][:message].should match(/^(undefined local variable or method `bar'|undefined method `bar' on an instance of)/)
538
+ trace[:extra][:key].should == 'value'
539
+ trace[:extra][:hash].should == {:inner_key => 'inner_value'}
540
+ end
541
+
542
+ context 'with nested exceptions' do
543
+ let(:crashing_code) do
544
+ proc do
545
+ begin
546
+ begin
547
+ fail CauseException.new('the cause')
548
+ rescue
549
+ fail StandardError.new('the error')
550
+ end
551
+ rescue => e
552
+ e
553
+ end
554
+ end
555
+ end
556
+
557
+ let(:rescued_exception) { crashing_code.call }
558
+ let(:message) { 'message' }
559
+ let(:extra) { {} }
560
+
561
+ context 'using ruby >= 2.1' do
562
+ next unless Exception.instance_methods.include?(:cause)
563
+
564
+ it 'sends the two exceptions in the trace_chain attribute' do
565
+ body = notifier.send(:build_payload_body_exception, message, rescued_exception, extra)
566
+
567
+ body[:trace].should be_nil
568
+ body[:trace_chain].should be_kind_of(Array)
569
+
570
+ chain = body[:trace_chain]
571
+ chain[0][:exception][:class].should match(/StandardError/)
572
+ chain[0][:exception][:message].should match(/the error/)
573
+
574
+ chain[1][:exception][:class].should match(/CauseException/)
575
+ chain[1][:exception][:message].should match(/the cause/)
576
+ end
577
+
578
+ context 'using ruby <= 2.1' do
579
+ next if Exception.instance_methods.include?(:cause)
580
+
581
+ it 'sends only the last exception in the trace attribute' do
582
+ body = notifier.send(:build_payload_body_exception, message, rescued_exception, extra)
583
+
584
+ body[:trace].should be_kind_of(Hash)
585
+ body[:trace_chain].should be_nil
586
+
587
+ body[:trace][:exception][:class].should match(/StandardError/)
588
+ body[:trace][:exception][:message].should match(/the error/)
589
+ end
590
+ end
591
+ end
592
+ end
593
+ end
594
+
595
+ context 'build_payload_body_message' do
596
+ it 'should build a message' do
597
+ body = notifier.send(:build_payload_body_message, 'message', nil)
598
+ body[:message][:body].should == 'message'
599
+ body[:trace].should be_nil
600
+ end
601
+
602
+ it 'should build a message with extra data' do
603
+ extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
604
+ body = notifier.send(:build_payload_body_message, 'message', extra_data)
605
+ body[:message][:body].should == 'message'
606
+ body[:message][:extra][:key].should == 'value'
607
+ body[:message][:extra][:hash].should == {:inner_key => 'inner_value'}
608
+ end
609
+
610
+ it 'should build an empty message with extra data' do
611
+ extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
612
+ body = notifier.send(:build_payload_body_message, nil, extra_data)
613
+ body[:message][:body].should == 'Empty message'
614
+ body[:message][:extra][:key].should == 'value'
615
+ body[:message][:extra][:hash].should == {:inner_key => 'inner_value'}
616
+ end
617
+ end
618
+
619
+ context 'evaluate_payload' do
620
+ let(:notifier) do
621
+ notifier = Rollbar.notifier
622
+
623
+ notifier.configure do |config|
624
+ config.logger = logger_mock
625
+ end
626
+
627
+ notifier
628
+ end
629
+
630
+ let(:logger_mock) { double("Rails.logger").as_null_object }
631
+
632
+ before(:each) do
633
+ configure
634
+ notifier.configure do |config|
635
+ config.logger = logger_mock
636
+ end
637
+ end
638
+
639
+ it 'should evaluate callables and store the result' do
640
+ a = 'some string'
641
+
642
+ payload = {
643
+ :evaluate1 => lambda { 1 + 1 },
644
+ :evaluate2 => Proc.new { 2 + 2 },
645
+ :hash => {
646
+ :inner_evaluate1 => a.method(:to_s),
647
+ :inner_evaluate2 => lambda { {:key => 'value'} }
648
+ }
649
+ }
650
+
651
+ payload_copy = payload.clone
652
+ notifier.send(:evaluate_payload, payload_copy)
653
+
654
+ payload_copy[:evaluate1].should == 2
655
+ payload_copy[:evaluate2].should == 4
656
+ payload_copy[:hash][:inner_evaluate1].should == 'some string'
657
+ payload_copy[:hash][:inner_evaluate2][:key].should == 'value'
658
+ end
659
+
660
+ it 'should not crash when the callable raises an exception' do
661
+ logger_mock.should_receive(:error).with("[Rollbar] Error while evaluating callable in payload for key evaluate1")
662
+
663
+ payload = {
664
+ :evaluate1 => lambda { a = b },
665
+ :evaluate2 => Proc.new { 2 + 2 },
666
+ :key => 'value'
667
+ }
668
+
669
+ payload_copy = payload.clone
670
+ notifier.send(:evaluate_payload, payload_copy)
671
+
672
+ payload_copy[:evaluate1].should be_nil
673
+ payload_copy[:evaluate2].should == 4
674
+ payload_copy[:key].should == 'value'
22
675
  end
676
+ end
677
+
678
+ context 'enforce_valid_utf8' do
679
+ it 'should replace invalid utf8 values' do
680
+ payload = {
681
+ :bad_value => "bad value 1\255",
682
+ :bad_value_2 => "bad\255 value 2",
683
+ "bad\255 key" => "good value",
684
+ :hash => {
685
+ :inner_bad_value => "\255\255bad value 3",
686
+ "inner \255bad key" => 'inner good value',
687
+ "bad array key\255" => [
688
+ 'good array value 1',
689
+ "bad\255 array value 1\255",
690
+ {
691
+ :inner_inner_bad => "bad inner \255inner value"
692
+ }
693
+ ]
694
+ }
695
+ }
23
696
 
697
+ payload_copy = payload.clone
698
+ notifier.send(:enforce_valid_utf8, payload_copy)
699
+
700
+ payload_copy[:bad_value].should == "bad value 1"
701
+ payload_copy[:bad_value_2].should == "bad value 2"
702
+ payload_copy["bad key"].should == "good value"
703
+ payload_copy.keys.should_not include("bad\456 key")
704
+ payload_copy[:hash][:inner_bad_value].should == "bad value 3"
705
+ payload_copy[:hash]["inner bad key"].should == 'inner good value'
706
+ payload_copy[:hash]["bad array key"].should == [
707
+ 'good array value 1',
708
+ 'bad array value 1',
709
+ {
710
+ :inner_inner_bad => 'bad inner inner value'
711
+ }
712
+ ]
713
+ end
714
+ end
715
+
716
+ context 'truncate_payload' do
717
+ it 'should truncate all nested strings in the payload' do
718
+ payload = {
719
+ :truncated => '1234567',
720
+ :not_truncated => '123456',
721
+ :hash => {
722
+ :inner_truncated => '123456789',
723
+ :inner_not_truncated => '567',
724
+ :array => ['12345678', '12', {:inner_inner => '123456789'}]
725
+ }
726
+ }
727
+
728
+ payload_copy = payload.clone
729
+ notifier.send(:truncate_payload, payload_copy, 6)
730
+
731
+ payload_copy[:truncated].should == '123...'
732
+ payload_copy[:not_truncated].should == '123456'
733
+ payload_copy[:hash][:inner_truncated].should == '123...'
734
+ payload_copy[:hash][:inner_not_truncated].should == '567'
735
+ payload_copy[:hash][:array].should == ['123...', '12', {:inner_inner => '123...'}]
736
+ end
737
+
738
+ it 'should truncate utf8 strings properly' do
739
+ payload = {
740
+ :truncated => 'Ŝǻмρļẻ śţяịņģ',
741
+ :not_truncated => '123456',
742
+ }
743
+
744
+ payload_copy = payload.clone
745
+ notifier.send(:truncate_payload, payload_copy, 6)
746
+
747
+ payload_copy[:truncated].should == "Ŝǻм..."
748
+ payload_copy[:not_truncated].should == '123456'
749
+ end
750
+ end
751
+ end
752
+
753
+ context 'reporting' do
754
+ let(:exception) do
24
755
  begin
25
756
  foo = bar
26
757
  rescue => e
27
- @exception = e
758
+ e
28
759
  end
29
760
  end
30
761
 
31
762
  let(:logger_mock) { double("Rails.logger").as_null_object }
763
+ let(:user) { User.create(:email => 'email@example.com', :encrypted_password => '', :created_at => Time.now, :updated_at => Time.now) }
764
+
765
+ before(:each) do
766
+ configure
767
+ Rollbar.configure do |config|
768
+ config.logger = logger_mock
769
+ end
770
+ end
771
+
772
+ after(:each) do
773
+ Rollbar.unconfigure
774
+ configure
775
+ end
32
776
 
33
777
  it 'should report exceptions without person or request data' do
34
778
  logger_mock.should_receive(:info).with('[Rollbar] Success')
35
- Rollbar.report_exception(@exception)
779
+ Rollbar.error(exception)
36
780
  end
37
781
 
38
782
  it 'should not report anything when disabled' do
39
783
  logger_mock.should_not_receive(:info).with('[Rollbar] Success')
784
+
40
785
  Rollbar.configure do |config|
41
786
  config.enabled = false
42
787
  end
43
788
 
44
- Rollbar.report_exception(@exception)
789
+ Rollbar.error(exception).should == 'disabled'
790
+ end
45
791
 
46
- Rollbar.configure do |config|
47
- config.enabled = true
48
- end
792
+ it 'should report exceptions without person or request data' do
793
+ logger_mock.should_receive(:info).with('[Rollbar] Success')
794
+ Rollbar.error(exception)
49
795
  end
50
796
 
51
797
  it 'should be enabled when freshly configured' do
@@ -56,65 +802,25 @@ describe Rollbar do
56
802
  Rollbar.unconfigure
57
803
 
58
804
  Rollbar.configuration.enabled.should be_nil
59
- Rollbar.report_exception(@exception).should == 'disabled'
805
+ Rollbar.error(exception).should == 'disabled'
60
806
  end
61
807
 
62
- it 'should stay disabled if configure is called again' do
63
- Rollbar.unconfigure
64
-
65
- # configure once, setting enabled to false.
66
- Rollbar.configure do |config|
67
- config.enabled = false
68
- end
69
-
70
- # now configure again (perhaps to change some other values)
71
- Rollbar.configure do |config| end
72
-
73
- Rollbar.configuration.enabled.should == false
74
- Rollbar.report_exception(@exception).should == 'disabled'
75
- end
76
-
77
- it 'should report exceptions with request and person data' do
78
- logger_mock.should_receive(:info).with('[Rollbar] Success')
79
- request_data = {
80
- :params => { :foo => "bar" },
81
- :url => 'http://localhost/',
82
- :user_ip => '127.0.0.1',
83
- :headers => {},
84
- :GET => { "baz" => "boz" },
85
- :session => { :user_id => 123 },
86
- :method => "GET",
87
- }
88
- person_data = {
89
- :id => 1,
90
- :username => "test",
91
- :email => "test@example.com"
92
- }
93
- Rollbar.report_exception(@exception, request_data, person_data)
94
- end
808
+ it 'should stay disabled if configure is called again' do
809
+ Rollbar.unconfigure
95
810
 
96
- it "should work with an IO object as rack.errors" do
97
- logger_mock.should_receive(:info).with('[Rollbar] Success')
98
- request_data = {
99
- :params => { :foo => "bar" },
100
- :url => 'http://localhost/',
101
- :user_ip => '127.0.0.1',
102
- :headers => {},
103
- :GET => { "baz" => "boz" },
104
- :session => { :user_id => 123 },
105
- :method => "GET",
106
- :env => { :"rack.errors" => IO.new(2, File::WRONLY) },
107
- }
108
- person_data = {
109
- :id => 1,
110
- :username => "test",
111
- :email => "test@example.com"
112
- }
113
- Rollbar.report_exception(@exception, request_data, person_data)
811
+ # configure once, setting enabled to false.
812
+ Rollbar.configure do |config|
813
+ config.enabled = false
814
+ end
815
+
816
+ # now configure again (perhaps to change some other values)
817
+ Rollbar.configure do |config| end
818
+
819
+ Rollbar.configuration.enabled.should == false
820
+ Rollbar.error(exception).should == 'disabled'
114
821
  end
115
822
 
116
823
  it 'should ignore ignored exception classes' do
117
- saved_filters = Rollbar.configuration.exception_level_filters
118
824
  Rollbar.configure do |config|
119
825
  config.exception_level_filters = { 'NameError' => 'ignore' }
120
826
  end
@@ -123,15 +829,24 @@ describe Rollbar do
123
829
  logger_mock.should_not_receive(:warn)
124
830
  logger_mock.should_not_receive(:error)
125
831
 
126
- Rollbar.report_exception(@exception)
832
+ Rollbar.error(exception)
833
+ end
127
834
 
128
- Rollbar.configure do |config|
129
- config.exception_level_filters = saved_filters
130
- end
835
+ it "should work with an IO object as rack.errors" do
836
+ logger_mock.should_receive(:info).with('[Rollbar] Success')
837
+
838
+ Rollbar.error(exception, :env => { :"rack.errors" => IO.new(2, File::WRONLY) })
131
839
  end
132
840
 
133
841
  it 'should ignore ignored persons' do
842
+ person_data = {
843
+ :id => 1,
844
+ :username => "test",
845
+ :email => "test@example.com"
846
+ }
847
+
134
848
  Rollbar.configure do |config|
849
+ config.payload_options = {:person => person_data}
135
850
  config.ignored_person_ids += [1]
136
851
  end
137
852
 
@@ -139,27 +854,23 @@ describe Rollbar do
139
854
  logger_mock.should_not_receive(:warn)
140
855
  logger_mock.should_not_receive(:error)
141
856
 
857
+ Rollbar.error(exception)
858
+ end
859
+
860
+ it 'should not ignore non-ignored persons' do
142
861
  person_data = {
143
862
  :id => 1,
144
863
  :username => "test",
145
864
  :email => "test@example.com"
146
865
  }
147
- Rollbar.report_exception(@exception, {}, person_data)
148
- end
149
-
150
- it 'should not ignore non-ignored persons' do
151
866
  Rollbar.configure do |config|
867
+ config.payload_options = { :person => person_data }
152
868
  config.ignored_person_ids += [1]
153
869
  end
154
870
 
155
871
  Rollbar.last_report = nil
156
872
 
157
- person_data = {
158
- :id => 1,
159
- :username => "test",
160
- :email => "test@example.com"
161
- }
162
- Rollbar.report_exception(@exception, {}, person_data)
873
+ Rollbar.error(exception)
163
874
  Rollbar.last_report.should be_nil
164
875
 
165
876
  person_data = {
@@ -167,7 +878,15 @@ describe Rollbar do
167
878
  :username => "test2",
168
879
  :email => "test2@example.com"
169
880
  }
170
- Rollbar.report_exception(@exception, {}, person_data)
881
+
882
+ new_options = {
883
+ :person => person_data
884
+ }
885
+
886
+ Rollbar.scoped(new_options) do
887
+ Rollbar.error(exception)
888
+ end
889
+
171
890
  Rollbar.last_report.should_not be_nil
172
891
  end
173
892
 
@@ -178,20 +897,16 @@ describe Rollbar do
178
897
  config.exception_level_filters = { 'NameError' => callable_mock }
179
898
  end
180
899
 
181
- callable_mock.should_receive(:call).with(@exception).at_least(:once).and_return("info")
900
+ callable_mock.should_receive(:call).with(exception).at_least(:once).and_return("info")
182
901
  logger_mock.should_receive(:info)
183
902
  logger_mock.should_not_receive(:warn)
184
903
  logger_mock.should_not_receive(:error)
185
904
 
186
- Rollbar.report_exception(@exception)
187
-
188
- Rollbar.configure do |config|
189
- config.exception_level_filters = saved_filters
190
- end
905
+ Rollbar.error(exception)
191
906
  end
192
907
 
193
908
  it 'should not report exceptions when silenced' do
194
- Rollbar.should_not_receive :schedule_payload
909
+ expect_any_instance_of(Rollbar::Notifier).to_not receive(:schedule_payload)
195
910
 
196
911
  begin
197
912
  test_var = 1
@@ -200,7 +915,7 @@ describe Rollbar do
200
915
  raise
201
916
  end
202
917
  rescue => e
203
- Rollbar.report_exception(e)
918
+ Rollbar.error(e)
204
919
  end
205
920
 
206
921
  test_var.should == 2
@@ -208,10 +923,13 @@ describe Rollbar do
208
923
 
209
924
  it 'should report exception objects with no backtrace' do
210
925
  payload = nil
211
- Rollbar.stub(:schedule_payload) do |*args|
926
+
927
+ notifier.stub(:schedule_payload) do |*args|
212
928
  payload = args[0]
213
929
  end
214
- Rollbar.report_exception(StandardError.new("oops"))
930
+
931
+ Rollbar.error(StandardError.new("oops"))
932
+
215
933
  payload["data"][:body][:trace][:frames].should == []
216
934
  payload["data"][:body][:trace][:exception][:class].should == "StandardError"
217
935
  payload["data"][:body][:trace][:exception][:message].should == "oops"
@@ -219,15 +937,15 @@ describe Rollbar do
219
937
 
220
938
  it 'should return the exception data with a uuid, on platforms with SecureRandom' do
221
939
  if defined?(SecureRandom) and SecureRandom.respond_to?(:uuid)
222
- Rollbar.stub(:schedule_payload) do |*args| end
223
- exception_data = Rollbar.report_exception(StandardError.new("oops"))
940
+ exception_data = Rollbar.error(StandardError.new("oops"))
224
941
  exception_data[:uuid].should_not be_nil
225
942
  end
226
943
  end
227
944
 
228
945
  it 'should report exception objects with nonstandard backtraces' do
229
946
  payload = nil
230
- Rollbar.stub(:schedule_payload) do |*args|
947
+
948
+ notifier.stub(:schedule_payload) do |*args|
231
949
  payload = args[0]
232
950
  end
233
951
 
@@ -239,27 +957,29 @@ describe Rollbar do
239
957
 
240
958
  exception = CustomException.new("oops")
241
959
 
242
- Rollbar.report_exception(exception)
960
+ notifier.error(exception)
243
961
 
244
962
  payload["data"][:body][:trace][:frames][0][:method].should == "custom backtrace line"
245
963
  end
246
964
 
247
965
  it 'should report exceptions with a custom level' do
248
966
  payload = nil
249
- Rollbar.stub(:schedule_payload) do |*args|
967
+
968
+ notifier.stub(:schedule_payload) do |*args|
250
969
  payload = args[0]
251
970
  end
252
971
 
253
- Rollbar.report_exception(@exception)
972
+ Rollbar.error(exception)
254
973
 
255
- payload["data"][:level].should == 'error'
974
+ payload['data'][:level].should == 'error'
256
975
 
257
- Rollbar.report_exception(@exception, nil, nil, 'debug')
976
+ Rollbar.log('debug', exception)
258
977
 
259
- payload["data"][:level].should == 'debug'
978
+ payload['data'][:level].should == 'debug'
260
979
  end
261
980
  end
262
981
 
982
+ # Backwards
263
983
  context 'report_message' do
264
984
  before(:each) do
265
985
  configure
@@ -296,6 +1016,8 @@ describe Rollbar do
296
1016
  :hash => { :a => 123, :b => "xyz" })
297
1017
  end
298
1018
 
1019
+ # END Backwards
1020
+
299
1021
  it 'should not crash with circular extra_data' do
300
1022
  a = { :foo => "bar" }
301
1023
  b = { :a => a }
@@ -304,7 +1026,7 @@ describe Rollbar do
304
1026
 
305
1027
  logger_mock.should_receive(:error).with(/\[Rollbar\] Reporting internal error encountered while sending data to Rollbar./)
306
1028
 
307
- Rollbar.report_message("Test message with circular extra data", 'debug', a)
1029
+ Rollbar.error("Test message with circular extra data", a)
308
1030
  end
309
1031
 
310
1032
  it 'should be able to report form validation errors when they are present' do
@@ -319,36 +1041,13 @@ describe Rollbar do
319
1041
  user.report_validation_errors_to_rollbar
320
1042
  end
321
1043
 
322
- after(:each) do
323
- Rollbar.configure do |config|
324
- config.logger = ::Rails.logger
325
- end
326
- end
327
- end
328
-
329
- context 'report_message_with_request' do
330
- before(:each) do
331
- configure
332
- Rollbar.configure do |config|
333
- config.logger = logger_mock
334
- end
335
- end
336
-
337
- let(:logger_mock) { double("Rails.logger").as_null_object }
338
- let(:user) { User.create(:email => 'email@example.com', :encrypted_password => '', :created_at => Time.now, :updated_at => Time.now) }
339
-
340
- it 'should report simple messages' do
341
- logger_mock.should_receive(:info).with('[Rollbar] Scheduling payload')
1044
+ it 'should report messages with extra data' do
342
1045
  logger_mock.should_receive(:info).with('[Rollbar] Success')
343
- Rollbar.report_message_with_request("Test message")
344
-
345
- Rollbar.last_report[:request].should be_nil
346
- Rollbar.last_report[:person].should be_nil
1046
+ Rollbar.info("Test message with extra data", :foo => "bar",
1047
+ :hash => { :a => 123, :b => "xyz" })
347
1048
  end
348
1049
 
349
1050
  it 'should report messages with request, person data and extra data' do
350
- Rollbar.last_report = nil
351
-
352
1051
  logger_mock.should_receive(:info).with('[Rollbar] Scheduling payload')
353
1052
  logger_mock.should_receive(:info).with('[Rollbar] Success')
354
1053
 
@@ -365,11 +1064,18 @@ describe Rollbar do
365
1064
  :extra_foo => 'extra_bar'
366
1065
  }
367
1066
 
368
- Rollbar.report_message_with_request("Test message", 'info', request_data, person_data, extra_data)
1067
+ Rollbar.configure do |config|
1068
+ config.payload_options = {
1069
+ :request => request_data,
1070
+ :person => person_data
1071
+ }
1072
+ end
1073
+
1074
+ Rollbar.info("Test message", extra_data)
369
1075
 
370
1076
  Rollbar.last_report[:request].should == request_data
371
1077
  Rollbar.last_report[:person].should == person_data
372
- Rollbar.last_report[:body][:message][:extra_foo].should == 'extra_bar'
1078
+ Rollbar.last_report[:body][:message][:extra][:extra_foo].should == 'extra_bar'
373
1079
  end
374
1080
  end
375
1081
 
@@ -380,11 +1086,18 @@ describe Rollbar do
380
1086
  config.logger = logger_mock
381
1087
  config.filepath = 'test.rollbar'
382
1088
  end
1089
+ end
1090
+
1091
+ after(:each) do
1092
+ Rollbar.unconfigure
1093
+ configure
1094
+ end
383
1095
 
1096
+ let(:exception) do
384
1097
  begin
385
1098
  foo = bar
386
1099
  rescue => e
387
- @exception = e
1100
+ e
388
1101
  end
389
1102
  end
390
1103
 
@@ -394,7 +1107,7 @@ describe Rollbar do
394
1107
  logger_mock.should_not_receive(:info).with('[Rollbar] Writing payload to file')
395
1108
  logger_mock.should_receive(:info).with('[Rollbar] Sending payload').once
396
1109
  logger_mock.should_receive(:info).with('[Rollbar] Success').once
397
- Rollbar.report_exception(@exception)
1110
+ Rollbar.error(exception)
398
1111
  end
399
1112
 
400
1113
  it 'should save the payload to a file if set' do
@@ -409,7 +1122,7 @@ describe Rollbar do
409
1122
  filepath = config.filepath
410
1123
  end
411
1124
 
412
- Rollbar.report_exception(@exception)
1125
+ Rollbar.error(exception)
413
1126
 
414
1127
  File.exist?(filepath).should == true
415
1128
  File.read(filepath).should include test_access_token
@@ -427,11 +1140,18 @@ describe Rollbar do
427
1140
  Rollbar.configure do |config|
428
1141
  config.logger = logger_mock
429
1142
  end
1143
+ end
1144
+
1145
+ after(:each) do
1146
+ Rollbar.unconfigure
1147
+ configure
1148
+ end
430
1149
 
1150
+ let(:exception) do
431
1151
  begin
432
1152
  foo = bar
433
1153
  rescue => e
434
- @exception = e
1154
+ e
435
1155
  end
436
1156
  end
437
1157
 
@@ -447,7 +1167,7 @@ describe Rollbar do
447
1167
  GirlFriday::WorkQueue.immediate!
448
1168
  end
449
1169
 
450
- Rollbar.report_exception(@exception)
1170
+ Rollbar.error(exception)
451
1171
 
452
1172
  Rollbar.configure do |config|
453
1173
  config.use_async = false
@@ -468,12 +1188,7 @@ describe Rollbar do
468
1188
  }
469
1189
  end
470
1190
 
471
- Rollbar.report_exception(@exception)
472
-
473
- Rollbar.configure do |config|
474
- config.use_async = false
475
- config.async_handler = Rollbar.default_async_handler
476
- end
1191
+ Rollbar.error(exception)
477
1192
  end
478
1193
 
479
1194
  # We should be able to send String payloads, generated
@@ -497,7 +1212,7 @@ describe Rollbar do
497
1212
  it 'sends a payload generated as String, not as a Hash' do
498
1213
  logger_mock.should_receive(:info).with('[Rollbar] Success')
499
1214
 
500
- Rollbar.report_exception(@exception)
1215
+ Rollbar.report_exception(exception)
501
1216
  end
502
1217
 
503
1218
  context 'with async failover handlers' do
@@ -536,7 +1251,7 @@ describe Rollbar do
536
1251
  it 'logs the error but doesnt try to report an internal error' do
537
1252
  expect(logger_mock).to receive(:error).with(log_message)
538
1253
 
539
- Rollbar.report_exception(exception)
1254
+ Rollbar.error(exception)
540
1255
  end
541
1256
  end
542
1257
 
@@ -548,7 +1263,7 @@ describe Rollbar do
548
1263
  expect(Rollbar).not_to receive(:report_internal_error)
549
1264
  expect(handler).to receive(:call)
550
1265
 
551
- Rollbar.report_exception(exception)
1266
+ Rollbar.error(exception)
552
1267
  end
553
1268
  end
554
1269
 
@@ -560,7 +1275,7 @@ describe Rollbar do
560
1275
  it 'calls the second handler and doesnt report internal error' do
561
1276
  expect(handler2).to receive(:call)
562
1277
 
563
- Rollbar.report_exception(exception)
1278
+ Rollbar.error(exception)
564
1279
  end
565
1280
  end
566
1281
 
@@ -572,7 +1287,7 @@ describe Rollbar do
572
1287
  it 'reports internal error' do
573
1288
  expect(logger_mock).to receive(:error)
574
1289
 
575
- Rollbar.report_exception(exception)
1290
+ Rollbar.error(exception)
576
1291
  end
577
1292
  end
578
1293
  end
@@ -589,12 +1304,7 @@ describe Rollbar do
589
1304
  config.use_sucker_punch
590
1305
  end
591
1306
 
592
- Rollbar.report_exception(@exception)
593
-
594
- Rollbar.configure do |config|
595
- config.use_async = false
596
- config.async_handler = Rollbar.default_async_handler
597
- end
1307
+ Rollbar.error(exception)
598
1308
  end
599
1309
  end
600
1310
 
@@ -614,161 +1324,7 @@ describe Rollbar do
614
1324
  config.async_handler = handler
615
1325
  end
616
1326
 
617
- Rollbar.report_exception(@exception)
618
-
619
- Rollbar.configure do |config|
620
- config.use_async = false
621
- config.async_handler = Rollbar.default_async_handler
622
- end
623
- end
624
- end
625
- end
626
-
627
- context 'message_data' do
628
- before(:each) do
629
- configure
630
- @message_body = "This is a test"
631
- @level = 'debug'
632
- end
633
-
634
- it 'should build a message' do
635
- data = Rollbar.send(:message_data, @message_body, @level, {})
636
- data[:body][:message][:body].should == @message_body
637
- data[:level].should == @level
638
- data[:custom].should be_nil
639
- end
640
-
641
- it 'should accept extra_data' do
642
- user_id = 123
643
- name = "Tester"
644
-
645
- data = Rollbar.send(:message_data, @message_body, 'info',
646
- :user_id => user_id, :name => name)
647
-
648
- data[:level].should == 'info'
649
- message = data[:body][:message]
650
- message[:body].should == @message_body
651
- message[:user_id].should == user_id
652
- message[:name].should == name
653
- end
654
-
655
- it 'should build a message with custom data when configured' do
656
- Rollbar.configure do |config|
657
- config.custom_data_method = lambda { {:foo => "bar", :hello => [1, 2, 3]} }
658
- end
659
-
660
- data = Rollbar.send(:message_data, @message_body, @level, {})
661
-
662
- data[:level].should == @level
663
- data[:body][:message][:body].should == @message_body
664
- data[:custom].should_not be_nil
665
- data[:custom][:foo].should == "bar"
666
- data[:custom][:hello][2].should == 3
667
-
668
- Rollbar.configure do |config|
669
- config.custom_data_method = nil
670
- end
671
- end
672
- end
673
-
674
- describe '.exception_data' do
675
- before(:each) do
676
- configure
677
- begin
678
- foo = bar
679
- rescue => e
680
- @exception = e
681
- end
682
- end
683
-
684
- it 'should accept force_level' do
685
- level = 'critical'
686
- data = Rollbar.send(:exception_data, @exception, level)
687
- data[:level].should == level
688
- end
689
-
690
- it 'should build valid exception data' do
691
- data = Rollbar.send(:exception_data, @exception)
692
-
693
- data[:level].should_not be_nil
694
- data[:custom].should be_nil
695
-
696
- trace = data[:body][:trace]
697
-
698
- frames = trace[:frames]
699
- frames.should be_a_kind_of(Array)
700
- frames.each do |frame|
701
- frame[:filename].should be_a_kind_of(String)
702
- frame[:lineno].should be_a_kind_of(Fixnum)
703
- if frame[:method]
704
- frame[:method].should be_a_kind_of(String)
705
- end
706
- end
707
-
708
- # should be NameError, but can be NoMethodError sometimes on rubinius 1.8
709
- # http://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/
710
- trace[:exception][:class].should match(/^(NameError|NoMethodError)$/)
711
- trace[:exception][:message].should match(/^(undefined local variable or method `bar'|undefined method `bar' on an instance of)/)
712
- end
713
-
714
- it 'should include custom data when configured' do
715
- Rollbar.configure do |config|
716
- config.custom_data_method = lambda { {:foo => "baz", :hello => [4, 5, 6]} }
717
- end
718
-
719
- data = Rollbar.send(:exception_data, @exception)
720
- data[:body][:trace].should_not be_nil
721
- data[:custom][:foo].should == "baz"
722
- data[:custom][:hello][2].should == 6
723
-
724
- Rollbar.configure do |config|
725
- config.custom_data_method = nil
726
- end
727
- end
728
-
729
- context 'with nested exceptions' do
730
- let(:crashing_code) do
731
- proc do
732
- begin
733
- begin
734
- fail CauseException.new('the cause')
735
- rescue
736
- fail StandardError.new('the error')
737
- end
738
- rescue => e
739
- e
740
- end
741
- end
742
- end
743
- let(:rescued_exception) { crashing_code.call }
744
-
745
- if Exception.instance_methods.include?(:cause)
746
- it 'sends the two exceptions in the trace_chain attribute' do
747
- data = Rollbar.send(:exception_data, rescued_exception)
748
- body = data[:body]
749
-
750
- body[:trace].should be_nil
751
- body[:trace_chain].should be_kind_of(Array)
752
-
753
- chain = body[:trace_chain]
754
- chain[0][:exception][:class].should match(/StandardError/)
755
- chain[0][:exception][:message].should match(/the error/)
756
-
757
- chain[1][:exception][:class].should match(/CauseException/)
758
- chain[1][:exception][:message].should match(/the cause/)
759
- end
760
-
761
- else
762
- it 'sends only the last exception in the trace attribute' do
763
- data = Rollbar.send(:exception_data, rescued_exception)
764
- body = data[:body]
765
-
766
- body[:trace].should be_kind_of(Hash)
767
- body[:trace_chain].should be_nil
768
-
769
- body[:trace][:exception][:class].should match(/StandardError/)
770
- body[:trace][:exception][:message].should match(/the error/)
771
- end
1327
+ Rollbar.error(exception)
772
1328
  end
773
1329
  end
774
1330
  end
@@ -780,15 +1336,18 @@ describe Rollbar do
780
1336
 
781
1337
  it 'should have use the Rails logger when configured to do so' do
782
1338
  configure
783
- Rollbar.send(:logger).should == ::Rails.logger
1339
+ expect(Rollbar.send(:logger)).to be_kind_of(Rollbar::LoggerProxy)
1340
+ expect(Rollbar.send(:logger).object).should == ::Rails.logger
784
1341
  end
785
1342
 
786
1343
  it 'should use the default_logger when no logger is set' do
787
1344
  logger = Logger.new(STDERR)
1345
+
788
1346
  Rollbar.configure do |config|
789
1347
  config.default_logger = lambda { logger }
790
1348
  end
791
- Rollbar.send(:logger).should == logger
1349
+
1350
+ Rollbar.send(:logger).object.should == logger
792
1351
  end
793
1352
 
794
1353
  it 'should have a default default_logger' do
@@ -800,72 +1359,11 @@ describe Rollbar do
800
1359
  end
801
1360
  end
802
1361
 
803
- context 'build_payload' do
804
- before(:each) do
805
- configure
806
- Rollbar.configure do |config|
807
- config.logger = logger_mock
808
- end
809
- end
810
-
811
- let(:logger_mock) { double("Rails.logger").as_null_object }
812
-
813
- it 'should build valid json' do
814
- data = { :foo => { :bar => 'baz'}}
815
- payload = Rollbar.send(:build_payload, data)
816
- payload["data"][:foo][:bar].should == "baz"
817
- end
818
-
819
- it 'should strip out invalid utf-8' do
820
- payload = Rollbar.send(:build_payload, {
821
- :good_key => "\255bad value",
822
- "bad\255 key" => "good value",
823
- "bad key 2\255" => "bad \255value",
824
- :hash => {
825
- "bad array \255key" => ["bad\255 array element", "good array element"]
826
- }
827
- })
828
-
829
- payload["data"][:good_key].should == 'bad value'
830
- payload["data"]["bad key"].should == 'good value'
831
- payload["data"]["bad key 2"].should == 'bad value'
832
- payload["data"][:hash].should == {
833
- "bad array key" => ["bad array element", "good array element"]
834
- }
835
- end
836
-
837
- it 'should truncate large strings if the payload is too big' do
838
- data = {:foo => {:bar => "baz"}, :large => 'a' * (128 * 1024), :small => 'b' * 1024}
839
- payload = Rollbar.send(:build_payload, data)
840
- json = Rollbar.send(:dump_payload, payload)
841
-
842
- hash = MultiJson.load(json)
843
- hash["data"]["large"].should == '%s...' % ('a' * 1021)
844
- hash["data"]["small"].should == 'b' * 1024
845
- end
846
-
847
- it 'should send a failsafe message if the payload cannot be reduced enough' do
848
- logger_mock.should_receive(:error).with(/Sending failsafe response due to Could not send payload due to it being too large after truncating attempts/)
849
- logger_mock.should_receive(:info).with('[Rollbar] Success')
850
-
851
- orig_max = Rollbar::MAX_PAYLOAD_SIZE
852
- Rollbar::MAX_PAYLOAD_SIZE = 1
853
- orig_send_failsafe = Rollbar.method(:send_failsafe)
854
-
855
- Rollbar.stub(:send_failsafe) do |message, exception|
856
- Rollbar::MAX_PAYLOAD_SIZE = orig_max
857
- orig_send_failsafe.call(message, exception)
858
- end
859
-
860
- Rollbar.report_exception(@exception)
861
- end
862
- end
863
-
864
1362
  context 'enforce_valid_utf8' do
865
1363
  it 'should replace invalid utf8 values' do
866
1364
  bad_key = "inner \x92bad key"
867
1365
  bad_key.force_encoding('ASCII-8BIT') if bad_key.respond_to?('force_encoding')
868
-
1366
+
869
1367
  payload = {
870
1368
  :bad_value => "bad value 1\255",
871
1369
  :bad_value_2 => "bad\255 value 2",
@@ -884,7 +1382,7 @@ describe Rollbar do
884
1382
  }
885
1383
 
886
1384
  payload_copy = payload.clone
887
- Rollbar.send(:enforce_valid_utf8, payload_copy)
1385
+ notifier.send(:enforce_valid_utf8, payload_copy)
888
1386
 
889
1387
  payload_copy[:bad_value].should == "bad value 1"
890
1388
  payload_copy[:bad_value_2].should == "bad value 2"
@@ -915,7 +1413,7 @@ describe Rollbar do
915
1413
  }
916
1414
 
917
1415
  payload_copy = payload.clone
918
- Rollbar.send(:truncate_payload, payload_copy, 6)
1416
+ notifier.send(:truncate_payload, payload_copy, 6)
919
1417
 
920
1418
  payload_copy[:truncated].should == '123...'
921
1419
  payload_copy[:not_truncated].should == '123456'
@@ -931,67 +1429,16 @@ describe Rollbar do
931
1429
  }
932
1430
 
933
1431
  payload_copy = payload.clone
934
- Rollbar.send(:truncate_payload, payload_copy, 6)
1432
+ notifier.send(:truncate_payload, payload_copy, 6)
935
1433
 
936
1434
  payload_copy[:truncated].should == "Ŝǻм..."
937
1435
  payload_copy[:not_truncated].should == '123456'
938
1436
  end
939
1437
  end
940
1438
 
941
- context 'base_data' do
942
- before(:each) { configure }
943
-
944
- it 'should have the correct notifier name' do
945
- Rollbar.send(:base_data)[:notifier][:name].should == 'rollbar-gem'
946
- end
947
-
948
- it 'should have the correct notifier version' do
949
- Rollbar.send(:base_data)[:notifier][:version].should == Rollbar::VERSION
950
- end
951
-
952
- it 'should have all the required keys' do
953
- data = Rollbar.send(:base_data)
954
- data[:timestamp].should_not be_nil
955
- data[:environment].should_not be_nil
956
- data[:level].should_not be_nil
957
- data[:language].should == 'ruby'
958
- data[:framework].should match(/^Rails/)
959
- end
960
-
961
- it 'should have default environment "unspecified"' do
962
- data = Rollbar.send(:base_data)
963
- data[:environment].should == 'unspecified'
964
- end
965
-
966
- it 'should have an overridden environment' do
967
- Rollbar.configure do |config|
968
- config.environment = 'overridden'
969
- end
970
-
971
- data = Rollbar.send(:base_data)
972
- data[:environment].should == 'overridden'
973
- end
974
-
975
- it 'should not have custom data under default configuration' do
976
- data = Rollbar.send(:base_data)
977
- data[:custom].should be_nil
978
- end
979
-
980
- it 'should have custom data when custom_data_method is configured' do
981
- Rollbar.configure do |config|
982
- config.custom_data_method = lambda { {:a => 1, :b => [2, 3, 4]} }
983
- end
984
-
985
- data = Rollbar.send(:base_data)
986
- data[:custom].should_not be_nil
987
- data[:custom][:a].should == 1
988
- data[:custom][:b][2].should == 4
989
- end
990
- end
991
-
992
1439
  context 'server_data' do
993
1440
  it 'should have the right hostname' do
994
- Rollbar.send(:server_data)[:host] == Socket.gethostname
1441
+ notifier.send(:server_data)[:host] == Socket.gethostname
995
1442
  end
996
1443
 
997
1444
  it 'should have root and branch set when configured' do
@@ -1001,7 +1448,7 @@ describe Rollbar do
1001
1448
  config.branch = 'master'
1002
1449
  end
1003
1450
 
1004
- data = Rollbar.send(:server_data)
1451
+ data = notifier.send(:server_data)
1005
1452
  data[:root].should == '/path/to/root'
1006
1453
  data[:branch].should == 'master'
1007
1454
  end
@@ -1020,7 +1467,7 @@ describe Rollbar do
1020
1467
  gem_paths.push(Gem::Specification.find_by_name(gem).gem_dir)
1021
1468
  }
1022
1469
 
1023
- data = Rollbar.send(:message_data, 'test', 'info', {})
1470
+ data = notifier.send(:build_payload, 'info', 'test', nil, {})['data']
1024
1471
  data[:project_package_paths].kind_of?(Array).should == true
1025
1472
  data[:project_package_paths].length.should == gem_paths.length
1026
1473
 
@@ -1043,7 +1490,7 @@ describe Rollbar do
1043
1490
  gem_paths.any?{|path| path.include? 'rollbar-gem'}.should == true
1044
1491
  gem_paths.any?{|path| path.include? 'rspec-rails'}.should == true
1045
1492
 
1046
- data = Rollbar.send(:message_data, 'test', 'info', {})
1493
+ data = notifier.send(:build_payload, 'info', 'test', nil, {})['data']
1047
1494
  data[:project_package_paths].kind_of?(Array).should == true
1048
1495
  data[:project_package_paths].length.should == gem_paths.length
1049
1496
  (data[:project_package_paths] - gem_paths).length.should == 0
@@ -1056,7 +1503,7 @@ describe Rollbar do
1056
1503
  config.project_gems = gems
1057
1504
  end
1058
1505
 
1059
- data = Rollbar.send(:message_data, 'test', 'info', {})
1506
+ data = notifier.send(:build_payload, 'info', 'test', nil, {})['data']
1060
1507
  data[:project_package_paths].kind_of?(Array).should == true
1061
1508
  data[:project_package_paths].length.should == 1
1062
1509
  end
@@ -1067,7 +1514,7 @@ describe Rollbar do
1067
1514
  begin
1068
1515
  1 / 0
1069
1516
  rescue => e
1070
- Rollbar.send(:report_internal_error, e)
1517
+ notifier.send(:report_internal_error, e)
1071
1518
  end
1072
1519
  end
1073
1520
  end
@@ -1077,12 +1524,12 @@ describe Rollbar do
1077
1524
  begin
1078
1525
  1 / 0
1079
1526
  rescue => e
1080
- Rollbar.send(:send_failsafe, "test failsafe", e)
1527
+ notifier.send(:send_failsafe, "test failsafe", e)
1081
1528
  end
1082
1529
  end
1083
1530
 
1084
1531
  it "should not crash when given all nils" do
1085
- Rollbar.send(:send_failsafe, nil, nil)
1532
+ notifier.send(:send_failsafe, nil, nil)
1086
1533
  end
1087
1534
  end
1088
1535
 
@@ -1104,6 +1551,69 @@ describe Rollbar do
1104
1551
  end
1105
1552
  end
1106
1553
 
1554
+ describe '.scoped' do
1555
+ let(:scope_options) do
1556
+ { :foo => 'bar' }
1557
+ end
1558
+
1559
+ it 'changes payload options inside the block' do
1560
+ Rollbar.reset_notifier!
1561
+ configure
1562
+
1563
+ current_notifier_id = Rollbar.notifier.object_id
1564
+
1565
+ Rollbar.scoped(scope_options) do
1566
+ configuration = Rollbar.notifier.configuration
1567
+
1568
+ expect(Rollbar.notifier.object_id).not_to be_eql(current_notifier_id)
1569
+ expect(configuration.payload_options).to be_eql(scope_options)
1570
+ end
1571
+
1572
+ expect(Rollbar.notifier.object_id).to be_eql(current_notifier_id)
1573
+ end
1574
+
1575
+ context 'if the block fails' do
1576
+ let(:crashing_block) { proc { fail } }
1577
+
1578
+ it 'restores the old notifier' do
1579
+ notifier = Rollbar.notifier
1580
+
1581
+ expect { Rollbar.scoped(&crashing_block) }.to raise_error
1582
+ expect(notifier).to be_eql(Rollbar.notifier)
1583
+ end
1584
+ end
1585
+
1586
+ context 'if the block creates a new thread' do
1587
+ let(:block) do
1588
+ proc do
1589
+ Thread.new do
1590
+ scope = Rollbar.notifier.configuration.payload_options
1591
+ Thread.main[:inner_scope] = scope
1592
+ end.join
1593
+ end
1594
+ end
1595
+
1596
+ let(:scope) do
1597
+ { :foo => 'bar' }
1598
+ end
1599
+
1600
+ it 'maintains the parent thread notifier scope' do
1601
+ Rollbar.scoped(scope, &block)
1602
+
1603
+ expect(Thread.main[:inner_scope]).to be_eql(scope)
1604
+ end
1605
+ end
1606
+ end
1607
+
1608
+ describe '.reset_notifier' do
1609
+ it 'resets the notifier' do
1610
+ notifier1_id = Rollbar.notifier.object_id
1611
+
1612
+ Rollbar.reset_notifier!
1613
+ expect(Rollbar.notifier.object_id).not_to be_eql(notifier1_id)
1614
+ end
1615
+ end
1616
+
1107
1617
  # configure with some basic params
1108
1618
  def configure
1109
1619
  Rollbar.reconfigure do |config|