bugsnag-maze-runner 9.11.2 → 9.12.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d720cd78e4048822fe49b967ff002b17569eb6919f4bcf63b2c7b261ffafb13
4
- data.tar.gz: eba331593b17b2670b83b3df6a6c947b0bb519c6d0542695a524bd44c1401b59
3
+ metadata.gz: 325db4804e14fcf97c4cb8f53782676a597d29975d1ead996810979e94466207
4
+ data.tar.gz: 9b63455da005c6e4a1db345c74301801538425573c1fc02737034b0717a81e46
5
5
  SHA512:
6
- metadata.gz: 761cbce7919681956370c78e7641eecee28592272446bbfaf8fbadd374ff0b910018cd6c2f60ae37f6ae29780f7e638adcaa5aa5b5a1590d55e22ac355f9e35a
7
- data.tar.gz: d29abfbdc4b50decb86214502f92b06d83cc16916fb3bf8b5137aebf489907f5b23889ac92b4199746adcfca72fb2c79b77ae8872ca6ef1ac5862492cc137bd0
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)
@@ -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.11.2'
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.11.2
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-18 00:00:00.000000000 Z
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