bugsnag-maze-runner 7.22.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/bin/bugsnag-print-load-paths +6 -0
  3. data/bin/download-logs +74 -0
  4. data/bin/maze-runner +174 -0
  5. data/bin/upload-app +56 -0
  6. data/lib/features/scripts/await-android-emulator.sh +11 -0
  7. data/lib/features/scripts/clear-android-app-data.sh +8 -0
  8. data/lib/features/scripts/force-stop-android-app.sh +8 -0
  9. data/lib/features/scripts/install-android-app.sh +15 -0
  10. data/lib/features/scripts/launch-android-app.sh +38 -0
  11. data/lib/features/scripts/launch-android-emulator.sh +15 -0
  12. data/lib/features/steps/android_steps.rb +51 -0
  13. data/lib/features/steps/app_automator_steps.rb +228 -0
  14. data/lib/features/steps/aws_sam_steps.rb +212 -0
  15. data/lib/features/steps/breadcrumb_steps.rb +80 -0
  16. data/lib/features/steps/browser_steps.rb +93 -0
  17. data/lib/features/steps/build_api_steps.rb +25 -0
  18. data/lib/features/steps/document_server_steps.rb +7 -0
  19. data/lib/features/steps/error_reporting_steps.rb +358 -0
  20. data/lib/features/steps/feature_flag_steps.rb +190 -0
  21. data/lib/features/steps/header_steps.rb +72 -0
  22. data/lib/features/steps/log_steps.rb +29 -0
  23. data/lib/features/steps/multipart_request_steps.rb +142 -0
  24. data/lib/features/steps/network_steps.rb +135 -0
  25. data/lib/features/steps/payload_steps.rb +257 -0
  26. data/lib/features/steps/proxy_steps.rb +34 -0
  27. data/lib/features/steps/query_parameter_steps.rb +31 -0
  28. data/lib/features/steps/request_assertion_steps.rb +186 -0
  29. data/lib/features/steps/runner_steps.rb +428 -0
  30. data/lib/features/steps/session_tracking_steps.rb +116 -0
  31. data/lib/features/steps/trace_steps.rb +206 -0
  32. data/lib/features/steps/value_steps.rb +119 -0
  33. data/lib/features/support/env.rb +7 -0
  34. data/lib/features/support/internal_hooks.rb +207 -0
  35. data/lib/maze/api/appium/file_manager.rb +29 -0
  36. data/lib/maze/appium_server.rb +112 -0
  37. data/lib/maze/assertions/request_set_assertions.rb +97 -0
  38. data/lib/maze/aws/sam.rb +112 -0
  39. data/lib/maze/aws_public_ip.rb +53 -0
  40. data/lib/maze/bugsnag_config.rb +42 -0
  41. data/lib/maze/checks/assert_check.rb +69 -0
  42. data/lib/maze/checks/noop_check.rb +34 -0
  43. data/lib/maze/client/appium/base_client.rb +131 -0
  44. data/lib/maze/client/appium/bb_client.rb +102 -0
  45. data/lib/maze/client/appium/bb_devices.rb +127 -0
  46. data/lib/maze/client/appium/bs_client.rb +91 -0
  47. data/lib/maze/client/appium/bs_devices.rb +141 -0
  48. data/lib/maze/client/appium/bs_legacy_client.rb +31 -0
  49. data/lib/maze/client/appium/local_client.rb +67 -0
  50. data/lib/maze/client/appium.rb +23 -0
  51. data/lib/maze/client/bb_api_client.rb +102 -0
  52. data/lib/maze/client/bb_client_utils.rb +181 -0
  53. data/lib/maze/client/bs_client_utils.rb +168 -0
  54. data/lib/maze/client/selenium/base_client.rb +15 -0
  55. data/lib/maze/client/selenium/bb_browsers.yml +188 -0
  56. data/lib/maze/client/selenium/bb_client.rb +38 -0
  57. data/lib/maze/client/selenium/bs_browsers.yml +257 -0
  58. data/lib/maze/client/selenium/bs_client.rb +89 -0
  59. data/lib/maze/client/selenium/local_client.rb +16 -0
  60. data/lib/maze/client/selenium.rb +16 -0
  61. data/lib/maze/compare.rb +161 -0
  62. data/lib/maze/configuration.rb +182 -0
  63. data/lib/maze/docker.rb +147 -0
  64. data/lib/maze/document_server.rb +46 -0
  65. data/lib/maze/driver/appium.rb +198 -0
  66. data/lib/maze/driver/browser.rb +124 -0
  67. data/lib/maze/errors.rb +52 -0
  68. data/lib/maze/generator.rb +55 -0
  69. data/lib/maze/helper.rb +122 -0
  70. data/lib/maze/hooks/appium_hooks.rb +55 -0
  71. data/lib/maze/hooks/browser_hooks.rb +15 -0
  72. data/lib/maze/hooks/command_hooks.rb +9 -0
  73. data/lib/maze/hooks/error_code_hook.rb +49 -0
  74. data/lib/maze/hooks/hooks.rb +61 -0
  75. data/lib/maze/http_request.rb +21 -0
  76. data/lib/maze/interactive_cli.rb +173 -0
  77. data/lib/maze/logger.rb +86 -0
  78. data/lib/maze/macos_utils.rb +14 -0
  79. data/lib/maze/maze_output.rb +88 -0
  80. data/lib/maze/network.rb +49 -0
  81. data/lib/maze/option/parser.rb +240 -0
  82. data/lib/maze/option/processor.rb +130 -0
  83. data/lib/maze/option/validator.rb +155 -0
  84. data/lib/maze/option.rb +62 -0
  85. data/lib/maze/plugins/bugsnag_reporting_plugin.rb +49 -0
  86. data/lib/maze/plugins/cucumber_report_plugin.rb +101 -0
  87. data/lib/maze/plugins/error_code_plugin.rb +21 -0
  88. data/lib/maze/plugins/global_retry_plugin.rb +38 -0
  89. data/lib/maze/proxy.rb +114 -0
  90. data/lib/maze/request_list.rb +87 -0
  91. data/lib/maze/request_repeater.rb +49 -0
  92. data/lib/maze/retry_handler.rb +67 -0
  93. data/lib/maze/runner.rb +149 -0
  94. data/lib/maze/schemas/OtelTraceSchema.json +390 -0
  95. data/lib/maze/schemas/trace_schema.rb +7 -0
  96. data/lib/maze/schemas/trace_validator.rb +98 -0
  97. data/lib/maze/server.rb +251 -0
  98. data/lib/maze/servlets/base_servlet.rb +27 -0
  99. data/lib/maze/servlets/command_servlet.rb +47 -0
  100. data/lib/maze/servlets/log_servlet.rb +64 -0
  101. data/lib/maze/servlets/reflective_servlet.rb +70 -0
  102. data/lib/maze/servlets/servlet.rb +199 -0
  103. data/lib/maze/servlets/temp.rb +0 -0
  104. data/lib/maze/servlets/trace_servlet.rb +13 -0
  105. data/lib/maze/store.rb +15 -0
  106. data/lib/maze/terminating_server.rb +129 -0
  107. data/lib/maze/timers.rb +51 -0
  108. data/lib/maze/wait.rb +35 -0
  109. data/lib/maze.rb +27 -0
  110. data/lib/utils/deep_merge.rb +17 -0
  111. data/lib/utils/selenium_money_patch.rb +17 -0
  112. metadata +451 -0
