airbrake-ruby 4.8.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/airbrake-ruby.rb +132 -57
- data/lib/airbrake-ruby/async_sender.rb +7 -30
- data/lib/airbrake-ruby/backtrace.rb +8 -7
- data/lib/airbrake-ruby/benchmark.rb +1 -1
- data/lib/airbrake-ruby/code_hunk.rb +1 -1
- data/lib/airbrake-ruby/config.rb +59 -15
- data/lib/airbrake-ruby/config/processor.rb +71 -0
- data/lib/airbrake-ruby/config/validator.rb +9 -3
- data/lib/airbrake-ruby/deploy_notifier.rb +1 -1
- data/lib/airbrake-ruby/file_cache.rb +1 -1
- data/lib/airbrake-ruby/filter_chain.rb +16 -1
- data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +2 -2
- data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +5 -5
- 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_whitelist.rb → keys_allowlist.rb} +3 -3
- data/lib/airbrake-ruby/filters/{keys_blacklist.rb → keys_blocklist.rb} +3 -3
- data/lib/airbrake-ruby/filters/keys_filter.rb +39 -20
- data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/sql_filter.rb +7 -7
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +5 -4
- data/lib/airbrake-ruby/grouppable.rb +12 -0
- data/lib/airbrake-ruby/ignorable.rb +1 -0
- data/lib/airbrake-ruby/inspectable.rb +2 -2
- data/lib/airbrake-ruby/loggable.rb +1 -1
- data/lib/airbrake-ruby/mergeable.rb +12 -0
- data/lib/airbrake-ruby/monotonic_time.rb +5 -0
- data/lib/airbrake-ruby/notice.rb +7 -14
- data/lib/airbrake-ruby/notice_notifier.rb +11 -3
- data/lib/airbrake-ruby/performance_breakdown.rb +16 -10
- data/lib/airbrake-ruby/performance_notifier.rb +80 -58
- data/lib/airbrake-ruby/promise.rb +1 -0
- data/lib/airbrake-ruby/query.rb +20 -15
- data/lib/airbrake-ruby/queue.rb +65 -0
- data/lib/airbrake-ruby/remote_settings.rb +105 -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 +14 -12
- data/lib/airbrake-ruby/stat.rb +26 -33
- data/lib/airbrake-ruby/sync_sender.rb +3 -2
- data/lib/airbrake-ruby/tdigest.rb +43 -58
- data/lib/airbrake-ruby/thread_pool.rb +11 -1
- data/lib/airbrake-ruby/truncator.rb +10 -4
- data/lib/airbrake-ruby/version.rb +11 -1
- data/spec/airbrake_spec.rb +206 -71
- data/spec/async_sender_spec.rb +3 -12
- data/spec/backtrace_spec.rb +44 -44
- data/spec/code_hunk_spec.rb +11 -11
- data/spec/config/processor_spec.rb +143 -0
- data/spec/config/validator_spec.rb +23 -6
- data/spec/config_spec.rb +40 -14
- data/spec/deploy_notifier_spec.rb +2 -2
- data/spec/filter_chain_spec.rb +28 -1
- data/spec/filters/dependency_filter_spec.rb +1 -1
- data/spec/filters/gem_root_filter_spec.rb +9 -9
- data/spec/filters/git_last_checkout_filter_spec.rb +21 -4
- data/spec/filters/git_repository_filter.rb +1 -1
- data/spec/filters/git_revision_filter_spec.rb +10 -10
- data/spec/filters/{keys_whitelist_spec.rb → keys_allowlist_spec.rb} +29 -28
- data/spec/filters/{keys_blacklist_spec.rb → keys_blocklist_spec.rb} +39 -29
- data/spec/filters/root_directory_filter_spec.rb +9 -9
- data/spec/filters/sql_filter_spec.rb +58 -60
- data/spec/filters/system_exit_filter_spec.rb +1 -1
- data/spec/filters/thread_filter_spec.rb +32 -30
- data/spec/fixtures/project_root/code.rb +9 -9
- data/spec/loggable_spec.rb +17 -0
- data/spec/monotonic_time_spec.rb +11 -0
- data/spec/notice_notifier/options_spec.rb +17 -17
- data/spec/notice_notifier_spec.rb +20 -20
- data/spec/notice_spec.rb +6 -6
- data/spec/performance_breakdown_spec.rb +0 -1
- data/spec/performance_notifier_spec.rb +220 -73
- data/spec/query_spec.rb +1 -1
- data/spec/queue_spec.rb +18 -0
- data/spec/remote_settings/callback_spec.rb +143 -0
- data/spec/remote_settings/settings_data_spec.rb +348 -0
- data/spec/remote_settings_spec.rb +187 -0
- data/spec/request_spec.rb +1 -3
- data/spec/response_spec.rb +8 -8
- data/spec/spec_helper.rb +6 -6
- data/spec/stat_spec.rb +2 -12
- data/spec/sync_sender_spec.rb +14 -12
- data/spec/tdigest_spec.rb +7 -7
- data/spec/thread_pool_spec.rb +39 -10
- data/spec/timed_trace_spec.rb +1 -1
- data/spec/truncator_spec.rb +12 -12
- metadata +32 -14
data/spec/query_spec.rb
CHANGED
data/spec/queue_spec.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
RSpec.describe Airbrake::Queue do
|
2
|
+
subject { described_class.new(queue: 'bananas', error_count: 0) }
|
3
|
+
|
4
|
+
describe "#ignore" do
|
5
|
+
it { is_expected.to respond_to(:ignore!) }
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#stash" do
|
9
|
+
it { is_expected.to respond_to(:stash) }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#route" do
|
13
|
+
it "always returns an empty route" do
|
14
|
+
queue = described_class.new(queue: 'a', error_count: 0)
|
15
|
+
expect(queue.route).to be_empty
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,143 @@
|
|
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) do |&block|
|
26
|
+
expect(block.call).to match(/applying remote settings/)
|
27
|
+
end
|
28
|
+
described_class.new(config).call(data)
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when the config disables error notifications" do
|
32
|
+
before do
|
33
|
+
config.error_notifications = false
|
34
|
+
allow(data).to receive(:error_notifications?).and_return(true)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "keeps the option disabled forever" do
|
38
|
+
callback = described_class.new(config)
|
39
|
+
|
40
|
+
callback.call(data)
|
41
|
+
expect(config.error_notifications).to eq(false)
|
42
|
+
|
43
|
+
callback.call(data)
|
44
|
+
expect(config.error_notifications).to eq(false)
|
45
|
+
|
46
|
+
callback.call(data)
|
47
|
+
expect(config.error_notifications).to eq(false)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when the config enables error notifications" do
|
52
|
+
before { config.error_notifications = true }
|
53
|
+
|
54
|
+
it "can disable and enable error notifications" do
|
55
|
+
expect(data).to receive(:error_notifications?).and_return(false)
|
56
|
+
|
57
|
+
callback = described_class.new(config)
|
58
|
+
callback.call(data)
|
59
|
+
expect(config.error_notifications).to eq(false)
|
60
|
+
|
61
|
+
expect(data).to receive(:error_notifications?).and_return(true)
|
62
|
+
callback.call(data)
|
63
|
+
expect(config.error_notifications).to eq(true)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when the config disables performance_stats" do
|
68
|
+
before do
|
69
|
+
config.performance_stats = false
|
70
|
+
allow(data).to receive(:performance_stats?).and_return(true)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "keeps the option disabled forever" do
|
74
|
+
callback = described_class.new(config)
|
75
|
+
|
76
|
+
callback.call(data)
|
77
|
+
expect(config.performance_stats).to eq(false)
|
78
|
+
|
79
|
+
callback.call(data)
|
80
|
+
expect(config.performance_stats).to eq(false)
|
81
|
+
|
82
|
+
callback.call(data)
|
83
|
+
expect(config.performance_stats).to eq(false)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "when the config enables performance stats" do
|
88
|
+
before { config.performance_stats = true }
|
89
|
+
|
90
|
+
it "can disable and enable performance_stats" do
|
91
|
+
expect(data).to receive(:performance_stats?).and_return(false)
|
92
|
+
|
93
|
+
callback = described_class.new(config)
|
94
|
+
callback.call(data)
|
95
|
+
expect(config.performance_stats).to eq(false)
|
96
|
+
|
97
|
+
expect(data).to receive(:performance_stats?).and_return(true)
|
98
|
+
callback.call(data)
|
99
|
+
expect(config.performance_stats).to eq(true)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "when error_host returns a value" do
|
104
|
+
it "sets the error_host option" do
|
105
|
+
config.error_host = 'http://api.airbrake.io'
|
106
|
+
allow(data).to receive(:error_host).and_return('https://api.example.com')
|
107
|
+
|
108
|
+
described_class.new(config).call(data)
|
109
|
+
expect(config.error_host).to eq('https://api.example.com')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "when error_host returns nil" do
|
114
|
+
it "doesn't modify the error_host option" do
|
115
|
+
config.error_host = 'http://api.airbrake.io'
|
116
|
+
allow(data).to receive(:error_host).and_return(nil)
|
117
|
+
|
118
|
+
described_class.new(config).call(data)
|
119
|
+
expect(config.error_host).to eq('http://api.airbrake.io')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "when apm_host returns a value" do
|
124
|
+
it "sets the apm_host option" do
|
125
|
+
config.apm_host = 'http://api.airbrake.io'
|
126
|
+
allow(data).to receive(:apm_host).and_return('https://api.example.com')
|
127
|
+
|
128
|
+
described_class.new(config).call(data)
|
129
|
+
expect(config.apm_host).to eq('https://api.example.com')
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "when apm_host returns nil" do
|
134
|
+
it "doesn't modify the apm_host option" do
|
135
|
+
config.apm_host = 'http://api.airbrake.io'
|
136
|
+
allow(data).to receive(:apm_host).and_return(nil)
|
137
|
+
|
138
|
+
described_class.new(config).call(data)
|
139
|
+
expect(config.apm_host).to eq('http://api.airbrake.io')
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
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
|