airbrake-ruby 5.1.1 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby/async_sender.rb +3 -1
  3. data/lib/airbrake-ruby/config/processor.rb +2 -1
  4. data/lib/airbrake-ruby/config.rb +14 -7
  5. data/lib/airbrake-ruby/context.rb +51 -0
  6. data/lib/airbrake-ruby/file_cache.rb +1 -1
  7. data/lib/airbrake-ruby/filter_chain.rb +2 -0
  8. data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
  9. data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +1 -1
  10. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +2 -2
  11. data/lib/airbrake-ruby/filters/git_repository_filter.rb +1 -1
  12. data/lib/airbrake-ruby/filters/git_revision_filter.rb +1 -1
  13. data/lib/airbrake-ruby/filters/keys_filter.rb +2 -2
  14. data/lib/airbrake-ruby/filters/sql_filter.rb +2 -2
  15. data/lib/airbrake-ruby/filters/thread_filter.rb +2 -3
  16. data/lib/airbrake-ruby/grouppable.rb +1 -1
  17. data/lib/airbrake-ruby/ignorable.rb +0 -2
  18. data/lib/airbrake-ruby/mergeable.rb +1 -1
  19. data/lib/airbrake-ruby/monotonic_time.rb +1 -1
  20. data/lib/airbrake-ruby/notice_notifier.rb +3 -4
  21. data/lib/airbrake-ruby/performance_notifier.rb +1 -2
  22. data/lib/airbrake-ruby/remote_settings/callback.rb +1 -1
  23. data/lib/airbrake-ruby/remote_settings/settings_data.rb +2 -2
  24. data/lib/airbrake-ruby/remote_settings.rb +27 -4
  25. data/lib/airbrake-ruby/tdigest.rb +10 -9
  26. data/lib/airbrake-ruby/thread_pool.rb +8 -6
  27. data/lib/airbrake-ruby/timed_trace.rb +1 -3
  28. data/lib/airbrake-ruby/version.rb +2 -2
  29. data/lib/airbrake-ruby.rb +3 -2
  30. data/spec/airbrake_spec.rb +139 -76
  31. data/spec/async_sender_spec.rb +10 -8
  32. data/spec/backtrace_spec.rb +13 -10
  33. data/spec/benchmark_spec.rb +5 -3
  34. data/spec/code_hunk_spec.rb +24 -15
  35. data/spec/config/processor_spec.rb +20 -3
  36. data/spec/config/validator_spec.rb +5 -2
  37. data/spec/config_spec.rb +25 -16
  38. data/spec/context_spec.rb +54 -0
  39. data/spec/deploy_notifier_spec.rb +6 -4
  40. data/spec/file_cache_spec.rb +1 -0
  41. data/spec/filter_chain_spec.rb +29 -24
  42. data/spec/filters/context_filter_spec.rb +14 -5
  43. data/spec/filters/dependency_filter_spec.rb +3 -1
  44. data/spec/filters/exception_attributes_filter_spec.rb +5 -3
  45. data/spec/filters/gem_root_filter_spec.rb +5 -2
  46. data/spec/filters/git_last_checkout_filter_spec.rb +10 -12
  47. data/spec/filters/git_repository_filter.rb +9 -9
  48. data/spec/filters/git_revision_filter_spec.rb +20 -20
  49. data/spec/filters/keys_allowlist_spec.rb +25 -16
  50. data/spec/filters/keys_blocklist_spec.rb +25 -18
  51. data/spec/filters/root_directory_filter_spec.rb +3 -3
  52. data/spec/filters/sql_filter_spec.rb +26 -26
  53. data/spec/filters/system_exit_filter_spec.rb +4 -2
  54. data/spec/filters/thread_filter_spec.rb +16 -14
  55. data/spec/loggable_spec.rb +2 -2
  56. data/spec/monotonic_time_spec.rb +8 -6
  57. data/spec/nested_exception_spec.rb +46 -46
  58. data/spec/notice_notifier/options_spec.rb +23 -13
  59. data/spec/notice_notifier_spec.rb +52 -47
  60. data/spec/notice_spec.rb +6 -2
  61. data/spec/performance_notifier_spec.rb +67 -60
  62. data/spec/promise_spec.rb +38 -32
  63. data/spec/remote_settings/callback_spec.rb +27 -8
  64. data/spec/remote_settings/settings_data_spec.rb +4 -4
  65. data/spec/remote_settings_spec.rb +23 -9
  66. data/spec/response_spec.rb +34 -12
  67. data/spec/stashable_spec.rb +5 -5
  68. data/spec/stat_spec.rb +7 -5
  69. data/spec/sync_sender_spec.rb +49 -16
  70. data/spec/tdigest_spec.rb +61 -56
  71. data/spec/thread_pool_spec.rb +65 -56
  72. data/spec/time_truncate_spec.rb +4 -2
  73. data/spec/timed_trace_spec.rb +32 -30
  74. data/spec/truncator_spec.rb +72 -43
  75. metadata +52 -49
