bugsnag-maze-runner 6.27.0 → 7.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/download-logs +14 -16
- data/bin/maze-runner +53 -15
- data/bin/upload-app +6 -6
- data/lib/features/steps/breadcrumb_steps.rb +44 -14
- data/lib/features/steps/error_reporting_steps.rb +16 -0
- data/lib/features/steps/network_steps.rb +66 -6
- data/lib/features/steps/payload_steps.rb +23 -0
- data/lib/features/steps/request_assertion_steps.rb +87 -8
- data/lib/features/steps/runner_steps.rb +22 -0
- data/lib/features/steps/session_tracking_steps.rb +1 -1
- data/lib/features/steps/trace_steps.rb +254 -0
- data/lib/features/support/internal_hooks.rb +31 -84
- data/lib/maze/api/appium/file_manager.rb +29 -0
- data/lib/maze/aws_public_ip.rb +53 -0
- data/lib/maze/checks/assert_check.rb +9 -31
- data/lib/maze/client/appium/base_client.rb +131 -0
- data/lib/maze/client/appium/bb_client.rb +102 -0
- data/lib/maze/client/appium/bb_devices.rb +127 -0
- data/lib/maze/client/appium/bs_client.rb +91 -0
- data/lib/maze/client/appium/bs_devices.rb +141 -0
- data/lib/maze/client/appium/bs_legacy_client.rb +31 -0
- data/lib/maze/client/appium/local_client.rb +67 -0
- data/lib/maze/client/appium.rb +23 -0
- data/lib/maze/client/bb_api_client.rb +102 -0
- data/lib/maze/client/bb_client_utils.rb +181 -0
- data/lib/maze/client/bs_client_utils.rb +168 -0
- data/lib/maze/client/selenium/base_client.rb +15 -0
- data/lib/maze/client/selenium/bb_browsers.yml +188 -0
- data/lib/maze/client/selenium/bb_client.rb +38 -0
- data/lib/maze/client/selenium/bs_browsers.yml +257 -0
- data/lib/maze/client/selenium/bs_client.rb +89 -0
- data/lib/maze/client/selenium/local_client.rb +16 -0
- data/lib/maze/client/selenium.rb +16 -0
- data/lib/maze/configuration.rb +18 -10
- data/lib/maze/docker.rb +40 -1
- data/lib/maze/driver/appium.rb +5 -24
- data/lib/maze/driver/browser.rb +12 -26
- data/lib/maze/errors.rb +32 -0
- data/lib/maze/generator.rb +55 -0
- data/lib/maze/helper.rb +7 -3
- data/lib/maze/hooks/appium_hooks.rb +29 -190
- data/lib/maze/hooks/browser_hooks.rb +2 -55
- data/lib/maze/hooks/error_code_hook.rb +49 -0
- data/lib/maze/hooks/hooks.rb +2 -2
- data/lib/maze/http_request.rb +21 -0
- data/lib/maze/logger.rb +16 -3
- data/lib/maze/maze_output.rb +88 -0
- data/lib/maze/option/parser.rb +17 -22
- data/lib/maze/option/processor.rb +21 -34
- data/lib/maze/option/validator.rb +38 -67
- data/lib/maze/option.rb +16 -18
- data/lib/maze/plugins/cucumber_report_plugin.rb +1 -1
- data/lib/maze/plugins/error_code_plugin.rb +21 -0
- data/lib/maze/request_list.rb +10 -5
- data/lib/maze/request_repeater.rb +49 -0
- data/lib/maze/retry_handler.rb +4 -13
- data/lib/maze/schemas/OtelTraceSchema.json +390 -0
- data/lib/maze/schemas/trace_schema.rb +7 -0
- data/lib/maze/schemas/trace_validator.rb +98 -0
- data/lib/maze/server.rb +74 -30
- data/lib/maze/servlets/base_servlet.rb +10 -5
- data/lib/maze/servlets/command_servlet.rb +10 -7
- data/lib/maze/servlets/log_servlet.rb +2 -2
- data/lib/maze/servlets/reflective_servlet.rb +12 -11
- data/lib/maze/servlets/servlet.rb +47 -8
- data/lib/maze/servlets/temp.rb +0 -0
- data/lib/maze/servlets/trace_servlet.rb +13 -0
- data/lib/maze.rb +2 -2
- data/lib/utils/deep_merge.rb +17 -0
- data/lib/utils/selenium_money_patch.rb +17 -0
- metadata +97 -17
- data/lib/maze/bitbar_devices.rb +0 -84
- data/lib/maze/bitbar_utils.rb +0 -112
- data/lib/maze/browser_stack_devices.rb +0 -160
- data/lib/maze/browser_stack_utils.rb +0 -164
- data/lib/maze/browsers_bs.yml +0 -220
- data/lib/maze/browsers_cbt.yml +0 -100
- data/lib/maze/capabilities.rb +0 -126
- data/lib/maze/driver/resilient_appium.rb +0 -51
- data/lib/maze/sauce_labs_utils.rb +0 -96
- data/lib/maze/smart_bear_utils.rb +0 -71
data/lib/maze/server.rb
CHANGED
@@ -9,44 +9,63 @@ require_relative './request_list'
|
|
9
9
|
module Maze
|
10
10
|
# Receives and stores requests through a WEBrick HTTPServer
|
11
11
|
class Server
|
12
|
+
ALLOWED_HTTP_VERBS = %w[OPTIONS GET POST PUT DELETE HEAD TRACE PATCH CONNECT]
|
13
|
+
DEFAULT_RESPONSE_DELAY = 0
|
14
|
+
DEFAULT_SAMPLING_PROBABILITY = 1
|
15
|
+
DEFAULT_STATUS_CODE = 200
|
12
16
|
|
13
17
|
class << self
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
attr_writer :response_delay_ms
|
18
|
+
# Sets the response delay generator.
|
19
|
+
#
|
20
|
+
# @param generator [Maze::Generator] The new generator
|
21
|
+
def set_response_delay_generator(generator)
|
22
|
+
@response_delay_generator&.close
|
23
|
+
@response_delay_generator = generator
|
24
|
+
end
|
22
25
|
|
23
|
-
#
|
24
|
-
|
26
|
+
# Sets the sampling probability generator.
|
27
|
+
#
|
28
|
+
# @param generator [Maze::Generator] The new generator
|
29
|
+
def set_sampling_probability_generator(generator)
|
30
|
+
@sampling_probability_generator&.close
|
31
|
+
@sampling_probability_generator = generator
|
32
|
+
end
|
25
33
|
|
26
|
-
#
|
27
|
-
|
34
|
+
# Sets the status code generator for the HTTP verb given. If no verb is given then the
|
35
|
+
# generator will be shared across all allowable HTTP verbs.
|
36
|
+
#
|
37
|
+
# @param generator [Maze::Generator] The new generator
|
38
|
+
# @param verb [String] HTTP verb
|
39
|
+
def set_status_code_generator(generator, verb = nil)
|
40
|
+
@status_code_generators ||= {}
|
41
|
+
Array(verb || ALLOWED_HTTP_VERBS).each do |verb|
|
42
|
+
old = @status_code_generators[verb]
|
43
|
+
@status_code_generators[verb] = generator
|
44
|
+
|
45
|
+
# Close the old generator unless it's still being used by another verb
|
46
|
+
old&.close unless @status_code_generators.value?(old)
|
47
|
+
end
|
48
|
+
end
|
28
49
|
|
29
50
|
# The intended HTTP status code on a successful request
|
30
51
|
#
|
31
|
-
# @
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
52
|
+
# @param verb [String] HTTP verb for which the status code is wanted
|
53
|
+
#
|
54
|
+
# @return [Integer] The HTTP status code for the verb given
|
55
|
+
def status_code(verb)
|
56
|
+
if @status_code_generators[verb].nil? || @status_code_generators[verb].closed?
|
57
|
+
DEFAULT_STATUS_CODE
|
58
|
+
else
|
59
|
+
@status_code_generators[verb].next
|
60
|
+
end
|
36
61
|
end
|
37
62
|
|
38
|
-
def
|
39
|
-
@
|
63
|
+
def sampling_probability
|
64
|
+
@sampling_probability_generator.next
|
40
65
|
end
|
41
66
|
|
42
67
|
def response_delay_ms
|
43
|
-
|
44
|
-
@response_delay_ms = 0 if reset_response_delay
|
45
|
-
delay
|
46
|
-
end
|
47
|
-
|
48
|
-
def reset_response_delay
|
49
|
-
@reset_response_delay ||= false
|
68
|
+
@response_delay_generator.next
|
50
69
|
end
|
51
70
|
|
52
71
|
# Provides dynamic access to request lists by name
|
@@ -64,6 +83,8 @@ module Maze
|
|
64
83
|
builds
|
65
84
|
when 'log', 'logs'
|
66
85
|
logs
|
86
|
+
when 'trace', 'traces'
|
87
|
+
traces
|
67
88
|
when 'upload', 'uploads'
|
68
89
|
uploads
|
69
90
|
when 'sourcemap', 'sourcemaps'
|
@@ -89,6 +110,13 @@ module Maze
|
|
89
110
|
@sessions ||= RequestList.new
|
90
111
|
end
|
91
112
|
|
113
|
+
# A list of trace requests received
|
114
|
+
#
|
115
|
+
# @return [RequestList] Received error requests
|
116
|
+
def traces
|
117
|
+
@traces ||= RequestList.new
|
118
|
+
end
|
119
|
+
|
92
120
|
# A list of build requests received
|
93
121
|
#
|
94
122
|
# @return [RequestList] Received build requests
|
@@ -145,9 +173,6 @@ module Maze
|
|
145
173
|
# Starts the WEBrick server in a separate thread
|
146
174
|
def start
|
147
175
|
attempts = 0
|
148
|
-
$logger.info 'Starting mock server'
|
149
|
-
@command_uuid = SecureRandom.uuid
|
150
|
-
$logger.info "Fixture commands UUID: #{@command_uuid}"
|
151
176
|
loop do
|
152
177
|
|
153
178
|
@thread = Thread.new do
|
@@ -161,7 +186,7 @@ module Maze
|
|
161
186
|
|
162
187
|
# Mount a block to respond to all requests with status:200
|
163
188
|
server.mount_proc '/' do |_request, response|
|
164
|
-
$logger.
|
189
|
+
$logger.debug 'Received request on server root, responding with 200'
|
165
190
|
response.header['Access-Control-Allow-Origin'] = '*'
|
166
191
|
response.body = 'Maze runner received request'
|
167
192
|
response.status = 200
|
@@ -173,9 +198,11 @@ module Maze
|
|
173
198
|
server.mount '/builds', Servlets::Servlet, :builds
|
174
199
|
server.mount '/uploads', Servlets::Servlet, :uploads
|
175
200
|
server.mount '/sourcemap', Servlets::Servlet, :sourcemaps
|
201
|
+
server.mount '/traces', Servlets::TraceServlet, :traces, Maze::Schemas::TRACE_SCHEMA
|
176
202
|
server.mount '/react-native-source-map', Servlets::Servlet, :sourcemaps
|
177
203
|
server.mount '/command', Servlets::CommandServlet
|
178
204
|
server.mount '/logs', Servlets::LogServlet
|
205
|
+
server.mount '/reflect', Servlets::ReflectiveServlet
|
179
206
|
server.start
|
180
207
|
rescue StandardError => e
|
181
208
|
$logger.warn "Failed to start mock server: #{e.message}"
|
@@ -202,6 +229,23 @@ module Maze
|
|
202
229
|
@thread&.kill if @thread&.alive?
|
203
230
|
@thread = nil
|
204
231
|
end
|
232
|
+
|
233
|
+
def reset!
|
234
|
+
# Reset generators
|
235
|
+
set_response_delay_generator(Maze::Generator.new [DEFAULT_RESPONSE_DELAY].cycle)
|
236
|
+
set_status_code_generator(Maze::Generator.new [DEFAULT_STATUS_CODE].cycle)
|
237
|
+
set_sampling_probability_generator(Maze::Generator.new [DEFAULT_SAMPLING_PROBABILITY].cycle)
|
238
|
+
|
239
|
+
# Clear request lists
|
240
|
+
errors.clear
|
241
|
+
sessions.clear
|
242
|
+
builds.clear
|
243
|
+
uploads.clear
|
244
|
+
sourcemaps.clear
|
245
|
+
traces.clear
|
246
|
+
logs.clear
|
247
|
+
invalid_requests.clear
|
248
|
+
end
|
205
249
|
end
|
206
250
|
end
|
207
251
|
end
|
@@ -11,11 +11,16 @@ module Maze
|
|
11
11
|
# @param response [HTTPResponse] The response to return
|
12
12
|
def do_OPTIONS(request, response)
|
13
13
|
response.header['Access-Control-Allow-Origin'] = '*'
|
14
|
-
response.header['Access-Control-Allow-Headers'] = %w[
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
response.header['Access-Control-Allow-Headers'] = %w[
|
15
|
+
Accept
|
16
|
+
Bugsnag-Api-Key
|
17
|
+
Bugsnag-Integrity
|
18
|
+
Bugsnag-Payload-Version
|
19
|
+
Bugsnag-Sent-At
|
20
|
+
Bugsnag-Span-Sampling
|
21
|
+
Content-Type
|
22
|
+
Origin
|
23
|
+
].join(',')
|
19
24
|
end
|
20
25
|
end
|
21
26
|
end
|
@@ -16,14 +16,15 @@ module Maze
|
|
16
16
|
response.header['Access-Control-Allow-Origin'] = '*'
|
17
17
|
|
18
18
|
commands = Maze::Server.commands
|
19
|
-
|
20
|
-
if commands.
|
21
|
-
response.body = 'No commands
|
22
|
-
response.status =
|
19
|
+
|
20
|
+
if commands.size_remaining == 0
|
21
|
+
response.body = '{"action": "noop", "message": "No commands queued"}'
|
22
|
+
response.status = 200
|
23
23
|
else
|
24
24
|
command = commands.current
|
25
|
-
|
26
|
-
|
25
|
+
command_json = JSON.pretty_generate(command)
|
26
|
+
command[:uuid] = Maze.run_uuid
|
27
|
+
response.body = command_json
|
27
28
|
response.status = 200
|
28
29
|
commands.next
|
29
30
|
end
|
@@ -37,8 +38,10 @@ module Maze
|
|
37
38
|
super
|
38
39
|
|
39
40
|
response.header['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
|
40
|
-
response.status = Server.status_code
|
41
|
+
response.status = Server.status_code('OPTIONS')
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
44
45
|
end
|
46
|
+
|
47
|
+
|
@@ -27,7 +27,7 @@ module Maze
|
|
27
27
|
@requests.add(hash)
|
28
28
|
|
29
29
|
response.header['Access-Control-Allow-Origin'] = '*'
|
30
|
-
response.status = Server.status_code
|
30
|
+
response.status = Server.status_code('POST')
|
31
31
|
rescue JSON::ParserError => e
|
32
32
|
msg = "Unable to parse request as JSON: #{e.message}"
|
33
33
|
$logger.error msg
|
@@ -57,7 +57,7 @@ module Maze
|
|
57
57
|
super
|
58
58
|
|
59
59
|
response.header['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
|
60
|
-
response.status = Server.status_code
|
60
|
+
response.status = Server.status_code('OPTIONS')
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'rack'
|
2
3
|
|
3
4
|
module Maze
|
4
5
|
module Servlets
|
@@ -7,7 +8,7 @@ module Maze
|
|
7
8
|
# - status - HTTP response code
|
8
9
|
# For GET requests these are expected to passed as GET parameters,
|
9
10
|
# for POST requests they are expected to be given as JSON fields.
|
10
|
-
class ReflectiveServlet <
|
11
|
+
class ReflectiveServlet < BaseServlet
|
11
12
|
|
12
13
|
# Accepts a GET request to provide a reflective response to.
|
13
14
|
#
|
@@ -26,17 +27,17 @@ module Maze
|
|
26
27
|
def do_POST(request, response)
|
27
28
|
|
28
29
|
content_type = request['Content-Type']
|
29
|
-
unless content_type == 'application/json'
|
30
|
-
msg = "Content-Type '#{content_type}' not supported - only application/json is supported at present"
|
31
|
-
$logger.error msg
|
32
|
-
response.status = 415
|
33
|
-
response.body = msg
|
34
|
-
return
|
35
|
-
end
|
36
30
|
|
37
|
-
|
38
|
-
|
39
|
-
|
31
|
+
# For JSON, pull the instructions from the body. Otherwise, take them from the query string.
|
32
|
+
if content_type == 'application/json'
|
33
|
+
body = JSON.parse(request.body)
|
34
|
+
delay_ms = body['delay_ms']
|
35
|
+
status = body['status']
|
36
|
+
else
|
37
|
+
query = Rack::Utils.parse_nested_query(request.query_string)
|
38
|
+
delay_ms = query['delay_ms']
|
39
|
+
status = query['status']
|
40
|
+
end
|
40
41
|
|
41
42
|
reflect response, delay_ms, status
|
42
43
|
rescue JSON::ParserError => e
|
@@ -1,18 +1,45 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'zlib'
|
4
|
+
require 'stringio'
|
5
|
+
require 'json_schemer'
|
6
|
+
require 'delegate'
|
7
|
+
|
3
8
|
module Maze
|
9
|
+
class HttpRequest < SimpleDelegator
|
10
|
+
def body
|
11
|
+
@body ||= decode_body
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def decode_body
|
17
|
+
delegate = __getobj__
|
18
|
+
if %r{^gzip$}.match(delegate['Content-Encoding'])
|
19
|
+
gz_element = Zlib::GzipReader.new(StringIO.new(delegate.body))
|
20
|
+
gz_element.read
|
21
|
+
else
|
22
|
+
delegate.body
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
4
27
|
module Servlets
|
5
28
|
|
6
29
|
# Receives and parses the requests and payloads sent from the test fixture
|
7
30
|
class Servlet < BaseServlet
|
31
|
+
prepend RequestRepeater
|
32
|
+
|
8
33
|
# Constructor
|
9
34
|
#
|
10
35
|
# @param server [HTTPServer] WEBrick HTTPServer
|
11
36
|
# @param request_type [Symbol] Request type that the servlet will receive
|
12
|
-
|
37
|
+
# @param schema [Dictionary] A `json-schema` describing the payload for POST requests
|
38
|
+
def initialize(server, request_type, schema=nil)
|
13
39
|
super server
|
14
40
|
@request_type = request_type
|
15
41
|
@requests = Server.list_for request_type
|
42
|
+
@schema = JSONSchemer.schema(schema) unless schema.nil?
|
16
43
|
end
|
17
44
|
|
18
45
|
# Logs an incoming GET WEBrick request.
|
@@ -30,9 +57,11 @@ module Maze
|
|
30
57
|
# @param request [HTTPRequest] The incoming GET request
|
31
58
|
# @param response [HTTPResponse] The response to return
|
32
59
|
def do_POST(request, response)
|
33
|
-
|
34
|
-
|
35
|
-
|
60
|
+
# Turn the WEBrick HttpRequest into our internal HttpRequest delegate
|
61
|
+
request = HttpRequest.new(request)
|
62
|
+
|
63
|
+
content_type = request['Content-Type']
|
64
|
+
if %r{^multipart/form-data; boundary=([^;]+)}.match(content_type)
|
36
65
|
boundary = WEBrick::HTTPUtils::dequote($1)
|
37
66
|
body = WEBrick::HTTPUtils.parse_form_data(request.body, boundary)
|
38
67
|
hash = {
|
@@ -50,6 +79,10 @@ module Maze
|
|
50
79
|
digests: digests
|
51
80
|
}
|
52
81
|
end
|
82
|
+
if @schema
|
83
|
+
schema_errors = @schema.validate(hash[:body])
|
84
|
+
hash[:schema_errors] = schema_errors.to_a
|
85
|
+
end
|
53
86
|
@requests.add(hash)
|
54
87
|
|
55
88
|
# For the response, delaying if configured to do so
|
@@ -58,8 +91,8 @@ module Maze
|
|
58
91
|
$logger.info "Waiting #{response_delay_ms} milliseconds before responding"
|
59
92
|
sleep response_delay_ms / 1000.0
|
60
93
|
end
|
61
|
-
response.header
|
62
|
-
response.status = Server.status_code
|
94
|
+
set_response_header response.header
|
95
|
+
response.status = Server.status_code('POST')
|
63
96
|
rescue JSON::ParserError => e
|
64
97
|
msg = "Unable to parse request as JSON: #{e.message}"
|
65
98
|
if Maze.config.captured_invalid_requests.include? @request_type
|
@@ -89,6 +122,10 @@ module Maze
|
|
89
122
|
end
|
90
123
|
end
|
91
124
|
|
125
|
+
def set_response_header(header)
|
126
|
+
header['Access-Control-Allow-Origin'] = '*'
|
127
|
+
end
|
128
|
+
|
92
129
|
# Logs and returns a set of valid headers for this servlet.
|
93
130
|
#
|
94
131
|
# @param request [HTTPRequest] The incoming GET request
|
@@ -97,7 +134,7 @@ module Maze
|
|
97
134
|
super
|
98
135
|
|
99
136
|
response.header['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
|
100
|
-
response.status = Server.status_code
|
137
|
+
response.status = Server.status_code('OPTIONS')
|
101
138
|
end
|
102
139
|
|
103
140
|
private
|
@@ -116,8 +153,10 @@ module Maze
|
|
116
153
|
body = WEBrick::HTTPUtils.parse_form_data(request.body, boundary)
|
117
154
|
$logger.debug 'BODY:'
|
118
155
|
LogUtil.log_hash(Logger::Severity::DEBUG, body)
|
119
|
-
|
156
|
+
when %r{^application/json$}
|
120
157
|
$logger.debug "BODY: #{JSON.pretty_generate(JSON.parse(request.body))}"
|
158
|
+
else
|
159
|
+
$logger.debug "BODY: #{request.body}"
|
121
160
|
end
|
122
161
|
end
|
123
162
|
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maze
|
4
|
+
module Servlets
|
5
|
+
class TraceServlet < Servlet
|
6
|
+
def set_response_header(header)
|
7
|
+
super
|
8
|
+
value = Maze::Server.sampling_probability
|
9
|
+
header['Bugsnag-Sampling-Probability'] = value unless value == 'null'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/maze.rb
CHANGED
@@ -7,10 +7,10 @@ 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 = '
|
10
|
+
VERSION = '7.23.0'
|
11
11
|
|
12
12
|
class << self
|
13
|
-
attr_accessor :check, :driver, :internal_hooks, :mode, :start_time, :dynamic_retry
|
13
|
+
attr_accessor :check, :driver, :internal_hooks, :mode, :start_time, :dynamic_retry, :public_address, :run_uuid
|
14
14
|
|
15
15
|
def config
|
16
16
|
@config ||= Maze::Configuration.new
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Hash
|
2
|
+
def deep_merge!(other_hash, &block)
|
3
|
+
merge!(other_hash) do |key, this_val, other_val|
|
4
|
+
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
5
|
+
this_val.deep_merge(other_val, &block)
|
6
|
+
elsif block_given?
|
7
|
+
block.call(key, this_val, other_val)
|
8
|
+
else
|
9
|
+
other_val
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def deep_merge(other_hash, &block)
|
15
|
+
dup.deep_merge!(other_hash, &block)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Log the full response so we see more than just the error code
|
2
|
+
module Selenium
|
3
|
+
module WebDriver
|
4
|
+
module Error
|
5
|
+
class ServerError < StandardError
|
6
|
+
def initialize(response)
|
7
|
+
if response.is_a? String
|
8
|
+
super(response)
|
9
|
+
else
|
10
|
+
$logger.error "Server response: #{response.inspect}"
|
11
|
+
super("status code #{response.code}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end # ServerError
|
15
|
+
end # Error
|
16
|
+
end # WebDriver
|
17
|
+
end # Selenium
|