bugsnag-maze-runner 9.11.2 → 9.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/bb-failed-sessions +94 -0
- data/lib/features/steps/app_automator_steps.rb +0 -159
- data/lib/features/steps/platform_dependent_steps.rb +204 -0
- data/lib/maze/client/bb_client_utils.rb +56 -0
- data/lib/maze/driver/appium.rb +46 -0
- data/lib/maze.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 325db4804e14fcf97c4cb8f53782676a597d29975d1ead996810979e94466207
|
4
|
+
data.tar.gz: 9b63455da005c6e4a1db345c74301801538425573c1fc02737034b0717a81e46
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7b981946519533317ff0f07782d12cc78cadda9e0f82227a6d7b7bc1d8ed4f0b52009040eab4fb5c399862e0b652583652f25e9921389fa64d996ea886d3c59
|
7
|
+
data.tar.gz: 9e0ee212669d3dbc3d78ef6ee29dd0843a6b0d0ee6ecb9282ed53761c5b6da180be2fe8fc7590db8d6012d2543c121c9cf9f27f3c631cfffc4fa85c5c3ba42e6
|
@@ -0,0 +1,94 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Required libraries and dependencies
|
5
|
+
require_relative '../lib/maze'
|
6
|
+
require_relative '../lib/maze/loggers/logger'
|
7
|
+
require_relative '../lib/maze/client/bb_client_utils'
|
8
|
+
require 'optimist'
|
9
|
+
require 'net/http'
|
10
|
+
require 'json'
|
11
|
+
require 'uri'
|
12
|
+
require 'date'
|
13
|
+
require 'csv'
|
14
|
+
|
15
|
+
class BBFailedSessions
|
16
|
+
def start(args)
|
17
|
+
# Define and parse command-line options
|
18
|
+
p = Optimist::Parser.new do
|
19
|
+
text 'Get unsuccessful runs from BitBar Cloud'
|
20
|
+
text ''
|
21
|
+
text 'Requires BITBAR_API_KEY'
|
22
|
+
text ''
|
23
|
+
text 'Usage [OPTIONS]'
|
24
|
+
text ''
|
25
|
+
opt :help,
|
26
|
+
'Print this help.'
|
27
|
+
opt :date,
|
28
|
+
"Date to filter the runs. Format: 'YYYY-MM-DD'",
|
29
|
+
:type => :string
|
30
|
+
opt :project,
|
31
|
+
"Name of the BitBar project",
|
32
|
+
:type => :string
|
33
|
+
opt :output,
|
34
|
+
"Path to the output CSV file",
|
35
|
+
:type => :string
|
36
|
+
end
|
37
|
+
|
38
|
+
# Parse the command-line arguments
|
39
|
+
opts = Optimist::with_standard_exception_handling p do
|
40
|
+
raise Optimist::HelpNeeded if ARGV.empty? # Show help screen if no arguments
|
41
|
+
p.parse ARGV
|
42
|
+
end
|
43
|
+
|
44
|
+
# Get the API key from environment variable
|
45
|
+
api_key = ENV['BITBAR_API_KEY']
|
46
|
+
|
47
|
+
# Check if BITBAR_API_KEY has been set
|
48
|
+
if api_key.nil?
|
49
|
+
$logger.warn "BITBAR_API_KEY has not been set"
|
50
|
+
Optimist::with_standard_exception_handling p do
|
51
|
+
raise Optimist::HelpNeeded
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# if date is not provided, use today's date
|
56
|
+
opts[:date] ||= DateTime.now.strftime('%Y-%m-%d')
|
57
|
+
|
58
|
+
# Fetch project information from BitBar
|
59
|
+
project_info = Maze::Client::BitBarClientUtils.get_ids api_key, opts[:project]
|
60
|
+
|
61
|
+
# Iterate over each project and fetch unsuccessful runs
|
62
|
+
for id, name in project_info
|
63
|
+
$logger.info "Getting unsuccessful runs #{name} (#{id}) on #{opts[:date]}"
|
64
|
+
runs = Maze::Client::BitBarClientUtils.get_unsuccessful_runs api_key, id, opts[:date]
|
65
|
+
|
66
|
+
# Array to store the data to be written to the CSV
|
67
|
+
data = []
|
68
|
+
|
69
|
+
# Collect the data from each run
|
70
|
+
runs.each do |run|
|
71
|
+
data << [ name, DateTime.strptime(run['createTime'].to_s, '%Q'), run['displayName'], run['uiLink'], run['config']['files'][0]['file']['userEmail'] ]
|
72
|
+
end
|
73
|
+
|
74
|
+
# Define the CSV file path
|
75
|
+
csv_file_path = opts[:output] || "failed_sessions_#{name.gsub('-', '_')}_#{opts[:date].gsub('/', '_')}.csv"
|
76
|
+
|
77
|
+
$logger.info "Saving data to CSV file at #{csv_file_path}"
|
78
|
+
|
79
|
+
# Write the data to a CSV file
|
80
|
+
CSV.open(csv_file_path, 'w') do |csv|
|
81
|
+
# Write the headers
|
82
|
+
csv << ['Project', 'Date', 'Test Name', 'Dashboard Link', 'User Email']
|
83
|
+
|
84
|
+
# Write the data rows
|
85
|
+
data.each do |row|
|
86
|
+
csv << row
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Start the process with command-line arguments
|
94
|
+
BBFailedSessions.new.start(ARGV)
|
@@ -64,104 +64,6 @@ When('I set the device orientation to {orientation}') do |orientation|
|
|
64
64
|
Maze.driver.set_rotation orientation
|
65
65
|
end
|
66
66
|
|
67
|
-
# Tests that the given payload value is correct for the target BrowserStack platform.
|
68
|
-
# This step will assume the expected and payload values are strings.
|
69
|
-
# If the step is invoked when a remote BrowserStack device is not in use this step will fail.
|
70
|
-
#
|
71
|
-
# The DataTable used for this step should have `ios` and `android` in the same row as their expected value:
|
72
|
-
# | android | Java.lang.RuntimeException |
|
73
|
-
# | ios | NSException |
|
74
|
-
#
|
75
|
-
# If the expected value is set to "@skip", the check should be skipped
|
76
|
-
# If the expected value is set to "@null", the check will be for null
|
77
|
-
# If the expected value is set to "@not_null", the check will be for a non-null value
|
78
|
-
#
|
79
|
-
# @step_input request_type [String] The type of request (error, session, build, etc)
|
80
|
-
# @step_input field_path [String] The field to test
|
81
|
-
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
82
|
-
Then('the {request_type} payload field {string} equals the platform-dependent string:') do |request_type, field_path, platform_values|
|
83
|
-
test_string_platform_values(request_type, field_path, platform_values)
|
84
|
-
end
|
85
|
-
|
86
|
-
# See `the error payload field {string} equals the platform-dependent string:`
|
87
|
-
#
|
88
|
-
# @step_input field_path [String] The field to test, prepended with "events.0"
|
89
|
-
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
90
|
-
Then('the event {string} equals the platform-dependent string:') do |field_path, platform_values|
|
91
|
-
test_string_platform_values('error', "events.0.#{field_path}", platform_values)
|
92
|
-
end
|
93
|
-
|
94
|
-
# Tests that the given payload value is correct for the target BrowserStack platform.
|
95
|
-
# This step will assume the expected and payload values are numeric.
|
96
|
-
# If the step is invoked when a remote BrowserStack device is not in use this step will fail.
|
97
|
-
#
|
98
|
-
# The DataTable used for this step should have `ios` and `android` in the same row as their expected value:
|
99
|
-
# | android | 1 |
|
100
|
-
# | ios | 5.5 |
|
101
|
-
#
|
102
|
-
# If the expected value is set to "@skip", the check should be skipped
|
103
|
-
# If the expected value is set to "@null", the check will be for null
|
104
|
-
# If the expected value is set to "@not_null", the check will be for a non-null value
|
105
|
-
#
|
106
|
-
# @step_input request_type [String] The type of request (error, session, build, etc)
|
107
|
-
# @step_input field_path [String] The field to test
|
108
|
-
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
109
|
-
Then('the {request_type} payload field {string} equals the platform-dependent numeric:') do |request_type, field_path, platform_values|
|
110
|
-
test_numeric_platform_values(request_type, field_path, platform_values)
|
111
|
-
end
|
112
|
-
|
113
|
-
# See `the payload field {string} equals the platform-dependent numeric:`
|
114
|
-
#
|
115
|
-
# @step_input field_path [String] The field to test, prepended with "events.0"
|
116
|
-
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
117
|
-
Then('the event {string} equals the platform-dependent numeric:') do |field_path, platform_values|
|
118
|
-
test_numeric_platform_values('error', "events.0.#{field_path}", platform_values)
|
119
|
-
end
|
120
|
-
|
121
|
-
# Tests that the given payload value is correct for the target BrowserStack platform.
|
122
|
-
# This step will assume the expected and payload values are booleans.
|
123
|
-
# If the step is invoked when a remote BrowserStack device is not in use this step will fail.
|
124
|
-
#
|
125
|
-
# The DataTable used for this step should have `ios` and `android` in the same row as their expected value:
|
126
|
-
# | android | 1 |
|
127
|
-
# | ios | 5 |
|
128
|
-
#
|
129
|
-
# If the expected value is set to "@skip", the check should be skipped
|
130
|
-
# If the expected value is set to "@null", the check will be for null
|
131
|
-
# If the expected value is set to "@not_null", the check will be for a non-null value
|
132
|
-
#
|
133
|
-
# @step_input request_type [String] The type of request (error, session, build, etc)
|
134
|
-
# @step_input field_path [String] The field to test
|
135
|
-
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
136
|
-
Then('the {request_type} payload field {string} equals the platform-dependent boolean:') do |request_type, field_path, platform_values|
|
137
|
-
test_boolean_platform_values(request_type, field_path, platform_values)
|
138
|
-
end
|
139
|
-
|
140
|
-
# See `the payload field {string} equals the platform-dependent boolean:`
|
141
|
-
#
|
142
|
-
# @step_input field_path [String] The field to test, prepended with "events.0"
|
143
|
-
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
144
|
-
Then('the event {string} equals the platform-dependent boolean:') do |field_path, platform_values|
|
145
|
-
test_boolean_platform_values('error', "events.0.#{field_path}", platform_values)
|
146
|
-
end
|
147
|
-
|
148
|
-
# See `the payload field {string} equals the platform-dependent string:`
|
149
|
-
#
|
150
|
-
# @step_input field_path [String] The field to test, prepended with "events.0.exceptions.0."
|
151
|
-
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
152
|
-
Then('the exception {string} equals the platform-dependent string:') do |field_path, platform_values|
|
153
|
-
test_string_platform_values('error', "events.0.exceptions.0.#{field_path}", platform_values)
|
154
|
-
end
|
155
|
-
|
156
|
-
# See `the payload field {string} equals the platform-dependent string:`
|
157
|
-
#
|
158
|
-
# @step_input field_path [String] The field to test, prepended with "events.0.exceptions.0.stacktrace.#!{num}"
|
159
|
-
# @step_input num [Integer] The index of the stack frame to test
|
160
|
-
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
161
|
-
Then('the {string} of stack frame {int} equals the platform-dependent string:') do |field_path, num, platform_values|
|
162
|
-
test_string_platform_values('error', "events.0.exceptions.0.stacktrace.#{num}.#{field_path}", platform_values)
|
163
|
-
end
|
164
|
-
|
165
67
|
# Sends keys to a given element, clearing it first
|
166
68
|
# Requires a running Appium driver
|
167
69
|
#
|
@@ -171,64 +73,3 @@ When('I clear and send the keys {string} to the element {string}') do |keys, ele
|
|
171
73
|
Maze.driver.clear_and_send_keys_to_element(element_id, keys)
|
172
74
|
end
|
173
75
|
|
174
|
-
def get_expected_platform_value(platform_values)
|
175
|
-
os = Maze::Helper.get_current_platform
|
176
|
-
expected_value = Hash[platform_values.raw][os.downcase]
|
177
|
-
raise("There is no expected value for the current platform \"#{os}\"") if expected_value.nil?
|
178
|
-
|
179
|
-
expected_value
|
180
|
-
end
|
181
|
-
|
182
|
-
def should_skip_platform_check(expected_value)
|
183
|
-
expected_value.eql?('@skip')
|
184
|
-
end
|
185
|
-
|
186
|
-
def test_string_platform_values(request_type, field_path, platform_values)
|
187
|
-
expected_value = get_expected_platform_value(platform_values)
|
188
|
-
return if should_skip_platform_check(expected_value)
|
189
|
-
|
190
|
-
list = Maze::Server.list_for(request_type)
|
191
|
-
payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
192
|
-
assert_equal_with_nullability(expected_value, payload_value)
|
193
|
-
end
|
194
|
-
|
195
|
-
def test_boolean_platform_values(request_type, field_path, platform_values)
|
196
|
-
expected_value = get_expected_platform_value(platform_values)
|
197
|
-
return if should_skip_platform_check(expected_value)
|
198
|
-
|
199
|
-
expected_bool = case expected_value.downcase
|
200
|
-
when 'true'
|
201
|
-
true
|
202
|
-
when 'false'
|
203
|
-
false
|
204
|
-
else
|
205
|
-
expected_value
|
206
|
-
end
|
207
|
-
list = Maze::Server.list_for(request_type)
|
208
|
-
payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
209
|
-
assert_equal_with_nullability(expected_bool, payload_value)
|
210
|
-
end
|
211
|
-
|
212
|
-
def test_numeric_platform_values(request_type, field_path, platform_values)
|
213
|
-
expected_value = get_expected_platform_value(platform_values)
|
214
|
-
return if should_skip_platform_check(expected_value)
|
215
|
-
|
216
|
-
list = Maze::Server.list_for(request_type)
|
217
|
-
payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
218
|
-
|
219
|
-
# Need to do a little more processing here to allow floats
|
220
|
-
special_value = expected_value.eql?('@null') || expected_value.eql?('@not_null')
|
221
|
-
expectation = special_value ? expected_value : expected_value.to_f
|
222
|
-
assert_equal_with_nullability(expectation, payload_value)
|
223
|
-
end
|
224
|
-
|
225
|
-
def assert_equal_with_nullability(expected_value, payload_value)
|
226
|
-
case expected_value
|
227
|
-
when '@null'
|
228
|
-
Maze.check.nil(payload_value)
|
229
|
-
when '@not_null'
|
230
|
-
Maze.check.not_nil(payload_value)
|
231
|
-
else
|
232
|
-
Maze.check.equal(expected_value, payload_value)
|
233
|
-
end
|
234
|
-
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
# @!group Platform dependent steps
|
2
|
+
|
3
|
+
# Tests that the given payload value is correct for the target BrowserStack platform.
|
4
|
+
# This step will assume the expected and payload values are strings.
|
5
|
+
# If the step is invoked when a remote BrowserStack device is not in use this step will fail.
|
6
|
+
#
|
7
|
+
# The DataTable used for this step should have `ios` and `android` in the same row as their expected value:
|
8
|
+
# | android | Java.lang.RuntimeException |
|
9
|
+
# | ios | NSException |
|
10
|
+
#
|
11
|
+
# If the expected value is set to "@skip", the check should be skipped
|
12
|
+
# If the expected value is set to "@null", the check will be for null
|
13
|
+
# If the expected value is set to "@not_null", the check will be for a non-null value
|
14
|
+
#
|
15
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
16
|
+
# @step_input field_path [String] The field to test
|
17
|
+
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
18
|
+
Then('the {request_type} payload field {string} equals the platform-dependent string:') do |request_type, field_path, platform_values|
|
19
|
+
test_string_platform_values(request_type, field_path, platform_values)
|
20
|
+
end
|
21
|
+
|
22
|
+
# See `the error payload field {string} equals the platform-dependent string:`
|
23
|
+
#
|
24
|
+
# @step_input field_path [String] The field to test, prepended with "events.0"
|
25
|
+
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
26
|
+
Then('the event {string} equals the platform-dependent string:') do |field_path, platform_values|
|
27
|
+
test_string_platform_values('error', "events.0.#{field_path}", platform_values)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Tests that the given payload value is correct for the target BrowserStack platform.
|
31
|
+
# This step will assume the expected and payload values are numeric.
|
32
|
+
# If the step is invoked when a remote BrowserStack device is not in use this step will fail.
|
33
|
+
#
|
34
|
+
# The DataTable used for this step should have `ios` and `android` in the same row as their expected value:
|
35
|
+
# | android | 1 |
|
36
|
+
# | ios | 5.5 |
|
37
|
+
#
|
38
|
+
# If the expected value is set to "@skip", the check should be skipped
|
39
|
+
# If the expected value is set to "@null", the check will be for null
|
40
|
+
# If the expected value is set to "@not_null", the check will be for a non-null value
|
41
|
+
#
|
42
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
43
|
+
# @step_input field_path [String] The field to test
|
44
|
+
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
45
|
+
Then('the {request_type} payload field {string} equals the platform-dependent numeric:') do |request_type, field_path, platform_values|
|
46
|
+
test_numeric_platform_values(request_type, field_path, platform_values)
|
47
|
+
end
|
48
|
+
|
49
|
+
# See `the payload field {string} equals the platform-dependent numeric:`
|
50
|
+
#
|
51
|
+
# @step_input field_path [String] The field to test, prepended with "events.0"
|
52
|
+
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
53
|
+
Then('the event {string} equals the platform-dependent numeric:') do |field_path, platform_values|
|
54
|
+
test_numeric_platform_values('error', "events.0.#{field_path}", platform_values)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Tests that the given payload value is correct for the target BrowserStack platform.
|
58
|
+
# This step will assume the expected and payload values are booleans.
|
59
|
+
# If the step is invoked when a remote BrowserStack device is not in use this step will fail.
|
60
|
+
#
|
61
|
+
# The DataTable used for this step should have `ios` and `android` in the same row as their expected value:
|
62
|
+
# | android | 1 |
|
63
|
+
# | ios | 5 |
|
64
|
+
#
|
65
|
+
# If the expected value is set to "@skip", the check should be skipped
|
66
|
+
# If the expected value is set to "@null", the check will be for null
|
67
|
+
# If the expected value is set to "@not_null", the check will be for a non-null value
|
68
|
+
#
|
69
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
70
|
+
# @step_input field_path [String] The field to test
|
71
|
+
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
72
|
+
Then('the {request_type} payload field {string} equals the platform-dependent boolean:') do |request_type, field_path, platform_values|
|
73
|
+
test_boolean_platform_values(request_type, field_path, platform_values)
|
74
|
+
end
|
75
|
+
|
76
|
+
# See `the payload field {string} equals the platform-dependent boolean:`
|
77
|
+
#
|
78
|
+
# @step_input field_path [String] The field to test, prepended with "events.0"
|
79
|
+
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
80
|
+
Then('the event {string} equals the platform-dependent boolean:') do |field_path, platform_values|
|
81
|
+
test_boolean_platform_values('error', "events.0.#{field_path}", platform_values)
|
82
|
+
end
|
83
|
+
|
84
|
+
# See `the payload field {string} equals the platform-dependent string:`
|
85
|
+
#
|
86
|
+
# @step_input field_path [String] The field to test, prepended with "events.0.exceptions.0."
|
87
|
+
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
88
|
+
Then('the exception {string} equals the platform-dependent string:') do |field_path, platform_values|
|
89
|
+
test_string_platform_values('error', "events.0.exceptions.0.#{field_path}", platform_values)
|
90
|
+
end
|
91
|
+
|
92
|
+
# See `the payload field {string} equals the platform-dependent string:`
|
93
|
+
#
|
94
|
+
# @step_input field_path [String] The field to test, prepended with "events.0.exceptions.0.stacktrace.#!{num}"
|
95
|
+
# @step_input num [Integer] The index of the stack frame to test
|
96
|
+
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
97
|
+
Then('the {string} of stack frame {int} equals the platform-dependent string:') do |field_path, num, platform_values|
|
98
|
+
test_string_platform_values('error', "events.0.exceptions.0.stacktrace.#{num}.#{field_path}", platform_values)
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Equality check routines
|
103
|
+
#
|
104
|
+
def test_string_platform_values(request_type, field_path, platform_values)
|
105
|
+
expected_value = get_expected_platform_value(platform_values)
|
106
|
+
return if should_skip_platform_check(expected_value)
|
107
|
+
|
108
|
+
list = Maze::Server.list_for(request_type)
|
109
|
+
payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
110
|
+
assert_equal_with_nullability(expected_value, payload_value)
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_boolean_platform_values(request_type, field_path, platform_values)
|
114
|
+
expected_value = get_expected_platform_value(platform_values)
|
115
|
+
return if should_skip_platform_check(expected_value)
|
116
|
+
|
117
|
+
expected_bool = case expected_value.downcase
|
118
|
+
when 'true'
|
119
|
+
true
|
120
|
+
when 'false'
|
121
|
+
false
|
122
|
+
else
|
123
|
+
expected_value
|
124
|
+
end
|
125
|
+
list = Maze::Server.list_for(request_type)
|
126
|
+
payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
127
|
+
assert_equal_with_nullability(expected_bool, payload_value)
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_numeric_platform_values(request_type, field_path, platform_values)
|
131
|
+
expected_value = get_expected_platform_value(platform_values)
|
132
|
+
return if should_skip_platform_check(expected_value)
|
133
|
+
|
134
|
+
list = Maze::Server.list_for(request_type)
|
135
|
+
payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
136
|
+
|
137
|
+
# Need to do a little more processing here to allow floats
|
138
|
+
special_value = expected_value.eql?('@null') || expected_value.eql?('@not_null')
|
139
|
+
expectation = special_value ? expected_value : expected_value.to_f
|
140
|
+
assert_equal_with_nullability(expectation, payload_value)
|
141
|
+
end
|
142
|
+
|
143
|
+
def assert_equal_with_nullability(expected_value, payload_value)
|
144
|
+
case expected_value
|
145
|
+
when '@null'
|
146
|
+
Maze.check.nil(payload_value)
|
147
|
+
when '@not_null'
|
148
|
+
Maze.check.not_nil(payload_value)
|
149
|
+
else
|
150
|
+
Maze.check.equal(expected_value, payload_value)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def get_expected_platform_value(platform_values)
|
155
|
+
os = Maze::Helper.get_current_platform
|
156
|
+
expected_value = Hash[platform_values.raw][os.downcase]
|
157
|
+
raise("There is no expected value for the current platform \"#{os}\"") if expected_value.nil?
|
158
|
+
|
159
|
+
expected_value
|
160
|
+
end
|
161
|
+
|
162
|
+
def should_skip_platform_check(expected_value)
|
163
|
+
expected_value.eql?('@skip')
|
164
|
+
end
|
165
|
+
|
166
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
167
|
+
# @step_input field_path [String] The field to test
|
168
|
+
# @step_input platform_values [DataTable] A table of acceptable regexes for each platform
|
169
|
+
Then('the {request_type} payload field {string} matches the platform-dependent regex:') do |request_type, field_path, platform_regexes|
|
170
|
+
match_string_platform_regexes(request_type, field_path, platform_regexes)
|
171
|
+
end
|
172
|
+
|
173
|
+
# See `the error payload field {string} equals the platform-dependent string:`
|
174
|
+
#
|
175
|
+
# @step_input field_path [String] The field to test, prepended with "events.0"
|
176
|
+
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
177
|
+
Then('the event {string} matches the platform-dependent regex:') do |field_path, platform_regexes|
|
178
|
+
match_string_platform_regexes('error', "events.0.#{field_path}", platform_regexes)
|
179
|
+
end
|
180
|
+
|
181
|
+
# @step_input field_path [String] The field to test, prepended with "events.0.exceptions.0."
|
182
|
+
# @step_input platform_values [DataTable] A table of acceptable regexes for each platform
|
183
|
+
Then('the exception {string} matches the platform-dependent regex:') do |field_path, platform_regexes|
|
184
|
+
match_string_platform_regexes('error', "events.0.exceptions.0.#{field_path}", platform_regexes)
|
185
|
+
end
|
186
|
+
|
187
|
+
# @step_input field_path [String] The field to test, prepended with "events.0.exceptions.0.stacktrace.#!{num}"
|
188
|
+
# @step_input num [Integer] The index of the stack frame to test
|
189
|
+
# @step_input platform_values [DataTable] A table of acceptable values for each platform
|
190
|
+
Then('the {string} of stack frame {int} matches the platform-dependent regex:') do |field_path, num, platform_regexes|
|
191
|
+
match_string_platform_regexes('error', "events.0.exceptions.0.stacktrace.#{num}.#{field_path}", platform_regexes)
|
192
|
+
end
|
193
|
+
|
194
|
+
#
|
195
|
+
# Regex match routines
|
196
|
+
#
|
197
|
+
def match_string_platform_regexes(request_type, field_path, platform_values)
|
198
|
+
expected_regex = get_expected_platform_value(platform_values)
|
199
|
+
return if should_skip_platform_check(expected_regex)
|
200
|
+
list = Maze::Server.list_for(request_type)
|
201
|
+
payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
202
|
+
|
203
|
+
Maze.check.match(expected_regex, payload_value)
|
204
|
+
end
|
@@ -175,6 +175,62 @@ module Maze
|
|
175
175
|
}
|
176
176
|
end
|
177
177
|
|
178
|
+
|
179
|
+
def get_ids(api_key, project_name = nil)
|
180
|
+
base_url = 'https://cloud.bitbar.com/api/me/projects?limit=100'
|
181
|
+
url = project_name ? "#{base_url}&filter=name_eq_#{project_name}" : base_url
|
182
|
+
|
183
|
+
uri = URI.parse(url)
|
184
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
185
|
+
http.use_ssl = true
|
186
|
+
|
187
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
188
|
+
request.basic_auth(api_key, '')
|
189
|
+
|
190
|
+
begin
|
191
|
+
response = http.request(request)
|
192
|
+
raise "HTTP request failed with code #{response.code}" unless response.is_a?(Net::HTTPSuccess)
|
193
|
+
json_body_data = JSON.parse(response.body)['data']
|
194
|
+
json_body_data.map { |project| [project['id'], project['name']] }
|
195
|
+
rescue JSON::ParserError
|
196
|
+
raise 'Failed to parse JSON response'
|
197
|
+
rescue StandardError => e
|
198
|
+
raise "An error occurred: #{e.message}"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def get_unsuccessful_runs(api_key, project_id, date)
|
203
|
+
new_date = date_to_milliseconds(date)
|
204
|
+
url = URI.parse("https://cloud.bitbar.com/api/me/projects/#{project_id}/runs?filter=successRatio_eq_0.0;d_createTime_on_#{new_date}")
|
205
|
+
|
206
|
+
http = Net::HTTP.new(url.host, url.port)
|
207
|
+
http.use_ssl = true
|
208
|
+
|
209
|
+
request = Net::HTTP::Get.new(url.request_uri)
|
210
|
+
request.basic_auth(api_key, '')
|
211
|
+
|
212
|
+
begin
|
213
|
+
response = http.request(request)
|
214
|
+
raise "HTTP request failed with code #{response.code}" unless response.is_a?(Net::HTTPSuccess)
|
215
|
+
JSON.parse(response.body)['data']
|
216
|
+
rescue JSON::ParserError
|
217
|
+
raise 'Failed to parse JSON response'
|
218
|
+
rescue StandardError => e
|
219
|
+
raise "An error occurred: #{e.message}"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def date_to_milliseconds(date_string)
|
224
|
+
begin
|
225
|
+
date_format = "%Y-%m-%d"
|
226
|
+
parsed_date = DateTime.strptime(date_string, date_format)
|
227
|
+
milliseconds = (parsed_date.to_time.to_f * 1000).to_i
|
228
|
+
milliseconds
|
229
|
+
rescue ArgumentError
|
230
|
+
raise "Invalid date format. Please use YYYY-MM-DD."
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
178
234
|
private
|
179
235
|
|
180
236
|
def start_tunnel_thread(cmd)
|
data/lib/maze/driver/appium.rb
CHANGED
@@ -81,15 +81,41 @@ module Maze
|
|
81
81
|
$logger.warn "StaleElementReferenceError occurred: #{e}"
|
82
82
|
false
|
83
83
|
end
|
84
|
+
rescue Selenium::WebDriver::Error::ServerError => e
|
85
|
+
# Assume the remote appium session has stopped, so crash out of the session
|
86
|
+
Maze.driver = nil
|
87
|
+
raise e
|
84
88
|
else
|
85
89
|
true
|
86
90
|
end
|
87
91
|
|
92
|
+
# A wrapper around launch_app adding extra error handling
|
93
|
+
def launch_app
|
94
|
+
super
|
95
|
+
rescue Selenium::WebDriver::Error::ServerError => e
|
96
|
+
# Assume the remote appium session has stopped, so crash out of the session
|
97
|
+
Maze.driver = nil
|
98
|
+
raise e
|
99
|
+
end
|
100
|
+
|
101
|
+
# A wrapper around close_app adding extra error handling
|
102
|
+
def close_app
|
103
|
+
super
|
104
|
+
rescue Selenium::WebDriver::Error::ServerError => e
|
105
|
+
# Assume the remote appium session has stopped, so crash out of the session
|
106
|
+
Maze.driver = nil
|
107
|
+
raise e
|
108
|
+
end
|
109
|
+
|
88
110
|
# A wrapper around find_element adding timer functionality
|
89
111
|
def find_element_timed(element_id)
|
90
112
|
@find_element_timer.time do
|
91
113
|
find_element(@element_locator, element_id)
|
92
114
|
end
|
115
|
+
rescue Selenium::WebDriver::Error::ServerError => e
|
116
|
+
# Assume the remote appium session has stopped, so crash out of the session
|
117
|
+
Maze.driver = nil
|
118
|
+
raise e
|
93
119
|
end
|
94
120
|
|
95
121
|
# Clicks a given element
|
@@ -100,6 +126,10 @@ module Maze
|
|
100
126
|
@click_element_timer.time do
|
101
127
|
element.click
|
102
128
|
end
|
129
|
+
rescue Selenium::WebDriver::Error::ServerError => e
|
130
|
+
# Assume the remote appium session has stopped, so crash out of the session
|
131
|
+
Maze.driver = nil
|
132
|
+
raise e
|
103
133
|
end
|
104
134
|
|
105
135
|
# Clicks a given element, ignoring any NoSuchElementError
|
@@ -114,6 +144,10 @@ module Maze
|
|
114
144
|
true
|
115
145
|
rescue Selenium::WebDriver::Error::NoSuchElementError
|
116
146
|
false
|
147
|
+
rescue Selenium::WebDriver::Error::ServerError => e
|
148
|
+
# Assume the remote appium session has stopped, so crash out of the session
|
149
|
+
Maze.driver = nil
|
150
|
+
raise e
|
117
151
|
end
|
118
152
|
|
119
153
|
# Clears a given element
|
@@ -124,6 +158,10 @@ module Maze
|
|
124
158
|
@clear_element_timer.time do
|
125
159
|
element.clear
|
126
160
|
end
|
161
|
+
rescue Selenium::WebDriver::Error::ServerError => e
|
162
|
+
# Assume the remote appium session has stopped, so crash out of the session
|
163
|
+
Maze.driver = nil
|
164
|
+
raise e
|
127
165
|
end
|
128
166
|
|
129
167
|
# Gets the application hierarchy XML
|
@@ -145,6 +183,10 @@ module Maze
|
|
145
183
|
@send_keys_timer.time do
|
146
184
|
element.send_keys(text)
|
147
185
|
end
|
186
|
+
rescue Selenium::WebDriver::Error::ServerError => e
|
187
|
+
# Assume the remote appium session has stopped, so crash out of the session
|
188
|
+
Maze.driver = nil
|
189
|
+
raise e
|
148
190
|
end
|
149
191
|
|
150
192
|
# Sets the rotation of the device
|
@@ -178,6 +220,10 @@ module Maze
|
|
178
220
|
@send_keys_timer.time do
|
179
221
|
element.send_keys(text)
|
180
222
|
end
|
223
|
+
rescue Selenium::WebDriver::Error::ServerError => e
|
224
|
+
# Assume the remote appium session has stopped, so crash out of the session
|
225
|
+
Maze.driver = nil
|
226
|
+
raise e
|
181
227
|
end
|
182
228
|
|
183
229
|
# Reset the currently running application after a given timeout
|
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.12.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.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Kirkland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cucumber
|
@@ -322,6 +322,7 @@ description: Automation steps and mock server to validaterequest payloads respon
|
|
322
322
|
email:
|
323
323
|
- steve@bugsnag.com
|
324
324
|
executables:
|
325
|
+
- bb-failed-sessions
|
325
326
|
- bugsnag-print-load-paths
|
326
327
|
- download-logs
|
327
328
|
- maze-runner
|
@@ -330,6 +331,7 @@ executables:
|
|
330
331
|
extensions: []
|
331
332
|
extra_rdoc_files: []
|
332
333
|
files:
|
334
|
+
- bin/bb-failed-sessions
|
333
335
|
- bin/bugsnag-print-load-paths
|
334
336
|
- bin/download-logs
|
335
337
|
- bin/maze-runner
|
@@ -356,6 +358,7 @@ files:
|
|
356
358
|
- lib/features/steps/multipart_request_steps.rb
|
357
359
|
- lib/features/steps/network_steps.rb
|
358
360
|
- lib/features/steps/payload_steps.rb
|
361
|
+
- lib/features/steps/platform_dependent_steps.rb
|
359
362
|
- lib/features/steps/proxy_steps.rb
|
360
363
|
- lib/features/steps/query_parameter_steps.rb
|
361
364
|
- lib/features/steps/request_assertion_steps.rb
|