airbrake-ruby 4.15.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby/async_sender.rb +4 -2
  3. data/lib/airbrake-ruby/backtrace.rb +6 -5
  4. data/lib/airbrake-ruby/config/processor.rb +77 -0
  5. data/lib/airbrake-ruby/config/validator.rb +6 -0
  6. data/lib/airbrake-ruby/config.rb +44 -35
  7. data/lib/airbrake-ruby/context.rb +51 -0
  8. data/lib/airbrake-ruby/file_cache.rb +1 -1
  9. data/lib/airbrake-ruby/filter_chain.rb +3 -0
  10. data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
  11. data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
  12. data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +1 -1
  13. data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
  14. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +3 -4
  15. data/lib/airbrake-ruby/filters/git_repository_filter.rb +11 -2
  16. data/lib/airbrake-ruby/filters/git_revision_filter.rb +3 -1
  17. data/lib/airbrake-ruby/filters/keys_filter.rb +23 -15
  18. data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
  19. data/lib/airbrake-ruby/filters/sql_filter.rb +11 -11
  20. data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
  21. data/lib/airbrake-ruby/filters/thread_filter.rb +4 -3
  22. data/lib/airbrake-ruby/grouppable.rb +1 -1
  23. data/lib/airbrake-ruby/ignorable.rb +1 -2
  24. data/lib/airbrake-ruby/mergeable.rb +1 -1
  25. data/lib/airbrake-ruby/monotonic_time.rb +1 -1
  26. data/lib/airbrake-ruby/notice.rb +1 -8
  27. data/lib/airbrake-ruby/notice_notifier.rb +4 -4
  28. data/lib/airbrake-ruby/performance_breakdown.rb +1 -6
  29. data/lib/airbrake-ruby/performance_notifier.rb +40 -54
  30. data/lib/airbrake-ruby/promise.rb +1 -0
  31. data/lib/airbrake-ruby/query.rb +1 -6
  32. data/lib/airbrake-ruby/queue.rb +1 -8
  33. data/lib/airbrake-ruby/remote_settings/callback.rb +44 -0
  34. data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
  35. data/lib/airbrake-ruby/remote_settings.rb +128 -0
  36. data/lib/airbrake-ruby/request.rb +1 -8
  37. data/lib/airbrake-ruby/stat.rb +2 -13
  38. data/lib/airbrake-ruby/sync_sender.rb +3 -2
  39. data/lib/airbrake-ruby/tdigest.rb +12 -9
  40. data/lib/airbrake-ruby/thread_pool.rb +9 -6
  41. data/lib/airbrake-ruby/time_truncate.rb +2 -2
  42. data/lib/airbrake-ruby/timed_trace.rb +1 -3
  43. data/lib/airbrake-ruby/truncator.rb +8 -2
  44. data/lib/airbrake-ruby/version.rb +11 -1
  45. data/lib/airbrake-ruby.rb +44 -54
  46. data/spec/airbrake_spec.rb +178 -92
  47. data/spec/async_sender_spec.rb +10 -8
  48. data/spec/backtrace_spec.rb +39 -36
  49. data/spec/benchmark_spec.rb +7 -5
  50. data/spec/code_hunk_spec.rb +26 -17
  51. data/spec/config/processor_spec.rb +167 -0
  52. data/spec/config/validator_spec.rb +23 -3
  53. data/spec/config_spec.rb +43 -55
  54. data/spec/context_spec.rb +54 -0
  55. data/spec/deploy_notifier_spec.rb +6 -4
  56. data/spec/file_cache_spec.rb +1 -0
  57. data/spec/filter_chain_spec.rb +29 -24
  58. data/spec/filters/context_filter_spec.rb +14 -5
  59. data/spec/filters/dependency_filter_spec.rb +3 -1
  60. data/spec/filters/exception_attributes_filter_spec.rb +5 -3
  61. data/spec/filters/gem_root_filter_spec.rb +9 -6
  62. data/spec/filters/git_last_checkout_filter_spec.rb +10 -12
  63. data/spec/filters/{git_repository_filter.rb → git_repository_filter_spec.rb} +26 -15
  64. data/spec/filters/git_revision_filter_spec.rb +20 -20
  65. data/spec/filters/keys_allowlist_spec.rb +26 -16
  66. data/spec/filters/keys_blocklist_spec.rb +35 -18
  67. data/spec/filters/root_directory_filter_spec.rb +7 -7
  68. data/spec/filters/sql_filter_spec.rb +28 -28
  69. data/spec/filters/system_exit_filter_spec.rb +4 -2
  70. data/spec/filters/thread_filter_spec.rb +16 -14
  71. data/spec/loggable_spec.rb +2 -2
  72. data/spec/monotonic_time_spec.rb +8 -6
  73. data/spec/nested_exception_spec.rb +46 -46
  74. data/spec/notice_notifier/options_spec.rb +25 -15
  75. data/spec/notice_notifier_spec.rb +54 -49
  76. data/spec/notice_spec.rb +7 -3
  77. data/spec/performance_breakdown_spec.rb +0 -12
  78. data/spec/performance_notifier_spec.rb +69 -87
  79. data/spec/promise_spec.rb +38 -32
  80. data/spec/query_spec.rb +1 -11
  81. data/spec/queue_spec.rb +1 -13
  82. data/spec/remote_settings/callback_spec.rb +162 -0
  83. data/spec/remote_settings/settings_data_spec.rb +348 -0
  84. data/spec/remote_settings_spec.rb +201 -0
  85. data/spec/request_spec.rb +1 -13
  86. data/spec/response_spec.rb +34 -12
  87. data/spec/spec_helper.rb +4 -4
  88. data/spec/stashable_spec.rb +5 -5
  89. data/spec/stat_spec.rb +7 -14
  90. data/spec/sync_sender_spec.rb +52 -17
  91. data/spec/tdigest_spec.rb +61 -56
  92. data/spec/thread_pool_spec.rb +67 -58
  93. data/spec/time_truncate_spec.rb +23 -6
  94. data/spec/timed_trace_spec.rb +32 -30
  95. data/spec/truncator_spec.rb +72 -43
  96. metadata +67 -51
