run_loop 2.0.10.pre1 → 2.1.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/run_loop/core.rb +280 -355
- data/lib/run_loop/core_simulator.rb +3 -7
- data/lib/run_loop/detect_aut/detect.rb +72 -0
- data/lib/run_loop/device.rb +111 -5
- data/lib/run_loop/environment.rb +5 -0
- data/lib/run_loop/instruments.rb +10 -38
- data/lib/run_loop/l10n.rb +1 -25
- data/lib/run_loop/logging.rb +1 -1
- data/lib/run_loop/sim_control.rb +2 -4
- data/lib/run_loop/version.rb +1 -1
- data/lib/run_loop/xcode.rb +2 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ea9c17ad6325b7381a689e16ea30c98b34e2765
|
4
|
+
data.tar.gz: a1f044d25c196213e310f2f70f096f35bb558c65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49f63b7057fb4448850252365b840843b05a4ac39f81db367dd32a52d0b23dc0cdcb67c8de22e4838f02bfb81ef7f2bf3c189da4d4953a008f1812b6bd108326
|
7
|
+
data.tar.gz: 30aed60ffb8069e15260ea81f02fa8a2261a59e473fcd4beaeacfcec940030671c6eb730423d088f73864cfc66daf18972df60a0cfc671013ed61e7f3b8f293f
|
data/lib/run_loop/core.rb
CHANGED
@@ -57,179 +57,24 @@ module RunLoop
|
|
57
57
|
SCRIPTS[key]
|
58
58
|
end
|
59
59
|
|
60
|
-
def self.detect_connected_device
|
61
|
-
begin
|
62
|
-
Timeout::timeout(1, RunLoop::TimeoutError) do
|
63
|
-
return `#{File.join(scripts_path, 'udidetect')}`.chomp
|
64
|
-
end
|
65
|
-
rescue RunLoop::TimeoutError => _
|
66
|
-
`killall udidetect &> /dev/null`
|
67
|
-
end
|
68
|
-
nil
|
69
|
-
end
|
70
|
-
|
71
|
-
# @deprecated 1.5.2 No public replacement.
|
72
|
-
#
|
73
|
-
# Raise an error if the application binary is not compatible with the
|
74
|
-
# target simulator.
|
75
|
-
#
|
76
|
-
# @note This method is implemented for CoreSimulator environments only;
|
77
|
-
# for Xcode < 6.0 this method does nothing.
|
78
|
-
#
|
79
|
-
# @param [Hash] launch_options These options need to contain the app bundle
|
80
|
-
# path and a udid that corresponds to a simulator name or simulator udid.
|
81
|
-
# In practical terms: call this after merging the original launch
|
82
|
-
# options with those options that are discovered.
|
83
|
-
#
|
84
|
-
# @param [RunLoop::SimControl] sim_control A simulator control object.
|
85
|
-
# @raise [RuntimeError] Raises an error if the `launch_options[:udid]`
|
86
|
-
# cannot be used to find a simulator.
|
87
|
-
# @raise [RunLoop::IncompatibleArchitecture] Raises an error if the
|
88
|
-
# application binary is not compatible with the target simulator.
|
89
|
-
def self.expect_compatible_simulator_architecture(launch_options, sim_control)
|
90
|
-
RunLoop.deprecated('1.5.2', 'No public replacement.')
|
91
|
-
logger = launch_options[:logger]
|
92
|
-
if sim_control.xcode_version_gte_6?
|
93
|
-
sim_identifier = launch_options[:udid]
|
94
|
-
simulator = sim_control.simulators.find do |simulator|
|
95
|
-
[simulator.instruments_identifier(sim_control.xcode),
|
96
|
-
simulator.udid].include?(sim_identifier)
|
97
|
-
end
|
98
|
-
|
99
|
-
if simulator.nil?
|
100
|
-
raise "Could not find simulator with identifier '#{sim_identifier}'"
|
101
|
-
end
|
102
|
-
|
103
|
-
lipo = RunLoop::Lipo.new(launch_options[:bundle_dir_or_bundle_id])
|
104
|
-
lipo.expect_compatible_arch(simulator)
|
105
|
-
RunLoop::Logging.log_debug(logger, "Simulator instruction set '#{simulator.instruction_set}' is compatible with #{lipo.info}")
|
106
|
-
true
|
107
|
-
else
|
108
|
-
RunLoop::Logging.log_debug(logger, "Xcode #{sim_control.xcode_version} detected; skipping simulator architecture check.")
|
109
|
-
false
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# Raise an error if the application binary is not compatible with the
|
114
|
-
# target simulator.
|
115
|
-
#
|
116
|
-
# @note This method is implemented for CoreSimulator environments only;
|
117
|
-
# for Xcode < 6.0 this method does nothing.
|
118
|
-
#
|
119
|
-
# @param [RunLoop::Device] device The device to install on.
|
120
|
-
# @param [RunLoop::App] app The app to install.
|
121
|
-
# @param [RunLoop::Xcode] xcode The active Xcode.
|
122
|
-
#
|
123
|
-
# @raise [RunLoop::IncompatibleArchitecture] Raises an error if the
|
124
|
-
# application binary is not compatible with the target simulator.
|
125
|
-
def self.expect_simulator_compatible_arch(device, app, xcode)
|
126
|
-
if !xcode.version_gte_6?
|
127
|
-
RunLoop.log_warn("Checking for compatible arches is only available in CoreSimulator environments")
|
128
|
-
return
|
129
|
-
end
|
130
|
-
|
131
|
-
lipo = RunLoop::Lipo.new(app.path)
|
132
|
-
lipo.expect_compatible_arch(device)
|
133
|
-
|
134
|
-
RunLoop.log_debug("Simulator instruction set '#{device.instruction_set}' is compatible with '#{lipo.info}'")
|
135
|
-
end
|
136
|
-
|
137
|
-
# Prepares the simulator for running.
|
138
|
-
#
|
139
|
-
# 1. enabling accessibility and software keyboard
|
140
|
-
# 2. installing / uninstalling apps
|
141
|
-
def self.prepare_simulator(launch_options, sim_control)
|
142
|
-
|
143
|
-
xcode = sim_control.xcode
|
144
|
-
|
145
|
-
# Respect option passed from Calabash
|
146
|
-
if launch_options[:relaunch_simulator]
|
147
|
-
sim_control.quit_sim
|
148
|
-
end
|
149
|
-
|
150
|
-
if !xcode.version_gte_6?
|
151
|
-
# Xcode 5.1.1
|
152
|
-
|
153
|
-
# Will quit the simulator!
|
154
|
-
sim_control.enable_accessibility_on_sims({:verbose => false})
|
155
|
-
else
|
156
|
-
|
157
|
-
# CoreSimulator
|
158
|
-
|
159
|
-
app_bundle_path = launch_options[:bundle_dir_or_bundle_id]
|
160
|
-
app = RunLoop::App.new(app_bundle_path)
|
161
|
-
|
162
|
-
unless app.valid?
|
163
|
-
if !File.exist?(app.path)
|
164
|
-
message = "App '#{app_bundle_path}' does not exist."
|
165
|
-
else
|
166
|
-
message = "App '#{app_bundle_path}' is not a valid .app bundle"
|
167
|
-
end
|
168
|
-
raise RuntimeError, message
|
169
|
-
end
|
170
|
-
|
171
|
-
udid = launch_options[:udid]
|
172
|
-
|
173
|
-
device = sim_control.simulators.find do |sim|
|
174
|
-
sim.udid == udid || sim.instruments_identifier(xcode) == udid
|
175
|
-
end
|
176
|
-
|
177
|
-
if device.nil?
|
178
|
-
raise RuntimeError,
|
179
|
-
"Could not find simulator with name or UDID that matches: '#{udid}'"
|
180
|
-
end
|
181
|
-
|
182
|
-
# Validate the architecture.
|
183
|
-
self.expect_simulator_compatible_arch(device, app, xcode)
|
184
|
-
|
185
|
-
# Quits the simulator.
|
186
|
-
core_sim = RunLoop::CoreSimulator.new(device, app)
|
187
|
-
|
188
|
-
# :reset is a legacy variable; has been replaced with :reset_app_sandbox
|
189
|
-
if launch_options[:reset] || launch_options[:reset_app_sandbox]
|
190
|
-
core_sim.reset_app_sandbox
|
191
|
-
end
|
192
|
-
|
193
|
-
# Will quit the simulator if it is running.
|
194
|
-
# @todo fix accessibility_enabled? so we don't have to quit the sim
|
195
|
-
# SimControl#accessibility_enabled? is always false during Core#prepare_simulator
|
196
|
-
# https://github.com/calabash/run_loop/issues/167
|
197
|
-
sim_control.ensure_accessibility(device)
|
198
|
-
|
199
|
-
# Will quit the simulator if it is running.
|
200
|
-
# @todo fix software_keyboard_enabled? so we don't have to quit the sim
|
201
|
-
# SimControl#software_keyboard_enabled? is always false during Core#prepare_simulator
|
202
|
-
# https://github.com/calabash/run_loop/issues/168
|
203
|
-
sim_control.ensure_software_keyboard(device)
|
204
|
-
|
205
|
-
# Launches the simulator if the app is not installed.
|
206
|
-
core_sim.install
|
207
|
-
|
208
|
-
# If CoreSimulator has already launched the simulator, it will not
|
209
|
-
# launching it again.
|
210
|
-
core_sim.launch_simulator
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
60
|
def self.run_with_options(options)
|
215
61
|
before = Time.now
|
216
62
|
|
217
63
|
self.prepare(options)
|
218
64
|
|
219
65
|
logger = options[:logger]
|
220
|
-
sim_control
|
66
|
+
sim_control = options[:sim_control] || options[:simctl] || RunLoop::SimControl.new
|
67
|
+
xcode = options[:xcode] || RunLoop::Xcode.new
|
68
|
+
instruments = options[:instruments] || RunLoop::Instruments.new
|
221
69
|
|
222
|
-
|
70
|
+
# Find the Device under test, the App under test, UIA strategy, and reset options
|
71
|
+
device = RunLoop::Device.detect_device(options, xcode, sim_control, instruments)
|
72
|
+
app_details = RunLoop::DetectAUT.detect_app_under_test(options)
|
73
|
+
uia_strategy = self.detect_uia_strategy(options, device, xcode)
|
74
|
+
reset_options = self.detect_reset_options(options)
|
223
75
|
|
224
|
-
instruments = RunLoop::Instruments.new
|
225
76
|
instruments.kill_instruments(xcode)
|
226
77
|
|
227
|
-
device_target = options[:udid] || options[:device_target] || detect_connected_device || 'simulator'
|
228
|
-
if device_target && device_target.to_s.downcase == 'device'
|
229
|
-
device_target = detect_connected_device
|
230
|
-
end
|
231
|
-
|
232
|
-
log_file = options[:log_path]
|
233
78
|
timeout = options[:timeout] || 30
|
234
79
|
|
235
80
|
results_dir = options[:results_dir] || RunLoop::DotDir.make_results_dir
|
@@ -253,8 +98,6 @@ module RunLoop
|
|
253
98
|
repl_path = File.join(results_dir, 'repl-cmd.pipe')
|
254
99
|
FileUtils.rm_f(repl_path)
|
255
100
|
|
256
|
-
uia_strategy = options[:uia_strategy]
|
257
|
-
|
258
101
|
if uia_strategy == :host
|
259
102
|
create_uia_pipe(repl_path)
|
260
103
|
else
|
@@ -271,39 +114,33 @@ module RunLoop
|
|
271
114
|
file.puts code
|
272
115
|
end
|
273
116
|
|
274
|
-
udid = options[:udid]
|
275
|
-
bundle_dir_or_bundle_id = options[:bundle_dir_or_bundle_id]
|
276
|
-
|
277
|
-
if !(udid && bundle_dir_or_bundle_id)
|
278
|
-
# Compute udid and bundle_dir / bundle_id from options and target depending on Xcode version
|
279
|
-
udid, bundle_dir_or_bundle_id = self.udid_and_bundle_for_launcher(device_target, options, sim_control)
|
280
|
-
end
|
281
|
-
|
282
117
|
args = options.fetch(:args, [])
|
283
118
|
|
284
|
-
log_file
|
119
|
+
log_file = options[:log_path] || File.join(results_dir, 'run_loop.out')
|
285
120
|
|
286
121
|
discovered_options =
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
122
|
+
{
|
123
|
+
:udid => device.udid,
|
124
|
+
:device => device,
|
125
|
+
:results_dir_trace => results_dir_trace,
|
126
|
+
:bundle_id => app_details[:bundle_id],
|
127
|
+
:app => app_details[:app] || app_details[:bundle_id],
|
128
|
+
:results_dir => results_dir,
|
129
|
+
:script => script,
|
130
|
+
:log_file => log_file,
|
131
|
+
:args => args
|
132
|
+
}
|
296
133
|
merged_options = options.merge(discovered_options)
|
297
134
|
|
298
|
-
if
|
299
|
-
self.prepare_simulator(
|
135
|
+
if device.simulator?
|
136
|
+
self.prepare_simulator(app_details[:app], device, xcode, sim_control, reset_options)
|
300
137
|
end
|
301
138
|
|
302
139
|
self.log_run_loop_options(merged_options, xcode)
|
303
140
|
|
304
141
|
automation_template = automation_template(instruments)
|
305
142
|
|
306
|
-
RunLoop::Logging.log_header(logger, "Starting on #{
|
143
|
+
RunLoop::Logging.log_header(logger, "Starting on #{device.name} App: #{app_details[:bundle_id]}")
|
307
144
|
|
308
145
|
pid = instruments.spawn(automation_template, merged_options, log_file)
|
309
146
|
|
@@ -311,14 +148,16 @@ module RunLoop
|
|
311
148
|
f.write pid
|
312
149
|
end
|
313
150
|
|
314
|
-
run_loop = {
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
151
|
+
run_loop = {
|
152
|
+
:pid => pid,
|
153
|
+
:index => 1,
|
154
|
+
:uia_strategy => uia_strategy,
|
155
|
+
:udid => device.udid,
|
156
|
+
:app => app_details[:bundle_id],
|
157
|
+
:repl_path => repl_path,
|
158
|
+
:log_file => log_file,
|
159
|
+
:results_dir => results_dir
|
160
|
+
}
|
322
161
|
|
323
162
|
uia_timeout = options[:uia_timeout] || RunLoop::Environment.uia_timeout || 10
|
324
163
|
|
@@ -326,8 +165,10 @@ module RunLoop
|
|
326
165
|
|
327
166
|
before_instruments_launch = Time.now
|
328
167
|
|
329
|
-
|
330
|
-
|
168
|
+
fifo_retry_on = [
|
169
|
+
RunLoop::Fifo::NoReaderConfiguredError,
|
170
|
+
RunLoop::Fifo::WriteTimedOut
|
171
|
+
]
|
331
172
|
|
332
173
|
begin
|
333
174
|
|
@@ -364,9 +205,9 @@ module RunLoop
|
|
364
205
|
|
365
206
|
Logfile: #{log_file}
|
366
207
|
|
367
|
-
#{File.read(log_file)}
|
208
|
+
#{File.read(log_file)}
|
368
209
|
|
369
|
-
)
|
210
|
+
)
|
370
211
|
raise RunLoop::TimeoutError, message
|
371
212
|
end
|
372
213
|
|
@@ -375,8 +216,11 @@ Logfile: #{log_file}
|
|
375
216
|
dylib_path = self.dylib_path_from_options(merged_options)
|
376
217
|
|
377
218
|
if dylib_path
|
378
|
-
|
379
|
-
|
219
|
+
if device.physical_device?
|
220
|
+
raise RuntimeError, "Injecting a dylib is not supported when targeting a device"
|
221
|
+
end
|
222
|
+
|
223
|
+
app = app_details[:app]
|
380
224
|
lldb = RunLoop::DylibInjector.new(app.executable_name, dylib_path)
|
381
225
|
lldb.retriable_inject_dylib
|
382
226
|
end
|
@@ -395,7 +239,7 @@ Logfile: #{log_file}
|
|
395
239
|
def self.include_calabash_script?(options)
|
396
240
|
|
397
241
|
if (options[:include_calabash_script] == false) || options[:dismiss_immediate_dialogs]
|
398
|
-
|
242
|
+
return false
|
399
243
|
end
|
400
244
|
if Core.script_for_key(:run_loop_basic) == options[:script]
|
401
245
|
return options[:include_calabash_script]
|
@@ -403,164 +247,71 @@ Logfile: #{log_file}
|
|
403
247
|
true
|
404
248
|
end
|
405
249
|
|
406
|
-
#
|
407
|
-
#
|
408
|
-
#
|
409
|
-
#
|
410
|
-
#
|
411
|
-
#
|
412
|
-
#
|
413
|
-
|
250
|
+
# Extracts the value of :inject_dylib from options Hash.
|
251
|
+
# @param options [Hash] arguments passed to {RunLoop.run}
|
252
|
+
# @return [String, nil] If the options contains :inject_dylibs and it is a
|
253
|
+
# path to a dylib that exists, return the path. Otherwise return nil or
|
254
|
+
# raise an error.
|
255
|
+
# @raise [RuntimeError] If :inject_dylib points to a path that does not exist.
|
256
|
+
# @raise [ArgumentError] If :inject_dylib is not a String.
|
257
|
+
def self.dylib_path_from_options(options)
|
258
|
+
inject_dylib = options.fetch(:inject_dylib, nil)
|
259
|
+
return nil if inject_dylib.nil?
|
260
|
+
unless inject_dylib.is_a? String
|
261
|
+
raise ArgumentError, "Expected :inject_dylib to be a path to a dylib, but found '#{inject_dylib}'"
|
262
|
+
end
|
263
|
+
dylib_path = File.expand_path(inject_dylib)
|
264
|
+
unless File.exist?(dylib_path)
|
265
|
+
raise "Cannot load dylib. The file '#{dylib_path}' does not exist."
|
266
|
+
end
|
267
|
+
dylib_path
|
268
|
+
end
|
269
|
+
|
270
|
+
# Returns the a default simulator to target. This default needs to be one
|
271
|
+
# that installed by default in the current Xcode version.
|
414
272
|
#
|
415
|
-
#
|
273
|
+
# For historical reasons, the most recent non-64b SDK should be used.
|
416
274
|
#
|
417
|
-
# @
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
sim.udid == value,
|
438
|
-
sim.name == value
|
439
|
-
].any?
|
440
|
-
end
|
441
|
-
!simulator.nil?
|
275
|
+
# @param [RunLoop::Xcode] xcode Used to detect the current xcode
|
276
|
+
# version.
|
277
|
+
def self.default_simulator(xcode=RunLoop::Xcode.new)
|
278
|
+
|
279
|
+
if xcode.version_gte_73?
|
280
|
+
"iPhone 6s (9.3)"
|
281
|
+
elsif xcode.version_gte_72?
|
282
|
+
"iPhone 6s (9.2)"
|
283
|
+
elsif xcode.version_gte_71?
|
284
|
+
"iPhone 6s (9.1)"
|
285
|
+
elsif xcode.version_gte_7?
|
286
|
+
"iPhone 5s (9.0)"
|
287
|
+
elsif xcode.version_gte_64?
|
288
|
+
"iPhone 5s (8.4 Simulator)"
|
289
|
+
elsif xcode.version_gte_63?
|
290
|
+
"iPhone 5s (8.3 Simulator)"
|
291
|
+
elsif xcode.version_gte_62?
|
292
|
+
"iPhone 5s (8.2 Simulator)"
|
293
|
+
elsif xcode.version_gte_61?
|
294
|
+
"iPhone 5s (8.1 Simulator)"
|
442
295
|
else
|
443
|
-
|
296
|
+
"iPhone 5s (8.0 Simulator)"
|
444
297
|
end
|
445
298
|
end
|
446
299
|
|
447
300
|
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
raise ArgumentError, "Expected :inject_dylib to be a path to a dylib, but found '#{inject_dylib}'"
|
460
|
-
end
|
461
|
-
dylib_path = File.expand_path(inject_dylib)
|
462
|
-
unless File.exist?(dylib_path)
|
463
|
-
raise "Cannot load dylib. The file '#{dylib_path}' does not exist."
|
464
|
-
end
|
465
|
-
dylib_path
|
466
|
-
end
|
467
|
-
|
468
|
-
# Returns the a default simulator to target. This default needs to be one
|
469
|
-
# that installed by default in the current Xcode version.
|
470
|
-
#
|
471
|
-
# For historical reasons, the most recent non-64b SDK should be used.
|
472
|
-
#
|
473
|
-
# @param [RunLoop::Xcode] xcode Used to detect the current xcode
|
474
|
-
# version.
|
475
|
-
def self.default_simulator(xcode=RunLoop::Xcode.new)
|
476
|
-
|
477
|
-
if xcode.version_gte_73?
|
478
|
-
"iPhone 6s (9.3)"
|
479
|
-
elsif xcode.version_gte_72?
|
480
|
-
"iPhone 6s (9.2)"
|
481
|
-
elsif xcode.version_gte_71?
|
482
|
-
"iPhone 6s (9.1)"
|
483
|
-
elsif xcode.version_gte_7?
|
484
|
-
"iPhone 5s (9.0)"
|
485
|
-
elsif xcode.version_gte_64?
|
486
|
-
"iPhone 5s (8.4 Simulator)"
|
487
|
-
elsif xcode.version_gte_63?
|
488
|
-
"iPhone 5s (8.3 Simulator)"
|
489
|
-
elsif xcode.version_gte_62?
|
490
|
-
"iPhone 5s (8.2 Simulator)"
|
491
|
-
elsif xcode.version_gte_61?
|
492
|
-
"iPhone 5s (8.1 Simulator)"
|
493
|
-
elsif xcode.version_gte_6?
|
494
|
-
"iPhone 5s (8.0 Simulator)"
|
495
|
-
else
|
496
|
-
"iPhone Retina (4-inch) - Simulator - iOS 7.1"
|
497
|
-
end
|
498
|
-
end
|
499
|
-
|
500
|
-
def self.udid_and_bundle_for_launcher(device_target, options, sim_control=RunLoop::SimControl.new)
|
501
|
-
xcode = sim_control.xcode
|
502
|
-
|
503
|
-
bundle_dir_or_bundle_id = options[:app] || RunLoop::Environment.bundle_id || RunLoop::Environment.path_to_app_bundle
|
504
|
-
|
505
|
-
unless bundle_dir_or_bundle_id
|
506
|
-
raise 'key :app or environment variable APP_BUNDLE_PATH, BUNDLE_ID or APP must be specified as path to app bundle (simulator) or bundle id (device)'
|
507
|
-
end
|
508
|
-
|
509
|
-
udid = nil
|
510
|
-
|
511
|
-
if xcode.version_gte_51?
|
512
|
-
if device_target.nil? || device_target.empty? || device_target == 'simulator'
|
513
|
-
device_target = self.default_simulator(xcode)
|
514
|
-
end
|
515
|
-
udid = device_target
|
516
|
-
|
517
|
-
unless self.simulator_target?(options)
|
518
|
-
bundle_dir_or_bundle_id = options[:bundle_id] if options[:bundle_id]
|
519
|
-
end
|
520
|
-
else
|
521
|
-
#TODO: this can be removed - Xcode < 5.1.1 not supported.
|
522
|
-
if device_target == 'simulator'
|
523
|
-
|
524
|
-
unless File.exist?(bundle_dir_or_bundle_id)
|
525
|
-
raise "Unable to find app in directory #{bundle_dir_or_bundle_id} when trying to launch simulator"
|
526
|
-
end
|
527
|
-
|
528
|
-
|
529
|
-
device = options[:device] || :iphone
|
530
|
-
device = device && device.to_sym
|
531
|
-
|
532
|
-
plistbuddy='/usr/libexec/PlistBuddy'
|
533
|
-
plistfile="#{bundle_dir_or_bundle_id}/Info.plist"
|
534
|
-
if device == :iphone
|
535
|
-
uidevicefamily=1
|
536
|
-
else
|
537
|
-
uidevicefamily=2
|
538
|
-
end
|
539
|
-
system("#{plistbuddy} -c 'Delete :UIDeviceFamily' '#{plistfile}'")
|
540
|
-
system("#{plistbuddy} -c 'Add :UIDeviceFamily array' '#{plistfile}'")
|
541
|
-
system("#{plistbuddy} -c 'Add :UIDeviceFamily:0 integer #{uidevicefamily}' '#{plistfile}'")
|
542
|
-
else
|
543
|
-
udid = device_target
|
544
|
-
bundle_dir_or_bundle_id = options[:bundle_id] if options[:bundle_id]
|
545
|
-
end
|
546
|
-
end
|
547
|
-
return udid, bundle_dir_or_bundle_id
|
548
|
-
end
|
549
|
-
|
550
|
-
def self.create_uia_pipe(repl_path)
|
551
|
-
begin
|
552
|
-
Timeout::timeout(5, RunLoop::TimeoutError) do
|
553
|
-
loop do
|
554
|
-
begin
|
555
|
-
FileUtils.rm_f(repl_path)
|
556
|
-
return repl_path if system(%Q[mkfifo "#{repl_path}"])
|
557
|
-
rescue Errno::EINTR => e
|
558
|
-
#retry
|
559
|
-
sleep(0.1)
|
301
|
+
def self.create_uia_pipe(repl_path)
|
302
|
+
begin
|
303
|
+
Timeout::timeout(5, RunLoop::TimeoutError) do
|
304
|
+
loop do
|
305
|
+
begin
|
306
|
+
FileUtils.rm_f(repl_path)
|
307
|
+
return repl_path if system(%Q[mkfifo "#{repl_path}"])
|
308
|
+
rescue Errno::EINTR => e
|
309
|
+
#retry
|
310
|
+
sleep(0.1)
|
311
|
+
end
|
560
312
|
end
|
561
313
|
end
|
562
|
-
|
563
|
-
rescue RunLoop::TimeoutError => _
|
314
|
+
rescue RunLoop::TimeoutError => _
|
564
315
|
raise RunLoop::TimeoutError, 'Unable to create pipe (mkfifo failed)'
|
565
316
|
end
|
566
317
|
end
|
@@ -581,7 +332,7 @@ Logfile: #{log_file}
|
|
581
332
|
RunLoop::Fifo.write(repl_path, cmd_str)
|
582
333
|
write_succeeded = validate_index_written(run_loop, index, logger)
|
583
334
|
rescue RunLoop::Fifo::NoReaderConfiguredError,
|
584
|
-
|
335
|
+
RunLoop::Fifo::WriteTimedOut => e
|
585
336
|
RunLoop::Logging.log_debug(logger, "Error while writing command (retry count #{i}). #{e}")
|
586
337
|
end
|
587
338
|
break if write_succeeded
|
@@ -744,13 +495,91 @@ Logfile: #{log_file}
|
|
744
495
|
end
|
745
496
|
|
746
497
|
message = ['Expected instruments to report an Automation tracetemplate.',
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
498
|
+
'Please report this as bug: https://github.com/calabash/run_loop/issues',
|
499
|
+
"In the bug report, include the output of:\n",
|
500
|
+
'$ xcrun xcodebuild -version',
|
501
|
+
"$ xcrun instruments -s templates\n"]
|
751
502
|
raise message.join("\n")
|
752
503
|
end
|
753
504
|
|
505
|
+
# @deprecated 2.1.0
|
506
|
+
# Replaced with Device.detect_physical_device_on_usb
|
507
|
+
def self.detect_connected_device
|
508
|
+
begin
|
509
|
+
Timeout::timeout(1, RunLoop::TimeoutError) do
|
510
|
+
return `#{File.join(scripts_path, 'udidetect')}`.chomp
|
511
|
+
end
|
512
|
+
rescue RunLoop::TimeoutError => _
|
513
|
+
`killall udidetect &> /dev/null`
|
514
|
+
end
|
515
|
+
nil
|
516
|
+
end
|
517
|
+
|
518
|
+
# @deprecated 2.1.0
|
519
|
+
# @!visibility private
|
520
|
+
# Are we targeting a simulator?
|
521
|
+
#
|
522
|
+
# @note The behavior of this method is different than the corresponding
|
523
|
+
# method in Calabash::Cucumber::Launcher method. If
|
524
|
+
# `:device_target => {nil | ''}`, then the calabash-ios method returns
|
525
|
+
# _false_. I am basing run-loop's behavior off the behavior in
|
526
|
+
# `self.udid_and_bundle_for_launcher`
|
527
|
+
#
|
528
|
+
# @see {Core::RunLoop.udid_and_bundle_for_launcher}
|
529
|
+
#
|
530
|
+
# @todo sim_control argument is no longer necessary and can be removed.
|
531
|
+
def self.simulator_target?(run_options, sim_control=nil)
|
532
|
+
# TODO Enable deprecation warning
|
533
|
+
# RunLoop.deprecated("2.1.0", "No replacement")
|
534
|
+
value = run_options[:device_target]
|
535
|
+
|
536
|
+
# Match the behavior of udid_and_bundle_for_launcher.
|
537
|
+
return true if value.nil? or value == ''
|
538
|
+
|
539
|
+
# 5.1 <= Xcode < 7.0
|
540
|
+
return true if value.downcase.include?('simulator')
|
541
|
+
|
542
|
+
# Not a physical device.
|
543
|
+
return false if value[DEVICE_UDID_REGEX, 0] != nil
|
544
|
+
|
545
|
+
# Check for named simulators and Xcode >= 7.0 simulators.
|
546
|
+
sim_control = run_options[:sim_control] || RunLoop::SimControl.new
|
547
|
+
xcode = sim_control.xcode
|
548
|
+
simulator = sim_control.simulators.find do |sim|
|
549
|
+
[
|
550
|
+
sim.instruments_identifier(xcode) == value,
|
551
|
+
sim.udid == value,
|
552
|
+
sim.name == value
|
553
|
+
].any?
|
554
|
+
end
|
555
|
+
!simulator.nil?
|
556
|
+
end
|
557
|
+
|
558
|
+
# @!visibility private
|
559
|
+
# @deprecated 2.1.0
|
560
|
+
#
|
561
|
+
# Do not call this method.
|
562
|
+
def self.udid_and_bundle_for_launcher(device_target, options, sim_control=RunLoop::SimControl.new)
|
563
|
+
RunLoop.deprecated("2.1.0", "No replacement")
|
564
|
+
xcode = sim_control.xcode
|
565
|
+
|
566
|
+
bundle_dir_or_bundle_id = options[:app] || RunLoop::Environment.bundle_id || RunLoop::Environment.path_to_app_bundle
|
567
|
+
|
568
|
+
unless bundle_dir_or_bundle_id
|
569
|
+
raise 'key :app or environment variable APP_BUNDLE_PATH, BUNDLE_ID or APP must be specified as path to app bundle (simulator) or bundle id (device)'
|
570
|
+
end
|
571
|
+
|
572
|
+
if device_target.nil? || device_target.empty? || device_target == 'simulator'
|
573
|
+
device_target = self.default_simulator(xcode)
|
574
|
+
end
|
575
|
+
udid = device_target
|
576
|
+
|
577
|
+
unless self.simulator_target?(options)
|
578
|
+
bundle_dir_or_bundle_id = options[:bundle_id] if options[:bundle_id]
|
579
|
+
end
|
580
|
+
return udid, bundle_dir_or_bundle_id
|
581
|
+
end
|
582
|
+
|
754
583
|
# @deprecated 1.0.5
|
755
584
|
def self.ensure_instruments_not_running!
|
756
585
|
RunLoop::Instruments.new.kill_instruments
|
@@ -794,10 +623,106 @@ Logfile: #{log_file}
|
|
794
623
|
|
795
624
|
private
|
796
625
|
|
626
|
+
# @!visibility private
|
627
|
+
#
|
628
|
+
# @param [Hash] options The launch options passed to .run_with_options
|
797
629
|
def self.prepare(run_options)
|
798
630
|
RunLoop::DotDir.rotate_result_directories
|
799
631
|
RunLoop::Instruments.rotate_cache_directories
|
800
632
|
true
|
801
633
|
end
|
634
|
+
|
635
|
+
# @!visibility private
|
636
|
+
#
|
637
|
+
# @param [RunLoop::Device] device The device under test.
|
638
|
+
# @param [RunLoop::Xcode] xcode The active Xcode
|
639
|
+
def self.default_uia_strategy(device, xcode)
|
640
|
+
if xcode.version_gte_7?
|
641
|
+
:host
|
642
|
+
elsif device.physical_device? && device.version >= RunLoop::Version.new("8.0")
|
643
|
+
:host
|
644
|
+
else
|
645
|
+
:preferences
|
646
|
+
end
|
647
|
+
end
|
648
|
+
|
649
|
+
# @!visibility private
|
650
|
+
#
|
651
|
+
# @param [Hash] options The launch options passed to .run_with_options
|
652
|
+
# @param [RunLoop::Device] device The device under test.
|
653
|
+
# @param [RunLoop::Xcode] xcode The active Xcode.
|
654
|
+
def self.detect_uia_strategy(options, device, xcode)
|
655
|
+
strategy = options[:uia_strategy] || self.default_uia_strategy(device, xcode)
|
656
|
+
|
657
|
+
if ![:host, :preferences, :shared_element].include?(strategy)
|
658
|
+
raise ArgumentError,
|
659
|
+
"Invalid strategy: expected '#{strategy}' to be :host, :preferences, or :shared_element"
|
660
|
+
end
|
661
|
+
strategy
|
662
|
+
end
|
663
|
+
|
664
|
+
# @!visibility private
|
665
|
+
#
|
666
|
+
# @param [Hash] options The launch options passed to .run_with_options
|
667
|
+
def self.detect_reset_options(options)
|
668
|
+
return options[:reset] if options.has_key?(:reset)
|
669
|
+
|
670
|
+
return options[:reset_app_sandbox] if options.has_key?(:reset_app_sandbox)
|
671
|
+
|
672
|
+
RunLoop::Environment.reset_between_scenarios?
|
673
|
+
end
|
674
|
+
|
675
|
+
# Prepares the simulator for running.
|
676
|
+
#
|
677
|
+
# 1. enabling accessibility and software keyboard
|
678
|
+
# 2. installing / uninstalling apps
|
679
|
+
def self.prepare_simulator(app, device, xcode, simctl, reset_options)
|
680
|
+
|
681
|
+
# Validate the architecture.
|
682
|
+
self.expect_simulator_compatible_arch(device, app)
|
683
|
+
|
684
|
+
# Quits the simulator.
|
685
|
+
core_sim = RunLoop::CoreSimulator.new(device, app, :xcode => xcode)
|
686
|
+
|
687
|
+
# Calabash 0.x can only reset the app sandbox (true/false).
|
688
|
+
# Calabash 2.x has advanced reset options.
|
689
|
+
if reset_options
|
690
|
+
core_sim.reset_app_sandbox
|
691
|
+
end
|
692
|
+
|
693
|
+
# Will quit the simulator if it is running.
|
694
|
+
# @todo fix accessibility_enabled? so we don't have to quit the sim
|
695
|
+
# SimControl#accessibility_enabled? is always false during Core#prepare_simulator
|
696
|
+
# https://github.com/calabash/run_loop/issues/167
|
697
|
+
simctl.ensure_accessibility(device)
|
698
|
+
|
699
|
+
# Will quit the simulator if it is running.
|
700
|
+
# @todo fix software_keyboard_enabled? so we don't have to quit the sim
|
701
|
+
# SimControl#software_keyboard_enabled? is always false during Core#prepare_simulator
|
702
|
+
# https://github.com/calabash/run_loop/issues/168
|
703
|
+
simctl.ensure_software_keyboard(device)
|
704
|
+
|
705
|
+
# Launches the simulator if the app is not installed.
|
706
|
+
core_sim.install
|
707
|
+
|
708
|
+
# If CoreSimulator has already launched the simulator, it will not launch it again.
|
709
|
+
core_sim.launch_simulator
|
710
|
+
end
|
711
|
+
|
712
|
+
# @!visibility private
|
713
|
+
# Raise an error if the application binary is not compatible with the
|
714
|
+
# target simulator.
|
715
|
+
#
|
716
|
+
# @param [RunLoop::Device] device The device to install on.
|
717
|
+
# @param [RunLoop::App] app The app to install.
|
718
|
+
#
|
719
|
+
# @raise [RunLoop::IncompatibleArchitecture] Raises an error if the
|
720
|
+
# application binary is not compatible with the target simulator.
|
721
|
+
def self.expect_simulator_compatible_arch(device, app)
|
722
|
+
lipo = RunLoop::Lipo.new(app.path)
|
723
|
+
lipo.expect_compatible_arch(device)
|
724
|
+
|
725
|
+
RunLoop.log_debug("Simulator instruction set '#{device.instruction_set}' is compatible with '#{lipo.info}'")
|
726
|
+
end
|
802
727
|
end
|
803
728
|
end
|
@@ -508,11 +508,9 @@ $ bundle exec run-loop simctl manage-processes
|
|
508
508
|
def sim_name
|
509
509
|
@sim_name ||= lambda {
|
510
510
|
if xcode.version_gte_7?
|
511
|
-
|
512
|
-
elsif xcode.version_gte_6?
|
513
|
-
'iOS Simulator'
|
511
|
+
"Simulator"
|
514
512
|
else
|
515
|
-
|
513
|
+
"iOS Simulator"
|
516
514
|
end
|
517
515
|
}.call
|
518
516
|
end
|
@@ -527,10 +525,8 @@ $ bundle exec run-loop simctl manage-processes
|
|
527
525
|
dev_dir = xcode.developer_dir
|
528
526
|
if xcode.version_gte_7?
|
529
527
|
"#{dev_dir}/Applications/Simulator.app"
|
530
|
-
elsif xcode.version_gte_6?
|
531
|
-
"#{dev_dir}/Applications/iOS Simulator.app"
|
532
528
|
else
|
533
|
-
"#{dev_dir}/
|
529
|
+
"#{dev_dir}/Applications/iOS Simulator.app"
|
534
530
|
end
|
535
531
|
}.call
|
536
532
|
end
|
@@ -3,6 +3,24 @@ module RunLoop
|
|
3
3
|
# @!visibility private
|
4
4
|
module DetectAUT
|
5
5
|
|
6
|
+
# @!visibility private
|
7
|
+
def self.detect_app_under_test(options)
|
8
|
+
app = self.detect_app(options)
|
9
|
+
if app.is_a?(RunLoop::App) || app.is_a?(RunLoop::Ipa)
|
10
|
+
{
|
11
|
+
:app => app,
|
12
|
+
:bundle_id => app.bundle_identifier,
|
13
|
+
:is_ipa => app.is_a?(RunLoop::Ipa)
|
14
|
+
}
|
15
|
+
else
|
16
|
+
{
|
17
|
+
:app => nil,
|
18
|
+
:bundle_id => app,
|
19
|
+
:is_ipa => false
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
6
24
|
# @!visibility private
|
7
25
|
class Detect
|
8
26
|
include RunLoop::DetectAUT::Errors
|
@@ -103,5 +121,59 @@ module RunLoop
|
|
103
121
|
end
|
104
122
|
end
|
105
123
|
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
# @!visibility private
|
128
|
+
def self.app_from_options(options)
|
129
|
+
options[:app] || options[:bundle_id]
|
130
|
+
end
|
131
|
+
|
132
|
+
# @!visibility private
|
133
|
+
def self.app_from_environment
|
134
|
+
RunLoop::Environment.path_to_app_bundle ||
|
135
|
+
RunLoop::Environment.bundle_id
|
136
|
+
end
|
137
|
+
|
138
|
+
# @!visibility private
|
139
|
+
def self.app_from_constant
|
140
|
+
(defined?(APP_BUNDLE_PATH) && APP_BUNDLE_PATH) ||
|
141
|
+
(defined?(APP) && APP)
|
142
|
+
end
|
143
|
+
|
144
|
+
# @!visibility private
|
145
|
+
def self.app_from_opts_or_env_or_constant(options)
|
146
|
+
self.app_from_options(options) ||
|
147
|
+
self.app_from_environment ||
|
148
|
+
self.app_from_constant
|
149
|
+
end
|
150
|
+
|
151
|
+
# @!visibility private
|
152
|
+
def self.detector
|
153
|
+
RunLoop::DetectAUT::Detect.new
|
154
|
+
end
|
155
|
+
|
156
|
+
# @!visibility private
|
157
|
+
def self.detect_app(options)
|
158
|
+
app = self.app_from_opts_or_env_or_constant(options)
|
159
|
+
|
160
|
+
# Options or constant defined an instance of App or Ipa
|
161
|
+
return app if app && (app.is_a?(RunLoop::App) || app.is_a?(RunLoop::Ipa))
|
162
|
+
|
163
|
+
# User provided no information, so we attempt to auto detect
|
164
|
+
if app.nil? || app == ""
|
165
|
+
return self.detector.app_for_simulator
|
166
|
+
end
|
167
|
+
|
168
|
+
extension = File.extname(app)
|
169
|
+
if extension == ".ipa" && File.exist?(app)
|
170
|
+
RunLoop::Ipa.new(app)
|
171
|
+
elsif extension == ".app" && File.exist?(app)
|
172
|
+
RunLoop::App.new(app)
|
173
|
+
else
|
174
|
+
# Probably a bundle identifier.
|
175
|
+
app
|
176
|
+
end
|
177
|
+
end
|
106
178
|
end
|
107
179
|
end
|
data/lib/run_loop/device.rb
CHANGED
@@ -128,6 +128,41 @@ Please update your sources.))
|
|
128
128
|
raise ArgumentError, "Could not find a device with a UDID or name matching '#{udid_or_name}'"
|
129
129
|
end
|
130
130
|
|
131
|
+
# @!visibility private
|
132
|
+
#
|
133
|
+
# Please don't call this method. It is for internal use only. The behavior
|
134
|
+
# may change at any time! You have been warned.
|
135
|
+
#
|
136
|
+
# @param [Hash] options The launch options passed to RunLoop::Core
|
137
|
+
# @param [RunLoop::Xcode] xcode An Xcode instance
|
138
|
+
# @param [RunLoop::SimControl] simctl A SimControl instance
|
139
|
+
# @param [RunLoop::Instruments] instruments An Instruments instance
|
140
|
+
#
|
141
|
+
# @raise [ArgumentError] If "device" is detected as the device target and
|
142
|
+
# there is no matching device.
|
143
|
+
# @raise [ArgumentError] If DEVICE_TARGET or options specify an identifier
|
144
|
+
# that does not match an iOS Simulator or phyiscal device.
|
145
|
+
def self.detect_device(options, xcode, simctl, instruments)
|
146
|
+
device = self.device_from_opts_or_env(options)
|
147
|
+
|
148
|
+
# Passed an instance of RunLoop::Device
|
149
|
+
return device if device && device.is_a?(RunLoop::Device)
|
150
|
+
|
151
|
+
# Need to infer what what the user wants from the environment and options.
|
152
|
+
if device == "device"
|
153
|
+
identifier = self.detect_physical_device_on_usb
|
154
|
+
self.ensure_physical_device_connected(identifier, options)
|
155
|
+
elsif device.nil? || device == "" || device == "simulator"
|
156
|
+
identifier = RunLoop::Core.default_simulator(xcode)
|
157
|
+
else
|
158
|
+
identifier = device
|
159
|
+
end
|
160
|
+
|
161
|
+
# Raises ArgumentError if no matching device can be found.
|
162
|
+
self.device_with_identifier(identifier, sim_control: simctl,
|
163
|
+
instruments: instruments)
|
164
|
+
end
|
165
|
+
|
131
166
|
# @!visibility private
|
132
167
|
def to_s
|
133
168
|
if simulator?
|
@@ -162,10 +197,8 @@ Please update your sources.))
|
|
162
197
|
|
163
198
|
if xcode.version_gte_7?
|
164
199
|
"#{name} (#{version_part})"
|
165
|
-
elsif xcode.version_gte_6?
|
166
|
-
"#{name} (#{version_part} Simulator)"
|
167
200
|
else
|
168
|
-
|
201
|
+
"#{name} (#{version_part} Simulator)"
|
169
202
|
end
|
170
203
|
end
|
171
204
|
end
|
@@ -173,13 +206,13 @@ Please update your sources.))
|
|
173
206
|
# Is this a physical device?
|
174
207
|
# @return [Boolean] Returns true if this is a device.
|
175
208
|
def physical_device?
|
176
|
-
|
209
|
+
!udid[DEVICE_UDID_REGEX, 0].nil?
|
177
210
|
end
|
178
211
|
|
179
212
|
# Is this a simulator?
|
180
213
|
# @return [Boolean] Returns true if this is a simulator.
|
181
214
|
def simulator?
|
182
|
-
|
215
|
+
!physical_device?
|
183
216
|
end
|
184
217
|
|
185
218
|
# Return the instruction set for this device.
|
@@ -572,5 +605,78 @@ Please update your sources.))
|
|
572
605
|
|
573
606
|
# TODO Is this a good idea? It speeds up rspec tests by a factor of ~2x...
|
574
607
|
SIM_CONTROL = RunLoop::SimControl.new
|
608
|
+
|
609
|
+
# @!visibility private
|
610
|
+
def self.device_from_options(options)
|
611
|
+
options[:device] || options[:device_target] || options[:udid]
|
612
|
+
end
|
613
|
+
|
614
|
+
# @!visibility private
|
615
|
+
def self.device_from_environment
|
616
|
+
RunLoop::Environment.device_target
|
617
|
+
end
|
618
|
+
|
619
|
+
# @!visibility private
|
620
|
+
def self.device_from_opts_or_env(options)
|
621
|
+
self.device_from_options(options) || self.device_from_environment
|
622
|
+
end
|
623
|
+
|
624
|
+
# @!visibility private
|
625
|
+
UDID_DETECT = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", 'scripts', "udidetect"))
|
626
|
+
|
627
|
+
# @!visibility private
|
628
|
+
def self.detect_physical_device_on_usb
|
629
|
+
require "command_runner"
|
630
|
+
|
631
|
+
udid = nil
|
632
|
+
begin
|
633
|
+
hash = CommandRunner.run([UDID_DETECT], timeout: 1)
|
634
|
+
udid = hash[:out].chomp
|
635
|
+
if udid == ""
|
636
|
+
udid = nil
|
637
|
+
end
|
638
|
+
rescue => e
|
639
|
+
RunLoop.log_debug("Running `udidetect` raised: #{e}")
|
640
|
+
ensure
|
641
|
+
`killall udidetect &> /dev/null`
|
642
|
+
end
|
643
|
+
udid
|
644
|
+
end
|
645
|
+
|
646
|
+
# @!visibility private
|
647
|
+
def self.ensure_physical_device_connected(identifier, options)
|
648
|
+
if identifier.nil?
|
649
|
+
env = self.device_from_environment
|
650
|
+
if env == "device"
|
651
|
+
message = "DEVICE_TARGET=device means that you want to test on physical device"
|
652
|
+
elsif env && env[DEVICE_UDID_REGEX, 0]
|
653
|
+
message = "DEVICE_TARGET=#{env} did not match any connected device"
|
654
|
+
else
|
655
|
+
if options[:device]
|
656
|
+
key = ":device"
|
657
|
+
elsif options[:device_target]
|
658
|
+
key = ":device_target"
|
659
|
+
else
|
660
|
+
key = ":udid"
|
661
|
+
end
|
662
|
+
message = "#{key} => \"device\" means that you want to test on a physical device"
|
663
|
+
end
|
664
|
+
|
665
|
+
raise ArgumentError, %Q[Expected a physical device to be connected via USB.
|
666
|
+
|
667
|
+
#{message}
|
668
|
+
|
669
|
+
1. Is your device connected?
|
670
|
+
2. Does your device appear in the output of `xcrun instruments -s devices`?
|
671
|
+
3. Does your device appear in Xcode > Windows > Devices without a warning message?
|
672
|
+
|
673
|
+
Please see the documentation about testing on physical devices.
|
674
|
+
|
675
|
+
https://github.com/calabash/calabash-ios/wiki/Testing-on-Physical-Devices
|
676
|
+
]
|
677
|
+
end
|
678
|
+
true
|
679
|
+
end
|
575
680
|
end
|
576
681
|
end
|
682
|
+
|
data/lib/run_loop/environment.rb
CHANGED
@@ -48,6 +48,11 @@ module RunLoop
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
# Should the app data be reset between Scenarios?
|
52
|
+
def self.reset_between_scenarios?
|
53
|
+
ENV["RESET_BETWEEN_SCENARIOS"] == "1"
|
54
|
+
end
|
55
|
+
|
51
56
|
# Returns the value of XCODEPROJ which can be used to specify an Xcode
|
52
57
|
# project directory (my.xcodeproj).
|
53
58
|
#
|
data/lib/run_loop/instruments.rb
CHANGED
@@ -198,20 +198,14 @@ module RunLoop
|
|
198
198
|
@instruments_templates ||= lambda do
|
199
199
|
args = ['instruments', '-s', 'templates']
|
200
200
|
hash = xcrun.exec(args, log_cmd: true)
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
end.compact
|
210
|
-
else
|
211
|
-
hash[:out].strip.split("\n").delete_if do |path|
|
212
|
-
not path =~ /tracetemplate/
|
213
|
-
end.map { |elm| elm.strip }
|
214
|
-
end
|
201
|
+
hash[:out].chomp.split("\n").map do |elm|
|
202
|
+
stripped = elm.strip.tr('"', '')
|
203
|
+
if stripped == '' || stripped == 'Known Templates:'
|
204
|
+
nil
|
205
|
+
else
|
206
|
+
stripped
|
207
|
+
end
|
208
|
+
end.compact
|
215
209
|
end.call
|
216
210
|
end
|
217
211
|
|
@@ -306,29 +300,7 @@ module RunLoop
|
|
306
300
|
array = ['instruments']
|
307
301
|
array << '-w'
|
308
302
|
|
309
|
-
|
310
|
-
# Ambiguous device name/identifier errors (from instruments)
|
311
|
-
if xcode.version_gte_7?
|
312
|
-
udid = options[:udid]
|
313
|
-
|
314
|
-
if udid[DEVICE_UDID_REGEX, 0]
|
315
|
-
array << udid
|
316
|
-
else
|
317
|
-
match = simulators.find do |simulator|
|
318
|
-
[simulator.name == udid,
|
319
|
-
simulator.udid == udid,
|
320
|
-
simulator.instruments_identifier(xcode) == udid].any?
|
321
|
-
end
|
322
|
-
|
323
|
-
if match
|
324
|
-
array << match.udid
|
325
|
-
else
|
326
|
-
array << udid
|
327
|
-
end
|
328
|
-
end
|
329
|
-
else
|
330
|
-
array << options[:udid]
|
331
|
-
end
|
303
|
+
array << options[:udid]
|
332
304
|
|
333
305
|
trace = options[:results_dir_trace]
|
334
306
|
if trace
|
@@ -339,7 +311,7 @@ module RunLoop
|
|
339
311
|
array << '-t'
|
340
312
|
array << automation_template
|
341
313
|
|
342
|
-
array << options[:
|
314
|
+
array << options[:bundle_id]
|
343
315
|
|
344
316
|
{
|
345
317
|
'UIARESULTSPATH' => options[:results_dir],
|
data/lib/run_loop/l10n.rb
CHANGED
@@ -70,31 +70,7 @@ module RunLoop
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def uikit_bundle_l10n_path
|
73
|
-
|
74
|
-
if !developer_dir
|
75
|
-
nil
|
76
|
-
else
|
77
|
-
if xcode.version_gte_6?
|
78
|
-
File.join(developer_dir, UIKIT_AXBUNDLE_PATH_CORE_SIM)
|
79
|
-
else
|
80
|
-
['7.1', '7.0', '6.1'].map do |sdk|
|
81
|
-
path = axbundle_path_for_sdk(developer_dir, sdk)
|
82
|
-
if File.exist?(path)
|
83
|
-
path
|
84
|
-
else
|
85
|
-
nil
|
86
|
-
end
|
87
|
-
end.compact.first
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# Xcode 5.1.1 path.
|
93
|
-
def axbundle_path_for_sdk(developer_dir, sdk)
|
94
|
-
File.join(developer_dir,
|
95
|
-
'Platforms/iPhoneSimulator.platform/Developer/SDKs',
|
96
|
-
"iPhoneSimulator#{sdk}.sdk",
|
97
|
-
'System/Library/AccessibilityBundles/UIKit.axbundle')
|
73
|
+
File.join(xcode.developer_dir, UIKIT_AXBUNDLE_PATH_CORE_SIM)
|
98
74
|
end
|
99
75
|
|
100
76
|
def is_full_name?(two_letter_country_code)
|
data/lib/run_loop/logging.rb
CHANGED
data/lib/run_loop/sim_control.rb
CHANGED
@@ -37,7 +37,9 @@ module RunLoop
|
|
37
37
|
end
|
38
38
|
|
39
39
|
# @!visibility private
|
40
|
+
# @deprecated 2.1.0
|
40
41
|
def xcode_version_gte_51?
|
42
|
+
RunLoop.deprecated("2.1.0", "No replacement.")
|
41
43
|
xcode.version_gte_51?
|
42
44
|
end
|
43
45
|
|
@@ -401,10 +403,6 @@ module RunLoop
|
|
401
403
|
end
|
402
404
|
|
403
405
|
def software_keyboard_enabled?(device)
|
404
|
-
unless xcode_version_gte_51?
|
405
|
-
raise RuntimeError, 'Keyboard enabling is only available on Xcode >= 6'
|
406
|
-
end
|
407
|
-
|
408
406
|
plist = device.simulator_preferences_plist_path
|
409
407
|
return false unless File.exist?(plist)
|
410
408
|
|
data/lib/run_loop/version.rb
CHANGED
data/lib/run_loop/xcode.rb
CHANGED
@@ -175,10 +175,12 @@ module RunLoop
|
|
175
175
|
version >= v60
|
176
176
|
end
|
177
177
|
|
178
|
+
# @deprecated 2.1.0
|
178
179
|
# Is the active Xcode version 5.1 or above?
|
179
180
|
#
|
180
181
|
# @return [Boolean] `true` if the current Xcode version is >= 5.1
|
181
182
|
def version_gte_51?
|
183
|
+
RunLoop.deprecated("2.1.0", "No replacement")
|
182
184
|
version >= v51
|
183
185
|
end
|
184
186
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: run_loop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.1.0.pre1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karl Krukow
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|