@@ -1,21 +1,21 @@
1
1
  RSpec.describe Airbrake::Filters::GitLastCheckoutFilter do
2
- subject { described_class.new('.') }
2
+ subject(:git_last_checkout_filter) { described_class.new('.') }
3
3
 
4
4
  let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
5
5
 
6
6
  context "when context/lastCheckout is defined" do
7
7
  it "doesn't attach anything to context/lastCheckout" do
8
8
  notice[:context][:lastCheckout] = '123'
9
- subject.call(notice)
9
+ git_last_checkout_filter.call(notice)
10
10
  expect(notice[:context][:lastCheckout]).to eq('123')
11
11
  end
12
12
  end
13
13
 
14
14
  context "when .git directory doesn't exist" do
15
- subject { described_class.new('root/dir') }
15
+ subject(:git_last_checkout_without_git_dir_filter) { described_class.new('root/dir') }
16
16
 
17
17
  it "doesn't attach anything to context/lastCheckout" do
18
- subject.call(notice)
18
+ git_last_checkout_without_git_dir_filter.call(notice)
19
19
  expect(notice[:context][:lastCheckout]).to be_nil
20
20
  end
21
21
  end
@@ -25,7 +25,7 @@ RSpec.describe Airbrake::Filters::GitLastCheckoutFilter do
25
25
  before { ENV['AIRBRAKE_DEPLOY_USERNAME'] = 'deployer' }
26
26
 
27
27
  it "attaches username from the environment" do
28
- subject.call(notice)
28
+ git_last_checkout_filter.call(notice)
29
29
  expect(notice[:context][:lastCheckout][:username]).to eq('deployer')
30
30
  end
31
31
  end
@@ -34,7 +34,7 @@ RSpec.describe Airbrake::Filters::GitLastCheckoutFilter do
34
34
  before { ENV['AIRBRAKE_DEPLOY_USERNAME'] = nil }
35
35
 
36
36
  it "attaches last checkouted username" do
37
- subject.call(notice)
37
+ git_last_checkout_filter.call(notice)
38
38
  username = notice[:context][:lastCheckout][:username]
39
39
  expect(username).not_to be_empty
40
40
  expect(username).not_to be_nil
@@ -42,20 +42,18 @@ RSpec.describe Airbrake::Filters::GitLastCheckoutFilter do
42
42
  end
43
43
 
44
44
  it "attaches last checkouted email" do
45
- subject.call(notice)
46
- expect(notice[:context][:lastCheckout][:email]).to(
47
- match(/\A\w+[\w.-]*@(\w+\.)*\w+\z/),
48
- )
45
+ git_last_checkout_filter.call(notice)
46
+ expect(notice[:context][:lastCheckout][:email]).to(match(/\A\w+@[\w\-.]+\z/))
49
47
  end
50
48
 
51
49
  it "attaches last checkouted revision" do
52
- subject.call(notice)
50
+ git_last_checkout_filter.call(notice)
53
51
  expect(notice[:context][:lastCheckout][:revision]).not_to be_empty