@@ -1,60 +1,71 @@
1
1
  RSpec.describe Airbrake::Filters::GitRepositoryFilter do
2
- subject { described_class.new('.') }
2
+ subject(:git_repository_filter) { described_class.new('.') }
3
3
 
4
- let(:notice) do
5
- Airbrake::Notice.new(Airbrake::Config.new, AirbrakeTestError.new)
6
- end
4
+ let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
7
5
 
8
6
  describe "#initialize" do
9
7
  it "parses standard git version" do
10
8
  allow_any_instance_of(Kernel)
11
9
  .to receive(:`).and_return('git version 2.18.0')
12
- expect { subject }.not_to raise_error
10
+ expect { git_repository_filter }.not_to raise_error
13
11
  end
14
12
 
15
13
  it "parses release candidate git version" do
16
14
  allow_any_instance_of(Kernel)
17
15
  .to receive(:`).and_return('git version 2.21.0-rc0')
18
- expect { subject }.not_to raise_error
16
+ expect { git_repository_filter }.not_to raise_error
19
17
  end
20
18
 
21
19
  it "parses git version with brackets" do
22
20
  allow_any_instance_of(Kernel)
23
21
  .to receive(:`).and_return('git version 2.17.2 (Apple Git-113)')
24
- expect { subject }.not_to raise_error
22
+ expect { git_repository_filter }.not_to raise_error
23
+ end
24
+
25
+ context "when Errno::EAGAIN is raised when detecting git version" do
26
+ it "doesn't attach anything to context/repository" do
27
+ allow_any_instance_of(Kernel).to receive(:`).and_raise(Errno::EAGAIN)
28
+ git_repository_filter.call(notice)
29
+ expect(notice[:context][:repository]).to be_nil
30
+ end
25
31
  end
26
32
  end
27
33
 
28
34
  context "when context/repository is defined" do
29
35
  it "doesn't attach anything to context/repository" do
30
36
  notice[:context][:repository] = 'git@github.com:kyrylo/test.git'
31
- subject.call(notice)
37
+ git_repository_filter.call(notice)
32
38
  expect(notice[:context][:repository]).to eq('git@github.com:kyrylo/test.git')
