run_loop 2.2.4 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/run_loop/cli/instruments.rb +9 -0
- data/lib/run_loop/core.rb +2 -4
- data/lib/run_loop/core_simulator.rb +232 -115
- data/lib/run_loop/device.rb +177 -105
- data/lib/run_loop/device_agent/Frameworks.zip +0 -0
- data/lib/run_loop/device_agent/app/DeviceAgent-Runner.app.zip +0 -0
- data/lib/run_loop/device_agent/bin/iOSDeviceManager +0 -0
- data/lib/run_loop/device_agent/client.rb +113 -37
- data/lib/run_loop/device_agent/ios_device_manager.rb +9 -14
- data/lib/run_loop/device_agent/ipa/DeviceAgent-Runner.app.zip +0 -0
- data/lib/run_loop/logging.rb +1 -1
- data/lib/run_loop/process_waiter.rb +35 -4
- data/lib/run_loop/simctl.rb +2 -2
- data/lib/run_loop/version.rb +1 -1
- data/scripts/lib/on_alert.js +33 -2
- data/vendor-licenses/CocoaAsyncSocket.LICENSE +4 -0
- data/vendor-licenses/CocoaHTTPServer.LICENSE +18 -0
- data/vendor-licenses/CocoaLumberjack.LICENSE +33 -0
- data/vendor-licenses/Facebook-WebDriverAgent.LICENSE +30 -0
- data/vendor-licenses/RoutingHTTPServer.LICENSE +19 -0
- metadata +8 -4
- data/vendor-licenses/xctestctl.LICENSE +0 -32
data/lib/run_loop/device.rb
CHANGED
@@ -31,7 +31,7 @@ module RunLoop
|
|
31
31
|
# exceeded - if the default 30 seconds has passed, the
|
32
32
|
# simulator is probably stable enough for subsequent
|
33
33
|
# operations.
|
34
|
-
:timeout => RunLoop::Environment.ci? ?
|
34
|
+
:timeout => RunLoop::Environment.ci? ? 240 : 120
|
35
35
|
}
|
36
36
|
|
37
37
|
attr_reader :name
|
@@ -322,124 +322,54 @@ version: #{version}
|
|
322
322
|
end
|
323
323
|
|
324
324
|
# @!visibility private
|
325
|
-
#
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
# 3. 1 and 2 must hold for 1.5 seconds.
|
331
|
-
#
|
332
|
-
# When the simulator version is >= iOS 9, two more conditions are added to
|
333
|
-
# get past the iOS 9+ boot screen.
|
334
|
-
#
|
335
|
-
# 4. Wait for com.apple.audio.SystemSoundServer-iOS-Simulator process to
|
336
|
-
# start.
|
337
|
-
# 5. 1 and 2 must hold for 1.5 seconds.
|
338
|
-
#
|
339
|
-
# When the simulator version is >= iOS 9 and the device is an iPad another
|
340
|
-
# condition is added because simctl fails to correctly install applications;
|
341
|
-
# the app and data container exists, but Springboard does not detect them.
|
342
|
-
#
|
343
|
-
# 6. 1 and 2 must hold for 1.5 seconds.
|
344
|
-
#
|
345
|
-
# TODO needs update for Xcode 8 + iOS 10 simulators.
|
346
|
-
def simulator_wait_for_stable_state
|
347
|
-
|
348
|
-
# How long to wait between stability checks.
|
349
|
-
# Shorter than this gives false positives.
|
350
|
-
delay = 0.5
|
351
|
-
|
352
|
-
# How many times to wait for stable state.
|
353
|
-
max_stable_count = 3
|
354
|
-
|
355
|
-
# How long to wait for iOS 9 boot screen.
|
356
|
-
boot_screen_wait_options = {
|
357
|
-
:max_boot_screen_wait => 10,
|
358
|
-
:raise_on_timeout => false
|
359
|
-
}
|
360
|
-
|
361
|
-
# How much additional time to wait for iOS 9+ iPads.
|
362
|
-
#
|
363
|
-
# Installing and launching on iPads is problematic.
|
364
|
-
# Sometimes the app is installed, but SpringBoard does
|
365
|
-
# not recognize that the app is installed even though
|
366
|
-
# simctl says that it is.
|
367
|
-
additional_ipad_delay = delay * 2
|
368
|
-
|
369
|
-
# Adjust for CI environments
|
370
|
-
if RunLoop::Environment.ci?
|
371
|
-
max_stable_count = 5
|
372
|
-
boot_screen_wait_options[:max_boot_screen_wait] = 20
|
373
|
-
additional_ipad_delay = delay * 4
|
374
|
-
end
|
375
|
-
|
376
|
-
# iOS 9 simulators have an additional boot screen.
|
377
|
-
is_gte_ios9 = version >= RunLoop::Version.new('9.0')
|
378
|
-
|
379
|
-
# Xcode 8 simulators do not need to wait for log file
|
380
|
-
is_xcode8 = RunLoop::Xcode.new.version_gte_8?
|
325
|
+
# In megabytes
|
326
|
+
def simulator_size_on_disk
|
327
|
+
data_path = File.join(simulator_root_dir, 'data')
|
328
|
+
RunLoop::Directory.size(data_path, :mb)
|
329
|
+
end
|
381
330
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
is_ipad = simulator_is_ipad?
|
331
|
+
# @!visibility private
|
332
|
+
def simulator_wait_for_stable_state
|
333
|
+
required = simulator_required_child_processes
|
386
334
|
|
387
335
|
timeout = SIM_STABLE_STATE_OPTIONS[:timeout]
|
388
336
|
now = Time.now
|
389
337
|
poll_until = now + timeout
|
390
338
|
|
391
339
|
RunLoop.log_debug("Waiting for simulator to stabilize with timeout: #{timeout} seconds")
|
340
|
+
footprint = simulator_size_on_disk
|
392
341
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
end
|
399
|
-
|
400
|
-
is_stable = false
|
401
|
-
waited_for_boot = false
|
402
|
-
waited_for_ipad = false
|
403
|
-
stable_count = 0
|
404
|
-
|
405
|
-
while Time.now < poll_until do
|
406
|
-
latest_dir_sha = simulator_data_directory_sha
|
407
|
-
if is_xcode8
|
408
|
-
latest_log_sha = true
|
342
|
+
if version.major >= 9 && footprint < 18
|
343
|
+
first_launch = true
|
344
|
+
elsif version.major == 8
|
345
|
+
if version.minor >= 3 && footprint < 19
|
346
|
+
first_launch = true
|
409
347
|
else
|
410
|
-
|
348
|
+
first_launch = footprint < 11
|
411
349
|
end
|
350
|
+
else
|
351
|
+
first_launch = false
|
352
|
+
end
|
412
353
|
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
process_name = "com.apple.audio.SystemSoundServer-iOS-Simulator"
|
421
|
-
RunLoop::ProcessWaiter.new(process_name, boot_screen_wait_options).wait_for_any
|
422
|
-
waited_for_boot = true
|
423
|
-
stable_count = 0
|
424
|
-
elsif is_gte_ios9 && is_ipad && !waited_for_ipad
|
425
|
-
RunLoop.log_debug("Waiting additional time for iOS 9 iPad to stabilize")
|
426
|
-
sleep(additional_ipad_delay)
|
427
|
-
waited_for_ipad = true
|
428
|
-
stable_count = 0
|
429
|
-
else
|
430
|
-
break
|
431
|
-
end
|
354
|
+
while !required.empty? && Time.now < poll_until do
|
355
|
+
sleep(0.5)
|
356
|
+
required = required.map do |process_name|
|
357
|
+
if simulator_process_running?(process_name)
|
358
|
+
nil
|
359
|
+
else
|
360
|
+
process_name
|
432
361
|
end
|
433
|
-
end
|
434
|
-
|
435
|
-
current_dir_sha = latest_dir_sha
|
436
|
-
current_log_sha = latest_log_sha
|
437
|
-
sleep(delay)
|
362
|
+
end.compact
|
438
363
|
end
|
439
364
|
|
440
|
-
if
|
365
|
+
if required.empty?
|
441
366
|
elapsed = Time.now - now
|
442
|
-
RunLoop.log_debug("
|
367
|
+
RunLoop.log_debug("All required simulator processes have started after #{elapsed}")
|
368
|
+
if first_launch
|
369
|
+
RunLoop.log_debug("Detected a first launch, waiting a little longer - footprint was #{footprint} MB")
|
370
|
+
sleep(RunLoop::Environment.ci? ? 10 : 5)
|
371
|
+
end
|
372
|
+
RunLoop.log_debug("Waited for #{elapsed} seconds for simulator to stabilize")
|
443
373
|
else
|
444
374
|
RunLoop.log_debug("Timed out after #{timeout} seconds waiting for simulator to stabilize")
|
445
375
|
end
|
@@ -541,9 +471,61 @@ failed with this output:
|
|
541
471
|
simulator_languages
|
542
472
|
end
|
543
473
|
|
474
|
+
# @!visibility private
|
475
|
+
def simulator_running_app_details
|
476
|
+
pids = simulator_running_app_pids
|
477
|
+
running_apps = {}
|
478
|
+
|
479
|
+
pids.each do |pid|
|
480
|
+
cmd = ["ps", "-o", "comm=", "-p", pid.to_s]
|
481
|
+
|
482
|
+
hash = run_shell_command(cmd)
|
483
|
+
out = hash[:out]
|
484
|
+
|
485
|
+
if out.nil? || out == "" || out.strip.nil?
|
486
|
+
nil
|
487
|
+
else
|
488
|
+
name = out.strip.split("/").last
|
489
|
+
|
490
|
+
cmd = ["ps", "-o", "command=", "-p", pid.to_s]
|
491
|
+
hash = run_shell_command(cmd)
|
492
|
+
out = hash[:out]
|
493
|
+
|
494
|
+
if out.nil? || out == "" || out.strip.nil?
|
495
|
+
nil
|
496
|
+
else
|
497
|
+
tokens = out.split("#{name} ")
|
498
|
+
|
499
|
+
# No arguments
|
500
|
+
if tokens.count == 1
|
501
|
+
args = ""
|
502
|
+
else
|
503
|
+
args = tokens.last.strip
|
504
|
+
end
|
505
|
+
|
506
|
+
running_apps[name] = {
|
507
|
+
args: args,
|
508
|
+
command: out.strip
|
509
|
+
}
|
510
|
+
end
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
running_apps
|
515
|
+
end
|
516
|
+
|
517
|
+
=begin
|
518
|
+
PRIVATE METHODS
|
519
|
+
=end
|
520
|
+
|
544
521
|
private
|
545
522
|
|
546
|
-
attr_reader :pbuddy, :simctl, :xcrun
|
523
|
+
attr_reader :pbuddy, :simctl, :xcrun, :xcode
|
524
|
+
|
525
|
+
# @!visibility private
|
526
|
+
def xcode
|
527
|
+
@xcode ||= RunLoop::Xcode.new
|
528
|
+
end
|
547
529
|
|
548
530
|
# @!visibility private
|
549
531
|
def xcrun
|
@@ -610,6 +592,76 @@ failed with this output:
|
|
610
592
|
udid
|
611
593
|
end
|
612
594
|
|
595
|
+
# @!visibility private
|
596
|
+
def simulator_required_child_processes
|
597
|
+
@simulator_required_child_processes ||= begin
|
598
|
+
required = ["backboardd", "installd", "SimulatorBridge", "SpringBoard"]
|
599
|
+
if xcode.version_gte_8? && version.major > 8
|
600
|
+
required << "medialibraryd"
|
601
|
+
end
|
602
|
+
|
603
|
+
if simulator_is_ipad? && version.major == 9
|
604
|
+
required << "com.apple.audio.SystemSoundServer-iOS-Simulator"
|
605
|
+
end
|
606
|
+
|
607
|
+
required
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
# @!visibility private
|
612
|
+
def simulator_launchd_sim_pid
|
613
|
+
waiter = RunLoop::ProcessWaiter.new("launchd_sim")
|
614
|
+
waiter.wait_for_any
|
615
|
+
|
616
|
+
return nil if !waiter.running_process?
|
617
|
+
|
618
|
+
pid = nil
|
619
|
+
|
620
|
+
waiter.pids.each do |launchd_sim_pid|
|
621
|
+
cmd = ["ps", "x", "-o", "pid,command", launchd_sim_pid.to_s]
|
622
|
+
hash = run_shell_command(cmd)
|
623
|
+
out = hash[:out]
|
624
|
+
process_line = out.split($-0)[1]
|
625
|
+
if !process_line || process_line == ""
|
626
|
+
false
|
627
|
+
else
|
628
|
+
pid = process_line.split(" ").first.strip
|
629
|
+
if process_line[/#{udid}/] == nil
|
630
|
+
RunLoop.log_debug("Terminating launchd_sim process with pid #{pid}")
|
631
|
+
RunLoop::ProcessTerminator.new(pid, "KILL", "launchd_sim").kill_process
|
632
|
+
pid = nil
|
633
|
+
end
|
634
|
+
end
|
635
|
+
end
|
636
|
+
pid
|
637
|
+
end
|
638
|
+
|
639
|
+
# @!visibility private
|
640
|
+
def process_parent_is_launchd_sim?(pid)
|
641
|
+
launchd_sim_pid = simulator_launchd_sim_pid
|
642
|
+
return false if !launchd_sim_pid
|
643
|
+
|
644
|
+
cmd = ["ps", "x", "-o", "ppid=", "-p", pid.to_s]
|
645
|
+
hash = run_shell_command(cmd)
|
646
|
+
|
647
|
+
out = hash[:out]
|
648
|
+
if out.nil? || out == ""
|
649
|
+
false
|
650
|
+
else
|
651
|
+
ppid = out.strip
|
652
|
+
ppid == launchd_sim_pid.to_s
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
# @!visibility private
|
657
|
+
def simulator_process_running?(process_name)
|
658
|
+
waiter = RunLoop::ProcessWaiter.new(process_name)
|
659
|
+
waiter.pids.any? do |pid|
|
660
|
+
process_parent_is_launchd_sim?(pid)
|
661
|
+
#process_parent_is_current_xcode?(pid)
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
613
665
|
# @!visibility private
|
614
666
|
def simulator_data_directory_sha
|
615
667
|
path = File.join(simulator_root_dir, 'data')
|
@@ -688,6 +740,26 @@ https://github.com/calabash/calabash-ios/wiki/Testing-on-Physical-Devices
|
|
688
740
|
end
|
689
741
|
true
|
690
742
|
end
|
743
|
+
|
744
|
+
# @!visibility private
|
745
|
+
def simulator_running_app_pids
|
746
|
+
simulator_running_user_app_pids +
|
747
|
+
simulator_running_system_app_pids
|
748
|
+
end
|
749
|
+
|
750
|
+
# @!visibility private
|
751
|
+
def simulator_running_user_app_pids
|
752
|
+
path = File.join(udid, "data", "Containers", "Bundle")
|
753
|
+
RunLoop::ProcessWaiter.pgrep_f(path)
|
754
|
+
end
|
755
|
+
|
756
|
+
# @!visibility private
|
757
|
+
def simulator_running_system_app_pids
|
758
|
+
base_dir = xcode.developer_dir
|
759
|
+
sim_apps_dir = "Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/Applications"
|
760
|
+
path = File.expand_path(File.join(base_dir, sim_apps_dir))
|
761
|
+
RunLoop::ProcessWaiter.pgrep_f(path)
|
762
|
+
end
|
691
763
|
end
|
692
764
|
end
|
693
765
|
|
Binary file
|
Binary file
|
Binary file
|
@@ -38,12 +38,20 @@ module RunLoop
|
|
38
38
|
|
39
39
|
# Ignored in the XTC.
|
40
40
|
# This key is subject to removal or changes
|
41
|
-
:device_agent_install_timeout => RunLoop::Environment.ci? ?
|
41
|
+
:device_agent_install_timeout => RunLoop::Environment.ci? ? 240 : 120,
|
42
42
|
# This value must always be false on the XTC.
|
43
43
|
# This is should only be used by gem maintainers or very advanced users.
|
44
|
-
:shutdown_device_agent_before_launch => false
|
44
|
+
:shutdown_device_agent_before_launch => false,
|
45
|
+
|
46
|
+
# This value was derived empirically by typing hundreds of strings
|
47
|
+
# using XCUIElement#typeText. It corresponds to the DeviceAgent
|
48
|
+
# constant CBX_DEFAULT_SEND_STRING_FREQUENCY which is 60. _Decrease_
|
49
|
+
# this value if you are timing out typing strings.
|
50
|
+
:characters_per_second => 12
|
45
51
|
}
|
46
52
|
|
53
|
+
AUT_LAUNCHED_BY_RUN_LOOP_ARG = "LAUNCHED_BY_RUN_LOOP"
|
54
|
+
|
47
55
|
# @!visibility private
|
48
56
|
#
|
49
57
|
# These defaults may change at any time.
|
@@ -67,7 +75,6 @@ module RunLoop
|
|
67
75
|
|
68
76
|
# @!visibility private
|
69
77
|
def self.run(options={})
|
70
|
-
# logger = options[:logger]
|
71
78
|
simctl = options[:sim_control] || options[:simctl] || RunLoop::Simctl.new
|
72
79
|
xcode = options[:xcode] || RunLoop::Xcode.new
|
73
80
|
instruments = options[:instruments] || RunLoop::Instruments.new
|
@@ -88,10 +95,19 @@ module RunLoop
|
|
88
95
|
default_options = {
|
89
96
|
:xcode => xcode
|
90
97
|
}
|
98
|
+
|
91
99
|
merged_options = default_options.merge(options)
|
92
100
|
|
93
101
|
if device.simulator? && app
|
102
|
+
RunLoop::Core.expect_simulator_compatible_arch(device, app)
|
103
|
+
|
104
|
+
if merged_options[:relaunch_simulator]
|
105
|
+
RunLoop.log_debug("Detected :relaunch_simulator option; will force simulator to restart")
|
106
|
+
RunLoop::CoreSimulator.quit_simulator
|
107
|
+
end
|
108
|
+
|
94
109
|
core_sim = RunLoop::CoreSimulator.new(device, app, merged_options)
|
110
|
+
|
95
111
|
if reset_options
|
96
112
|
core_sim.reset_app_sandbox
|
97
113
|
end
|
@@ -100,7 +116,7 @@ module RunLoop
|
|
100
116
|
core_sim.install
|
101
117
|
end
|
102
118
|
|
103
|
-
cbx_launcher = Client.detect_cbx_launcher(
|
119
|
+
cbx_launcher = Client.detect_cbx_launcher(merged_options, device)
|
104
120
|
|
105
121
|
code_sign_identity = options[:code_sign_identity]
|
106
122
|
if !code_sign_identity
|
@@ -114,6 +130,10 @@ module RunLoop
|
|
114
130
|
aut_args = options.fetch(:args, [])
|
115
131
|
aut_env = options.fetch(:env, {})
|
116
132
|
|
133
|
+
if !aut_args.include?(AUT_LAUNCHED_BY_RUN_LOOP_ARG)
|
134
|
+
aut_args << AUT_LAUNCHED_BY_RUN_LOOP_ARG
|
135
|
+
end
|
136
|
+
|
117
137
|
launcher_options = {
|
118
138
|
code_sign_identity: code_sign_identity,
|
119
139
|
device_agent_install_timeout: install_timeout,
|
@@ -282,6 +302,9 @@ INSTANCE METHODS
|
|
282
302
|
# @!visibility private
|
283
303
|
#
|
284
304
|
# Experimental!
|
305
|
+
#
|
306
|
+
# This will launch the other app using the same arguments and environment
|
307
|
+
# as the AUT.
|
285
308
|
def launch_other_app(bundle_id)
|
286
309
|
launch_aut(bundle_id)
|
287
310
|
end
|
@@ -327,7 +350,9 @@ INSTANCE METHODS
|
|
327
350
|
|
328
351
|
# @!visibility private
|
329
352
|
def clear_text
|
330
|
-
|
353
|
+
# Tries to touch the keyboard delete key, but falls back on typing the
|
354
|
+
# backspace character.
|
355
|
+
options = enter_text_http_options("\b")
|
331
356
|
parameters = {
|
332
357
|
:gesture => "clear_text"
|
333
358
|
}
|
@@ -342,7 +367,7 @@ INSTANCE METHODS
|
|
342
367
|
if !keyboard_visible?
|
343
368
|
raise RuntimeError, "Keyboard must be visible"
|
344
369
|
end
|
345
|
-
options = enter_text_http_options
|
370
|
+
options = enter_text_http_options(string.to_s)
|
346
371
|
parameters = {
|
347
372
|
:gesture => "enter_text",
|
348
373
|
:options => {
|
@@ -362,7 +387,7 @@ INSTANCE METHODS
|
|
362
387
|
# 1. Removes duplicate check.
|
363
388
|
# 2. It turns out DeviceAgent query can be very slow.
|
364
389
|
def enter_text_without_keyboard_check(string)
|
365
|
-
options = enter_text_http_options
|
390
|
+
options = enter_text_http_options(string.to_s)
|
366
391
|
parameters = {
|
367
392
|
:gesture => "enter_text",
|
368
393
|
:options => {
|
@@ -752,6 +777,20 @@ Timed out after #{timeout} seconds waiting for the keyboard to appear.
|
|
752
777
|
end
|
753
778
|
end
|
754
779
|
|
780
|
+
# @!visibility private
|
781
|
+
def wait_for_no_keyboard(timeout=WAIT_DEFAULTS[:timeout])
|
782
|
+
options = WAIT_DEFAULTS.dup
|
783
|
+
options[:timeout] = timeout
|
784
|
+
message = %Q[
|
785
|
+
|
786
|
+
Timed out after #{timeout} seconds waiting for the keyboard to disappear.
|
787
|
+
|
788
|
+
]
|
789
|
+
wait_for(message, options) do
|
790
|
+
!keyboard_visible?
|
791
|
+
end
|
792
|
+
end
|
793
|
+
|
755
794
|
# @!visibility private
|
756
795
|
def wait_for_alert(timeout=WAIT_DEFAULTS[:timeout])
|
757
796
|
options = WAIT_DEFAULTS.dup
|
@@ -784,23 +823,52 @@ Timed out after #{timeout} seconds waiting for an alert to disappear.
|
|
784
823
|
# @!visibility private
|
785
824
|
def wait_for_text_in_view(text, uiquery, options={})
|
786
825
|
merged_options = WAIT_DEFAULTS.merge(options)
|
787
|
-
result = wait_for_view(uiquery, merged_options)
|
788
|
-
|
789
|
-
# This is not quite right. It is possible to get a false positive.
|
790
|
-
# If result does not have "value" or "label" and the text is nil
|
791
|
-
candidates = [result["value"],
|
792
|
-
result["label"]]
|
793
|
-
match = candidates.any? do |elm|
|
794
|
-
elm == text
|
795
|
-
end
|
796
|
-
if !match
|
797
|
-
fail(%Q[
|
798
826
|
|
799
|
-
|
827
|
+
begin
|
828
|
+
wait_for("TMP", merged_options) do
|
829
|
+
view = query(uiquery).first
|
830
|
+
|
831
|
+
if view
|
832
|
+
# Guard against this edge case:
|
833
|
+
#
|
834
|
+
# Text is "" and value or label keys do not exist in view which
|
835
|
+
# implies that value or label was the empty string (see the
|
836
|
+
# DeviceAgent JSONUtils and Facebook macros).
|
837
|
+
if text == "" || text == nil
|
838
|
+
view["value"] == nil && view["label"] == nil
|
839
|
+
else
|
840
|
+
[view["value"], view["label"]].any? { |elm| elm == text }
|
841
|
+
end
|
842
|
+
else
|
843
|
+
false
|
844
|
+
end
|
845
|
+
end
|
846
|
+
rescue merged_options[:exception_class] => e
|
847
|
+
view = query(uiquery)
|
848
|
+
if !view
|
849
|
+
message = %Q[
|
850
|
+
Timed out wait after #{merged_options[:timeout]} seconds waiting for a view to match:
|
800
851
|
|
801
|
-
#{
|
852
|
+
#{uiquery}
|
802
853
|
|
803
|
-
]
|
854
|
+
]
|
855
|
+
else
|
856
|
+
message = %Q[
|
857
|
+
Timed out after #{merged_options[:timeout]} seconds waiting for a view matching:
|
858
|
+
|
859
|
+
'#{uiquery}'
|
860
|
+
|
861
|
+
to have 'value' or 'label' matching text:
|
862
|
+
|
863
|
+
'#{text}'
|
864
|
+
|
865
|
+
Found:
|
866
|
+
|
867
|
+
#{JSON.pretty_generate(view)}
|
868
|
+
|
869
|
+
]
|
870
|
+
end
|
871
|
+
fail(merged_options[:exception_class], message)
|
804
872
|
end
|
805
873
|
end
|
806
874
|
|
@@ -1069,8 +1137,11 @@ PRIVATE
|
|
1069
1137
|
# @!visibility private
|
1070
1138
|
#
|
1071
1139
|
# A patch while we are trying to figure out what is wrong with text entry.
|
1072
|
-
def enter_text_http_options
|
1073
|
-
|
1140
|
+
def enter_text_http_options(string)
|
1141
|
+
characters = string.length + 1
|
1142
|
+
characters_per_second = DEFAULTS[:characters_per_second]
|
1143
|
+
to_type_timeout = [characters/characters_per_second, 2.0].max
|
1144
|
+
timeout = (DEFAULTS[:http_timeout] * 3) + to_type_timeout
|
1074
1145
|
{
|
1075
1146
|
:timeout => timeout,
|
1076
1147
|
:interval => 0.1,
|
@@ -1178,21 +1249,26 @@ PRIVATE
|
|
1178
1249
|
hash
|
1179
1250
|
end
|
1180
1251
|
|
1181
|
-
#
|
1182
|
-
# that iOSDeviceManager will be able to handle this for us.
|
1252
|
+
# @!visibility private
|
1183
1253
|
def cbx_runner_stale?
|
1184
|
-
false
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1254
|
+
return false if RunLoop::Environment.xtc?
|
1255
|
+
return false if cbx_launcher.name == :xcodebuild
|
1256
|
+
return false if !running?
|
1257
|
+
|
1258
|
+
version_info = server_version
|
1259
|
+
running_version_timestamp = version_info[:bundle_version].to_i
|
1260
|
+
|
1261
|
+
app = RunLoop::App.new(cbx_launcher.runner.runner)
|
1262
|
+
plist_buddy = RunLoop::PlistBuddy.new
|
1263
|
+
version_timestamp = plist_buddy.plist_read("CFBundleVersion", app.info_plist_path).to_i
|
1190
1264
|
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1265
|
+
if running_version_timestamp == version_timestamp
|
1266
|
+
RunLoop.log_debug("The running DeviceAgent version is the same as the version on disk")
|
1267
|
+
false
|
1268
|
+
else
|
1269
|
+
RunLoop.log_debug("The running DeviceAgent version is not the same as the version on disk")
|
1270
|
+
true
|
1271
|
+
end
|
1196
1272
|
end
|
1197
1273
|
|
1198
1274
|
# @!visibility private
|
@@ -1289,7 +1365,7 @@ Please install it.
|
|
1289
1365
|
client = http_client(http_options)
|
1290
1366
|
request = request("session",
|
1291
1367
|
{
|
1292
|
-
:
|
1368
|
+
:bundle_id => bundle_id,
|
1293
1369
|
:launchArgs => aut_args,
|
1294
1370
|
:environment => aut_env
|
1295
1371
|
})
|