54
52
  expect(notice[:context][:lastCheckout][:revision].size).to eq(40)
55
53
  end
56
54
 
57
55
  it "attaches last checkouted time" do
58
- subject.call(notice)
56
+ git_last_checkout_filter.call(notice)
59
57
  expect(notice[:context][:lastCheckout][:time]).not_to be_empty
60
58
  expect(notice[:context][:lastCheckout][:time].size).to eq(25)
61
59
  end
@@ -1,5 +1,5 @@
1
1
  RSpec.describe Airbrake::Filters::GitRepositoryFilter do
2
- subject { described_class.new('.') }
2
+ subject(:git_repository_filter) { described_class.new('.') }
3
3
 
4
4
  let(:notice) do
5
5
  Airbrake::Notice.new(Airbrake::Config.new, AirbrakeTestError.new)
@@ -9,42 +9,42 @@ RSpec.describe Airbrake::Filters::GitRepositoryFilter do
9
9
  it "parses standard git version" do
10
10
  allow_any_instance_of(Kernel)
11
11
  .to receive(:`).and_return('git version 2.18.0')
12
- expect { subject }.not_to raise_error
12
+ expect { git_repository_filter }.not_to raise_error
13
13
  end
14
14
 
15
15
  it "parses release candidate git version" do
16
16
  allow_any_instance_of(Kernel)
17
17
  .to receive(:`).and_return('git version 2.21.0-rc0')
18
- expect { subject }.not_to raise_error
18
+ expect { git_repository_filter }.not_to raise_error
19
19
  end
20
20
 
21
21
  it "parses git version with brackets" do
22
22
  allow_any_instance_of(Kernel)
