airbrake-ruby 4.15.0-java → 5.0.2-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.
- checksums.yaml +4 -4
- data/lib/airbrake-ruby.rb +22 -33
- data/lib/airbrake-ruby/async_sender.rb +1 -1
- data/lib/airbrake-ruby/backtrace.rb +6 -5
- data/lib/airbrake-ruby/config.rb +30 -30
- data/lib/airbrake-ruby/config/processor.rb +69 -0
- data/lib/airbrake-ruby/config/validator.rb +6 -0
- data/lib/airbrake-ruby/file_cache.rb +1 -1
- data/lib/airbrake-ruby/filter_chain.rb +1 -0
- data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +1 -2
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +3 -0
- data/lib/airbrake-ruby/filters/git_revision_filter.rb +2 -0
- data/lib/airbrake-ruby/filters/keys_filter.rb +21 -13
- data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/sql_filter.rb +4 -4
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +2 -0
- data/lib/airbrake-ruby/ignorable.rb +1 -0
- data/lib/airbrake-ruby/notice.rb +1 -8
- data/lib/airbrake-ruby/notice_notifier.rb +1 -0
- data/lib/airbrake-ruby/performance_breakdown.rb +1 -6
- data/lib/airbrake-ruby/performance_notifier.rb +2 -15
- data/lib/airbrake-ruby/promise.rb +1 -0
- data/lib/airbrake-ruby/query.rb +1 -6
- data/lib/airbrake-ruby/queue.rb +1 -8
- data/lib/airbrake-ruby/remote_settings.rb +145 -0
- data/lib/airbrake-ruby/remote_settings/callback.rb +44 -0
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
- data/lib/airbrake-ruby/request.rb +1 -8
- data/lib/airbrake-ruby/stat.rb +1 -12
- data/lib/airbrake-ruby/sync_sender.rb +3 -2
- data/lib/airbrake-ruby/tdigest.rb +2 -0
- data/lib/airbrake-ruby/thread_pool.rb +1 -0
- data/lib/airbrake-ruby/truncator.rb +8 -2
- data/lib/airbrake-ruby/version.rb +11 -1
- data/spec/airbrake_spec.rb +45 -22
- data/spec/backtrace_spec.rb +26 -26
- data/spec/code_hunk_spec.rb +2 -2
- data/spec/config/processor_spec.rb +125 -0
- data/spec/config/validator_spec.rb +18 -1
- data/spec/config_spec.rb +11 -32
- data/spec/filters/gem_root_filter_spec.rb +4 -4
- data/spec/filters/keys_allowlist_spec.rb +1 -0
- data/spec/filters/keys_blocklist_spec.rb +10 -0
- data/spec/filters/root_directory_filter_spec.rb +4 -4
- data/spec/filters/sql_filter_spec.rb +2 -2
- data/spec/notice_notifier/options_spec.rb +2 -2
- data/spec/notice_notifier_spec.rb +2 -2
- data/spec/notice_spec.rb +1 -1
- data/spec/performance_breakdown_spec.rb +0 -12
- data/spec/performance_notifier_spec.rb +0 -25
- data/spec/query_spec.rb +1 -11
- data/spec/queue_spec.rb +1 -13
- data/spec/remote_settings/callback_spec.rb +141 -0
- data/spec/remote_settings/settings_data_spec.rb +348 -0
- data/spec/remote_settings_spec.rb +230 -0
- data/spec/request_spec.rb +1 -13
- data/spec/spec_helper.rb +4 -4
- data/spec/stat_spec.rb +0 -9
- data/spec/sync_sender_spec.rb +3 -1
- metadata +18 -6
@@ -151,6 +151,7 @@ RSpec.describe Airbrake::Filters::KeysAllowlist do
|
|
151
151
|
# thing. One is a Java exception, the other is a Ruby exception.
|
152
152
|
# Likely a bug: https://github.com/jruby/jruby/issues/1903
|
153
153
|
raise ex unless RUBY_ENGINE == 'jruby'
|
154
|
+
|
154
155
|
expect { subject.call(notice) }.to raise_error(java.lang.StackOverflowError)
|
155
156
|
end
|
156
157
|
end
|
@@ -150,6 +150,16 @@ RSpec.describe Airbrake::Filters::KeysBlocklist do
|
|
150
150
|
{ bongo: { bish: '[Filtered]' } },
|
151
151
|
],
|
152
152
|
)
|
153
|
+
|
154
|
+
it "doesn't mutate the original hash" do
|
155
|
+
params = { bongo: { bish: 'bash' } }
|
156
|
+
notice[:params] = params
|
157
|
+
|
158
|
+
blocklist = described_class.new([:bish])
|
159
|
+
blocklist.call(notice)
|
160
|
+
|
161
|
+
expect(params[:bongo][:bish]).to eq('bash')
|
162
|
+
end
|
153
163
|
end
|
154
164
|
|
155
165
|
context "and it is recursive" do
|
@@ -5,18 +5,18 @@ RSpec.describe Airbrake::Filters::RootDirectoryFilter do
|
|
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
|
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
|
15
|
+
# rubocop:enable Layout/LineLength
|
16
16
|
|
17
17
|
subject.call(notice)
|
18
18
|
|
19
|
-
# rubocop:disable
|
19
|
+
# rubocop:disable Layout/LineLength
|
20
20
|
expect(notice[:errors].first[:backtrace]).to(
|
21
21
|
eq(
|
22
22
|
[
|
@@ -27,7 +27,7 @@ RSpec.describe Airbrake::Filters::RootDirectoryFilter do
|
|
27
27
|
],
|
28
28
|
),
|
29
29
|
)
|
30
|
-
# rubocop:enable
|
30
|
+
# rubocop:enable Layout/LineLength
|
31
31
|
end
|
32
32
|
|
33
33
|
it "does not filter file when it is nil" do
|
@@ -22,7 +22,7 @@ RSpec.describe Airbrake::Filters::SqlFilter do
|
|
22
22
|
|
23
23
|
ALL_DIALECTS = %i[mysql postgres sqlite cassandra oracle].freeze
|
24
24
|
|
25
|
-
# rubocop:disable
|
25
|
+
# rubocop:disable Layout/LineLength
|
26
26
|
[
|
27
27
|
{
|
28
28
|
input: 'SELECT * FROM things;',
|
@@ -229,7 +229,7 @@ RSpec.describe Airbrake::Filters::SqlFilter do
|
|
229
229
|
].each do |test|
|
230
230
|
include_examples 'query filtering', test
|
231
231
|
end
|
232
|
-
# rubocop:enable
|
232
|
+
# rubocop:enable Layout/LineLength
|
233
233
|
|
234
234
|
[
|
235
235
|
'COMMIT',
|
@@ -149,10 +149,10 @@ RSpec.describe Airbrake::NoticeNotifier do
|
|
149
149
|
expect(proxied_request.header['proxy-authorization'].first)
|
150
150
|
.to eq('Basic dXNlcjpwYXNzd29yZA==')
|
151
151
|
|
152
|
-
# rubocop:disable
|
152
|
+
# rubocop:disable Layout/LineLength
|
153
153
|
expect(proxied_request.request_line)
|
154
154
|
.to eq("POST http://localhost:#{proxy.config[:Port]}/api/v3/projects/105138/notices HTTP/1.1\r\n")
|
155
|
-
# rubocop:enable
|
155
|
+
# rubocop:enable Layout/LineLength
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
@@ -309,7 +309,7 @@ RSpec.describe Airbrake::NoticeNotifier do
|
|
309
309
|
|
310
310
|
notice = subject.build_notice(Exception.new)
|
311
311
|
|
312
|
-
# rubocop:disable
|
312
|
+
# rubocop:disable Layout/LineLength
|
313
313
|
expect(notice[:errors].first[:backtrace]).to eq(
|
314
314
|
[
|
315
315
|
{ file: 'org/jruby/RubyKernel.java', line: 998, function: 'eval' },
|
@@ -317,7 +317,7 @@ RSpec.describe Airbrake::NoticeNotifier do
|
|
317
317
|
{ file: '/ruby/stdlib/irb.rb:489', line: 489, function: 'block in eval_input' },
|
318
318
|
],
|
319
319
|
)
|
320
|
-
# rubocop:enable
|
320
|
+
# rubocop:enable Layout/LineLength
|
321
321
|
end
|
322
322
|
end
|
323
323
|
|
data/spec/notice_spec.rb
CHANGED
@@ -268,7 +268,7 @@ RSpec.describe Airbrake::Notice do
|
|
268
268
|
it "sets a payload value" do
|
269
269
|
hash = { bingo: 'bango' }
|
270
270
|
notice[:params] = hash
|
271
|
-
expect(notice[:params]).to
|
271
|
+
expect(notice[:params]).to eq(hash)
|
272
272
|
end
|
273
273
|
|
274
274
|
it "raises error if notice is ignored" do
|
@@ -3,21 +3,9 @@ RSpec.describe Airbrake::PerformanceBreakdown do
|
|
3
3
|
subject do
|
4
4
|
described_class.new(
|
5
5
|
method: 'GET', route: '/', response_type: '', groups: {},
|
6
|
-
start_time: Time.now
|
7
6
|
)
|
8
7
|
end
|
9
8
|
|
10
9
|
it { is_expected.to respond_to(:stash) }
|
11
10
|
end
|
12
|
-
|
13
|
-
describe "#end_time" do
|
14
|
-
it "is always equal to start_time + 1 second by default" do
|
15
|
-
time = Time.now
|
16
|
-
performance_breakdown = described_class.new(
|
17
|
-
method: 'GET', route: '/', response_type: '', groups: {},
|
18
|
-
start_time: time
|
19
|
-
)
|
20
|
-
expect(performance_breakdown.end_time).to eq(time + 1)
|
21
|
-
end
|
22
|
-
end
|
23
11
|
end
|
@@ -541,31 +541,6 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
541
541
|
end
|
542
542
|
end
|
543
543
|
|
544
|
-
context "when :start_time is specified (deprecated)" do
|
545
|
-
before do
|
546
|
-
allow(Kernel).to receive(:warn)
|
547
|
-
end
|
548
|
-
|
549
|
-
it "uses the value of :start_time to update stat" do
|
550
|
-
subject.notify(
|
551
|
-
Airbrake::Query.new(
|
552
|
-
method: 'POST',
|
553
|
-
route: '/foo',
|
554
|
-
query: 'SELECT * FROM things',
|
555
|
-
start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
|
556
|
-
end_time: Time.new(2018, 1, 1, 0, 50, 0, 0),
|
557
|
-
),
|
558
|
-
)
|
559
|
-
subject.close
|
560
|
-
|
561
|
-
expect(
|
562
|
-
a_request(:put, queries).with(
|
563
|
-
body: /"count":1,"sum":60000.0,"sumsq":3600000000.0/,
|
564
|
-
),
|
565
|
-
).to have_been_made
|
566
|
-
end
|
567
|
-
end
|
568
|
-
|
569
544
|
context "when provided :timing is zero" do
|
570
545
|
it "doesn't notify" do
|
571
546
|
queue = Airbrake::Queue.new(queue: 'bananas', error_count: 0, timing: 0)
|
data/spec/query_spec.rb
CHANGED
@@ -2,20 +2,10 @@ RSpec.describe Airbrake::Query do
|
|
2
2
|
describe "#stash" do
|
3
3
|
subject do
|
4
4
|
described_class.new(
|
5
|
-
method: 'GET', route: '/', query: '',
|
5
|
+
method: 'GET', route: '/', query: '',
|
6
6
|
)
|
7
7
|
end
|
8
8
|
|
9
9
|
it { is_expected.to respond_to(:stash) }
|
10
10
|
end
|
11
|
-
|
12
|
-
describe "#end_time" do
|
13
|
-
it "is always equal to start_time + 1 second by default" do
|
14
|
-
time = Time.now
|
15
|
-
query = described_class.new(
|
16
|
-
method: 'GET', route: '/', query: '', start_time: time,
|
17
|
-
)
|
18
|
-
expect(query.end_time).to eq(time + 1)
|
19
|
-
end
|
20
|
-
end
|
21
11
|
end
|
data/spec/queue_spec.rb
CHANGED
@@ -9,21 +9,9 @@ RSpec.describe Airbrake::Queue do
|
|
9
9
|
it { is_expected.to respond_to(:stash) }
|
10
10
|
end
|
11
11
|
|
12
|
-
describe "#end_time" do
|
13
|
-
it "is always equal to start_time + 1 second by default" do
|
14
|
-
time = Time.now
|
15
|
-
queue = described_class.new(
|
16
|
-
queue: 'bananas', error_count: 0, start_time: time,
|
17
|
-
)
|
18
|
-
expect(queue.end_time).to eq(time + 1)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
12
|
describe "#route" do
|
23
13
|
it "always returns an empty route" do
|
24
|
-
queue = described_class.new(
|
25
|
-
queue: 'a', error_count: 0, start_time: Time.now,
|
26
|
-
)
|
14
|
+
queue = described_class.new(queue: 'a', error_count: 0)
|
27
15
|
expect(queue.route).to be_empty
|
28
16
|
end
|
29
17
|
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
RSpec.describe Airbrake::RemoteSettings::Callback do
|
2
|
+
describe "#call" do
|
3
|
+
let(:logger) { Logger.new(File::NULL) }
|
4
|
+
|
5
|
+
let(:config) do
|
6
|
+
Airbrake::Config.new(
|
7
|
+
project_id: 123,
|
8
|
+
logger: logger,
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:data) do
|
13
|
+
instance_double(Airbrake::RemoteSettings::SettingsData)
|
14
|
+
end
|
15
|
+
|
16
|
+
before do
|
17
|
+
allow(data).to receive(:to_h)
|
18
|
+
allow(data).to receive(:error_host)
|
19
|
+
allow(data).to receive(:apm_host)
|
20
|
+
allow(data).to receive(:error_notifications?)
|
21
|
+
allow(data).to receive(:performance_stats?)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "logs given data" do
|
25
|
+
expect(logger).to receive(:debug).with(/applying remote settings/)
|
26
|
+
described_class.new(config).call(data)
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when the config disables error notifications" do
|
30
|
+
before do
|
31
|
+
config.error_notifications = false
|
32
|
+
allow(data).to receive(:error_notifications?).and_return(true)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "keeps the option disabled forever" do
|
36
|
+
callback = described_class.new(config)
|
37
|
+
|
38
|
+
callback.call(data)
|
39
|
+
expect(config.error_notifications).to eq(false)
|
40
|
+
|
41
|
+
callback.call(data)
|
42
|
+
expect(config.error_notifications).to eq(false)
|
43
|
+
|
44
|
+
callback.call(data)
|
45
|
+
expect(config.error_notifications).to eq(false)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when the config enables error notifications" do
|
50
|
+
before { config.error_notifications = true }
|
51
|
+
|
52
|
+
it "can disable and enable error notifications" do
|
53
|
+
expect(data).to receive(:error_notifications?).and_return(false)
|
54
|
+
|
55
|
+
callback = described_class.new(config)
|
56
|
+
callback.call(data)
|
57
|
+
expect(config.error_notifications).to eq(false)
|
58
|
+
|
59
|
+
expect(data).to receive(:error_notifications?).and_return(true)
|
60
|
+
callback.call(data)
|
61
|
+
expect(config.error_notifications).to eq(true)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when the config disables performance_stats" do
|
66
|
+
before do
|
67
|
+
config.performance_stats = false
|
68
|
+
allow(data).to receive(:performance_stats?).and_return(true)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "keeps the option disabled forever" do
|
72
|
+
callback = described_class.new(config)
|
73
|
+
|
74
|
+
callback.call(data)
|
75
|
+
expect(config.performance_stats).to eq(false)
|
76
|
+
|
77
|
+
callback.call(data)
|
78
|
+
expect(config.performance_stats).to eq(false)
|
79
|
+
|
80
|
+
callback.call(data)
|
81
|
+
expect(config.performance_stats).to eq(false)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when the config enables performance stats" do
|
86
|
+
before { config.performance_stats = true }
|
87
|
+
|
88
|
+
it "can disable and enable performance_stats" do
|
89
|
+
expect(data).to receive(:performance_stats?).and_return(false)
|
90
|
+
|
91
|
+
callback = described_class.new(config)
|
92
|
+
callback.call(data)
|
93
|
+
expect(config.performance_stats).to eq(false)
|
94
|
+
|
95
|
+
expect(data).to receive(:performance_stats?).and_return(true)
|
96
|
+
callback.call(data)
|
97
|
+
expect(config.performance_stats).to eq(true)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "when error_host returns a value" do
|
102
|
+
it "sets the error_host option" do
|
103
|
+
config.error_host = 'http://api.airbrake.io'
|
104
|
+
allow(data).to receive(:error_host).and_return('https://api.example.com')
|
105
|
+
|
106
|
+
described_class.new(config).call(data)
|
107
|
+
expect(config.error_host).to eq('https://api.example.com')
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context "when error_host returns nil" do
|
112
|
+
it "doesn't modify the error_host option" do
|
113
|
+
config.error_host = 'http://api.airbrake.io'
|
114
|
+
allow(data).to receive(:error_host).and_return(nil)
|
115
|
+
|
116
|
+
described_class.new(config).call(data)
|
117
|
+
expect(config.error_host).to eq('http://api.airbrake.io')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when apm_host returns a value" do
|
122
|
+
it "sets the apm_host option" do
|
123
|
+
config.apm_host = 'http://api.airbrake.io'
|
124
|
+
allow(data).to receive(:apm_host).and_return('https://api.example.com')
|
125
|
+
|
126
|
+
described_class.new(config).call(data)
|
127
|
+
expect(config.apm_host).to eq('https://api.example.com')
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "when apm_host returns nil" do
|
132
|
+
it "doesn't modify the apm_host option" do
|
133
|
+
config.apm_host = 'http://api.airbrake.io'
|
134
|
+
allow(data).to receive(:apm_host).and_return(nil)
|
135
|
+
|
136
|
+
described_class.new(config).call(data)
|
137
|
+
expect(config.apm_host).to eq('http://api.airbrake.io')
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,348 @@
|
|
1
|
+
RSpec.describe Airbrake::RemoteSettings::SettingsData do
|
2
|
+
let(:project_id) { 123 }
|
3
|
+
|
4
|
+
describe "#merge!" do
|
5
|
+
it "returns self" do
|
6
|
+
settings_data = described_class.new(project_id, {})
|
7
|
+
expect(settings_data.merge!({})).to eql(settings_data)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "merges the given hash with the data" do
|
11
|
+
settings_data = described_class.new(project_id, {})
|
12
|
+
settings_data.merge!('poll_sec' => 123, 'config_route' => 'abc')
|
13
|
+
|
14
|
+
expect(settings_data.interval).to eq(123)
|
15
|
+
expect(settings_data.config_route(''))
|
16
|
+
.to eq('/abc')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#interval" do
|
21
|
+
context "when given data has zero interval" do
|
22
|
+
let(:data) do
|
23
|
+
{ 'poll_sec' => 0 }
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns the default interval" do
|
27
|
+
expect(described_class.new(project_id, data).interval).to eq(600)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when given data has negative interval" do
|
32
|
+
let(:data) do
|
33
|
+
{ 'poll_sec' => -1 }
|
34
|
+
end
|
35
|
+
|
36
|
+
it "returns the default interval" do
|
37
|
+
expect(described_class.new(project_id, data).interval).to eq(600)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when given data has nil interval" do
|
42
|
+
let(:data) do
|
43
|
+
{ 'poll_sec' => nil }
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns the default interval" do
|
47
|
+
expect(described_class.new(project_id, data).interval).to eq(600)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when given data has a positive interval" do
|
52
|
+
let(:data) do
|
53
|
+
{ 'poll_sec' => 123 }
|
54
|
+
end
|
55
|
+
|
56
|
+
it "returns the interval from data" do
|
57
|
+
expect(described_class.new(project_id, data).interval).to eq(123)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#config_route" do
|
63
|
+
let(:host) { 'http://example.com/' }
|
64
|
+
|
65
|
+
context "when remote config specifies a config route" do
|
66
|
+
let(:data) do
|
67
|
+
{ 'config_route' => '123/cfg/321/cfg.json' }
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns the config route with the provided location" do
|
71
|
+
expect(described_class.new(project_id, data).config_route(host)).to eq(
|
72
|
+
'http://example.com/123/cfg/321/cfg.json',
|
73
|
+
)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "when remote config DOES NOT specify a config route" do
|
78
|
+
it "returns the config route with the default location" do
|
79
|
+
expect(described_class.new(project_id, {}).config_route(host)).to eq(
|
80
|
+
"http://example.com/2020-06-18/config/#{project_id}/config.json",
|
81
|
+
)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when a config route is specified but is set to nil" do
|
86
|
+
let(:data) do
|
87
|
+
{ 'config_route' => nil }
|
88
|
+
end
|
89
|
+
|
90
|
+
it "returns the config route with the default location" do
|
91
|
+
expect(described_class.new(project_id, data).config_route(host)).to eq(
|
92
|
+
"http://example.com/2020-06-18/config/#{project_id}/config.json",
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when a config route is specified but is set to an empty string" do
|
98
|
+
let(:data) do
|
99
|
+
{ 'config_route' => '' }
|
100
|
+
end
|
101
|
+
|
102
|
+
it "returns the route with the default instead" do
|
103
|
+
expect(described_class.new(project_id, data).config_route(host)).to eq(
|
104
|
+
"http://example.com/2020-06-18/config/#{project_id}/config.json",
|
105
|
+
)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#error_notifications?" do
|
111
|
+
context "when the 'errors' setting is present" do
|
112
|
+
context "and when it is enabled" do
|
113
|
+
let(:data) do
|
114
|
+
{
|
115
|
+
'settings' => [
|
116
|
+
{
|
117
|
+
'name' => 'errors',
|
118
|
+
'enabled' => true,
|
119
|
+
},
|
120
|
+
],
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
it "returns true" do
|
125
|
+
expect(described_class.new(project_id, data).error_notifications?)
|
126
|
+
.to eq(true)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "and when it is disabled" do
|
131
|
+
let(:data) do
|
132
|
+
{
|
133
|
+
'settings' => [
|
134
|
+
{
|
135
|
+
'name' => 'errors',
|
136
|
+
'enabled' => false,
|
137
|
+
},
|
138
|
+
],
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
it "returns false" do
|
143
|
+
expect(described_class.new(project_id, data).error_notifications?)
|
144
|
+
.to eq(false)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context "when the 'errors' setting is missing" do
|
150
|
+
let(:data) do
|
151
|
+
{ 'settings' => [] }
|
152
|
+
end
|
153
|
+
|
154
|
+
it "returns true" do
|
155
|
+
expect(described_class.new(project_id, data).error_notifications?)
|
156
|
+
.to eq(true)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "#performance_stats?" do
|
162
|
+
context "when the 'apm' setting is present" do
|
163
|
+
context "and when it is enabled" do
|
164
|
+
let(:data) do
|
165
|
+
{
|
166
|
+
'settings' => [
|
167
|
+
{
|
168
|
+
'name' => 'apm',
|
169
|
+
'enabled' => true,
|
170
|
+
},
|
171
|
+
],
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
175
|
+
it "returns true" do
|
176
|
+
expect(described_class.new(project_id, data).performance_stats?)
|
177
|
+
.to eq(true)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context "and when it is disabled" do
|
182
|
+
let(:data) do
|
183
|
+
{
|
184
|
+
'settings' => [
|
185
|
+
{
|
186
|
+
'name' => 'apm',
|
187
|
+
'enabled' => false,
|
188
|
+
},
|
189
|
+
],
|
190
|
+
}
|
191
|
+
end
|
192
|
+
|
193
|
+
it "returns false" do
|
194
|
+
expect(described_class.new(project_id, data).performance_stats?)
|
195
|
+
.to eq(false)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
context "when the 'apm' setting is missing" do
|
201
|
+
let(:data) do
|
202
|
+
{ 'settings' => [] }
|
203
|
+
end
|
204
|
+
|
205
|
+
it "returns true" do
|
206
|
+
expect(described_class.new(project_id, data).performance_stats?)
|
207
|
+
.to eq(true)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe "#error_host" do
|
213
|
+
context "when the 'errors' setting is present" do
|
214
|
+
context "and when 'endpoint' is specified" do
|
215
|
+
let(:endpoint) { 'https://api.example.com/' }
|
216
|
+
|
217
|
+
let(:data) do
|
218
|
+
{
|
219
|
+
'settings' => [
|
220
|
+
{
|
221
|
+
'name' => 'errors',
|
222
|
+
'enabled' => true,
|
223
|
+
'endpoint' => endpoint,
|
224
|
+
},
|
225
|
+
],
|
226
|
+
}
|
227
|
+
end
|
228
|
+
|
229
|
+
it "returns the endpoint" do
|
230
|
+
expect(described_class.new(project_id, data).error_host).to eq(endpoint)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context "and when an endpoint is NOT specified" do
|
235
|
+
let(:data) do
|
236
|
+
{
|
237
|
+
'settings' => [
|
238
|
+
{
|
239
|
+
'name' => 'errors',
|
240
|
+
'enabled' => true,
|
241
|
+
},
|
242
|
+
],
|
243
|
+
}
|
244
|
+
end
|
245
|
+
|
246
|
+
it "returns nil" do
|
247
|
+
expect(described_class.new(project_id, data).error_host).to be_nil
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
context "when the 'errors' setting is missing" do
|
253
|
+
let(:data) do
|
254
|
+
{ 'settings' => [] }
|
255
|
+
end
|
256
|
+
|
257
|
+
it "returns nil" do
|
258
|
+
expect(described_class.new(project_id, data).error_host).to be_nil
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe "#apm_host" do
|
264
|
+
context "when the 'apm' setting is present" do
|
265
|
+
context "and when 'endpoint' is specified" do
|
266
|
+
let(:endpoint) { 'https://api.example.com/' }
|
267
|
+
|
268
|
+
let(:data) do
|
269
|
+
{
|
270
|
+
'settings' => [
|
271
|
+
{
|
272
|
+
'name' => 'apm',
|
273
|
+
'enabled' => true,
|
274
|
+
'endpoint' => endpoint,
|
275
|
+
},
|
276
|
+
],
|
277
|
+
}
|
278
|
+
end
|
279
|
+
|
280
|
+
it "returns the endpoint" do
|
281
|
+
expect(described_class.new(project_id, data).apm_host).to eq(endpoint)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context "and when an endpoint is NOT specified" do
|
286
|
+
let(:data) do
|
287
|
+
{
|
288
|
+
'settings' => [
|
289
|
+
{
|
290
|
+
'name' => 'apm',
|
291
|
+
'enabled' => true,
|
292
|
+
},
|
293
|
+
],
|
294
|
+
}
|
295
|
+
end
|
296
|
+
|
297
|
+
it "returns nil" do
|
298
|
+
expect(described_class.new(project_id, data).apm_host).to be_nil
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
context "when the 'apm' setting is missing" do
|
304
|
+
let(:data) do
|
305
|
+
{ 'settings' => [] }
|
306
|
+
end
|
307
|
+
|
308
|
+
it "returns nil" do
|
309
|
+
expect(described_class.new(project_id, data).apm_host).to be_nil
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
describe "#to_h" do
|
315
|
+
let(:data) do
|
316
|
+
{
|
317
|
+
'poll_sec' => 123,
|
318
|
+
'settings' => [
|
319
|
+
{
|
320
|
+
'name' => 'apm',
|
321
|
+
'enabled' => false,
|
322
|
+
},
|
323
|
+
],
|
324
|
+
}
|
325
|
+
end
|
326
|
+
|
327
|
+
subject { described_class.new(project_id, data) }
|
328
|
+
|
329
|
+
it "returns a hash representation of settings" do
|
330
|
+
expect(described_class.new(project_id, data).to_h).to eq(data)
|
331
|
+
end
|
332
|
+
|
333
|
+
it "doesn't allow mutation of the original data object" do
|
334
|
+
hash = subject.to_h
|
335
|
+
hash['poll_sec'] = 0
|
336
|
+
|
337
|
+
expect(subject.to_h).to eq(
|
338
|
+
'poll_sec' => 123,
|
339
|
+
'settings' => [
|
340
|
+
{
|
341
|
+
'name' => 'apm',
|
342
|
+
'enabled' => false,
|
343
|
+
},
|
344
|
+
],
|
345
|
+
)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|