bugsnag-maze-runner 9.36.0 → 10.1.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: fea2efe5108b520669c020cb35a9e03a4ab9bc7f88a6136ed866aab64641a4af
4
- data.tar.gz: 6940e0f5213b8c62bc73bb2888dc81f7946fbbffcb06316b499946a03f7580b8
3
+ metadata.gz: d59bb98b603f22702c5da83fc40f70e12dcba5553b1177075dea770c97a154a3
4
+ data.tar.gz: d0e404e19355099925754b022ac30f00d56050beb8d1740e8c1ced2b32705d4f
5
5
  SHA512:
6
- metadata.gz: 4243f48064e91757b1fb549bff897e0d9d9398076ac4e1fb0ac0512d391b3aa317038c042d679b80403337de4d06651d565ea2af564c045a5be146241e72efda
7
- data.tar.gz: '0580471cf0ca9ab9de0e278806357c00d20adeacf4b5f577ae7b3fc6e4c1c8cc203bb0cccc9479d865757c1fe6f8cee34965d95d7ecb283842069cb7605d0afc'
6
+ metadata.gz: 11e455f30a38488c0169b7f21536c295ab007ed8dfae1afcce8fe34fb3461ee2e7d93b6db35fb746989ca28bd7ece7fa97ead621b0eb421764a4e03e6c9e2772
7
+ data.tar.gz: 970798d5594c687c269f9d3043fc70e86808d63098fdc9017a226bb71c08422dc6cf55634c025f877c52cd750c39ad80d5b625d8f5184e304f94883d034b75cf
data/bin/maze-runner CHANGED
@@ -29,7 +29,6 @@ require_relative '../lib/maze/client/appium/base_client'
29
29
  require_relative '../lib/maze/client/appium/bb_client'
30
30
  require_relative '../lib/maze/client/appium/bb_devices'
31
31
  require_relative '../lib/maze/client/appium/bs_client'
32
- require_relative '../lib/maze/client/appium/bs_legacy_client'
33
32
  require_relative '../lib/maze/client/appium/bs_devices'
34
33
  require_relative '../lib/maze/client/appium/local_client'
35
34
  require_relative '../lib/maze/client/appium/session_metadata'
@@ -42,7 +41,6 @@ require_relative '../lib/maze/client/selenium/local_client'
42
41
  require_relative '../lib/maze/aws_public_ip'
43
42
  require_relative '../lib/maze/compare'
44
43
  require_relative '../lib/maze/docker'
45
- require_relative '../lib/maze/document_server'
46
44
  require_relative '../lib/maze/errors'
47
45
  require_relative '../lib/maze/generator'
48
46
  require_relative '../lib/maze/helper'
@@ -49,38 +49,9 @@ When('I send the app to the background for {int} second(s)') do |timeout|
49
49
  Maze::Api::Appium::AppManager.new.background(timeout)
50
50
  end
51
51
 
52
- # Clears a given element
53
- # Requires a running Appium driver
54
- #
55
- # @step_input element_id [String] The locator id
56
- # @deprecated To be removed in the next major version
57
- When('I clear the element {string}') do |element_id|
58
- Maze.driver.clear_element(element_id)
59
- end
60
-
61
- # Sends keys to a given element
62
- # Requires a running Appium driver
63
- #
64
- # @step_input keys [String] The keys to send to the element
65
- # @step_input element_id [String] The locator id
66
- # @deprecated To be removed in the next major version
67
- When('I send the keys {string} to the element {string}') do |keys, element_id|
68
- Maze.driver.send_keys_to_element(element_id, keys)
69
- end
70
-
71
52
  # Set the device orientation to either portrait or landscape
72
53
  # Requires a running Appium driver
73
54
  When('I set the device orientation to {orientation}') do |orientation|
74
55
  Maze::Api::Appium::DeviceManager.new.set_rotation orientation
75
56
  end
76
57
 
77
- # Sends keys to a given element, clearing it first
78
- # Requires a running Appium driver
79
- #
80
- # @step_input keys [String] The keys to send to the element
81
- # @step_input element_id [String] The locator id
82
- # @deprecated To be removed in the next major version
83
- When('I clear and send the keys {string} to the element {string}') do |keys, element_id|
84
- Maze.driver.clear_and_send_keys_to_element(element_id, keys)
85
- end
86
-
@@ -136,14 +136,6 @@ Then('the event {string} equals {float} to {int} decimal place(s)') do |field, f
136
136
  step "the error payload field \"events.0.#{field}\" equals #{float_value} to #{places} decimal places"
137
137
  end
138
138
 
139
- # Tests whether a value in the first event entry equals an integer.
140
- #
141
- # @step_input field [String] The relative location of the value to test
142
- # @step_input value [Integer] The integer to test against
143
- Then('the event {string} equals {int}') do |field, value|
144
- step "the error payload field \"events.0.#{field}\" equals #{value}"
145
- end
146
-
147
139
  # Tests whether a value in the first event entry starts with a string.
148
140
  #
149
141
  # @step_input field [String] The relative location of the value to test
@@ -76,16 +76,6 @@ Then('the {request_type} payload field {string} is not null') do |request_type,
76
76
  Maze.check.not_nil(Maze::Helper.read_key_path(list.current[:body], field_path))
