bugsnag-maze-runner 9.6.0 → 9.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/features/support/internal_hooks.rb +13 -9
- data/lib/maze/client/appium/bb_client.rb +9 -7
- data/lib/maze/client/appium/bb_devices.rb +72 -28
- data/lib/maze/server.rb +7 -0
- data/lib/maze/servlets/command_servlet.rb +26 -15
- data/lib/maze.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6101c495b7debb939e4bb83f21dbc015c13f7bc58ce797d69fb90e618c6be6d
|
4
|
+
data.tar.gz: 69f5fdd5eec4c1f5bc8e9ed2aaa188531a6f54e80ec26471873ef93e7ecb1ecd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0438524dc2173c1f31b323cca182e651ea1fc095727ee4658c5bb14baa986b5a17230fcd64460dd9eb9e805469c84eae2d3eadb85ae47668501a70dd1211e090'
|
7
|
+
data.tar.gz: bcf7dfcf91d8093099733839d06b38b1cea25548617eebad4f88a01910d8f64d6e0db26de0de5ebe38977e1cfa2b64d3fed80f8bc693d5ec6071c8dc633f5bb0
|
@@ -238,17 +238,21 @@ AfterAll do
|
|
238
238
|
# Ensure the logger output is in the correct location
|
239
239
|
Maze::Hooks::LoggerHooks.after_all
|
240
240
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
241
|
+
if Maze.config.file_log
|
242
|
+
# create a zip file from the maze_output directory
|
243
|
+
maze_output = File.join(Dir.pwd, 'maze_output')
|
244
|
+
maze_output_zip = File.join(Dir.pwd, 'maze_output.zip')
|
245
|
+
|
246
|
+
# zip a folder with files and subfolders
|
247
|
+
Zip::File.open(maze_output_zip, Zip::File::CREATE) do |zipfile|
|
248
|
+
Dir["#{maze_output}/**/**"].each do |file|
|
249
|
+
zipfile.add(file.sub(Dir.pwd + '/', ''), file)
|
250
|
+
end
|
247
251
|
end
|
248
|
-
end
|
249
252
|
|
250
|
-
|
251
|
-
|
253
|
+
# Move the zip file to the maze_output folder
|
254
|
+
FileUtils.mv(maze_output_zip, maze_output)
|
255
|
+
end
|
252
256
|
|
253
257
|
metrics = Maze::MetricsProcessor.new(Maze::Server.metrics)
|
254
258
|
metrics.process
|
@@ -34,6 +34,10 @@ module Maze
|
|
34
34
|
interval = 10
|
35
35
|
elsif error.message.include? 'Could not proxy command to the remote server'
|
36
36
|
interval = 10
|
37
|
+
elsif error.message.include? 'Could not find a connected Android device'
|
38
|
+
interval = 10
|
39
|
+
elsif error.message.include? '\'platformVersion\' must be a valid version number.'
|
40
|
+
interval = 10
|
37
41
|
else
|
38
42
|
# Do not retry in any other case
|
39
43
|
end
|
@@ -54,26 +58,24 @@ module Maze
|
|
54
58
|
end
|
55
59
|
|
56
60
|
def device_capabilities
|
57
|
-
# Doubling up on capabilities in both the `appium:options` and `appium` sub dictionaries.
|
58
|
-
# See PLAT-11087
|
59
61
|
config = Maze.config
|
60
62
|
common_caps = {
|
61
63
|
'noReset' => true,
|
62
64
|
'newCommandTimeout' => 600
|
63
65
|
}
|
64
66
|
capabilities = {
|
65
|
-
'appium:options' => common_caps,
|
66
|
-
'appium' => common_caps,
|
67
67
|
'bitbar:options' => {
|
68
|
-
# Some capabilities probably belong in the top level
|
69
|
-
# of the hash, but BitBar picks them up from here.
|
70
68
|
'apiKey' => config.access_key,
|
71
69
|
'app' => config.app,
|
72
70
|
'findDevice' => false,
|
73
71
|
'testTimeout' => 7200
|
74
72
|
}
|
75
73
|
}
|
76
|
-
|
74
|
+
if Maze.config.appium_version && Maze.config.appium_version.to_f < 2.0
|
75
|
+
capabilities.merge!(common_caps)
|
76
|
+
else
|
77
|
+
capabilities['appium:options'] = common_caps
|
78
|
+
end
|
77
79
|
capabilities.deep_merge! BitBarClientUtils.dashboard_capabilities
|
78
80
|
capabilities.deep_merge! BitBarDevices.get_available_device(config.device)
|
79
81
|
capabilities['bitbar:options']['appiumVersion'] = config.appium_version unless config.appium_version.nil?
|
@@ -18,22 +18,44 @@ module Maze
|
|
18
18
|
if device_group_ids
|
19
19
|
# Device group found - find a free device in it
|
20
20
|
$logger.trace "Got group ids #{device_group_ids} for #{device_or_group_names}"
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
if device_group_ids.size > 1
|
22
|
+
group_id = false
|
23
|
+
group_count, device = api_client.find_device_in_groups(device_group_ids)
|
24
|
+
if device.nil?
|
25
|
+
raise 'There are no devices available'
|
26
|
+
else
|
27
|
+
$logger.info "#{group_count} device(s) currently available in group(s) '#{device_or_group_names}'"
|
28
|
+
end
|
24
29
|
else
|
25
|
-
|
30
|
+
# Since there is only one group, we can use it verbatim
|
31
|
+
$logger.info "Using device group #{device_or_group_names}"
|
32
|
+
group_id = true
|
33
|
+
device_name = device_group_ids.first
|
26
34
|
end
|
27
35
|
else
|
28
36
|
# See if there is a device with the given name
|
29
37
|
device = api_client.find_device device_or_group_names
|
30
38
|
end
|
31
39
|
|
32
|
-
|
33
|
-
|
34
|
-
|
40
|
+
# If a single device has been identified use that to determine other characteristics
|
41
|
+
if device
|
42
|
+
device_name = device['displayName']
|
43
|
+
platform = device['platform'].downcase
|
44
|
+
platform_version = device['softwareVersion']['releaseVersion']
|
35
45
|
|
36
|
-
|
46
|
+
$logger.info "Selected device: #{device_name} (#{platform} #{platform_version})"
|
47
|
+
else
|
48
|
+
# If a device group has been identified, extrapolate characteristics from the group name
|
49
|
+
if android_match = Regexp.new('(ANDROID|android)_(\d{1,2})').match(device_or_group_names)
|
50
|
+
platform = 'android'
|
51
|
+
platform_version = android_match[2]
|
52
|
+
elsif ios_match = Regexp.new('(IOS|ios)_(\d{1,2})').match(device_or_group_names)
|
53
|
+
platform = 'ios'
|
54
|
+
platform_version = ios_match[2]
|
55
|
+
end
|
56
|
+
|
57
|
+
$logger.info "Selected device group: #{device_or_group_names} (#{platform} #{platform_version})"
|
58
|
+
end
|
37
59
|
|
38
60
|
# TODO: Setting the config here is rather a side effect and factoring it out would be better.
|
39
61
|
# For now, though, it means not having to provide the --os and --os-version options on the command line.
|
@@ -42,9 +64,9 @@ module Maze
|
|
42
64
|
|
43
65
|
case platform
|
44
66
|
when 'android'
|
45
|
-
make_android_hash(device_name)
|
67
|
+
make_android_hash(device_name, group_id)
|
46
68
|
when 'ios'
|
47
|
-
make_ios_hash(device_name)
|
69
|
+
make_ios_hash(device_name, group_id)
|
48
70
|
else
|
49
71
|
throw "Invalid device platform specified #{platform}"
|
50
72
|
end
|
@@ -90,9 +112,7 @@ module Maze
|
|
90
112
|
end
|
91
113
|
end
|
92
114
|
|
93
|
-
def
|
94
|
-
# Tripling up on capabilities in the `appium:options`, `appium` sub dictionaries and base dictionary.
|
95
|
-
# See PLAT-11087
|
115
|
+
def android_base_hash
|
96
116
|
appium_options = {
|
97
117
|
'automationName' => 'UiAutomator2',
|
98
118
|
'autoGrantPermissions' => true,
|
@@ -103,20 +123,31 @@ module Maze
|
|
103
123
|
appium_options['appPackage'] = Maze.config.app_package unless Maze.config.app_package.nil?
|
104
124
|
hash = {
|
105
125
|
'platformName' => 'Android',
|
106
|
-
'deviceName' => 'Android Phone'
|
107
|
-
'appium:options' => appium_options,
|
108
|
-
'appium' => appium_options,
|
109
|
-
'bitbar:options' => {
|
110
|
-
'device' => device,
|
111
|
-
}
|
126
|
+
'deviceName' => 'Android Phone'
|
112
127
|
}
|
113
|
-
|
128
|
+
if Maze.config.appium_version && Maze.config.appium_version.to_f < 2.0
|
129
|
+
hash.merge!(appium_options)
|
130
|
+
else
|
131
|
+
hash['appium:options'] = appium_options
|
132
|
+
end
|
133
|
+
hash.dup
|
134
|
+
end
|
135
|
+
|
136
|
+
def make_android_hash(device, group_id = false)
|
137
|
+
hash = android_base_hash
|
138
|
+
if group_id
|
139
|
+
hash['bitbar:options'] = {
|
140
|
+
'deviceGroupId' => device
|
141
|
+
}
|
142
|
+
else
|
143
|
+
hash['bitbar:options'] = {
|
144
|
+
'device' => device
|
145
|
+
}
|
146
|
+
end
|
114
147
|
hash.freeze
|
115
148
|
end
|
116
149
|
|
117
|
-
def
|
118
|
-
# Tripling up on capabilities in the `appium:options`, `appium` sub dictionaries and base dictionary.
|
119
|
-
# See PLAT-11087
|
150
|
+
def ios_base_hash
|
120
151
|
appium_options = {
|
121
152
|
'automationName' => 'XCUITest',
|
122
153
|
'shouldTerminateApp' => 'true',
|
@@ -125,13 +156,26 @@ module Maze
|
|
125
156
|
hash = {
|
126
157
|
'platformName' => 'iOS',
|
127
158
|
'deviceName' => 'iPhone device',
|
128
|
-
|
129
|
-
|
130
|
-
|
159
|
+
}
|
160
|
+
if Maze.config.appium_version && Maze.config.appium_version.to_f < 2.0
|
161
|
+
hash.merge!(appium_options)
|
162
|
+
else
|
163
|
+
hash['appium:options'] = appium_options
|
164
|
+
end
|
165
|
+
hash.dup
|
166
|
+
end
|
167
|
+
|
168
|
+
def make_ios_hash(device, group_id = false)
|
169
|
+
hash = ios_base_hash
|
170
|
+
if group_id
|
171
|
+
hash['bitbar:options'] = {
|
172
|
+
'deviceGroupId' => device
|
173
|
+
}
|
174
|
+
else
|
175
|
+
hash['bitbar:options'] = {
|
131
176
|
'device' => device
|
132
177
|
}
|
133
|
-
|
134
|
-
hash.merge!(appium_options)
|
178
|
+
end
|
135
179
|
hash.freeze
|
136
180
|
end
|
137
181
|
end
|
data/lib/maze/server.rb
CHANGED
@@ -15,6 +15,12 @@ module Maze
|
|
15
15
|
DEFAULT_STATUS_CODE = 200
|
16
16
|
|
17
17
|
class << self
|
18
|
+
|
19
|
+
# Records the previous command UUID sent to the test fixture
|
20
|
+
#
|
21
|
+
# @return [String] The UUID of the last command sent
|
22
|
+
attr_accessor :last_command_uuid
|
23
|
+
|
18
24
|
# Sets the response delay generator.
|
19
25
|
#
|
20
26
|
# @param generator [Maze::Generator] The new generator
|
@@ -236,6 +242,7 @@ module Maze
|
|
236
242
|
server.mount '/logs', Servlets::LogServlet
|
237
243
|
server.mount '/metrics', Servlets::Servlet, :metrics
|
238
244
|
server.mount '/reflect', Servlets::ReflectiveServlet
|
245
|
+
server.mount '/docs', WEBrick::HTTPServlet::FileHandler, Maze.config.document_server_root unless Maze.config.document_server_root.nil?
|
239
246
|
server.start
|
240
247
|
rescue StandardError => e
|
241
248
|
Bugsnag.notify e
|
@@ -19,17 +19,7 @@ module Maze
|
|
19
19
|
|
20
20
|
if request.query.empty?
|
21
21
|
# Non-idempotent mode - return the "current" command
|
22
|
-
|
23
|
-
|
24
|
-
if commands.size_remaining == 0
|
25
|
-
response.body = NOOP_COMMAND
|
26
|
-
response.status = 200
|
27
|
-
else
|
28
|
-
command = commands.current
|
29
|
-
response.body = JSON.pretty_generate(command)
|
30
|
-
response.status = 200
|
31
|
-
commands.next
|
32
|
-
end
|
22
|
+
send_current_command(response)
|
33
23
|
else
|
34
24
|
# Idempotent mode
|
35
25
|
after_uuid = request.query['after']
|
@@ -44,6 +34,21 @@ module Maze
|
|
44
34
|
response.header['Access-Control-Allow-Origin'] = '*'
|
45
35
|
end
|
46
36
|
|
37
|
+
def send_current_command(response)
|
38
|
+
commands = Maze::Server.commands
|
39
|
+
|
40
|
+
if commands.size_remaining == 0
|
41
|
+
response.body = NOOP_COMMAND
|
42
|
+
response.status = 200
|
43
|
+
else
|
44
|
+
command = commands.current
|
45
|
+
Server.last_command_uuid = command[:uuid]
|
46
|
+
response.body = JSON.pretty_generate(command)
|
47
|
+
response.status = 200
|
48
|
+
commands.next
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
47
52
|
def command_after(uuid, response)
|
48
53
|
commands = Maze::Server.commands
|
49
54
|
if uuid.empty?
|
@@ -52,14 +57,20 @@ module Maze
|
|
52
57
|
index = commands.all.find_index {|command| command[:uuid] == uuid }
|
53
58
|
end
|
54
59
|
if index.nil?
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
60
|
+
# If the UUID given matches the last UUID sent by the server, we can assume the fixture has failed to reset
|
61
|
+
if uuid.eql?(Server.last_command_uuid)
|
62
|
+
send_current_command(response)
|
63
|
+
else
|
64
|
+
msg = "Request invalid - there is no command with a UUID of #{uuid} to follow on from"
|
65
|
+
$logger.error msg
|
66
|
+
response.body = msg
|
67
|
+
response.status = 400
|
68
|
+
end
|
59
69
|
else
|
60
70
|
if index + 1 < commands.size_all
|
61
71
|
# Respond with the next command in the queue
|
62
72
|
command = commands.get(index + 1)
|
73
|
+
Server.last_command_uuid = command[:uuid]
|
63
74
|
command_json = JSON.pretty_generate(command)
|
64
75
|
response.body = command_json
|
65
76
|
response.status = 200
|
data/lib/maze.rb
CHANGED
@@ -7,7 +7,7 @@ require_relative 'maze/timers'
|
|
7
7
|
# Glues the various parts of MazeRunner together that need to be accessed globally,
|
8
8
|
# providing an alternative to the proliferation of global variables or singletons.
|
9
9
|
module Maze
|
10
|
-
VERSION = '9.
|
10
|
+
VERSION = '9.8.0'
|
11
11
|
|
12
12
|
class << self
|
13
13
|
attr_accessor :check, :driver, :internal_hooks, :mode, :start_time, :dynamic_retry, :public_address,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bugsnag-maze-runner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 9.
|
4
|
+
version: 9.8.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-
|
11
|
+
date: 2024-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cucumber
|
@@ -240,14 +240,14 @@ dependencies:
|
|
240
240
|
requirements:
|
241
241
|
- - "~>"
|
242
242
|
- !ruby/object:Gem::Version
|
243
|
-
version:
|
243
|
+
version: '7.0'
|
244
244
|
type: :development
|
245
245
|
prerelease: false
|
246
246
|
version_requirements: !ruby/object:Gem::Requirement
|
247
247
|
requirements:
|
248
248
|
- - "~>"
|
249
249
|
- !ruby/object:Gem::Version
|
250
|
-
version:
|
250
|
+
version: '7.0'
|
251
251
|
- !ruby/object:Gem::Dependency
|
252
252
|
name: markdown
|
253
253
|
requirement: !ruby/object:Gem::Requirement
|