23
23
  .to receive(:`).and_return('git version 2.17.2 (Apple Git-113)')
24
- expect { subject }.not_to raise_error
24
+ expect { git_repository_filter }.not_to raise_error
25
25
  end
26
26
  end
27
27
 
28
28
  context "when context/repository is defined" do
29
29
  it "doesn't attach anything to context/repository" do
30
30
  notice[:context][:repository] = 'git@github.com:kyrylo/test.git'
31
- subject.call(notice)
31
+ git_repository_filter.call(notice)
32
32
  expect(notice[:context][:repository]).to eq('git@github.com:kyrylo/test.git')
33
33
  end
34
34
  end
35
35
 
36
36
  context "when .git directory doesn't exist" do
37
- subject { described_class.new('root/dir') }
37
+ git_repository_filter { described_class.new('root/dir') }
38
38
 
39
39
  it "doesn't attach anything to context/repository" do
40
- subject.call(notice)
40
+ git_repository_filter.call(notice)
41
41
  expect(notice[:context][:repository]).to be_nil
42
42
  end
43
43
  end
44
44
 
45
45
  context "when .git directory exists" do
46
46
  it "attaches context/repository" do
47
- subject.call(notice)
47
+ git_repository_filter.call(notice)
48
48
  expect(notice[:context][:repository]).to eq(
49
49
  'ssh://git@github.com/airbrake/airbrake-ruby.git',
50
50
  )
@@ -54,7 +54,7 @@ RSpec.describe Airbrake::Filters::GitRepositoryFilter do
54
54
  context "when git is not in PATH" do
55
55
  it "does not attach context/repository" do
56
56
  ENV['PATH'] = ''
57
- subject.call(notice)
57
+ git_repository_filter.call(notice)
58
58
  expect(notice[:context][:repository]).to be_nil
59
59
  end
60
60
  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,14 +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
161
 
155
- expect { subject.call(notice) }.to raise_error(java.lang.StackOverflowError)
162
+ expect do
163
+ keys_allowlist_filter.call(notice)
164
+ end.to raise_error(java.lang.StackOverflowError)
156
165
  end
157
166
  end
158
167
  end
@@ -165,7 +174,7 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
165
174
  context "when it contains query params" do
166
175
  it "filters the params" do
167
176
  notice[:context][:url] = 'http://localhost:3000/crash?foo=bar&baz=bongo&bish=bash'
168
- subject.call(notice)
177
+ keys_allowlist_filter.call(notice)
169
178
  expect(notice[:context][:url]).to(
170
179
  eq('http://localhost:3000/crash?foo=[Filtered]&baz=[Filtered]&bish=bash'),
171
180
  )
@@ -176,7 +185,7 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
176
185
  it "leaves the URL unfiltered" do
177
186
  notice[:context][:url] =
178
187
  'http://localhost:3000/cra]]]sh?foo=bar&baz=bongo&bish=bash'
179
- subject.call(notice)
188
+ keys_allowlist_filter.call(notice)
180
189
  expect(notice[:context][:url]).to(
181
190
  eq('http://localhost:3000/cra]]]sh?foo=bar&baz=bongo&bish=bash'),
182
191
  )
@@ -186,7 +195,7 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
186
195
  context "when it is without a query" do
187
196
  it "leaves the URL untouched" do
188
197
  notice[:context][:url] = 'http://localhost:3000/crash'
189
- subject.call(notice)
198
+ keys_allowlist_filter.call(notice)
190
199
  expect(notice[:context][:url]).to(eq('http://localhost:3000/crash'))
191
200
  end
192
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
 
@@ -185,7 +192,7 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
185
192
  notice[:context][:url] =
186
193
  'http://localhost:3000/crash?foo=bar&baz=bongo&bish=bash&color=%23FFAAFF'
187
194
 
188
- subject.call(notice)
195
+ keys_blocklist_filter.call(notice)
189
196
  expect(notice[:context][:url]).to(
190
197
  eq('http://localhost:3000/crash?foo=bar&baz=bongo&bish=[Filtered]&color=%23FFAAFF'),
191
198
  )
@@ -197,7 +204,7 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
197
204
 
198
205
  it "filters out the user" do
199
206
  notice[:context][:user] = { id: 1337, name: 'Bingo Bango' }
200
- subject.call(notice)
207
+ keys_blocklist_filter.call(notice)
201
208
  expect(notice[:context][:user]).to eq('[Filtered]')
202
209
  end
203
210
  end
@@ -207,7 +214,7 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
207
214
 
208
215
  it "filters out individual user fields" do
209
216
  notice[:context][:user] = { id: 1337, name: 'Bingo Bango' }
210
- subject.call(notice)
217
+ keys_blocklist_filter.call(notice)
211
218
  expect(notice[:context][:user][:name]).to eq('[Filtered]')
212
219
  end
213
220
  end
@@ -218,7 +225,7 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
218
225
 
219
226
  it "filters out the headers" do
220
227
  notice[:context][:headers] = { 'HTTP_COOKIE' => 'banana' }
221
- subject.call(notice)
228
+ keys_blocklist_filter.call(notice)
222
229
  expect(notice[:context][:headers]).to eq('[Filtered]')
223
230
  end
224
231
 
@@ -227,7 +234,7 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
227
234
 
228
235
  it "filters out individual header fields" do
229
236
  notice[:context][:headers] = { 'HTTP_COOKIE' => 'banana' }
230
- subject.call(notice)
237
+ keys_blocklist_filter.call(notice)
231
238
  expect(notice[:context][:headers]['HTTP_COOKIE']).to eq('[Filtered]')
232
239
  end
233
240
  end
@@ -1,5 +1,5 @@
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) }
@@ -14,7 +14,7 @@ RSpec.describe Airbrake::Filters::RootDirectoryFilter do
14
14
  ]
15
15
  # rubocop:enable Layout/LineLength
16
16
 
17
- subject.call(notice)
17
+ root_directory_filter.call(notice)
18
18
 
19
19
  # rubocop:disable Layout/LineLength
20
20
  expect(notice[:errors].first[:backtrace]).to(
@@ -32,7 +32,7 @@ RSpec.describe Airbrake::Filters::RootDirectoryFilter do
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