33
39
  end
34
40
  end
35
41
 
36
42
  context "when .git directory doesn't exist" do
37
- subject { described_class.new('root/dir') }
43
+ subject(:git_repository_filter) { described_class.new('root/dir') }
38
44
 
39
45
  it "doesn't attach anything to context/repository" do
40
- subject.call(notice)
46
+ git_repository_filter.call(notice)
41
47
  expect(notice[:context][:repository]).to be_nil
42
48
  end
43
49
  end
44
50
 
45
51
  context "when .git directory exists" do
46
52
  it "attaches context/repository" do
47
- subject.call(notice)
48
- expect(notice[:context][:repository]).to eq(
49
- 'ssh://git@github.com/airbrake/airbrake-ruby.git',
53
+ git_repository_filter.call(notice)
54
+ expect(notice[:context][:repository]).to match(
55
+ 'github.com/airbrake/airbrake-ruby',
50
56
  )
51
57
  end
52
58
  end
53
59
 
54
60
  context "when git is not in PATH" do
61
+ let!(:path) { ENV['PATH'] }
62
+
63
+ before { ENV['PATH'] = '' }
64
+
65
+ after { ENV['PATH'] = path }
66
+
55
67
  it "does not attach context/repository" do
56
- ENV['PATH'] = ''
57
- subject.call(notice)
68
+ git_repository_filter.call(notice)
58
69
  expect(notice[:context][:repository]).to be_nil
59
70
  end
60
71
  end
@@ -1,5 +1,5 @@
1
1
  RSpec.describe Airbrake::Filters::GitRevisionFilter do
2
- subject { described_class.new('root/dir') }
2
+ subject(:git_revision_filter) { described_class.new('root/dir') }
3
3
 
4
4
  # 'let!', not 'let' to make sure Notice doesn't call File.exist? with
5
5
  # unexpected arguments.
@@ -8,88 +8,88 @@ RSpec.describe Airbrake::Filters::GitRevisionFilter do
8
8
  context "when context/revision is defined" do
9
9
  it "doesn't attach anything to context/revision" do
10
10
  notice[:context][:revision] = '1.2.3'
11
- subject.call(notice)
11
+ git_revision_filter.call(notice)
12
12
  expect(notice[:context][:revision]).to eq('1.2.3')
13
13
  end
14
14
  end
15
15
 
16
16
  context "when .git directory doesn't exist" do
17
17
  it "doesn't attach anything to context/revision" do
18
- subject.call(notice)
18
+ git_revision_filter.call(notice)
19
19
  expect(notice[:context][:revision]).to be_nil
20
20
  end
21
21
  end
22
22
 
23
23
  context "when .git directory exists" do
24
24
  before do
25
- expect(File).to receive(:exist?).with('root/dir/.git').and_return(true)
25
+ allow(File).to receive(:exist?).with('root/dir/.git').and_return(true)
26
26
  end
27
27
 
28
28
  context "and when HEAD doesn't exist" do
29
29
  before do
30
- expect(File).to receive(:exist?).with('root/dir/.git/HEAD').and_return(false)
30
+ allow(File).to receive(:exist?).with('root/dir/.git/HEAD').and_return(false)
31
31
  end
32
32
 
33
33
  it "doesn't attach anything to context/revision" do
34
- subject.call(notice)
34
+ git_revision_filter.call(notice)
35
35
  expect(notice[:context][:revision]).to be_nil
36
36
  end
37
37
  end
38
38
 
39
39
  context "and when HEAD exists" do
40
40
  before do
41
- expect(File).to receive(:exist?).with('root/dir/.git/HEAD').and_return(true)
41
+ allow(File).to receive(:exist?).with('root/dir/.git/HEAD').and_return(true)
42
42
  end
43
43
 
44
44
  context "and also when HEAD doesn't start with 'ref: '" do
45
45
  before do
46
- expect(File).to(
46
+ allow(File).to(
47
47
  receive(:read).with('root/dir/.git/HEAD').and_return('refs/foo'),
48
48
  )
49
49
  end
50
50
 
51
51
  it "attaches the content of HEAD to context/revision" do
52
- subject.call(notice)
52
+ git_revision_filter.call(notice)
53
53
  expect(notice[:context][:revision]).to eq('refs/foo')
54
54
  end
55
55
  end
56
56
 
57
- context "and also when HEAD starts with 'ref: " do
57
+ context "and also when HEAD starts with 'ref: '" do
58
58
  before do
59
- expect(File).to(
59
+ allow(File).to(
60
60
  receive(:read).with('root/dir/.git/HEAD').and_return("ref: refs/foo\n"),
61
61
  )
62
62
  end
63
63
 
64
64
  context "when the ref exists" do
65
65
  before do
66
- expect(File).to(
66
+ allow(File).to(
67
67
  receive(:exist?).with('root/dir/.git/refs/foo').and_return(true),
68
68
  )
69
- expect(File).to(
69
+ allow(File).to(
70
70
  receive(:read).with('root/dir/.git/refs/foo').and_return("d34db33f\n"),
71
71
  )
72
72
  end
73
73
 
74
74
  it "attaches the revision from the ref to context/revision" do
75
- subject.call(notice)
75
+ git_revision_filter.call(notice)
76
76
  expect(notice[:context][:revision]).to eq('d34db33f')
77
77
  end
78
78
  end
79
79
 
80
80
  context "when the ref doesn't exist" do
81
81
  before do
82
- expect(File).to(
82
+ allow(File).to(
83
83
  receive(:exist?).with('root/dir/.git/refs/foo').and_return(false),
84
84
  )
85
85
  end
86
86
 
87
87
  context "and when '.git/packed-refs' exists" do
88
88
  before do
89
- expect(File).to(
89
+ allow(File).to(
90
90
  receive(:exist?).with('root/dir/.git/packed-refs').and_return(true),
91
91
  )
92
- expect(File).to(
92
+ allow(File).to(
93
93
  receive(:readlines).with('root/dir/.git/packed-refs').and_return(
94
94
  [
95
95
  "# pack-refs with: peeled fully-peeled\n",
@@ -102,20 +102,20 @@ RSpec.describe Airbrake::Filters::GitRevisionFilter do
102
102
  end
103
103
 
104
104
  it "attaches the revision from 'packed-refs' to context/revision" do
105
- subject.call(notice)
105
+ git_revision_filter.call(notice)
106
106
  expect(notice[:context][:revision]).to eq('d34db33f')
107
107
  end
108
108
  end
109
109
 
110
110
  context "and when '.git/packed-refs' doesn't exist" do
111
111
  before do
112
- expect(File).to(
112
+ allow(File).to(
113
113
  receive(:exist?).with('root/dir/.git/packed-refs').and_return(false),
114
114
  )
115
115
  end
116
116
 
117
117
  it "attaches the content of HEAD to context/revision" do
118
- subject.call(notice)
118
+ git_revision_filter.call(notice)
119
119
  expect(notice[:context][:revision]).to eq('refs/foo')
120
120
  end
121
121
  end
@@ -1,5 +1,5 @@
1
1
  RSpec.describe Airbrake::Filters::KeysAllowlist do
2
- subject { described_class.new(patterns) }
2
+ subject(:keys_allowlist_filter) { described_class.new(patterns) }
3
3
 
4
4
  let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
5
5
 
@@ -8,11 +8,15 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
8
8
 
9
9
  it "filters out the matching values" do
10
10
  notice[:params] = params.first
11
- subject.call(notice)
11
+ keys_allowlist_filter.call(notice)
12
12
  expect(notice[:params]).to eq(params.last)
13
13
  end
14
14
  end
15
15
 
16
+ before do
17
+ allow(Airbrake::Loggable.instance).to receive(:error)
18
+ end
19
+
16
20
  context "when a pattern is a Regexp" do
17
21
  include_examples(
18
22
  'pattern matching',
@@ -69,11 +73,12 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
69
73
  )
70
74
 
71
75
  it "logs an error" do
72
- expect(Airbrake::Loggable.instance).to receive(:error).with(
73
- /KeysAllowlist is invalid.+patterns: \[#<Object:.+>\]/,
74
- )
75
76
  keys_allowlist = described_class.new(patterns)
76
77
  keys_allowlist.call(notice)
78
+
79
+ expect(Airbrake::Loggable.instance).to have_received(:error).with(
80
+ /KeysAllowlist is invalid.+patterns: \[#<Object:.+>\]/,
81
+ )
77
82
  end
78
83
  end
79
84
 
@@ -82,11 +87,12 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
82
87
 
83
88
  context "and when the filter is called once" do
84
89
  it "logs an error" do
85
- expect(Airbrake::Loggable.instance).to receive(:error).with(
86
- /KeysAllowlist is invalid.+patterns: \[#<Proc:.+>\]/,
87
- )
88
90
  keys_allowlist = described_class.new(patterns)
89
91
  keys_allowlist.call(notice)
92
+
93
+ expect(Airbrake::Loggable.instance).to have_received(:error).with(
94
+ /KeysAllowlist is invalid.+patterns: \[#<Proc:.+>\]/,
95
+ )
90
96
  end
91
97
 
92
98
  include_examples(
@@ -112,11 +118,12 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
112
118
  )
113
119
 
114
120
  it "logs an error" do
115
- expect(Airbrake::Loggable.instance).to receive(:error).with(
116
- /KeysAllowlist is invalid.+patterns: \[#<Object:.+>\]/,
117
- )
118
121
  keys_allowlist = described_class.new(patterns)
119
122
  keys_allowlist.call(notice)
123
+
124
+ expect(Airbrake::Loggable.instance).to have_received(:error).with(
125
+ /KeysAllowlist is invalid.+patterns: \[#<Object:.+>\]/,
126
+ )
120
127
  end
121
128
  end
122
129
 
@@ -145,13 +152,16 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
145
152
  notice[:params] = bongo
146
153
 
147
154
  begin
148
- expect { subject.call(notice) }.to raise_error(SystemStackError)
155
+ expect { keys_allowlist_filter.call(notice) }.to raise_error(SystemStackError)
149
156
  rescue RSpec::Expectations::ExpectationNotMetError => ex
150
157
  # JRuby might raise two different exceptions, which represent the same
151
158
  # thing. One is a Java exception, the other is a Ruby exception.
152
159
  # Likely a bug: https://github.com/jruby/jruby/issues/1903
153
160
  raise ex unless RUBY_ENGINE == 'jruby'
154
- expect { subject.call(notice) }.to raise_error(java.lang.StackOverflowError)
161
+
162
+ expect do
163
+ keys_allowlist_filter.call(notice)
164
+ end.to raise_error(java.lang.StackOverflowError)
155
165
  end
156
166
  end
157
167
  end
@@ -164,7 +174,7 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
164
174
  context "when it contains query params" do
165
175
  it "filters the params" do
166
176
  notice[:context][:url] = 'http://localhost:3000/crash?foo=bar&baz=bongo&bish=bash'
167
- subject.call(notice)
177
+ keys_allowlist_filter.call(notice)
168
178
  expect(notice[:context][:url]).to(
169
179
  eq('http://localhost:3000/crash?foo=[Filtered]&baz=[Filtered]&bish=bash'),
170
180
  )
@@ -175,7 +185,7 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
175
185
  it "leaves the URL unfiltered" do
176
186
  notice[:context][:url] =
177
187
  'http://localhost:3000/cra]]]sh?foo=bar&baz=bongo&bish=bash'
178
- subject.call(notice)
188
+ keys_allowlist_filter.call(notice)
179
189
  expect(notice[:context][:url]).to(
180
190
  eq('http://localhost:3000/cra]]]sh?foo=bar&baz=bongo&bish=bash'),
181
191
  )
@@ -185,7 +195,7 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
185
195
  context "when it is without a query" do
186
196
  it "leaves the URL untouched" do
187
197
  notice[:context][:url] = 'http://localhost:3000/crash'
188
- subject.call(notice)
198
+ keys_allowlist_filter.call(notice)
189
199
  expect(notice[:context][:url]).to(eq('http://localhost:3000/crash'))
190
200
  end
191
201
  end
@@ -1,5 +1,5 @@
1
1
  RSpec.describe Airbrake::Filters::KeysBlocklist do
2
- subject { described_class.new(patterns) }
2
+ subject(:keys_blocklist_filter) { described_class.new(patterns) }
3
3
 
4
4
  let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
5
5
 
@@ -8,11 +8,15 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
8
8
 
9
9
  it "filters out the matching values" do
10
10
  notice[:params] = params.first
11
- subject.call(notice)
11
+ keys_blocklist_filter.call(notice)
12
12
  expect(notice[:params]).to eq(params.last)
13
13
  end
14
14
  end
15
15
 
16
+ before do
17
+ allow(Airbrake::Loggable.instance).to receive(:error)
18
+ end
19
+
16
20
  context "when a pattern is a Regexp" do
17
21
  include_examples(
18
22
  'pattern matching',
@@ -29,7 +33,7 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
29
33
  # https://github.com/airbrake/airbrake/issues/739
30
34
  it "doesn't fail" do
31
35
  notice[:params] = { bingo: { {} => 'unfiltered' } }
32
- expect { subject.call(notice) }.not_to raise_error
36
+ expect { keys_blocklist_filter.call(notice) }.not_to raise_error
33
37
  end
34
38
  end
35
39
  end
@@ -90,11 +94,12 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
90
94
  )
91
95
 
92
96
  it "logs an error" do
93
- expect(Airbrake::Loggable.instance).to receive(:error).with(
94
- /KeysBlocklist is invalid.+patterns: \[#<Object:.+>\]/,
95
- )
96
97
  keys_blocklist = described_class.new(patterns)
97
98
  keys_blocklist.call(notice)
99
+
100
+ expect(Airbrake::Loggable.instance).to have_received(:error).with(
101
+ /KeysBlocklist is invalid.+patterns: \[#<Object:.+>\]/,
102
+ )
98
103
  end
99
104
  end
100
105
 
@@ -103,18 +108,19 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
103
108
 
104
109
  context "and when the filter is called once" do
105
110
  it "logs an error" do
106
- expect(Airbrake::Loggable.instance).to receive(:error).with(
107
- /KeysBlocklist is invalid.+patterns: \[#<Proc:.+>\]/,
108
- )
109
111
  keys_blocklist = described_class.new(patterns)
110
112
  keys_blocklist.call(notice)
113
+
114
+ expect(Airbrake::Loggable.instance).to have_received(:error).with(
115
+ /KeysBlocklist is invalid.+patterns: \[#<Proc:.+>\]/,
116
+ )
111
117
  end
112
118
  end
113
119
 
114
120
  context "and when the filter is called twice" do
115
121
  it "unwinds procs and filters keys" do
116
122
  notice[:params] = { bingo: 'bango', bongo: 'bish' }
117
- 2.times { subject.call(notice) }
123
+ 2.times { keys_blocklist_filter.call(notice) }
118
124
  expect(notice[:params]).to eq(bingo: '[Filtered]', bongo: 'bish')
119
125
  end
120
126
  end
@@ -132,11 +138,12 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
132
138
  )
133
139
 
134
140
  it "logs an error" do
135
- expect(Airbrake::Loggable.instance).to receive(:error).with(
136
- /KeysBlocklist is invalid.+patterns: \[#<Object:.+>\]/,
137
- )
138
141
  keys_blocklist = described_class.new(patterns)
139
142
  keys_blocklist.call(notice)
143
+
144
+ expect(Airbrake::Loggable.instance).to have_received(:error).with(
145
+ /KeysBlocklist is invalid.+patterns: \[#<Object:.+>\]/,
146
+ )
140
147
  end
141
148
  end
142
149
 
@@ -150,6 +157,16 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
150
157
  { bongo: { bish: '[Filtered]' } },
151
158
  ],
152
159
  )
160
+
161
+ it "doesn't mutate the original hash" do
162
+ params = { bongo: { bish: 'bash' } }
163
+ notice[:params] = params
164
+
165
+ blocklist = described_class.new([:bish])
166
+ blocklist.call(notice)
167
+
168
+ expect(params[:bongo][:bish]).to eq('bash')
169
+ end
153
170
  end
154
171
 
155
172
  context "and it is recursive" do
@@ -175,7 +192,7 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
175
192
  notice[:context][:url] =
176
193
  'http://localhost:3000/crash?foo=bar&baz=bongo&bish=bash&color=%23FFAAFF'
177
194
 
178
- subject.call(notice)
195
+ keys_blocklist_filter.call(notice)
179
196
  expect(notice[:context][:url]).to(
180
197
  eq('http://localhost:3000/crash?foo=bar&baz=bongo&bish=[Filtered]&color=%23FFAAFF'),
181
198
  )
@@ -187,7 +204,7 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
187
204
 
188
205
  it "filters out the user" do
189
206
  notice[:context][:user] = { id: 1337, name: 'Bingo Bango' }
190
- subject.call(notice)
207
+ keys_blocklist_filter.call(notice)
191
208
  expect(notice[:context][:user]).to eq('[Filtered]')
192
209
  end
193
210
  end
@@ -197,7 +214,7 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
197
214
 
198
215
  it "filters out individual user fields" do
199
216
  notice[:context][:user] = { id: 1337, name: 'Bingo Bango' }
200
- subject.call(notice)
217
+ keys_blocklist_filter.call(notice)
201
218
  expect(notice[:context][:user][:name]).to eq('[Filtered]')
202
219
  end
203
220
  end
@@ -208,7 +225,7 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
208
225
 
209
226
  it "filters out the headers" do
210
227
  notice[:context][:headers] = { 'HTTP_COOKIE' => 'banana' }
211
- subject.call(notice)
228
+ keys_blocklist_filter.call(notice)
212
229
  expect(notice[:context][:headers]).to eq('[Filtered]')
213
230
  end
214
231
 
@@ -217,7 +234,7 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
217
234
 
218
235
  it "filters out individual header fields" do
219
236
  notice[:context][:headers] = { 'HTTP_COOKIE' => 'banana' }
220
- subject.call(notice)
237
+ keys_blocklist_filter.call(notice)
221
238
  expect(notice[:context][:headers]['HTTP_COOKIE']).to eq('[Filtered]')
222
239
  end
223
240
  end
@@ -1,22 +1,22 @@
1
1
  RSpec.describe Airbrake::Filters::RootDirectoryFilter do
2
- subject { described_class.new(root_directory) }
2
+ subject(:root_directory_filter) { described_class.new(root_directory) }
3
3
 
4
4
  let(:root_directory) { '/var/www/project' }
5
5
  let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
6
6
 
7
7
  it "replaces root directory in the backtrace with a label" do
8
- # rubocop:disable Metrics/LineLength
8
+ # rubocop:disable Layout/LineLength
9
9
  notice[:errors].first[:backtrace] = [
10
10
  { file: "/home/kyrylo/code/airbrake/ruby/spec/spec_helper.rb" },
11
11
  { file: "#{root_directory}/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb " },
12
12
  { file: "/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb" },
13
13
  { file: "#{root_directory}/gems/rspec-core-3.3.2/exe/rspec" },
14
14
  ]
15
- # rubocop:enable Metrics/LineLength
15
+ # rubocop:enable Layout/LineLength
16
16
 
17
- subject.call(notice)
17
+ root_directory_filter.call(notice)
18
18
 
19
- # rubocop:disable Metrics/LineLength
19
+ # rubocop:disable Layout/LineLength
20
20
  expect(notice[:errors].first[:backtrace]).to(
21
21
  eq(
22
22
  [
@@ -27,12 +27,12 @@ RSpec.describe Airbrake::Filters::RootDirectoryFilter do
27
27
  ],
28
28
  ),
29
29
  )
30
- # rubocop:enable Metrics/LineLength
30
+ # rubocop:enable Layout/LineLength
31
31
  end
32
32
 
33
33
  it "does not filter file when it is nil" do
34
34
  expect(notice[:errors].first[:file]).to be_nil
35
- expect { subject.call(notice) }.not_to(
35
+ expect { root_directory_filter.call(notice) }.not_to(
36
36
  change { notice[:errors].first[:file] },
37
37
  )
38
38
  end