airbrake-ruby 5.1.0-java → 6.0.0-java

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.
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 +15 -6
  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 +1 -1
  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 +8 -7
  25. data/lib/airbrake-ruby/tdigest.rb +10 -9
  26. data/lib/airbrake-ruby/thread_pool.rb +5 -3
  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 +26 -17
  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 +19 -19
  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 +40 -7
  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 -55
  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,4 +1,6 @@
1
1
  RSpec.describe Airbrake::CodeHunk do
2
+ subject(:code_hunk) { described_class.new }
3
+
2
4
  after do
3
5
  %w[empty_file.rb code.rb banana.rb short_file.rb long_line.txt].each do |f|
4
6
  Airbrake::FileCache[project_root_path(f)] = nil
@@ -27,10 +29,12 @@ RSpec.describe Airbrake::CodeHunk do
27
29
  end
28
30
 
29
31
  context "when a file has less than NLINES lines before start line" do
30
- subject { described_class.new.get(project_root_path('code.rb'), 1) }
32
+ subject(:code_hunk) do
33
+ described_class.new.get(project_root_path('code.rb'), 1)
34
+ end
31
35
 
32
36
  it do
33
- is_expected.to(
37
+ expect(code_hunk).to(
34
38
  eq(
35
39
  1 => 'module Airbrake',
36
40
  2 => ' ##',
@@ -43,10 +47,12 @@ RSpec.describe Airbrake::CodeHunk do
43
47
  end
44
48
 
45
49
  context "when a file has less than NLINES lines after end line" do
46
- subject { described_class.new.get(project_root_path('code.rb'), 222) }
50
+ subject(:code_hunk) do
51
+ described_class.new.get(project_root_path('code.rb'), 222)
52
+ end
47
53
 
48
54
  it do
49
- is_expected.to(
55
+ expect(code_hunk).to(
50
56
  eq(
51
57
  220 => ' end',
52
58
  221 => 'end',
@@ -56,12 +62,12 @@ RSpec.describe Airbrake::CodeHunk do
56
62
  end
57
63
 
58
64
  context "when a file has less than NLINES lines before and after" do
59
- subject do
65
+ subject(:code_hunk) do
60
66
  described_class.new.get(project_root_path('short_file.rb'), 2)
61
67
  end
62
68
 
63
69
  it do
64
- is_expected.to(
70
+ expect(code_hunk).to(
65
71
  eq(
66
72
  1 => 'module Banana',
67
73
  2 => ' attr_reader :bingo',
@@ -72,10 +78,12 @@ RSpec.describe Airbrake::CodeHunk do
72
78
  end
73
79
 
74
80
  context "when a file has enough lines before and after" do
75
- subject { described_class.new.get(project_root_path('code.rb'), 100) }
81
+ subject(:code_hunk) do
82
+ described_class.new.get(project_root_path('code.rb'), 100)
83
+ end
76
84
 
77
85
  it do
78
- is_expected.to(
86
+ expect(code_hunk).to(
79
87
  eq(
80
88
  98 => ' return json if json && json.bytesize <= MAX_NOTICE_SIZE',
81
89
  99 => ' end',
@@ -88,27 +96,28 @@ RSpec.describe Airbrake::CodeHunk do
88
96
  end
89
97
 
90
98
  context "when a line exceeds the length limit" do
91
- subject do
99
+ subject(:code_hunk) do
92
100
  described_class.new.get(project_root_path('long_line.txt'), 1)
93
101
  end
94
102
 
95
103
  it "strips the line" do
96
- expect(subject[1]).to eq('l' + 'o' * 196 + 'ng')
104
+ expect(code_hunk[1]).to eq("l#{'o' * 196}ng")
97
105
  end
98
106
  end
99
107
 
100
108
  context "when an error occurrs while fetching code" do
101
109
  before do
102
- expect(Airbrake::FileCache).to receive(:[]).and_raise(Errno::EACCES)
110
+ allow(Airbrake::Loggable.instance).to receive(:error)
111
+ allow(Airbrake::FileCache).to receive(:[]).and_raise(Errno::EACCES)
103
112
  end
104
113
 
105
114
  it "logs error and returns nil" do
106
- expect(Airbrake::Loggable.instance).to receive(:error).with(
107
- /can't read code hunk.+Permission denied/,
108
- )
109
- expect(subject.get(project_root_path('code.rb'), 1)).to(
115
+ expect(code_hunk.get(project_root_path('code.rb'), 1)).to(
110
116
  eq(1 => ''),
111
117
  )
118
+ expect(Airbrake::Loggable.instance).to have_received(:error).with(
119
+ /can't read code hunk.+Permission denied/,
120
+ )
112
121
  end
113
122
  end
114
123
  end
@@ -44,12 +44,17 @@ RSpec.describe Airbrake::Config::Processor do
44
44
  end
45
45
 
46
46
  describe "#process_remote_configuration" do
47
+ before do
48
+ allow(Airbrake::RemoteSettings).to receive(:poll)
49
+ end
50
+
47
51
  context "when the config doesn't define a project_id" do
48
52
  let(:config) { Airbrake::Config.new(project_id: nil) }
49
53
 
50
54
  it "doesn't set remote settings" do
51
- expect(Airbrake::RemoteSettings).not_to receive(:poll)
52
55
  described_class.new(config).process_remote_configuration
56
+
57
+ expect(Airbrake::RemoteSettings).not_to have_received(:poll)
53
58
  end
54
59
  end
55
60
 
@@ -57,8 +62,9 @@ RSpec.describe Airbrake::Config::Processor do
57
62
  let(:config) { Airbrake::Config.new(project_id: 123, environment: 'test') }
58
63
 
59
64
  it "doesn't set remote settings" do
60
- expect(Airbrake::RemoteSettings).not_to receive(:poll)
61
65
  described_class.new(config).process_remote_configuration
66
+
67
+ expect(Airbrake::RemoteSettings).not_to have_received(:poll)
62
68
  end
63
69
  end
64
70
 
@@ -68,8 +74,19 @@ RSpec.describe Airbrake::Config::Processor do
68
74
  end
69
75
 
70
76
  it "sets remote settings" do
71
- expect(Airbrake::RemoteSettings).to receive(:poll)
72
77
  described_class.new(config).process_remote_configuration
78
+
79
+ expect(Airbrake::RemoteSettings).to have_received(:poll)
80
+ end
81
+ end
82
+
83
+ context "when the config disables the remote_config option" do
84
+ let(:config) { Airbrake::Config.new(project_id: 123, remote_config: false) }
85
+
86
+ it "doesn't set remote settings" do
87
+ described_class.new(config).process_remote_configuration
88
+
89
+ expect(Airbrake::RemoteSettings).not_to have_received(:poll)
73
90
  end
74
91
  end
75
92
  end
@@ -175,9 +175,12 @@ RSpec.describe Airbrake::Config::Validator do
175
175
  end
176
176
 
177
177
  it "warns about 'no effect'" do
178
- expect(config.logger).to receive(:warn)
179
- .with(/'ignore_environments' has no effect/)
178
+ allow(config.logger).to receive(:warn)
179
+
180
180
  described_class.check_notify_ability(config)
181
+
182
+ expect(config.logger).to have_received(:warn)
183
+ .with(/'ignore_environments' has no effect/)
181
184
  end
182
185
  end
183
186
 
data/spec/config_spec.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  RSpec.describe Airbrake::Config do
2
+ subject(:config) { described_class.new }
3
+
2
4
  let(:resolved_promise) { Airbrake::Promise.new.resolve }
3
5
  let(:rejected_promise) { Airbrake::Promise.new.reject }
4
6
 
@@ -26,26 +28,31 @@ RSpec.describe Airbrake::Config do
26
28
  its(:query_stats) { is_expected.to eq(true) }
27
29
  its(:job_stats) { is_expected.to eq(true) }
28
30
  its(:error_notifications) { is_expected.to eq(true) }
31
+ its(:remote_config) { is_expected.to eq(true) }
29
32
 
30
33
  its(:remote_config_host) do
31
- is_expected.to eq('https://v1-production-notifier-configs.s3.amazonaws.com')
34
+ is_expected.to eq('https://notifier-configs.airbrake.io')
32
35
  end
33
36
 
34
37
  describe "#new" do
35
38
  context "when user config is passed" do
36
39
  subject { described_class.new(logger: StringIO.new) }
40
+
37
41
  its(:logger) { is_expected.to be_a(StringIO) }
38
42
  end
39
43
  end
40
44
 
41
45
  describe "#valid?" do
42
- context "when #validate returns a resolved promise" do
43
- before { expect(subject).to receive(:validate).and_return(resolved_promise) }
46
+ context "when the config is valid" do
47
+ before do
48
+ config.project_id = 123
49
+ config.project_key = 'abc'
50
+ end
51
+
44
52
  it { is_expected.to be_valid }
45
53
  end
46
54
 
47
- context "when #validate returns a rejected promise" do
48
- before { expect(subject).to receive(:validate).and_return(rejected_promise) }
55
+ context "when the config is invalid" do
49
56
  it { is_expected.not_to be_valid }
50
57
  end
51
58
  end
@@ -53,7 +60,7 @@ RSpec.describe Airbrake::Config do
53
60
  describe "#ignored_environment?" do
54
61
  context "when Validator returns a resolved promise" do
55
62
  before do
56
- expect(Airbrake::Config::Validator).to receive(:check_notify_ability)
63
+ allow(Airbrake::Config::Validator).to receive(:check_notify_ability)
57
64
  .and_return(resolved_promise)
58
65
  end
59
66
 
@@ -62,7 +69,7 @@ RSpec.describe Airbrake::Config do
62
69
 
63
70
  context "when Validator returns a rejected promise" do
64
71
  before do
65
- expect(Airbrake::Config::Validator).to receive(:check_notify_ability)
72
+ allow(Airbrake::Config::Validator).to receive(:check_notify_ability)
66
73
  .and_return(rejected_promise)
67
74
  end
68
75
 
@@ -95,19 +102,21 @@ RSpec.describe Airbrake::Config do
95
102
  end
96
103
 
97
104
  describe "#check_configuration" do
98
- let(:user_config) { {} }
99
-
100
105
  subject { described_class.new(valid_params.merge(user_config)) }
101
106
 
107
+ let(:user_config) { {} }
108
+
102
109
  its(:check_configuration) { is_expected.to be_an(Airbrake::Promise) }
103
110
 
104
111
  context "when config is invalid" do
105
112
  let(:user_config) { { project_id: nil } }
113
+
106
114
  its(:check_configuration) { is_expected.to be_rejected }
107
115
  end
108
116
 
109
117
  context "when current environment is ignored" do
110
118
  let(:user_config) { { environment: 'test', ignore_environments: ['test'] } }
119
+
111
120
  its(:check_configuration) { is_expected.to be_rejected }
112
121
  end
113
122
 
@@ -119,12 +128,12 @@ RSpec.describe Airbrake::Config do
119
128
  describe "#check_performance_options" do
120
129
  it "returns a promise" do
121
130
  resource = Airbrake::Query.new(method: '', route: '', query: '', timing: 1)
122
- expect(subject.check_performance_options(resource))
131
+ expect(config.check_performance_options(resource))
123
132
  .to be_an(Airbrake::Promise)
124
133
  end
125
134
 
126
135
  context "when performance stats are disabled" do
127
- before { subject.performance_stats = false }
136
+ before { config.performance_stats = false }
128
137
 
129
138
  let(:resource) do
130
139
  Airbrake::Request.new(
@@ -133,7 +142,7 @@ RSpec.describe Airbrake::Config do
133
142
  end
134
143
 
135
144
  it "returns a rejected promise" do
136
- promise = subject.check_performance_options(resource)
145
+ promise = config.check_performance_options(resource)
137
146
  expect(promise.value).to eq(
138
147
  'error' => "The Performance Stats feature is disabled",
139
148
  )
@@ -141,14 +150,14 @@ RSpec.describe Airbrake::Config do
141
150
  end
142
151
 
143
152
  context "when query stats are disabled" do
144
- before { subject.query_stats = false }
153
+ before { config.query_stats = false }
145
154
 
146
155
  let(:resource) do
147
156
  Airbrake::Query.new(method: 'GET', route: '/foo', query: '', timing: 1)
148
157
  end
149
158
 
150
159
  it "returns a rejected promise" do
151
- promise = subject.check_performance_options(resource)
160
+ promise = config.check_performance_options(resource)
152
161
  expect(promise.value).to eq(
153
162
  'error' => "The Query Stats feature is disabled",
154
163
  )
@@ -156,14 +165,14 @@ RSpec.describe Airbrake::Config do
156
165
  end
157
166
 
158
167
  context "when job stats are disabled" do
159
- before { subject.job_stats = false }
168
+ before { config.job_stats = false }
160
169
 
161
170
  let(:resource) do
162
171
  Airbrake::Queue.new(queue: 'foo_queue', error_count: 0, timing: 1)
163
172
  end
164
173
 
165
174
  it "returns a rejected promise" do
166
- promise = subject.check_performance_options(resource)
175
+ promise = config.check_performance_options(resource)
167
176
  expect(promise.value).to eq(
168
177
  'error' => "The Job Stats feature is disabled",
169
178
  )
@@ -173,7 +182,7 @@ RSpec.describe Airbrake::Config do
173
182
 
174
183
  describe "#logger" do
175
184
  it "sets logger level to Logger::WARN" do
176
- expect(subject.logger.level).to eq(Logger::WARN)
185
+ expect(config.logger.level).to eq(Logger::WARN)
177
186
  end
178
187
  end
179
188
  end
@@ -0,0 +1,54 @@
1
+ RSpec.describe Airbrake::Context do
2
+ subject(:context) { described_class.current }
3
+
4
+ before { described_class.current.clear }
5
+
6
+ after { described_class.current.clear }
7
+
8
+ describe "#merge!" do
9
+ it "merges the given context with the current one" do
10
+ context.merge!(apples: 'oranges')
11
+ expect(context.to_h).to match(apples: 'oranges')
12
+ end
13
+ end
14
+
15
+ describe "#clear" do
16
+ it "clears the context" do
17
+ context.merge!(apples: 'oranges')
18
+ context.clear
19
+ expect(context.to_h).to be_empty
20
+ end
21
+ end
22
+
23
+ describe "#to_h" do
24
+ it "returns a hash representation of the context" do
25
+ expect(context.to_h).to be_a(Hash)
26
+ end
27
+ end
28
+
29
+ describe "#empty?" do
30
+ context "when the context has data" do
31
+ it "returns true" do
32
+ context.merge!(apples: 'oranges')
33
+ expect(context).not_to be_empty
34
+ end
35
+ end
36
+
37
+ context "when the context has NO data" do
38
+ it "returns false" do
39
+ expect(context).to be_empty
40
+ end
41
+ end
42
+ end
43
+
44
+ context "when another thread is spawned" do
45
+ it "doesn't clash with other threads' contexts" do
46
+ described_class.current.merge!(apples: 'oranges')
47
+ th = Thread.new do
48
+ described_class.current.merge!(foos: 'bars')
49
+ end
50
+ th.join
51
+ expect(described_class.current.to_h).to match(apples: 'oranges')
52
+ end
53
+ end
54
+ end
@@ -4,17 +4,19 @@ RSpec.describe Airbrake::DeployNotifier do
4
4
  end
5
5
 
6
6
  describe "#notify" do
7
+ subject(:deploy_notifier) { described_class.new }
8
+
7
9
  it "returns a promise" do
8
10
  stub_request(:post, 'https://api.airbrake.io/api/v4/projects/1/deploys')
9
11
  .to_return(status: 201, body: '{}')
10
- expect(subject.notify({})).to be_an(Airbrake::Promise)
12
+ expect(deploy_notifier.notify({})).to be_an(Airbrake::Promise)
11
13
  end
12
14
 
13
15
  context "when config is invalid" do
14
16
  before { Airbrake::Config.instance.merge(project_id: nil) }
15
17
 
16
18
  it "returns a rejected promise" do
17
- promise = subject.notify({})
19
+ promise = deploy_notifier.notify({})
18
20
  expect(promise).to be_rejected
19
21
  end
20
22
  end
@@ -28,7 +30,7 @@ RSpec.describe Airbrake::DeployNotifier do
28
30
  instance_of(Airbrake::Promise),
29
31
  URI('https://api.airbrake.io/api/v4/projects/1/deploys'),
30
32
  )
31
- subject.notify(environment: 'barenv')
33
+ deploy_notifier.notify(environment: 'barenv')
32
34
  end
33
35
  end
34
36
 
@@ -41,7 +43,7 @@ RSpec.describe Airbrake::DeployNotifier do
41
43
  instance_of(Airbrake::Promise),
42
44
  URI('https://api.airbrake.io/api/v4/projects/1/deploys'),
43
45
  )
44
- subject.notify({})
46
+ deploy_notifier.notify({})
45
47
  end
46
48
  end
47
49
  end
@@ -1,5 +1,6 @@
1
1
  RSpec.describe Airbrake::FileCache do
2
2
  before { described_class.reset }
3
+
3
4
  after { described_class.reset }
4
5
 
5
6
  describe ".[]=" do
@@ -1,4 +1,6 @@
1
1
  RSpec.describe Airbrake::FilterChain do
2
+ subject(:filter_chain) { described_class.new }
3
+
2
4
  let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
3
5
 
4
6
  describe "#refine" do
@@ -19,24 +21,27 @@ RSpec.describe Airbrake::FilterChain do
19
21
  it "executes filters from heaviest to lightest" do
20
22
  notice[:params][:bingo] = []
21
23
 
22
- (0...3).reverse_each { |i| subject.add_filter(filter.new(i)) }
23
- subject.refine(notice)
24
+ (0...3).reverse_each { |i| filter_chain.add_filter(filter.new(i)) }
25
+ filter_chain.refine(notice)
24
26
 
25
27
  expect(notice[:params][:bingo]).to eq([2, 1, 0])
26
28
  end
27
29
 
28
30
  it "stops execution once a notice was ignored" do
29
31
  f2 = filter.new(2)
30
- expect(f2).to receive(:call)
32
+ allow(f2).to receive(:call)
31
33
 
32
34
  f1 = proc { |notice| notice.ignore! }
33
35
 
34
36
  f0 = filter.new(-1)
35
- expect(f0).not_to receive(:call)
37
+ allow(f0).to receive(:call)
38
+
39
+ [f2, f1, f0].each { |f| filter_chain.add_filter(f) }
36
40
 
37
- [f2, f1, f0].each { |f| subject.add_filter(f) }
41
+ filter_chain.refine(notice)
38
42
 
39
- subject.refine(notice)
43
+ expect(f2).to have_received(:call)
44
+ expect(f0).not_to have_received(:call)
40
45
  end
41
46
  end
42
47
 
@@ -63,56 +68,56 @@ RSpec.describe Airbrake::FilterChain do
63
68
  notice[:params][:foo] = []
64
69
 
65
70
  f1 = filter.new(1)
66
- subject.add_filter(f1)
71
+ filter_chain.add_filter(f1)
67
72
 
68
73
  foo_filter_mock = double
69
- expect(foo_filter_mock).to(
70
- receive(:name).at_least(:once).and_return('FooFilter'),
71
- )
72
- subject.delete_filter(foo_filter_mock)
74
+ allow(foo_filter_mock).to receive(:name).at_least(:once).and_return('FooFilter')
75
+ filter_chain.delete_filter(foo_filter_mock)
76
+
77
+ expect(foo_filter_mock).to have_received(:name)
73
78
 
74
79
  f2 = filter.new(2)
75
- subject.add_filter(f2)
80
+ filter_chain.add_filter(f2)
76
81
 
77
- subject.refine(notice)
82
+ filter_chain.refine(notice)
78
83
  expect(notice[:params][:foo]).to eq([2])
79
84
  end
80
85
  end
81
86
 
82
87
  describe "#inspect" do
83
88
  it "returns a string representation of an empty FilterChain" do
84
- expect(subject.inspect).to eq('[]')
89
+ expect(filter_chain.inspect).to eq('[]')
85
90
  end
86
91
 
87
92
  it "returns a string representation of a non-empty FilterChain" do
88
- subject.add_filter(proc {})
89
- expect(subject.inspect).to eq('[Proc]')
93
+ filter_chain.add_filter(proc {})
94
+ expect(filter_chain.inspect).to eq('[Proc]')
90
95
  end
91
96
  end
92
97
 
93
98
  describe "#includes?" do
94
99
  context "when a custom filter class is included in the filter chain" do
95
100
  it "returns true" do
96
- klass = Class.new {}
101
+ klass = Class.new
97
102
 
98
- subject.add_filter(klass.new)
99
- expect(subject.includes?(klass)).to eq(true)
103
+ filter_chain.add_filter(klass.new)
104
+ expect(filter_chain.includes?(klass)).to eq(true)
100
105
  end
101
106
  end
102
107
 
103
108
  context "when Proc filter class is included in the filter chain" do
104
109
  it "returns true" do
105
- subject.add_filter(proc {})
106
- expect(subject.includes?(Proc)).to eq(true)
110
+ filter_chain.add_filter(proc {})
111
+ expect(filter_chain.includes?(Proc)).to eq(true)
107
112
  end
108
113
  end
109
114
 
110
115
  context "when filter class is NOT included in the filter chain" do
111
116
  it "returns false" do
112
- klass = Class.new {}
117
+ klass = Class.new
113
118
 
114
- subject.add_filter(proc {})
115
- expect(subject.includes?(klass)).to eq(false)
119
+ filter_chain.add_filter(proc {})
120
+ expect(filter_chain.includes?(klass)).to eq(false)
116
121
  end
117
122
  end
118
123
  end
@@ -3,21 +3,30 @@ RSpec.describe Airbrake::Filters::ContextFilter do
3
3
 
4
4
  context "when the current context is empty" do
5
5
  it "doesn't merge anything with params" do
6
- described_class.new({}).call(notice)
6
+ described_class.new.call(notice)
7
7
  expect(notice[:params]).to be_empty
8
8
  end
9
9
  end
10
10
 
11
11
  context "when the current context has some data" do
12
12
  it "merges the data with params" do
13
- described_class.new(apples: 'oranges').call(notice)
13
+ Airbrake.merge_context(apples: 'oranges')
14
+ described_class.new.call(notice)
14
15
  expect(notice[:params]).to eq(airbrake_context: { apples: 'oranges' })
15
16
  end
16
17
 
17
- it "clears the data from the provided context" do
18
+ it "clears the data from the current context" do
18
19
  context = { apples: 'oranges' }
19
- described_class.new(context).call(notice)
20
- expect(context).to be_empty
20
+ Airbrake.merge_context(context)
21
+ described_class.new.call(notice)
22
+ expect(Airbrake::Context.current).to be_empty
23
+ end
24
+
25
+ it "does not mutate the provided context object" do
26
+ context = { apples: 'oranges' }
27
+ Airbrake.merge_context(context)
28
+ described_class.new.call(notice)
29
+ expect(context).to match(apples: 'oranges')
21
30
  end
22
31
  end
23
32
  end
@@ -1,9 +1,11 @@
1
1
  RSpec.describe Airbrake::Filters::DependencyFilter do
2
+ subject(:dependency_filter) { described_class.new }
3
+
2
4
  let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
3
5
 
4
6
  describe "#call" do
5
7
  it "attaches loaded dependencies to context/versions/dependencies" do
6
- subject.call(notice)
8
+ dependency_filter.call(notice)
7
9
  expect(notice[:context][:versions][:dependencies]).to include(
8
10
  'airbrake-ruby' => Airbrake::AIRBRAKE_RUBY_VERSION,
9
11
  )
@@ -1,4 +1,6 @@
1
1
  RSpec.describe Airbrake::Filters::ExceptionAttributesFilter do
2
+ subject(:exception_attributes_filter) { described_class.new }
3
+
2
4
  describe "#call" do
3
5
  let(:notice) { Airbrake::Notice.new(ex) }
4
6
 
@@ -12,7 +14,7 @@ RSpec.describe Airbrake::Filters::ExceptionAttributesFilter do
12
14
  end
13
15
 
14
16
  it "doesn't raise" do
15
- expect { subject.call(notice) }.not_to raise_error
17
+ expect { exception_attributes_filter.call(notice) }.not_to raise_error
16
18
  expect(notice[:params]).to be_empty
17
19
  end
18
20
  end
@@ -27,7 +29,7 @@ RSpec.describe Airbrake::Filters::ExceptionAttributesFilter do
27
29
  end
28
30
 
29
31
  it "doesn't raise" do
30
- expect { subject.call(notice) }.not_to raise_error
32
+ expect { exception_attributes_filter.call(notice) }.not_to raise_error
31
33
  expect(notice[:params]).to be_empty
32
34
  end
33
35
  end
@@ -42,7 +44,7 @@ RSpec.describe Airbrake::Filters::ExceptionAttributesFilter do
42
44
  end
43
45
 
44
46
  it "merges parameters with the notice" do
45
- subject.call(notice)
47
+ exception_attributes_filter.call(notice)
46
48
  expect(notice[:params]).to eq(foo: '1')
47
49
  end
48
50
  end
@@ -1,9 +1,12 @@
1
1
  RSpec.describe Airbrake::Filters::GemRootFilter do
2
+ subject(:gem_root_filter) { described_class.new }
3
+
2
4
  let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
3
5
  let(:root1) { '/my/gem/root' }
4
6
  let(:root2) { '/my/other/gem/root' }
5
7
 
6
8
  before { Gem.path << root1 << root2 }
9
+
7
10
  after { 2.times { Gem.path.pop } }
8
11
 
9
12
  it "replaces gem root in the backtrace with a label" do
@@ -16,7 +19,7 @@ RSpec.describe Airbrake::Filters::GemRootFilter do
16
19
  ]
17
20
  # rubocop:enable Layout/LineLength
18
21
 
19
- subject.call(notice)
22
+ gem_root_filter.call(notice)
20
23
 
21
24
  # rubocop:disable Layout/LineLength
22
25
  expect(notice[:errors].first[:backtrace]).to(
@@ -34,7 +37,7 @@ RSpec.describe Airbrake::Filters::GemRootFilter do
34
37
 
35
38
  it "does not filter file when it is nil" do
36
39
  expect(notice[:errors].first[:file]).to be_nil
37
- expect { subject.call(notice) }.not_to(
40
+ expect { gem_root_filter.call(notice) }.not_to(
38
41
  change { notice[:errors].first[:file] },
39
42
  )
40
43
  end