@@ -0,0 +1,257 @@
1
+ # Selenium capabilities for browsers available on BrowserStack
2
+ ---
3
+ ie_8:
4
+ browserName: "ie"
5
+ browserVersion: "8"
6
+ os: "windows"
7
+ osVersion: "7"
8
+
9
+ ie_9:
10
+ browserName: "ie"
11
+ browserVersion: "9"
12
+ os: "windows"
13
+ osVersion: "7"
14
+
15
+ ie_10:
16
+ browserName: "ie"
17
+ browserVersion: "10"
18
+ os: "windows"
19
+ osVersion: "8"
20
+
21
+ ie_11:
22
+ browserName: "ie"
23
+ browserVersion: "11"
24
+ os: "windows"
25
+ osVersion: "10"
26
+
27
+ edge_14:
28
+ browserName: "edge"
29
+ browserVersion: "14"
30
+ os: "windows"
31
+ osVersion: "10"
32
+
33
+ edge_15:
34
+ browserName: "edge"
35
+ browserVersion: "15"
36
+ os: "windows"
37
+ osVersion: "10"
38
+
39
+ edge_17:
40
+ browser: "edge"
41
+ browser_version: "17"
42
+ os: "windows"
43
+ os_version: "10"
44
+
45
+ edge_80:
46
+ browser: "edge"
47
+ browser_version: "80"
48
+ os: "windows"
49
+ os_version: "11"
50
+
51
+ safari_6:
52
+ browserName: "safari"
53
+ browserVersion: "6"
54
+ os: "OS X"
55
+ osVersion: "lion"
56
+
57
+ safari_10:
58
+ browserName: "safari"
59
+ browserVersion: "10.0"
60
+ os: "OS X"
61
+ osVersion: "sierra"
62
+
63
+ safari_11:
64
+ browserName: "safari"
65
+ browserVersion: "11.1"
66
+ os: "OS X"
67
+ osVersion: "High Sierra"
68
+
69
+ safari_13:
70
+ browserName: "Safari"
71
+ browserVersion: "13.0"
72
+ os: "OS X"
73
+ osVersion: "Catalina"
74
+
75
+ safari_14:
76
+ browserName: "Safari"
77
+ browserVersion: "14.0"
78
+ os: "OS X"
79
+ osVersion: "Big Sur"
80
+
81
+ safari_15:
82
+ browserName: "Safari"
83
+ browserVersion: "15.0"
84
+ os: "OS X"
85
+ osVersion: "Monterey"
86
+
87
+ safari_16:
88
+ browserName: "Safari"
89
+ browserVersion: "16.0"
90
+ os: "OS X"
91
+ osVersion: "Ventura"
92
+
93
+ iphone_6s:
94
+ browserName: "iphone"
95
+ device: "iPhone 6S"
96
+ os: "ios"
97
+ osVersion: "9.0"
98
+ realMobile: true
99
+
100
+ iphone_7:
101
+ browserName: "iphone"
102
+ device: "iPhone 7"
103
+ os: "ios"
104
+ osVersion: "10.3"
105
+ realMobile: true
106
+
107
+ iphone_x:
108
+ browserName: "iphone"
109
+ device: "iPhone X"
110
+ os: "ios"
111
+ osVersion: "11"
112
+ realMobile: true
113
+
114
+ iphone_xs:
115
+ browserName: "iphone"
116
+ device: "iPhone XS"
117
+ os: "ios"
118
+ osVersion: "12"
119
+ realMobile: true
120
+
121
+ iphone_13:
122
+ browserName: "iphone"
123
+ device: "iPhone 13"
124
+ os: "ios"
125
+ osVersion: "15.4"
126
+ realMobile: true
127
+
128
+ android_nexus5:
129
+ browserName: "Android Browser"
130
+ device: "Google Nexus 5"
131
+ os: "android"
132
+ osVersion: "4.4"
133
+ realMobile: true
134
+
135
+ android_s6:
136
+ browserName: "Android Browser"
137
+ device: "Samsung Galaxy S6"
138
+ os: "android"
139
+ osVersion: "5.0"
140
+ realMobile: true
141
+
142
+ android_s7:
143
+ browserName: "Android Browser"
144
+ device: "Samsung Galaxy S7"
145
+ os: "android"
146
+ osVersion: "6.0"
147
+ realMobile: true
148
+
149
+ android_s8:
150
+ browserName: "Android Browser"
151
+ device: "Samsung Galaxy S8 Plus"
152
+ os: "android"
153
+ osVersion: "7.0"
154
+ realMobile: true
155
+
156
+ firefox_30:
157
+ browserName: "firefox"
158
+ browserVersion: "30"
159
+ os: "windows"
160
+ osVersion: "7"
161
+
162
+ firefox_56:
163
+ browserName: "firefox"
164
+ browserVersion: "56"
165
+ os: "windows"
166
+ osVersion: "10"
167
+
168
+ firefox_60:
169
+ browserName: "firefox"
170
+ browserVersion: "60"
171
+ os: "windows"
172
+ osVersion: "10"
173
+
174
+ firefox_78:
175
+ browser: "firefox"
176
+ browser_version: "78"
177
+ os: "windows"
178
+ os_version: "10"
179
+
180
+ firefox_latest:
181
+ browserName: "firefox"
182
+ browserVersion: "latest"
183
+ os: "windows"
184
+ osVersion: "10"
185
+
186
+ chrome_30:
187
+ browserName: "chrome"
188
+ browserVersion: "30.0"
189
+ os: "windows"
190
+ osVersion: "7"
191
+
192
+ chrome_32:
193
+ browserName: "chrome"
194
+ browserVersion: "32.0"
195
+ os: "windows"
196
+ osVersion: "7"
197
+
198
+ chrome_34:
199
+ browserName: "chrome"
200
+ browserVersion: "34.0"
201
+ os: "windows"
202
+ osVersion: "7"
203
+
204
+ chrome_36:
205
+ browserName: "chrome"
206
+ browserVersion: "36.0"
207
+ os: "windows"
208
+ osVersion: "7"
209
+
210
+ chrome_38:
211
+ browserName: "chrome"
212
+ browserVersion: "38.0"
213
+ os: "windows"
214
+ osVersion: "7"
215
+
216
+ chrome_40:
217
+ browserName: "chrome"
218
+ browserVersion: "40.0"
219
+ os: "windows"
220
+ osVersion: "7"
221
+
222
+ chrome_42:
223
+ browserName: "chrome"
224
+ browserVersion: "42.0"
225
+ os: "windows"
226
+ osVersion: "7"
227
+
228
+ chrome_43:
229
+ browserName: "chrome"
230
+ browserVersion: "43.0"
231
+ os: "windows"
232
+ osVersion: "7"
233
+
234
+ chrome_53:
235
+ browser: "chrome"
236
+ browser_version: "53.0"
237
+ os: "windows"
238
+ os_version: "10"
239
+
240
+ chrome_61:
241
+ browserName: "chrome"
242
+ browserVersion: "61.0"
243
+ os: "windows"
244
+ osVersion: "10"
245
+
246
+ chrome_72:
247
+ browser: "chrome"
248
+ browser_version: "72.0"
249
+ os: "windows"
250
+ os_version: "10"
251
+
252
+ chrome_latest:
253
+ browserName: "chrome"
254
+ browserVersion: "latest"
255
+ os: "windows"
256
+ osVersion: "10"
257
+ seleniumVersion: "3.14.0"
@@ -0,0 +1,89 @@
1
+ require 'selenium-webdriver'
2
+
3
+ module Maze
4
+ module Client
5
+ module Selenium
6
+ class BrowserStackClient < BaseClient
7
+ def start_session
8
+ # Set up the capabilities
9
+ browsers = YAML.safe_load(File.read("#{__dir__}/bs_browsers.yml"))
10
+
11
+ config = Maze.config
12
+ browser = browsers[config.browser]
13
+
14
+ if config.legacy_driver?
15
+ capabilities = ::Selenium::WebDriver::Remote::Capabilities.new
16
+ capabilities['browserstack.local'] = 'true'
17
+ capabilities['browserstack.localIdentifier'] = Maze.run_uuid
18
+ capabilities['browserstack.console'] = 'errors'
19
+
20
+ # Convert W3S capabilities to JSON-WP
21
+ capabilities['browser'] = browser['browserName']
22
+ capabilities['browser_version'] = browser['browserVersion']
23
+ capabilities['device'] = browser['device']
24
+ capabilities['os'] = browser['os']
25
+ capabilities['os_version'] = browser['osVersion']
26
+
27
+ capabilities.merge! JSON.parse(config.capabilities_option)
28
+ capabilities.merge! project_name_capabilities
29
+ config.capabilities = capabilities
30
+ else
31
+ capabilities = {
32
+ 'bstack:options' => {
33
+ 'local' => 'true',
34
+ 'localIdentifier' => Maze.run_uuid
35
+ }
36
+ }
37
+ capabilities.deep_merge! browser
38
+ capabilities.deep_merge! JSON.parse(config.capabilities_option)
39
+ capabilities.merge! project_name_capabilities
40
+ config.capabilities = ::Selenium::WebDriver::Remote::Capabilities.new capabilities
41
+ end
42
+
43
+ # Start the tunnel
44
+ Maze::Client::BrowserStackClientUtils.start_local_tunnel config.bs_local,
45
+ Maze.run_uuid,
46
+ config.access_key
47
+
48
+ # Start the driver
49
+ selenium_url = "https://#{config.username}:#{config.access_key}@hub.browserstack.com/wd/hub"
50
+ Maze.driver = Maze::Driver::Browser.new :remote, selenium_url, config.capabilities
51
+ Maze.driver.start_driver
52
+
53
+ # Log details for the session
54
+ log_session_info
55
+ end
56
+
57
+ def stop_session
58
+ super
59
+ Maze::Client::BrowserStackClientUtils.stop_local_tunnel
60
+ end
61
+
62
+ private
63
+
64
+ # Determines and returns sensible project and build capabilities
65
+ #
66
+ # @return [Hash] A hash containing the 'project' and 'build' capabilities
67
+ def project_name_capabilities
68
+ # Default to values for running locally
69
+ project = 'local'
70
+
71
+ if ENV['BUILDKITE']
72
+ # Project
73
+ project = ENV['BUILDKITE_PIPELINE_NAME']
74
+ end
75
+ {
76
+ project: project,
77
+ build: Maze.run_uuid
78
+ }
79
+ end
80
+
81
+ def log_session_info
82
+ # Log a link to the BrowserStack session search dashboard
83
+ url = "https://automate.browserstack.com/dashboard/v2/search?query=#{Maze.run_uuid}&type=builds"
84
+ $logger.info Maze::LogUtil.linkify url, 'BrowserStack session(s)'
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,16 @@
1
+ module Maze
2
+ module Client
3
+ module Selenium
4
+ class LocalClient < BaseClient
5
+ def start_session
6
+ Maze.driver = Maze::Driver::Browser.new Maze.config.browser.to_sym
7
+ Maze.driver.start_driver
8
+ end
9
+
10
+ def stop_session
11
+ # No need to quit the local driver
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Maze
2
+ module Client
3
+ module Selenium
4
+ def self.start
5
+ client_class =
6
+ case Maze.config.farm
7
+ when :bb then BitBarClient
8
+ when :bs then BrowserStackClient
9
+ when :local then LocalClient
10
+ end
11
+
12
+ client_class.new.tap(&:start_session)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maze
4
+ # Routines for conducting comparisons
5
+ module Compare
6
+ # Provides a way to delivering results of element comparisons to test steps
7
+ class Result
8
+ # @!attribute [r] reasons
9
+ # @return [Array] An array of reasons for a comparison result
10
+ attr_reader :reasons
11
+
12
+ # @!attribute [w] equal
13
+ # @param [Boolean] Indicates if the comparison indicated the elements were equal
14
+ attr_writer :equal
15
+
16
+ # @!attribute [r] keys
17
+ # @return [Array] An array of keys checked
18
+ attr_reader :keys
19
+
20
+ # Creates the Result object
21
+ def initialize
22
+ @equal = true
23
+ @keys = []
24
+ @reasons = []
25
+ end
26
+
27
+ # Indicates if the values compared to produced this result were equal
28
+ #
29
+ # @return [Boolean] Whether the elements were equal
30
+ def equal?
31
+ @equal
32
+ end
33
+
34
+ # Returns the keys traversed in order to compare the end values
35
+ #
36
+ # @return [String] The keypath used in the test
37
+ def keypath
38
+ keys.length > 0 ? keys.reverse.join('.') : '<root>'
39
+ end
40
+
41
+ # Provides a standard assertion of equality, with standardised output
42
+ def assert_equal
43
+ Maze.check.true(@equal, "The compared fields do not match:\n #{result.reasons.join('\n')}")
44
+ end
45
+ end
46
+
47
+ class << self
48
+ # Compares two objects for value equality, traversing to compare each
49
+ # nested object.
50
+ #
51
+ # @param obj1 [Any] The first object to compare
52
+ # @param obj2 [Any] The second object to compare
53
+ # @param result [Result|nil] Optional. Used for comparing recursively
54
+ #
55
+ # @return [Result] The result of comparing the objects
56
+ def value(obj1, obj2, result = nil)
57
+ result ||= Result.new
58
+ return result if obj1 == 'IGNORE'
59
+
60
+ if obj1 == 'NUMBER'
61
+ if obj2.is_a?(Numeric)
62
+ return result
63
+ else
64
+ result.equal = false
65
+ result.reasons << "A Number was expected, '#{obj2.class} received"
66
+ return result
67
+ end
68
+ end
69
+
70
+ unless obj1.class == obj2.class
71
+ result.equal = false
72
+ result.reasons << "Object types differ - expected '#{obj1.class}', received '#{obj2.class}'"
73
+ return result
74
+ end
75
+
76
+ case obj1
77
+ when Array
78
+ array(obj1, obj2, result)
79
+ when Hash
80
+ hash(obj1, obj2, result)
81
+ when String
82
+ string(obj1, obj2, result)
83
+ else
84
+ result.reasons << "#{obj1} is not equal to #{obj2}" unless (result.equal = (obj1 == obj2))
85
+ end
86
+ result
87
+ end
88
+
89
+ # Compares two arrays for value equality, traversing and comparing each element.
90
+ # Results are written to the given Result object.
91
+ #
92
+ # @param array1 [Array] The first array to compare
93
+ # @param array2 [Array] The second array to compare
94
+ # @param result [Result] The Result to store the results
95
+ def array(array1, array2, result)
96
+ unless array1.length == array2.length
97
+ result.equal = false
98
+ result.reasons << "Expected #{array1.length} items in array, received #{array2.length}"
99
+ return
100
+ end
101
+
102
+ array1.each_with_index do |obj1, index|
103
+ value(obj1, array2[index], result)
104
+ unless result.equal?
105
+ result.keys << index.to_s
106
+ break
107
+ end
108
+ end
109
+ end
110
+
111
+ # Compares two hashes for value equality, traversing and comparing each key-value pair.
112
+ # Results are written to the given Result object.
113
+ #
114
+ # @param hash1 [Hash] The first hash to compare
115
+ # @param hash2 [Hash] The second hash to compare
116
+ # @param result [Result] The Result to store the results
117
+ def hash(hash1, hash2, result)
118
+ unless hash1.keys.length == hash2.keys.length
119
+ result.equal = false
120
+ missing = hash1.keys - hash2.keys
121
+ unexpected = hash2.keys - hash1.keys
122
+ result.reasons << "Missing keys from hash: #{missing.join(',')}" unless missing.empty?
123
+ result.reasons << "Unexpected keys in hash: #{unexpected.join(',')}" unless unexpected.empty?
124
+ return
125
+ end
126
+
127
+ hash1.each do |key, value|
128
+ value(value, hash2[key], result)
129
+ unless result.equal?
130
+ result.keys << key
131
+ break
132
+ end
133
+ end
134
+ end
135
+
136
+ # Compares two strings, writing the results to the given Result object.
137
+ #
138
+ # @param template [String] The expected string
139
+ # @param str2 [String] The string to compare
140
+ # @param result [Result] The Result to store the results
141
+ def string(template, str2, result)
142
+ return if template == str2 || regex_match(template, str2)
143
+
144
+ result.equal = false
145
+ result.reasons << "'#{str2}' does not match '#{template}'"
146
+ end
147
+
148
+ # Matches a string against a regex
149
+ #
150
+ # @param template [String] The regex to test with
151
+ # @param value [String] The value to test
152
+ #
153
+ # @return [Boolean] Whether the regex produced a match
154
+ def regex_match(template, value)
155
+ regex = template
156
+ regex = "^#{regex}$" unless regex.start_with?('^') || regex.end_with?('$')
157
+ value =~ /#{regex}/
158
+ end
159
+ end
160
+ end
161
+ end