Top Level Namespace
Defined Under Namespace
Modules: Cucumber, Maze, Selenium
Classes: Hash
Constant Summary
collapse
- TIMESTAMP_REGEX =
A regex providing the pattern expected from timestamps
/^\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:[\d\.]+(Z|[+-]\d{2}:\d{2})?$/
-
#assert_attribute(field, key, expected) ⇒ Object
-
#assert_received_spans(span_count, list) ⇒ Object
-
#attribute_value_matches?(attribute_value, expected_type, expected_value) ⇒ Boolean
-
#check_attribute_equal(field, attribute, attr_type, expected) ⇒ Object
-
#get_attribute_value(field, attribute, attr_type) ⇒ Object
-
#spans_from_request_list(list) ⇒ Object
Feature flag steps
collapse
App Automator steps
collapse
Error reporting steps
collapse
Multipart request assertion steps
collapse
Request assertion steps
collapse
Instance Method Summary
collapse
Instance Method Details
#assert_attribute(field, key, expected) ⇒ Object
276
277
278
279
280
|
# File 'lib/features/steps/trace_steps.rb', line 276
def assert_attribute(field, key, expected)
list = Maze::Server.traces
attributes = Maze::Helper.read_key_path(list.current[:body], "#{field}.attributes")
Maze.check.equal attributes.find { |a| a['key'] == key }, { 'key' => key, 'value' => expected }
end
|
#assert_equal_with_nullability(expected_value, payload_value) ⇒ Object
219
220
221
222
223
224
225
226
227
228
|
# File 'lib/features/steps/app_automator_steps.rb', line 219
def assert_equal_with_nullability(expected_value, payload_value)
case expected_value
when '@null'
Maze.check.nil(payload_value)
when '@not_null'
Maze.check.not_nil(payload_value)
else
Maze.check.equal(expected_value, payload_value)
end
end
|
#assert_received_requests(request_count, list, list_name, precise = true) ⇒ Object
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
# File 'lib/features/steps/request_assertion_steps.rb', line 11
def assert_received_requests(request_count, list, list_name, precise = true)
timeout = Maze.config.receive_requests_wait
wait = Maze::Wait.new(timeout: timeout)
received = wait.until { list.size_remaining >= request_count }
unless received
raise Test::Unit::AssertionFailedError.new <<-MESSAGE
Expected #{request_count} #{list_name} but received #{list.size_remaining} within the #{timeout}s timeout.
This could indicate that:
- Bugsnag crashed with a fatal error.
- Bugsnag did not make the requests that it should have done.
- The requests were made, but not deemed to be valid (e.g. missing integrity header).
- The requests made were prevented from being received due to a network or other infrastructure issue.
Please check the Maze Runner and device logs to confirm.)
MESSAGE
end
if precise
Maze.check.equal(request_count, list.size_remaining, "#{list.size_remaining} #{list_name} received")
else
Maze.check.operator(request_count, :<=, list.size_remaining, "#{list.size_remaining} #{list_name} received")
end
end
|
#assert_received_spans(span_count, list) ⇒ Object
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
|
# File 'lib/features/steps/trace_steps.rb', line 238
def assert_received_spans(span_count, list)
timeout = Maze.config.receive_requests_wait
wait = Maze::Wait.new(timeout: timeout)
received = wait.until { spans_from_request_list(list).size >= span_count }
received_count = spans_from_request_list(list).size
unless received
raise Test::Unit::AssertionFailedError.new <<-MESSAGE
Expected #{span_count} spans but received #{received_count} within the #{timeout}s timeout.
This could indicate that:
- Bugsnag crashed with a fatal error.
- Bugsnag did not make the requests that it should have done.
- The requests were made, but not deemed to be valid (e.g. missing integrity header).
- The requests made were prevented from being received due to a network or other infrastructure issue.
Please check the Maze Runner and device logs to confirm.)
MESSAGE
end
Maze.check.operator(span_count, :<=, received_count, "#{received_count} spans received")
Maze::Schemas::Validator.verify_against_schema(list, 'trace')
Maze::Schemas::Validator.validate_payload_elements(list, 'trace')
end
|
#attribute_value_matches?(attribute_value, expected_type, expected_value) ⇒ Boolean
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
# File 'lib/features/steps/trace_steps.rb', line 214
def attribute_value_matches?(attribute_value, expected_type, expected_value)
unless attribute_value.keys.include?(expected_type)
return false
end
case expected_type
when 'bytesValue', 'stringValue'
expected_value.eql?(attribute_value[expected_type])
when 'intValue'
expected_value.to_i.eql?(attribute_value[expected_type].to_i)
when 'doubleValue'
expected_value.to_f.eql?(attribute_value[expected_type])
when 'boolValue'
expected_value.eql?('true').eql?(attribute_value[expected_type])
when 'arrayValue', 'kvlistValue'
$logger.error('Span attribute validation does not currently support the "arrayValue" or "kvlistValue" types')
false
else
$logger.error("An invalid attribute type was expected: '#{expected_type}'")
false
end
end
|
#check_attribute_equal(field, attribute, attr_type, expected) ⇒ Object
271
272
273
274
|
# File 'lib/features/steps/trace_steps.rb', line 271
def check_attribute_equal(field, attribute, attr_type, expected)
value = get_attribute_value field, attribute, attr_type
Maze.check.equal value, expected
end
|
#create_defaulting_generator(codes, default) ⇒ Object
96
97
98
99
100
101
102
103
104
105
106
107
|
# File 'lib/features/steps/network_steps.rb', line 96
def create_defaulting_generator(codes, default)
enumerator = Enumerator.new do |yielder|
codes.each do |code|
yielder.yield code
end
loop do
yielder.yield default
end
end
Maze::Generator.new enumerator
end
|
#get_attribute_value(field, attribute, attr_type) ⇒ Object
263
264
265
266
267
268
269
|
# File 'lib/features/steps/trace_steps.rb', line 263
def get_attribute_value(field, attribute, attr_type)
list = Maze::Server.list_for 'trace'
attributes = Maze::Helper.read_key_path list.current[:body], "#{field}.attributes"
attribute = attributes.find { |a| a['key'] == attribute }
value = attribute&.dig 'value', attr_type
attr_type == 'intValue' && value.is_a?(String) ? value.to_i : value
end
|
168
169
170
171
172
173
174
|
# File 'lib/features/steps/app_automator_steps.rb', line 168
def get_expected_platform_value(platform_values)
os = Maze::Helper.get_current_platform
expected_value = Hash[platform_values.raw][os.downcase]
raise("There is no expected value for the current platform \"#{os}\"") if expected_value.nil?
expected_value
end
|
#has_feature_flags?(event) ⇒ Boolean
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
|
# File 'lib/features/steps/feature_flag_steps.rb', line 176
def has_feature_flags?(event)
if event.has_key?('featureFlags')
Maze.check.false(
event['featureFlags'].nil?,
'The feature flags key was present, but null'
)
Maze.check.true(
event['featureFlags'].is_a?(Array),
"The feature flags key was present, but the value: #{event['featureFlags']} must be an array"
)
!event['featureFlags'].empty?
else
false
end
end
|
#output_received_requests(request_type) ⇒ Object
171
172
173
174
175
176
177
178
179
180
181
182
183
|
# File 'lib/features/support/internal_hooks.rb', line 171
def output_received_requests(request_type)
request_queue = Maze::Server.list_for(request_type)
count = request_queue.size_all
if count == 0
$logger.info "No #{request_type} received"
else
$logger.info "#{count} #{request_type} were received:"
request_queue.all.each.with_index(1) do |request, number|
$stdout.puts "--- #{request_type} #{number} of #{count}"
Maze::LogUtil.log_hash(Logger::Severity::INFO, request)
end
end
end
|
#parse_multipart_body(body) ⇒ Hash
Takes a hashmap and parses all fields into strings or hashes depending on their format Used to convert a multipart/form-data request into a JSON comparable hash
63
64
65
66
67
68
69
|
# File 'lib/features/steps/multipart_request_steps.rb', line 63
def parse_multipart_body(body)
body.each_with_object({}) do |(k, v), out|
out[k] = JSON.parse(v.to_s)
rescue JSON::ParserError
out[k] = v.to_s
end
end
|
176
177
178
|
# File 'lib/features/steps/app_automator_steps.rb', line 176
def should_skip_platform_check(expected_value)
expected_value.eql?('@skip')
end
|
#spans_from_request_list(list) ⇒ Object
206
207
208
209
210
211
212
|
# File 'lib/features/steps/trace_steps.rb', line 206
def spans_from_request_list list
return list.remaining
.flat_map { |req| req[:body]['resourceSpans'] }
.flat_map { |r| r['scopeSpans'] }
.flat_map { |s| s['spans'] }
.select { |s| !s.nil? }
end
|
206
207
208
209
210
211
212
213
214
215
216
217
|
# File 'lib/features/steps/app_automator_steps.rb', line 206
def test_numeric_platform_values(request_type, field_path, platform_values)
expected_value = get_expected_platform_value(platform_values)
return if should_skip_platform_check(expected_value)
list = Maze::Server.list_for(request_type)
payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
special_value = expected_value.eql?('@null') || expected_value.eql?('@not_null')
expectation = special_value ? expected_value : expected_value.to_f
assert_equal_with_nullability(expectation, payload_value)
end
|
#test_unhandled_state(event, unhandled, severity = nil) ⇒ Object
Tests whether an event has the correct attributes we’d expect for un/handled events
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
|
# File 'lib/features/steps/error_reporting_steps.rb', line 338
def test_unhandled_state(event, unhandled, severity = nil)
expected_unhandled_state = unhandled ? 'true' : 'false'
expected_severity = if severity
severity
elsif unhandled
'error'
else
'warning'
end
steps %(
Then the error payload field "events.#{event}.unhandled" is #{expected_unhandled_state}
And the error payload field "events.#{event}.severity" equals "#{expected_severity}"
)
return if Maze::Helper.read_key_path(Maze::Server.errors.current[:body], "events.#{event}.session").nil?
session_field = unhandled ? 'unhandled' : 'handled'
steps %(
And the error payload field "events.#{event}.session.events.#{session_field}" is greater than 0
)
end
|
Verifies a request contains the correct Content-Type header and some contents for a multipart/form-data request
12
13
14
15
16
17
18
19
20
|
# File 'lib/features/steps/multipart_request_steps.rb', line 12
def valid_multipart_form_data?(request)
content_regex = Regexp.new('^multipart\\/form-data; boundary=[\\h-]+$')
= request[:request]['Content-Type']
Maze.check.match(content_regex, )
Maze.check.true(
request[:body].size.positive?,
"Multipart request payload contained #{request[:body].size} fields"
)
end
|
#validate_error_reporting_thread(payload_key, payload_value) ⇒ Object
Tests that a thread from the first event, identified by a particular key-value pair, is the error reporting thread.
322
323
324
325
326
327
328
329
330
331
|
# File 'lib/features/steps/error_reporting_steps.rb', line 322
def validate_error_reporting_thread(payload_key, payload_value)
threads = Maze::Server.errors.current[:body]['events'].first['threads']
Maze.check.kind_of Array, threads
count = 0
threads.each do |thread|
count += 1 if thread[payload_key].to_s == payload_value && thread['errorReportingThread'] == true
end
Maze.check.equal(1, count)
end
|
#verify_feature_flags_with_table(event, table) ⇒ Object
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
# File 'lib/features/steps/feature_flag_steps.rb', line 139
def verify_feature_flags_with_table(event, table)
Maze.check.true(
has_feature_flags?(event),
"Expected feature flags were not present in event: #{event}"
)
feature_flags = event['featureFlags']
expected_features = table.hashes
Maze.check.true(
feature_flags.size == expected_features.size,
"Expected #{expected_features.size} features,
found #{feature_flags}"
)
expected_features.each do |expected|
flag_name = expected['featureFlag']
variant = expected['variant']
Maze.check.true(
feature_flags.one? { |flag| flag['featureFlag'].eql?(flag_name) },
"Expected single flag with 'featureFlag' value: #{flag_name}. Present flags: #{feature_flags}"
)
flag = feature_flags.find { |flag| flag['featureFlag'].eql?(flag_name) }
if variant.nil? || expected['variant'].empty?
Maze.check.false(
flag.has_key?('variant'),
"Feature flag: #{flag} expected to have no variant. All flags: #{feature_flags}"
)
else
Maze.check.true(
flag.has_key?('variant') && flag['variant'].eql?(variant),
"Feature flag: #{flag} did not have variant: #{variant}. All flags: #{feature_flags}"
)
end
end
end
|