77
77
  end
78
78
 
79
- # Tests that a payload element equals an integer.
80
- #
81
- # @step_input request_type [String] The type of request (error, session, build, etc)
82
- # @step_input field_path [String] Path to the tested element
83
- # @step_input int_value [Integer] The value to test against
84
- Then('the {request_type} payload field {string} equals {int}') do |request_type, field_path, int_value|
85
- Maze.check.equal(int_value,
86
- Maze::Helper.read_key_path(Maze::Server.list_for(request_type).current[:body], field_path))
87
- end
88
-
89
79
  # Tests that a payload element equals a float.
90
80
  #
91
81
  # @step_input request_type [String] The type of request (error, session, build, etc)
@@ -12,16 +12,16 @@ BeforeAll do
12
12
 
13
13
  # Infer mode of operation from config, one of:
14
14
  # - Appium (using either remote or local devices)
15
- # - Browser (Selenium with local or remote browsers)
15
+ # - Selenium (Selenium with local or remote browsers)
16
16
  # - Command (the software under test is invoked with a system call)
17
- # TODO Consider making this a specific command line option defaulting to Appium
18
- is_appium = [:bs, :bb, :local].include?(Maze.config.farm) && !Maze.config.app.nil?
19
- is_browser = !Maze.config.browser.nil?
17
+ is_appium = ([:bs, :bb, :local].include?(Maze.config.farm) && !Maze.config.app.nil?) ||
18
+ (Maze.config.farm == :bb && !Maze.config.device.nil? && !Maze.config.browser.nil?)
19
+ is_browser = Maze.config.device.nil? && !Maze.config.browser.nil?
20
20
  if is_appium
21
21
  Maze.mode = :appium
22
22
  Maze.internal_hooks = Maze::Hooks::AppiumHooks.new
23
23
  elsif is_browser
24
- Maze.mode = :browser
24
+ Maze.mode = :selenium
25
25
  Maze.internal_hooks = Maze::Hooks::BrowserHooks.new
26
26
  else
27
27
  Maze.mode = :command
@@ -57,20 +57,11 @@ BeforeAll do
57
57
  # Call any blocks registered by the client
58
58
  Maze.hooks.call_before_all
59
59
 
60
- # Start document server, if asked for
61
- # This must happen after any client hooks have run, so that they can set the server root
62
- Maze::DocumentServer.start unless Maze.config.document_server_root.nil?
63
-
64
60
  # Determine public IP if enabled
65
61
  if Maze.config.aws_public_ip
66
62
  public_ip = Maze::AwsPublicIp.new
67
63
  Maze.public_address = public_ip.address
68
64
  $logger.info "Public address: #{Maze.public_address}"
69
-
70
- unless Maze.config.document_server_root.nil?
71
- Maze.public_document_server_address = public_ip.document_server_address
72
- $logger.info "Public document server address: #{Maze.public_document_server_address}"
73
- end
74
65
  end
75
66
 
76
67
  # An initial setup for total success status
@@ -102,7 +93,7 @@ Before do |scenario|
102
93
 
103
94
  # Skip scenario if the driver it needs has failed
104
95
  $logger.debug "Before hook - Maze.driver&.failed?: #{Maze.driver&.failed?}"
105
- if (Maze.mode == :appium || Maze.mode == :browser) && Maze.driver.failed?
96
+ if (Maze.mode == :appium || Maze.mode == :selenium) && Maze.driver.failed?
106
97
  $logger.debug "Failing scenario because the #{Maze.mode.to_s} driver failed: #{Maze.driver.failure_reason}"
107
98
  scenario.fail('Cannot run scenario - driver failed')
108
99
  end
@@ -146,9 +137,6 @@ After do |scenario|
146
137
  # Call any blocks registered by the client
147
138
  Maze.hooks.call_after scenario
148
139
 
149
- # Stop document server if started by the Cucumber step
150
- Maze::DocumentServer.manual_stop
151
-
152
140
  # Stop terminating server if started by the Cucumber step
153
141
  Maze::TerminatingServer.stop
154
142
 
@@ -253,7 +241,7 @@ After do |scenario|
253
241
 
254
242
  # Fail the scenario if the driver failed, if the scenario hasn't already failed
255
243
  $logger.debug "After hook 2 - Maze.driver&.failed?: #{Maze.driver&.failed?}"
256
- if (Maze.mode == :appium || Maze.mode == :browser) && Maze.driver.failed? && !scenario.failed?
244
+ if (Maze.mode == :appium || Maze.mode == :selenium) && Maze.driver.failed? && !scenario.failed?
257
245
  $logger.debug "Marking scenario as failed because driver failed: #{Maze.driver.failure_reason}"
258
246
  Maze.scenario.mark_as_failed Maze.driver.failure_reason
259
247
  end
@@ -5,29 +5,17 @@ module Maze
5
5
  class AwsPublicIp
6
6
  attr_reader :host
7
7
  attr_reader :port
8
- attr_reader :document_server_port
9
8
 
10
9
  def address
11
10
  "#{@ip}:#{@port}"
12
11
  end
13
12
 
