bugsnag-maze-runner 9.2.0 → 9.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/features/steps/breadcrumb_steps.rb +1 -1
- data/lib/features/steps/multipart_request_steps.rb +3 -3
- data/lib/features/steps/network_steps.rb +1 -1
- data/lib/features/steps/payload_steps.rb +3 -3
- data/lib/maze/client/appium/base_client.rb +4 -1
- data/lib/maze/client/appium/bb_client.rb +2 -0
- data/lib/maze/hooks/appium_hooks.rb +6 -1
- data/lib/maze/schemas/trace_validator.rb +38 -0
- data/lib/maze.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dacde3d4eb35539a0dbaf40020e42b1d08cac2a20a733a7b03588168677bda74
|
4
|
+
data.tar.gz: c9a60049b25661b69885754b9dc11cd44024af2abc7131c719b7d67d94754ee0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 12688ef4e48762c83b9535529ddc5881f30ea19f1779eb475e447d7046d6f80f98ccdbf1cb4b5319b943758e07e0dda9ed79bf1bfb2ae039f2d108d2d5f13715
|
7
|
+
data.tar.gz: b8e56857f38a47bf60474deb504b7a90fe9661f06f8597ec95948bfd47c76ff1b6a904953c5498eb1a592bec886cb4d9ce79320d7779b69a4be977661ab7b601
|
@@ -74,7 +74,7 @@ end
|
|
74
74
|
# @step_input json_fixture [String] A path to the JSON fixture to compare against
|
75
75
|
Then('the event contains a breadcrumb matching the JSON fixture in {string}') do |json_fixture|
|
76
76
|
breadcrumbs = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], 'events.0.breadcrumbs')
|
77
|
-
expected = JSON.parse(open(json_fixture, &:read))
|
77
|
+
expected = JSON.parse(File.open(json_fixture, &:read))
|
78
78
|
match = breadcrumbs.any? { |breadcrumb| Maze::Compare.value(expected, breadcrumb).equal? }
|
79
79
|
Maze.check.true(match, 'No breadcrumbs in the event matched the given breadcrumb')
|
80
80
|
end
|
@@ -78,7 +78,7 @@ Then('the {request_type} multipart body does not match the JSON file in {string}
|
|
78
78
|
payload_list = Maze::Server.list_for request_type
|
79
79
|
raw_payload_value = payload_list.current[:body]
|
80
80
|
payload_value = parse_multipart_body(raw_payload_value)
|
81
|
-
expected_value = JSON.parse(open(json_path, &:read))
|
81
|
+
expected_value = JSON.parse(File.open(json_path, &:read))
|
82
82
|
result = Maze::Compare.value(expected_value, payload_value)
|
83
83
|
Maze.check.false(result.equal?, "Payload:\n#{payload_value}\nExpected:#{expected_value}")
|
84
84
|
end
|
@@ -93,7 +93,7 @@ Then('the {request_type} multipart body matches the JSON file in {string}') do |
|
|
93
93
|
payload_list = Maze::Server.list_for request_type
|
94
94
|
raw_payload_value = payload_list.current[:body]
|
95
95
|
payload_value = parse_multipart_body(raw_payload_value)
|
96
|
-
expected_value = JSON.parse(open(json_path, &:read))
|
96
|
+
expected_value = JSON.parse(File.open(json_path, &:read))
|
97
97
|
result = Maze::Compare.value(expected_value, payload_value)
|
98
98
|
Maze.check.true(result.equal?, "The payload field '#{result.keypath}' does not match the fixture:\n #{result.reasons.join('\n')}")
|
99
99
|
end
|
@@ -108,7 +108,7 @@ Then('the {request_type} multipart field {string} matches the JSON file in {stri
|
|
108
108
|
Maze.check.true(File.exist?(json_path), "'#{json_path}' does not exist")
|
109
109
|
payload_list = Maze::Server.list_for request_type
|
110
110
|
payload_value = JSON.parse(payload_list.current[:body][field_path].to_s)
|
111
|
-
expected_value = JSON.parse(open(json_path, &:read))
|
111
|
+
expected_value = JSON.parse(File.open(json_path, &:read))
|
112
112
|
result = Maze::Compare.value(expected_value, payload_value)
|
113
113
|
Maze.check.true(result.equal?, "The multipart field '#{result.keypath}' does not match the fixture:\n #{result.reasons.join('\n')}")
|
114
114
|
end
|
@@ -8,7 +8,7 @@
|
|
8
8
|
# @step_input fixture_path [String] Path to a JSON fixture
|
9
9
|
Then('the {request_type} payload body does not match the JSON fixture in {string}') do |request_type, fixture_path|
|
10
10
|
payload_value = Maze::Server.list_for(request_type).current[:body]
|
11
|
-
expected_value = JSON.parse(open(fixture_path, &:read))
|
11
|
+
expected_value = JSON.parse(File.open(fixture_path, &:read))
|
12
12
|
result = Maze::Compare.value(expected_value, payload_value)
|
13
13
|
Maze.check.false(result.equal?, "Payload:\n#{payload_value}\nExpected:#{expected_value}")
|
14
14
|
end
|
@@ -19,7 +19,7 @@ end
|
|
19
19
|
# @step_input fixture_path [String] Path to a JSON fixture
|
20
20
|
Then('the {request_type} payload body matches the JSON fixture in {string}') do |request_type, fixture_path|
|
21
21
|
payload_value = Maze::Server.list_for(request_type).current[:body]
|
22
|
-
expected_value = JSON.parse(open(fixture_path, &:read))
|
22
|
+
expected_value = JSON.parse(File.open(fixture_path, &:read))
|
23
23
|
result = Maze::Compare.value(expected_value, payload_value)
|
24
24
|
Maze.check.true(result.equal?,
|
25
25
|
"The payload field '#{result.keypath}' does not match the fixture:\n #{result.reasons.join('\n')}")
|
@@ -34,7 +34,7 @@ Then('the {request_type}(|a b) payload field {string} matches the JSON fixture i
|
|
34
34
|
do |request_type, field_path, fixture_path|
|
35
35
|
list = Maze::Server.list_for(request_type)
|
36
36
|
payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
37
|
-
expected_value = JSON.parse(open(fixture_path, &:read))
|
37
|
+
expected_value = JSON.parse(File.open(fixture_path, &:read))
|
38
38
|
result = Maze::Compare.value(expected_value, payload_value)
|
39
39
|
Maze.check.true(result.equal?,
|
40
40
|
"The payload field '#{result.keypath}' does not match the fixture:\n #{result.reasons.join('\n')}")
|
@@ -22,7 +22,10 @@ module Maze
|
|
22
22
|
when 'android'
|
23
23
|
Maze.driver.session_capabilities['appPackage']
|
24
24
|
when 'ios'
|
25
|
-
Maze.driver.session_capabilities['CFBundleIdentifier']
|
25
|
+
unless app_id = Maze.driver.session_capabilities['CFBundleIdentifier']
|
26
|
+
app_id = Maze.driver.session_capabilities['bundleID']
|
27
|
+
end
|
28
|
+
app_id
|
26
29
|
end
|
27
30
|
|
28
31
|
# Ensure the device is unlocked
|
@@ -32,6 +32,8 @@ module Maze
|
|
32
32
|
interval = 120
|
33
33
|
elsif error.message.include? 'Appium Settings app is not running'
|
34
34
|
interval = 10
|
35
|
+
elsif error.message.include? 'Could not proxy command to the remote server'
|
36
|
+
interval = 10
|
35
37
|
else
|
36
38
|
# Do not retry in any other case
|
37
39
|
end
|
@@ -32,7 +32,12 @@ module Maze
|
|
32
32
|
|
33
33
|
# Reset the server to ensure that test fixtures cannot fetch
|
34
34
|
# commands from the previous scenario (in idempotent mode).
|
35
|
-
|
35
|
+
begin
|
36
|
+
Maze.driver.terminate_app Maze.driver.app_id
|
37
|
+
rescue Selenium::WebDriver::Error::UnknownError
|
38
|
+
$logger.warn 'terminate_app failed, using the slower but more forceful close_app instead'
|
39
|
+
Maze.driver.close_app
|
40
|
+
end
|
36
41
|
Maze::Server.reset!
|
37
42
|
Maze.driver.activate_app Maze.driver.app_id
|
38
43
|
end
|
@@ -9,6 +9,7 @@ module Maze
|
|
9
9
|
HEX_STRING_32 = '^[A-Fa-f0-9]{32}$'
|
10
10
|
SAMPLING_HEADER_ENTRY = '((1(.0)?|0(\.[0-9]+)?):[0-9]+)'
|
11
11
|
SAMPLING_HEADER = "^#{SAMPLING_HEADER_ENTRY}(;#{SAMPLING_HEADER_ENTRY})*$"
|
12
|
+
HOUR_TOLERANCE = 60 * 60 * 1000 * 1000 * 1000 # 1 hour in nanoseconds
|
12
13
|
|
13
14
|
# Contains a set of pre-defined validations for ensuring traces are correct
|
14
15
|
class TraceValidator
|
@@ -38,15 +39,40 @@ module Maze
|
|
38
39
|
element_int_in_range('resourceSpans.0.scopeSpans.0.spans.0.kind', 0..5)
|
39
40
|
regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.startTimeUnixNano', '^[0-9]+$')
|
40
41
|
regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.endTimeUnixNano', '^[0-9]+$')
|
42
|
+
element_contains('resourceSpans.0.resource.attributes', 'service.version')
|
43
|
+
element_contains('resourceSpans.0.resource.attributes', 'device.id')
|
44
|
+
each_element_contains('resourceSpans.0.scopeSpans.0.spans', 'attributes', 'bugsnag.sampling.p')
|
41
45
|
element_contains('resourceSpans.0.resource.attributes', 'deployment.environment')
|
42
46
|
element_contains('resourceSpans.0.resource.attributes', 'telemetry.sdk.name')
|
43
47
|
element_contains('resourceSpans.0.resource.attributes', 'telemetry.sdk.version')
|
48
|
+
validate_timestamp('resourceSpans.0.scopeSpans.0.spans.0.startTimeUnixNano', HOUR_TOLERANCE)
|
49
|
+
validate_timestamp('resourceSpans.0.scopeSpans.0.spans.0.endTimeUnixNano', HOUR_TOLERANCE)
|
44
50
|
element_a_greater_or_equal_element_b(
|
45
51
|
'resourceSpans.0.scopeSpans.0.spans.0.endTimeUnixNano',
|
46
52
|
'resourceSpans.0.scopeSpans.0.spans.0.startTimeUnixNano'
|
47
53
|
)
|
48
54
|
end
|
49
55
|
|
56
|
+
def validate_timestamp(path, tolerance)
|
57
|
+
timestamp = Maze::Helper.read_key_path(@body, path)
|
58
|
+
unless timestamp.kind_of?(String)
|
59
|
+
@success = false
|
60
|
+
@errors << "Timestamp was expected to be a string, was '#{timestamp.class.name}'"
|
61
|
+
return
|
62
|
+
end
|
63
|
+
parsed_timestamp = timestamp.to_i
|
64
|
+
unless parsed_timestamp > 0
|
65
|
+
@success = false
|
66
|
+
@errors << "Timestamp was expected to be a positive integer, was '#{parsed_timestamp}'"
|
67
|
+
return
|
68
|
+
end
|
69
|
+
time_in_nanos = Time.now.to_i * 1000000000
|
70
|
+
unless (time_in_nanos - parsed_timestamp).abs < tolerance
|
71
|
+
@success = false
|
72
|
+
@errors << "Timestamp was expected to be within #{tolerance} nanoseconds of the current time (#{time_in_nanos}), was '#{parsed_timestamp}'"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
50
76
|
def validate_header(name)
|
51
77
|
value = @headers[name]
|
52
78
|
if value.nil? || value.size > 1
|
@@ -133,6 +159,18 @@ module Maze
|
|
133
159
|
end
|
134
160
|
end
|
135
161
|
|
162
|
+
def each_element_contains(container_path, attribute_path, key_value)
|
163
|
+
container = Maze::Helper.read_key_path(@body, container_path)
|
164
|
+
if container.nil? || !container.kind_of?(Array)
|
165
|
+
@success = false
|
166
|
+
@errors << "Element '#{container_path}' was expected to be an array, was '#{container}'"
|
167
|
+
return
|
168
|
+
end
|
169
|
+
container.each_with_index do |_item, index|
|
170
|
+
element_contains("#{container_path}.#{index}.#{attribute_path}", key_value)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
136
174
|
def element_a_greater_or_equal_element_b(path_a, path_b)
|
137
175
|
element_a = Maze::Helper.read_key_path(@body, path_a)
|
138
176
|
element_b = Maze::Helper.read_key_path(@body, path_b)
|
data/lib/maze.rb
CHANGED
@@ -7,7 +7,7 @@ require_relative 'maze/timers'
|
|
7
7
|
# Glues the various parts of MazeRunner together that need to be accessed globally,
|
8
8
|
# providing an alternative to the proliferation of global variables or singletons.
|
9
9
|
module Maze
|
10
|
-
VERSION = '9.
|
10
|
+
VERSION = '9.3.0'
|
11
11
|
|
12
12
|
class << self
|
13
13
|
attr_accessor :check, :driver, :internal_hooks, :mode, :start_time, :dynamic_retry, :public_address,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bugsnag-maze-runner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 9.
|
4
|
+
version: 9.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Kirkland
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cucumber
|
@@ -454,11 +454,11 @@ files:
|
|
454
454
|
- lib/maze/wait.rb
|
455
455
|
- lib/utils/deep_merge.rb
|
456
456
|
- lib/utils/selenium_money_patch.rb
|
457
|
-
homepage:
|
457
|
+
homepage:
|
458
458
|
licenses:
|
459
459
|
- MIT
|
460
460
|
metadata: {}
|
461
|
-
post_install_message:
|
461
|
+
post_install_message:
|
462
462
|
rdoc_options: []
|
463
463
|
require_paths:
|
464
464
|
- lib
|
@@ -474,7 +474,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
474
474
|
version: '0'
|
475
475
|
requirements: []
|
476
476
|
rubygems_version: 3.1.6
|
477
|
-
signing_key:
|
477
|
+
signing_key:
|
478
478
|
specification_version: 4
|
479
479
|
summary: Bugsnag API request validation harness
|
480
480
|
test_files: []
|