14
- def document_server_address
15
- return nil if @document_server_port.nil?
16
-
17
- "#{@ip}:#{@document_server_port}"
18
- end
19
-
20
13
  def initialize
21
14
  # This class is only relevant on Buildkite
22
15
  return unless ENV['BUILDKITE']
23
16
 
24
17
  @ip = determine_public_ip
25
18
  @port = determine_public_port Maze.config.port
26
-
27
- unless Maze.config.document_server_root.nil?
28
- @document_server_port = determine_public_port Maze.config.document_server_port
29
- end
30
-
31
19
  end
32
20
 
33
21
  # Determines the public IP address of the running AWS instance
@@ -29,21 +29,20 @@ module Maze
29
29
  start_driver(Maze.config)
30
30
 
31
31
  # Set bundle/app id for later use
32
- Maze.driver.app_id = case Maze::Helper.get_current_platform
33
- when 'android'
34
- Maze.driver.session_capabilities['appPackage']
35
- when 'ios'
36
- unless app_id = Maze.driver.session_capabilities['CFBundleIdentifier']
37
- app_id = Maze.driver.session_capabilities['bundleId']
32
+ unless Maze.config.app.nil?
33
+ Maze.driver.app_id = case Maze::Helper.get_current_platform
34
+ when 'android'
35
+ Maze.driver.session_capabilities['appPackage']
36
+ when 'ios'
37
+ unless app_id = Maze.driver.session_capabilities['CFBundleIdentifier']
38
+ app_id = Maze.driver.session_capabilities['bundleId']
39
+ end
40
+ app_id
38
41
  end
39
- app_id
40
- end
41
-
42
- if Maze.driver.app_id.nil?
43
- $logger.error "Failed to determine app id."
44
- $logger.debug "session_capabilities: #{Maze.driver.session_capabilities.inspect}"
45
42
  end
46
43
 
44
+ $logger.error "Failed to determine app id." if Maze.driver.app_id.nil?
45
+
47
46
  # Log the device information after it's started
48
47
  write_device_info
49
48
 
@@ -5,7 +5,7 @@ module Maze
5
5
  def prepare_session
6
6
  config = Maze.config
7
7
  config.app = Maze::Client::BitBarClientUtils.upload_app config.access_key,
8
- config.app
8
+ config.app if config.app
9
9
  if Maze::Client::BitBarClientUtils.use_local_tunnel?
10
10
  Maze::Client::BitBarClientUtils.start_local_tunnel config.sb_local,
11
11
  config.username,
@@ -51,7 +51,7 @@ module Maze
51
51
  end
52
52
 
53
53
  def start_scenario
54
- unless Maze.config.legacy_driver?
54
+ unless Maze.config.browser
55
55
  # Write Maze's address to file and push to the device
56
56
  maze_address = Maze.public_address || "local:#{Maze.config.port}"
57
57
  Maze::Api::Appium::FileManager.new.write_app_file(JSON.generate({ maze_address: maze_address }),
@@ -83,6 +83,10 @@ module Maze
83
83
  capabilities.deep_merge! BitBarClientUtils.dashboard_capabilities
84
84
  capabilities.deep_merge! BitBarDevices.get_available_device(config.device)
85
85
  capabilities['bitbar:options']['appiumVersion'] = config.appium_version unless config.appium_version.nil?
86
+ unless config.browser.nil?
87
+ capabilities['bitbar:options']['acceptInsecureCerts'] = true
88
+ capabilities['browserName'] = config.browser
89
+ end
86
90
  capabilities.deep_merge! JSON.parse(config.capabilities_option)
87
91
 
88
92
  capabilities
@@ -31,12 +31,10 @@ module Maze
31
31
  end
32
32
 
33
33
  def start_scenario
34
- unless Maze.config.legacy_driver?
35
- # Write Maze's address to file and push to the device
36
- maze_address = "bs-local.com:#{Maze.config.port}"
37
- Maze::Api::Appium::FileManager.new.write_app_file(JSON.generate({ maze_address: maze_address }),
38
- FIXTURE_CONFIG)
39
- end
34
+ # Write Maze's address to file and push to the device
35
+ maze_address = "bs-local.com:#{Maze.config.port}"
36
+ Maze::Api::Appium::FileManager.new.write_app_file(JSON.generate({ maze_address: maze_address }),
37
+ FIXTURE_CONFIG)
40
38
 
41
39
  super
42
40
  end
@@ -5,14 +5,7 @@ module Maze
5
5
  client_class =
6
6
  case Maze.config.farm
7
7
  when :bb then BitBarClient
8
- when :bs
9
- if Maze.config.legacy_driver?
10
- $logger.info 'Using the Legacy (JWP) Appium client'
11
- BrowserStackLegacyClient
12
- else
13
- $logger.info 'Using the W3C Appium client'
14
- BrowserStackClient
15
- end
8
+ when :bs then BrowserStackClient
16
9
  when :local then LocalClient
17
10
  end
18
11
 
@@ -23,45 +23,23 @@ module Maze
23
23
  end
24
24
 
25
25
  def create_capabilities(config)
26
- if config.legacy_driver?
27
- capabilities = ::Selenium::WebDriver::Remote::Capabilities.new
28
- capabilities['browserstack.local'] = 'true'
29
- capabilities['browserstack.localIdentifier'] = Maze.run_uuid
30
- capabilities['browserstack.console'] = 'errors'
31
- capabilities['acceptInsecureCerts'] = 'true'
32
- capabilities.merge! JSON.parse(config.capabilities_option)
33
- capabilities.merge! project_name_capabilities
34
- add_browser_capabilities(config, capabilities)
35
- else
36
- raw_capabilities = {
37
- 'acceptInsecureCerts' => true,
38
- 'bstack:options' => {
39
- 'local' => 'true',
40
- 'localIdentifier' => Maze.run_uuid
41
- }
26
+ raw_capabilities = {
27
+ 'acceptInsecureCerts' => true,
28
+ 'bstack:options' => {
29
+ 'local' => 'true',
30
+ 'localIdentifier' => Maze.run_uuid
42
31
  }
43
- raw_capabilities.deep_merge! JSON.parse(config.capabilities_option)
44
- raw_capabilities.merge! project_name_capabilities
45
- add_browser_capabilities(config, raw_capabilities)
46
- capabilities = ::Selenium::WebDriver::Remote::Capabilities.new raw_capabilities
47
- end
32
+ }
33
+ raw_capabilities.deep_merge! JSON.parse(config.capabilities_option)
34
+ raw_capabilities.merge! project_name_capabilities
35
+ add_browser_capabilities(config, raw_capabilities)
36
+ capabilities = ::Selenium::WebDriver::Remote::Capabilities.new raw_capabilities
48
37
  config.capabilities = capabilities
49
38
  end
50
39
 
51
40
  def add_browser_capabilities(config, capabilities)
52
41
  browsers = YAML.safe_load(File.read("#{__dir__}/bs_browsers.yml"))
53
- browser = browsers[config.browser]
54
-
55
- if config.legacy_driver?
56
- # Convert W3S capabilities to JSON-WP
57
- capabilities['browser'] = browser['browserName']
58
- capabilities['browser_version'] = browser['browserVersion']
59
- capabilities['device'] = browser['device']
60
- capabilities['os'] = browser['os']
61
- capabilities['os_version'] = browser['osVersion']
62
- else
63
- capabilities.deep_merge! browser
64
- end
42
+ capabilities.deep_merge! browsers[config.browser]
65
43
  end
66
44
 
67
45
  def stop_session
@@ -15,7 +15,6 @@ module Maze
15
15
  self.span_timestamp_validation = true
16
16
  self.unmanaged_traces_mode = false
17
17
  self.client_mode_validation = true
18
- @legacy_driver = false
19
18
  end
20
19
 
21
20
  #
@@ -41,12 +40,6 @@ module Maze
41
40
  # Document server root
42
41
  attr_accessor :document_server_root
43
42
 
44
- # Document server bind address
45
- attr_accessor :document_server_bind_address
46
-
47
- # Document server port
48
- attr_accessor :document_server_port
49
-
50
43
  #
51
44
  # Common configuration
52
45
  #
@@ -194,15 +187,6 @@ module Maze
194
187
  # URL of the Selenium server
195
188
  attr_accessor :selenium_server_url
196
189
 
197
- # Whether the legacy (JSON-WP) Appium driver should be used
198
- def legacy_driver?
199
- @legacy_driver
200
- end
201
-
202
- def legacy_driver=(value)
203
- @legacy_driver = value
204
- end
205
-
206
190
  #
207
191
  # Local testing specific configuration
208
192
  #
@@ -40,8 +40,6 @@ module Maze
40
40
  # Timers
41
41
  @find_element_timer = Maze.timers.add 'Appium - find element'
42
42
  @click_element_timer = Maze.timers.add 'Appium - click element'
43
- @clear_element_timer = Maze.timers.add 'Appium - clear element'
44
- @send_keys_timer = Maze.timers.add 'Appium - send keys to element'
45
43
 
46
44
  super({
47
45
  'caps' => @capabilities,
@@ -82,6 +80,33 @@ module Maze
82
80
  @failure_reason = reason
83
81
  end
84
82
 
83
+ def javascript?
84
+ return false if Maze.config.browser.nil?
85
+ @driver.execute_script('return true')
86
+ rescue Selenium::WebDriver::Error::UnsupportedOperationError
87
+ false
88
+ end
89
+
90
+
91
+ # Provided for mobile browsers - check if the browser supports local storage
92
+ def local_storage?
93
+ # Assume we can use local storage if we aren't able to verify by running JavaScript
94
+ return true unless javascript?
95
+
96
+ result = @driver.execute_script <<-JAVASCRIPT
97
+ try {
98
+ window.localStorage.setItem('__localstorage_test__', 1234)
99
+ window.localStorage.removeItem('__localstorage_test__')
100
+ return true
101
+ } catch (err) {
102
+ return err
103
+ }
104
+ JAVASCRIPT
105
+
106
+ result == true
107
+ end
108
+
109
+
85
110
  # Checks for an element, waiting until it is present or the method times out
86
111
  #
87
112
  # @param element_id [String] the element to search for
@@ -168,20 +193,6 @@ module Maze
168
193
  raise e
169
194
  end
170
195
 
171
- # Clears a given element
172
- #
173
- # @param element_id [String] the element to clear
174
- def clear_element(element_id)
175
- element = find_element_timed(element_id)
176
- @clear_element_timer.time do
177
- element.clear
178
- end
179
- rescue Selenium::WebDriver::Error::ServerError => e
180
- # Assume the remote appium session has stopped, so crash out of the session
181
- fail_driver(e)
182
- raise e
183
- end
184
-
185
196
  # Gets the application hierarchy XML
186
197
  def page_source
187
198
  @driver.page_source
@@ -192,21 +203,6 @@ module Maze
192
203
  @driver.unlock
193
204
  end
194
205
 
195
- # Sends keys to a given element
196
- #
197
- # @param element_id [String] the element to send text to
198
- # @param text [String] the text to send
199
- def send_keys_to_element(element_id, text)
200
- element = find_element_timed(element_id)
201
- @send_keys_timer.time do
202
- element.send_keys(text)
203
- end
204
- rescue Selenium::WebDriver::Error::ServerError => e
205
- # Assume the remote appium session has stopped, so crash out of the session
206
- fail_driver(e)
207
- raise e
208
- end
209
-
210
206
  # Sets the rotation of the device
211
207
  #
212
208
  # @param orientation [Symbol] :portrait or :landscape
@@ -218,40 +214,6 @@ module Maze
218
214
  @driver.window_size
219
215
  end
220
216
 
221
- # Send keys to the device without a specific element
222
- #
223
- # @param text [String] the text to send
224
- def send_keys(text)
225
- @driver.send_keys(text)
226
- end
227
-
228
- # Sends keys to a given element, clearing it first
229
- #
230
- # @param element_id [String] the element to clear and send text to
231
- # @param text [String] the text to send
232
- def clear_and_send_keys_to_element(element_id, text)
233
- element = find_element_timed(element_id)
234
- @clear_element_timer.time do
235
- element.clear
236
- end
237
-
238
- @send_keys_timer.time do
239
- element.send_keys(text)
240
- end
241
- rescue Selenium::WebDriver::Error::ServerError => e
242
- # Assume the remote appium session has stopped, so crash out of the session
243
- fail_driver(e)
244
- raise e
245
- end
246
-
247
- # Reset the currently running application after a given timeout
248
- #
249
- # @param timeout [Number] the amount of time in seconds to wait before resetting
250
- def reset_with_timeout(timeout = 0.1)
251
- sleep(timeout)
252
- reset
253
- end
254
-
255
217
  def device_info
256
218
  driver.execute_script('mobile:deviceInfo')
257
219
  end
@@ -58,7 +58,7 @@ module Maze
58
58
 
59
59
  # check if Selenium supports running javascript in the current browser
60
60
  def javascript?
61
- @driver.execute_script('return true')
61
+ !Maze.config.browser.nil? && @driver.execute_script('return true')
62
62
  rescue Selenium::WebDriver::Error::UnsupportedOperationError
63
63
  false
64
64
  end
@@ -128,15 +128,9 @@ module Maze
128
128
  $logger.info "Starting Selenium driver"
129
129
  time = Time.now
130
130
  if driver_for == :remote
131
- if Maze.config.legacy_driver?
132
- driver = ::Selenium::WebDriver.for :remote,
133
- url: selenium_url,
134
- desired_capabilities: @capabilities
135
- else
136
- driver = ::Selenium::WebDriver.for :remote,
137
- url: selenium_url,
138
- capabilities: @capabilities
139
- end
131
+ driver = ::Selenium::WebDriver.for :remote,
132
+ url: selenium_url,
133
+ capabilities: @capabilities
140
134
  else
141
135
  if driver_for == :chrome
142
136
  options = Selenium::WebDriver::Options.chrome
data/lib/maze/helper.rb CHANGED
@@ -89,7 +89,7 @@ module Maze
89
89
  # Returns the current platform all lower-case.
90
90
  # @return Typically 'ios', 'android', 'mac' or 'browser'
91
91
  def get_current_platform
92
- if Maze.mode == :browser
92
+ if Maze.mode == :selenium || (Maze.mode == :appium && Maze.config.browser)
93
93
  os = 'browser'
94
94
  else
95
95
  os = case Maze.config.farm
@@ -29,7 +29,7 @@ module Maze
29
29
  if Maze.config.os == 'macos'
30
30
  # Close the app - without the sleep launching the app for the next scenario intermittently fails
31
31
  system("killall -KILL #{Maze.config.app} && sleep 1")
32
- elsif [:bb, :bs, :local].include? Maze.config.farm
32
+ elsif [:bb, :bs, :local].include?(Maze.config.farm) && Maze.config.browser.nil?
33
33
  close_fallback = Maze.config.appium_version && Maze.config.appium_version.to_f < 2.0
34
34
  begin
35
35
  manager.terminate(!close_fallback)
@@ -45,7 +45,7 @@ module Maze
45
45
  # Reset the server before relaunching the app to ensure that test fixtures cannot fetch
46
46
  # commands from the previous scenario (in idempotent mode).
47
47
  Maze::Server.reset!
48
- manager.activate
48
+ manager.activate if Maze.config.browser.nil?
49
49
  end
50
50
  rescue => error
51
51
  # Notify and re-raise for Cucumber to handle
@@ -85,14 +85,6 @@ module Maze
85
85
  'Document server root',
86
86
  short: :none,
87
87
  type: :string
88
- opt Option::DS_BIND_ADDRESS,
89
- 'Document server bind address',
90
- short: :none,
91
- type: :string
92
- opt Option::DS_PORT,
93
- 'Document server port',
94
- short: :none,
95
- default: 9340
96
88
 
97
89
  text ''
98
90
  text 'Appium options:'
@@ -29,8 +29,6 @@ module Maze
29
29
 
30
30
  # Document server options
31
31
  config.document_server_root = options[Maze::Option::DS_ROOT]
32
- config.document_server_bind_address = options[Maze::Option::DS_BIND_ADDRESS]
33
- config.document_server_port = options[Maze::Option::DS_PORT]
34
32
 
35
33
  # Logger options
36
34
  config.file_log = options[Maze::Option::FILE_LOG]
@@ -52,7 +50,6 @@ module Maze
52
50
  config.capabilities_option = options[Maze::Option::CAPABILITIES]
53
51
  config.app_activity = options[Maze::Option::APP_ACTIVITY]
54
52
  config.app_package = options[Maze::Option::APP_PACKAGE]
55
- config.legacy_driver = !ENV['USE_LEGACY_DRIVER'].nil?
56
53
  config.start_tunnel = options[Maze::Option::TUNNEL]
57
54
 
58
55
  # Farm specific options
@@ -63,11 +60,7 @@ module Maze
63
60
  if !device_option.empty?
64
61
  config.device = device_option.first
65
62
  config.device_list = device_option.drop(1)
66
- if config.legacy_driver?
67
- config.os_version = Maze::Client::Appium::BrowserStackDevices::DEVICE_HASH[config.device]['os_version'].to_f
68
- else
69
- config.os_version = Maze::Client::Appium::BrowserStackDevices::DEVICE_HASH[config.device]['platformVersion'].to_f
70
- end
63
+ config.os_version = Maze::Client::Appium::BrowserStackDevices::DEVICE_HASH[config.device]['platformVersion'].to_f
71
64
  elsif !browser_option.empty?
72
65
  config.browser = browser_option.first
73
66
  config.browser_list = browser_option.drop(1)
@@ -84,7 +77,12 @@ module Maze
84
77
  device_option = options[Maze::Option::DEVICE]
85
78
  browser_option = options[Maze::Option::BROWSER]
86
79
  browser_version = options[Maze::Option::BROWSER_VERSION]
87
- if !device_option.empty?
80
+ if !device_option.empty? && !browser_option.empty?
81
+ config.device = device_option.first
82
+ config.device_list = device_option.drop(1)
83
+ config.browser = browser_option.first
84
+ config.browser_list = browser_option.drop(1)
85
+ elsif !device_option.empty?
88
86
  config.device = device_option.first
89
87
  config.device_list = device_option.drop(1)
90
88
  elsif !browser_option.empty?
@@ -113,7 +113,8 @@ module Maze
113
113
  # Device
114
114
  if browser.empty? && device.empty?
115
115
  errors << "Either --#{Option::BROWSER} or --#{Option::DEVICE} must be specified"
116
- elsif !browser.empty?
116
+ elsif !browser.empty? && device.empty?
117
+ # Desktop browsers (Selenium)
117
118
  browsers = YAML.safe_load(File.read("#{__dir__}/../client/selenium/bb_browsers.yml"))
118
119
 
119
120
  rejected_browsers = browser.reject { |br| browsers.include? br }
@@ -129,7 +130,8 @@ module Maze
129
130
  errors << "Browser types '#{rejected_browsers.join(', ')}' unknown on BitBar. Must be one of: #{browser_list}."
130
131
  end
131
132
 
132
- elsif !device.empty?
133
+ elsif browser.empty? && !device.empty?
134
+ # Mobile app testing
133
135
  app = Maze::Helper.read_at_arg_file options[Option::APP]
134
136
  if app.nil?
135
137
  errors << "--#{Option::APP} must be provided when running on a device"
@@ -140,6 +142,8 @@ module Maze
140
142
  errors << "app file '#{app}' not found" unless File.exist?(app)
141
143
  end
142
144
  end
145
+ else
146
+ # TODO - Mobile browser testing
143
147
  end
144
148
  end
145
149
 
data/lib/maze/option.rb CHANGED
@@ -3,10 +3,6 @@
3
3
  # Provides the set of Maze Runner command line options
4
4
  module Maze
5
5
  module Option
6
- # Document server options
7
- DS_BIND_ADDRESS = 'document-server-bind-address'
8
- DS_PORT = 'document-server-port'
9
-
10
6
  # Server options
11
7
  HTTPS = 'https'
12
8
  BIND_ADDRESS = 'bind-address'
@@ -23,7 +23,7 @@ module Maze
23
23
  configuration.options[:retry] = 0
24
24
 
25
25
  # Guard to check if the case should be retried
26
- should_retry = event.result.failed? && Maze::RetryHandler.should_retry?(test_case, event)
26
+ should_retry = event.result.failed? && Maze::RetryHandler.should_retry?(test_case)
27
27
 
28
28
  next unless should_retry
29
29
 
@@ -14,25 +14,11 @@ module Maze
14
14
  # Determines whether a failed test_case should be restarted
15
15
  #
16
16
  # @param test_case [Cucumber::RunningTestCase] The current test_case or scenario
17
- # @param event [Cucumber::Core::Event] The triggering event
18
- def should_retry?(test_case, event)
17
+ def should_retry?(test_case)
19
18
  # Only retry if the option is set and we haven't already retried
20
19
  return false if !Maze.config.enable_retries || retried_previously?(test_case)
21
20
 
22
- if retry_on_driver_error?(event)
23
- if Maze.mode == :appium
24
- if Maze.config.farm.eql?(:bb)
25
- Maze::Hooks::ErrorCodeHook.exit_code = Maze::Api::ExitCode::APPIUM_SESSION_FAILURE
26
- return false
27
- else
28
- $logger.warn "Retrying #{test_case.name} due to appium driver error: #{event.result.exception}"
29
- Maze.driver.restart
30
- end
31
- elsif Maze.mode == :browser
32
- $logger.warn "Retrying #{test_case.name} due to selenium driver error: #{event.result.exception}"
33
- Maze.driver.refresh
34
- end
35
- elsif retry_on_tag?(test_case)
21
+ if retry_on_tag?(test_case)
36
22
  $logger.warn "Retrying #{test_case.name} due to retry tag"
37
23
  elsif Maze.dynamic_retry
38
24
  $logger.warn "Retrying #{test_case.name} due to dynamic retry set"
@@ -53,12 +39,6 @@ module Maze
53
39
  global_retried[test_case] += 1
54
40
  end
55
41
 
56
- def retry_on_driver_error?(event)
57
- error_class = event.result.exception.class
58
- maze_errors = Maze::Error::ERROR_CODES
59
- Maze.driver && maze_errors.include?(error_class) && maze_errors[error_class][:retry]
60
- end
61
-
62
42
  def retry_on_tag?(test_case)
63
43
  test_case.tags.any? do |tag|
64
44
  RETRY_TAGS.include?(tag.name)
data/lib/maze.rb CHANGED
@@ -8,11 +8,11 @@ require_relative 'maze/timers'
8
8
  # providing an alternative to the proliferation of global variables or singletons.
9
9
  module Maze
10
10
 
11
- VERSION = '9.36.0'
11
+ VERSION = '10.1.0'
12
12
 
13
13
  class << self
14
14
  attr_accessor :check, :driver, :internal_hooks, :mode, :start_time, :dynamic_retry, :public_address,
15
- :public_document_server_address, :run_uuid, :scenario
15
+ :run_uuid, :scenario
16
16
 
17
17
  def config
18
18
  @config ||= Maze::Configuration.new
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bugsnag-maze-runner
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.36.0
4
+ version: 10.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Kirkland
8
+ - Josh Edney
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2025-08-26 00:00:00.000000000 Z
12
+ date: 2025-09-02 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: cucumber
@@ -16,14 +17,14 @@ dependencies:
16
17
  requirements:
17
18
  - - "~>"
18
19
  - !ruby/object:Gem::Version
19
- version: '7.1'
20
+ version: '10.0'
20
21
  type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
25
  - - "~>"
25
26
  - !ruby/object:Gem::Version
26
- version: '7.1'
27
+ version: '10.0'
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: os
29
30
  requirement: !ruby/object:Gem::Requirement
@@ -72,14 +73,14 @@ dependencies:
72
73
  requirements:
73
74
  - - "~>"
74
75
  - !ruby/object:Gem::Version
75
- version: 1.7.0
76
+ version: 1.9.0
76
77
  type: :runtime
77
78
  prerelease: false
78
79
  version_requirements: !ruby/object:Gem::Requirement
79
80
  requirements:
80
81
  - - "~>"
81
82
  - !ruby/object:Gem::Version
82
- version: 1.7.0
83
+ version: 1.9.0
83
84
  - !ruby/object:Gem::Dependency
84
85
  name: appium_lib
85
86
  requirement: !ruby/object:Gem::Requirement
@@ -136,20 +137,6 @@ dependencies:
136
137
  - - "~>"
137
138
  - !ruby/object:Gem::Version
138
139
  version: '6.24'
139
- - !ruby/object:Gem::Dependency
140
- name: cucumber-expressions
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: 6.0.0
146
- type: :runtime
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: 6.0.0
153
140
  - !ruby/object:Gem::Dependency
154
141
  name: curb
155
142
  requirement: !ruby/object:Gem::Requirement
@@ -390,7 +377,7 @@ dependencies:
390
377
  version: 0.9.6
391
378
  description: Automation steps and mock server to validaterequest payloads response.
392
379
  email:
393
- - steve@bugsnag.com
380
+ - notifiers@bugsnag.com
394
381
  executables:
395
382
  - bb-failed-sessions
396
383
  - benchmarks-to-datadog
@@ -421,8 +408,6 @@ files:
421
408
  - lib/features/steps/breadcrumb_steps.rb
422
409
  - lib/features/steps/browser_steps.rb
423
410
  - lib/features/steps/build_api_steps.rb
424
- - lib/features/steps/deprecated_steps.rb
425
- - lib/features/steps/document_server_steps.rb
426
411
  - lib/features/steps/error_reporting_steps.rb
427
412
  - lib/features/steps/feature_flag_steps.rb
428
413
  - lib/features/steps/header_steps.rb
@@ -461,7 +446,6 @@ files:
461
446
  - lib/maze/client/appium/bb_devices.rb
462
447
  - lib/maze/client/appium/bs_client.rb
463
448
  - lib/maze/client/appium/bs_devices.rb
464
- - lib/maze/client/appium/bs_legacy_client.rb
465
449
  - lib/maze/client/appium/local_client.rb
466
450
  - lib/maze/client/appium/session_metadata.rb
467
451
  - lib/maze/client/bb_api_client.rb
@@ -477,7 +461,6 @@ files:
477
461
  - lib/maze/compare.rb
478
462
  - lib/maze/configuration.rb
479
463
  - lib/maze/docker.rb
480
- - lib/maze/document_server.rb
481
464
  - lib/maze/driver/appium.rb
482
465
  - lib/maze/driver/browser.rb
483
466
  - lib/maze/error_monitor/assert_error_middleware.rb
@@ -550,7 +533,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
550
533
  requirements:
551
534
  - - ">="
552
535
  - !ruby/object:Gem::Version
553
- version: 2.5.0
536
+ version: '3.1'
554
537
  required_rubygems_version: !ruby/object:Gem::Requirement
555
538
  requirements:
556
539
  - - ">="
@@ -560,5 +543,5 @@ requirements: []
560
543
  rubygems_version: 3.5.3
561
544
  signing_key:
562
545
  specification_version: 4
563
- summary: Bugsnag API request validation harness
546
+ summary: Bugsnag SDK test harness
564
547
  test_files: []
@@ -1,8 +0,0 @@
1
- # @!group Deprecated steps
2
-
3
- # Waits for a given number of spans to be received, which may be spread across one or more trace requests.
4
- #
5
- # @step_input span_count [Integer] The number of spans to wait for
6
- When('I wait for {int} span(s)') do |span_count|
7
- assert_received_spans Maze::Server.list_for('traces'), span_count
8
- end
@@ -1,7 +0,0 @@
1
- # @!group Document steps
2
-
3
- # Starts the document server manually. It will be stopped automatically at the end of each scenario
4
- # (if started in this way).
5
- When('I start the document server') do
6
- Maze::DocumentServer.manual_start
7
- end
@@ -1,31 +0,0 @@
1
- module Maze
2
- module Client
3
- module Appium
4
- class BrowserStackLegacyClient < BrowserStackClient
5
- def device_capabilities
6
- config = Maze.config
7
- capabilities = {
8
- 'app' => config.app,
9
- 'browserstack.console' => 'errors',
10
- 'deviceOrientation' => 'portrait',
11
- 'noReset' => 'true'
12
- }
13
- device_caps = Maze::Client::Appium::BrowserStackDevices::DEVICE_HASH[config.device]
14
- capabilities.deep_merge! device_caps
15
- capabilities.deep_merge! JSON.parse(config.capabilities_option)
16
- capabilities.merge! project_name_capabilities
17
- capabilities['browserstack.appium_version'] = config.appium_version unless config.appium_version.nil?
18
- unless device_caps['platformName'] == 'android' && device_caps['platformVersion'].to_i <= 6
19
- capabilities['disableAnimations'] = 'true'
20
- end
21
- if Maze.config.start_tunnel
22
- capabilities['browserstack.localIdentifier'] = Maze.run_uuid
23
- capabilities['browserstack.local'] = 'true'
24
- end
25
-
26
- capabilities
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'webrick'
4
-
5
- module Maze
6
- # HTTP server for a given document root
7
- class DocumentServer
8
- class << self
9
- # Start the document server. This is intended to be called only once per test run.
10
- # Use manual_start for finer grained control.
11
- def start
12
- @thread = Thread.new do
13
- options = {
14
- DocumentRoot: Maze.config.document_server_root,
15
- Port: Maze.config.document_server_port,
16
- Logger: $logger,
17
- AccessLog: []
18
- }
19
- options[:BindAddress] = Maze.config.document_server_bind_address unless Maze.config.document_server_bind_address.nil?
20
- server = WEBrick::HTTPServer.new(options)
21
- server.mount '/reflect', Servlets::ReflectiveServlet
22
-
23
- $logger.info "Starting document server for root: #{Maze.config.document_server_root}"
24
- server.start
25
- end
26
- end
27
-
28
- # Starts the document server "manually" (via a Cucumber step as opposed to command line option)
29
- def manual_start
30
- if !@thread.nil? && @thread.alive?
31
- $logger.warn 'Document Server has already been started on the command line, ignoring manual start'
32
- return
33
- end
34
- @manual_start = true
35
- start
36
- end
37
-
38
- def manual_stop
39
- return unless @manual_start
40
-
41
- @thread.kill
42
- @manual_start = false
43
- end
44
- end
45
- end
46
- end