run_loop 2.4.1 → 2.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5fa8d6acd657ee7230c4095b970215199e1e9d03
4
- data.tar.gz: b06b85cde2448ca8f5a97f79a834c237f920d008
3
+ metadata.gz: 47c4ac8c0ca04201b1f2a083ef93cb906835c4ab
4
+ data.tar.gz: 9665bb55f30876e01542533f5312604879f2c3da
5
5
  SHA512:
6
- metadata.gz: ccd75f46828607b5e5d40df9acfa688f15ff5b812f9366657b9638cb93cd316080b02652f97f8bdcc0299ffeb167461925a85b26c2177313b9f52960126f70c9
7
- data.tar.gz: c87f40e81cad88dcd0f5d29b9d49a76920f3b06f263d2ad8fab45fd84eff07c509ea43f7a6af64ee1e7c8ac05172952b0878920edf18182a5ed139628993d0c0
6
+ metadata.gz: 26077ed5f0322bf945f258cecf869dd378d3b1e12c4897cf3a9add7cfe22644e133c53b241c986298248d4dd6d038c7bda697f691e8a61148c363c9b4df0f8c1
7
+ data.tar.gz: 90607898903b3236f2af292918413fb3ff9e7d1c2d09e1d66e159d37d0f6a681bcfc9dedc5e4dc4fb2743954400d4a468bee01606136db5f609c6b2d0762c0c4
@@ -1,11 +1,13 @@
1
- require 'thor'
2
- require 'run_loop'
3
- require 'run_loop/cli/errors'
4
1
 
5
2
  module RunLoop
6
3
  module CLI
4
+
5
+ require 'thor'
7
6
  class Simctl < Thor
8
7
 
8
+ require 'run_loop'
9
+ require 'run_loop/cli/errors'
10
+
9
11
  attr_reader :simctl
10
12
 
11
13
  desc 'tail', 'Tail the log file of the booted simulator'
@@ -187,6 +189,60 @@ module RunLoop
187
189
  end
188
190
  end
189
191
 
192
+ desc "erase <simulator>", "Erases the simulator"
193
+
194
+ method_option 'debug',
195
+ :desc => 'Enable debug logging.',
196
+ :aliases => '-v',
197
+ :required => false,
198
+ :default => false,
199
+ :type => :boolean
200
+
201
+ def erase(simulator=nil)
202
+
203
+ debug = options[:debug]
204
+
205
+ RunLoop::Environment.with_debugging(debug) do
206
+ if !simulator
207
+ identifier = RunLoop::Core.default_simulator(xcode)
208
+ else
209
+ identifier = simulator
210
+ end
211
+
212
+ options = {simctl: simctl, xcode: xcode}
213
+ device = RunLoop::Device.device_with_identifier(identifier, options)
214
+
215
+ RunLoop::CoreSimulator.erase(device, options)
216
+ end
217
+ end
218
+
219
+ desc "launch <simulator>", "Launches the simulator"
220
+
221
+ method_option 'debug',
222
+ :desc => 'Enable debug logging.',
223
+ :aliases => '-v',
224
+ :required => false,
225
+ :default => false,
226
+ :type => :boolean
227
+
228
+ def launch(simulator=nil)
229
+ debug = options[:debug]
230
+
231
+ RunLoop::Environment.with_debugging(debug) do
232
+ if !simulator
233
+ identifier = RunLoop::Core.default_simulator(xcode)
234
+ else
235
+ identifier = simulator
236
+ end
237
+
238
+ options = {simctl: simctl, xcode: xcode}
239
+ device = RunLoop::Device.device_with_identifier(identifier, options)
240
+
241
+ core_sim = RunLoop::CoreSimulator.new(device, nil)
242
+ core_sim.launch_simulator
243
+ end
244
+ end
245
+
190
246
  no_commands do
191
247
  def expect_device(options)
192
248
  device_from_options = options[:device]
data/lib/run_loop/core.rb CHANGED
@@ -320,7 +320,9 @@ Logfile: #{log_file}
320
320
  # version.
321
321
  def self.default_simulator(xcode=RunLoop::Xcode.new)
322
322
 
323
- if xcode.version_gte_83?
323
+ if xcode.version_gte_90?
324
+ "iPhone 7 (11.0)"
325
+ elsif xcode.version_gte_83?
324
326
  "iPhone 7 (10.3)"
325
327
  elsif xcode.version_gte_82?
326
328
  "iPhone 7 (10.2)"
@@ -157,6 +157,8 @@ class RunLoop::CoreSimulator
157
157
  # @!visibility private
158
158
  # Quit any Simulator.app or iOS Simulator.app
159
159
  def self.quit_simulator
160
+ RunLoop::DeviceAgent::Xcodebuild.terminate_simulator_tests
161
+
160
162
  SIMULATOR_QUIT_PROCESSES.each do |process_details|
161
163
  process_name = process_details[0]
162
164
  send_term_first = process_details[1]
@@ -375,6 +377,11 @@ class RunLoop::CoreSimulator
375
377
  options = { :timeout => 5, :raise_on_timeout => true }
376
378
  RunLoop::ProcessWaiter.new(sim_name, options).wait_for_any
377
379
 
380
+ # open -g no longer launches application in the background. We want the
381
+ # Simulator to open in the background because when it is opened in the
382
+ # foreground, it steals (key application) focus which is disruptive.
383
+ send_simulator_to_background
384
+
378
385
  if merged_options[:wait_for_stable]
379
386
  device.simulator_wait_for_stable_state
380
387
  end
@@ -599,6 +606,23 @@ Command had no output.
599
606
  hash
600
607
  end
601
608
 
609
+ # @!visibility private
610
+ def send_simulator_to_background
611
+ script = "tell application \"System Events\" to tell process \"#{sim_name}\" to set visible to false"
612
+ begin
613
+ system("osascript", "-e", script)
614
+ rescue => _
615
+ RunLoop.log_debug("Could not put simulator into the background")
616
+ end
617
+
618
+ script = "tell application \"System Events\" to tell process \"#{sim_name}\" to set visible to true"
619
+ begin
620
+ system("osascript", "-e", script)
621
+ rescue => _
622
+ RunLoop.log_debug("Could not put simulator into the foreground")
623
+ end
624
+ end
625
+
602
626
  # @!visibility private
603
627
  def uninstall_app_with_simctl
604
628
  launch_simulator
@@ -737,6 +761,14 @@ Command had no output.
737
761
  end
738
762
  end
739
763
 
764
+ # @!visibility private
765
+ def device_agent_launched_by_xcode?(running_apps)
766
+ process_info = running_apps["XCTRunner"] || running_apps["DeviceAgent-Runner"]
767
+ return false if !process_info
768
+
769
+ process_info[:args][/CBX_LAUNCHED_BY_XCODE/]
770
+ end
771
+
740
772
  # @!visibility private
741
773
  def running_apps_require_relaunch?
742
774
  running_apps = device.simulator_running_app_details
@@ -747,11 +779,9 @@ Command had no output.
747
779
  end
748
780
 
749
781
  # DeviceAgent is running, but it was launched by Xcode.
750
- if running_apps["XCTRunner"]
751
- if running_apps["XCTRunner"][:args][/CBX_LAUNCHED_BY_XCODE/]
752
- RunLoop.log_debug("Simulator relaunch required: XCTRunner is controlled by Xcode")
753
- return true
754
- end
782
+ if device_agent_launched_by_xcode?(running_apps)
783
+ RunLoop.log_debug("Simulator relaunch required: XCTRunner is controlled by Xcode")
784
+ return true
755
785
  end
756
786
 
757
787
  # No app was passed to initializer.
@@ -314,11 +314,29 @@ version: #{version}
314
314
  end
315
315
 
316
316
  # @!visibility private
317
- def simulator_global_preferences_path
318
- @simulator_global_preferences_path ||= lambda do
319
- return nil if physical_device?
320
- File.join(simulator_root_dir, "data/Library/Preferences/.GlobalPreferences.plist")
321
- end.call
317
+ def simulator_global_preferences_path(timeout=10)
318
+ return nil if physical_device?
319
+
320
+ path = File.join(simulator_root_dir,
321
+ "data/Library/Preferences/.GlobalPreferences.plist")
322
+
323
+ return path if File.exist?(path)
324
+
325
+ start = Time.now
326
+ while !File.exist?(path) && (start + timeout) < Time.now
327
+ sleep(1.0)
328
+ end
329
+
330
+ return path if File.exist?(path)
331
+
332
+ raise(RuntimeError, %Q[
333
+ Timed out waiting for .GlobalPreferences.plist after #{Time.now - start} seconds.
334
+
335
+ File does not exist at path:
336
+
337
+ #{path}
338
+
339
+ ])
322
340
  end
323
341
 
324
342
  # @!visibility private
@@ -39,10 +39,20 @@ module RunLoop
39
39
  # Ignored in the XTC.
40
40
  # This key is subject to removal or changes
41
41
  :device_agent_install_timeout => RunLoop::Environment.ci? ? 240 : 120,
42
+
42
43
  # This value must always be false on the XTC.
43
44
  # This is should only be used by gem maintainers or very advanced users.
44
45
  :shutdown_device_agent_before_launch => false,
45
46
 
47
+ # This value controls whether or not DeviceAgent should terminate the
48
+ # the Application Under Test (AUT) when a new testing session is
49
+ # started. The default behavior is to _not_ terminate the AUT if it
50
+ # is already running. If you want your next test to start with your
51
+ # application in a freshly launched state, set this option to true.
52
+ #
53
+ # If the AUT is not running, DeviceAgent performs no action.
54
+ :terminate_aut_before_test => false,
55
+
46
56
  # This value was derived empirically by typing hundreds of strings
47
57
  # using XCUIElement#typeText. It corresponds to the DeviceAgent
48
58
  # constant CBX_DEFAULT_SEND_STRING_FREQUENCY which is 60. _Decrease_
@@ -122,10 +132,18 @@ module RunLoop
122
132
  code_sign_identity = RunLoop::Environment::code_sign_identity
123
133
  end
124
134
 
135
+ provisioning_profile = options[:provisioning_profile]
136
+ if !provisioning_profile
137
+ provisioning_profile = RunLoop::Environment::provisioning_profile
138
+ end
139
+
125
140
  install_timeout = options.fetch(:device_agent_install_timeout,
126
141
  DEFAULTS[:device_agent_install_timeout])
127
- shutdown_before_launch = options.fetch(:shutdown_device_agent_before_launch,
128
- DEFAULTS[:shutdown_device_agent_before_launch])
142
+ shutdown_device_agent_before_launch = options.fetch(:shutdown_device_agent_before_launch,
143
+ DEFAULTS[:shutdown_device_agent_before_launch])
144
+ terminate_aut_before_test = options.fetch(:terminate_aut_before_test,
145
+ DEFAULTS[:terminate_aut_before_test])
146
+
129
147
  aut_args = options.fetch(:args, [])
130
148
  aut_env = options.fetch(:env, {})
131
149
 
@@ -135,8 +153,10 @@ module RunLoop
135
153
 
136
154
  launcher_options = {
137
155
  code_sign_identity: code_sign_identity,
156
+ provisioning_profile: provisioning_profile,
138
157
  device_agent_install_timeout: install_timeout,
139
- shutdown_device_agent_before_launch: shutdown_before_launch,
158
+ shutdown_device_agent_before_launch: shutdown_device_agent_before_launch,
159
+ terminate_aut_before_test: terminate_aut_before_test,
140
160
  dylib_injection_details: dylib_injection_details,
141
161
  aut_args: aut_args,
142
162
  aut_env: aut_env
@@ -152,6 +172,7 @@ module RunLoop
152
172
  :app => bundle_id,
153
173
  :automator => :device_agent,
154
174
  :code_sign_identity => code_sign_identity,
175
+ :provisioning_profile => provisioning_profile,
155
176
  :launcher => cbx_launcher.name,
156
177
  :launcher_pid => xcuitest.launcher_pid,
157
178
  :launcher_options => xcuitest.launcher_options
@@ -674,14 +695,21 @@ Could not dismiss SpringBoard alert by touching button with title '#{button_titl
674
695
  def rotate_home_button_to(position, sleep_for=1.0)
675
696
  orientation = normalize_orientation_position(position)
676
697
  parameters = {
677
- :orientation => orientation
698
+ :orientation => orientation,
699
+ :seconds_to_sleep_after => sleep_for
678
700
  }
679
701
  request = request("rotate_home_button_to", parameters)
680
702
  client = http_client(http_options)
681
703
  response = client.post(request)
682
- json = expect_300_response(response)
683
- sleep(sleep_for)
684
- json
704
+ expect_300_response(response)
705
+ end
706
+
707
+ # @!visibility private
708
+ def orientations
709
+ request = request("orientations")
710
+ client = http_client(http_options)
711
+ response = client.get(request)
712
+ expect_300_response(response)
685
713
  end
686
714
 
687
715
  # @!visibility private
@@ -1287,10 +1315,6 @@ PRIVATE
1287
1315
  kill = RunLoop::ProcessTerminator.new(pid, "KILL", process_name, kill_options)
1288
1316
  kill.kill_process
1289
1317
  end
1290
-
1291
- if process_name == :xcodebuild
1292
- sleep(10)
1293
- end
1294
1318
  end
1295
1319
  end
1296
1320
  hash
@@ -1420,13 +1444,16 @@ Please install it.
1420
1444
  # internal callers to do not.
1421
1445
  aut_args = launcher_options.fetch(:aut_args, [])
1422
1446
  aut_env = launcher_options.fetch(:aut_env, {})
1447
+ terminate_aut = launcher_options.fetch(:terminate_aut_before_test, false)
1448
+
1423
1449
  begin
1424
1450
  client = http_client(http_options)
1425
1451
  request = request("session",
1426
1452
  {
1427
1453
  :bundle_id => bundle_id,
1428
1454
  :launchArgs => aut_args,
1429
- :environment => aut_env
1455
+ :environment => aut_env,
1456
+ :terminate_aut_if_running => terminate_aut
1430
1457
  })
1431
1458
  response = client.post(request)
1432
1459
  RunLoop.log_debug("Launched #{bundle_id} on #{device}")
@@ -7,6 +7,8 @@ module RunLoop
7
7
  # A wrapper around the test-control binary.
8
8
  class IOSDeviceManager < RunLoop::DeviceAgent::LauncherStrategy
9
9
 
10
+ require "run_loop/regex"
11
+
10
12
  EXIT_CODES = {
11
13
  "0" => :success,
12
14
  "2" => :false
@@ -98,6 +100,7 @@ but binary does not exist at that path.
98
100
  # @!visibility private
99
101
  def launch(options)
100
102
  code_sign_identity = options[:code_sign_identity]
103
+ provisioning_profile = options[:provisioning_profile]
101
104
  install_timeout = options[:device_agent_install_timeout]
102
105
 
103
106
  RunLoop::DeviceAgent::Frameworks.instance.install
@@ -105,12 +108,15 @@ but binary does not exist at that path.
105
108
 
106
109
  start = Time.now
107
110
  if device.simulator?
108
- cbxapp = RunLoop::App.new(runner.runner)
111
+ RunLoop::DeviceAgent::Xcodebuild.terminate_simulator_tests
109
112
 
113
+ cbxapp = RunLoop::App.new(runner.runner)
110
114
  sim = CoreSimulator.new(device, cbxapp)
115
+
111
116
  sim.install
112
117
  sim.launch_simulator
113
118
  else
119
+ RunLoop::DeviceAgent::Xcodebuild.terminate_device_test(device.udid)
114
120
 
115
121
  if !install_timeout
116
122
  raise ArgumentError, %Q[
@@ -125,16 +131,17 @@ Expected :device_agent_install_timeout key in options:
125
131
  shell_options = {:log_cmd => true, :timeout => install_timeout}
126
132
 
127
133
  args = [
128
- cmd, "install",
129
- "--device-id", device.udid,
130
- # -a <== --app-bundle (1.0.4) and --app-path (> 1.0.4)
131
- "-a", runner.runner
134
+ cmd, "install", runner.runner, "--device-id", device.udid
132
135
  ]
133
136
 
134
137
  if code_sign_identity
135
138
  args = args + ["--codesign-identity", code_sign_identity]
136
139
  end
137
140
 
141
+ if provisioning_profile
142
+ args = args + ["--provisioning-profile", provisioning_profile]
143
+ end
144
+
138
145
  start = Time.now
139
146
  hash = run_shell_command(args, shell_options)
140
147
 
@@ -149,10 +156,11 @@ Could not install #{runner.runner}. iOSDeviceManager says:
149
156
  end
150
157
  end
151
158
 
152
- RunLoop::log_debug("Took #{Time.now - start} seconds to install DeviceAgent");
159
+ RunLoop::log_debug("Took #{Time.now - start} seconds to install DeviceAgent")
153
160
 
154
161
  cmd = "xcrun"
155
- args = ["xcodebuild", "test-without-building",
162
+ args = ["xcodebuild",
163
+ "test-without-building",
156
164
  "-xctestrun", path_to_xctestrun,
157
165
  "-destination", "id=#{device.udid}",
158
166
  "-derivedDataPath", Xcodebuild.derived_data_directory]
@@ -162,6 +170,7 @@ Could not install #{runner.runner}. iOSDeviceManager says:
162
170
  FileUtils.touch(log_file)
163
171
 
164
172
  env = {
173
+ # zsh support
165
174
  "CLOBBER" => "1"
166
175
  }
167
176
 
@@ -180,9 +189,7 @@ Could not install #{runner.runner}. iOSDeviceManager says:
180
189
  cmd = RunLoop::DeviceAgent::IOSDeviceManager.ios_device_manager
181
190
 
182
191
  args = [
183
- cmd, "is_installed",
184
- "--device-id", device.udid,
185
- "--bundle-identifier", bundle_identifier
192
+ cmd, "is-installed", bundle_identifier, "--device-id", device.udid
186
193
  ]
187
194
 
188
195
  start = Time.now
@@ -116,7 +116,69 @@ Use the CBXWS environment variable to override the default.
116
116
  relative = File.expand_path(File.join(this_dir, "..", "..", "..", ".."))
117
117
  File.join(relative, "DeviceAgent.iOS/DeviceAgent.xcworkspace")
118
118
  end
119
+
120
+ # @visibility private
121
+ def self.terminate_simulator_tests
122
+ should_term_test = lambda do |process_description|
123
+ xcodebuild_destination_is_simulator?(process_description)
124
+ end
125
+
126
+ self.terminate_xcodebuild_test_processes(should_term_test)
127
+ end
128
+
129
+ # @visibility private
130
+ def self.terminate_device_test(udid)
131
+ should_term_test = lambda do |process_description|
132
+ process_description[/id=#{udid}/]
133
+ end
134
+ self.terminate_xcodebuild_test_processes(should_term_test)
135
+ end
136
+
137
+ # @visibility private
138
+ def self.terminate_xcodebuild_test_processes(should_term_test)
139
+ options = { :timeout => 0.5, :raise_on_timeout => false }
140
+ pids = RunLoop::ProcessWaiter.new("xcodebuild", options).pids
141
+ pids.each do |pid|
142
+ if should_term_test.call(process_env(pid))
143
+ RunLoop.log_debug("Will terminate xcodebuild process: #{pid}")
144
+ terminate_xcodebuild_test_process(pid)
145
+ end
146
+ end
147
+ end
148
+
149
+ # @visibility private
150
+ def self.terminate_xcodebuild_test_process(pid)
151
+ term_options = { :timeout => 1.5 }
152
+ kill_options = { :timeout => 1.0 }
153
+
154
+ process_name = "xcodebuild test-without-building"
155
+
156
+ term = RunLoop::ProcessTerminator.new(pid.to_i,
157
+ "TERM",
158
+ process_name,
159
+ term_options)
160
+ if !term.kill_process
161
+ kill = RunLoop::ProcessTerminator.new(pid.to_i,
162
+ "KILL",
163
+ process_name,
164
+ kill_options)
165
+ kill.kill_process
166
+ end
167
+ sleep(1.0)
168
+ end
169
+
170
+ # @visibility private
171
+ def self.xcodebuild_destination_is_simulator?(process_description)
172
+ process_description[/-destination id=#{RunLoop::Regex::CORE_SIMULATOR_UDID_REGEX}/]
173
+ end
174
+
175
+ # @visibility private
176
+ def self.process_env(pid)
177
+ options = {:log_cmd => true}
178
+ args = ["ps", "-p", pid.to_s, "-wwwE"]
179
+ hash = RunLoop::Shell.run_shell_command(args, options)
180
+ hash[:out]
181
+ end
119
182
  end
120
183
  end
121
184
  end
122
-
@@ -162,7 +162,7 @@ module RunLoop
162
162
  end
163
163
  end
164
164
 
165
- # Returns the value of CODESIGN_IDENTITY
165
+ # Returns the value of CODE_SIGN_IDENTITY
166
166
  def self.code_sign_identity
167
167
  value = ENV["CODE_SIGN_IDENTITY"]
168
168
  if !value || value == ""
@@ -172,6 +172,16 @@ module RunLoop
172
172
  end
173
173
  end
174
174
 
175
+ # Returns the value of PROVISIONING_PROFILE
176
+ def self.provisioning_profile
177
+ value = ENV["PROVISIONING_PROFILE"]
178
+ if !value || value == ""
179
+ nil
180
+ else
181
+ value
182
+ end
183
+ end
184
+
175
185
  # Returns the value of KEYCHAIN
176
186
  #
177
187
  # Use this to specify a non-default KEYCHAIN for code signing.
data/lib/run_loop/l10n.rb CHANGED
@@ -18,6 +18,7 @@ module RunLoop
18
18
  end
19
19
 
20
20
  UIKIT_AXBUNDLE_PATH_CORE_SIM = 'Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/AccessibilityBundles/UIKit.axbundle/'
21
+ UIKIT_AXBUNDLE_PATH_CORE_SIM_XCODE_9 = "Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/AccessibilityBundles/UIKit.axbundle"
21
22
 
22
23
  LANG_CODE_TO_LANG_NAME_MAP = {
23
24
  'en' => 'English',
@@ -70,7 +71,11 @@ module RunLoop
70
71
  end
71
72
 
72
73
  def uikit_bundle_l10n_path
73
- File.join(xcode.developer_dir, UIKIT_AXBUNDLE_PATH_CORE_SIM)
74
+ if xcode.version_gte_90?
75
+ File.join(xcode.developer_dir, UIKIT_AXBUNDLE_PATH_CORE_SIM_XCODE_9)
76
+ else
77
+ File.join(xcode.developer_dir, UIKIT_AXBUNDLE_PATH_CORE_SIM)
78
+ end
74
79
  end
75
80
 
76
81
  def is_full_name?(two_letter_country_code)
@@ -1,5 +1,5 @@
1
1
  module RunLoop
2
- VERSION = "2.4.1"
2
+ VERSION = "2.5.0"
3
3
 
4
4
  # A model of a software release version that can be used to compare two versions.
5
5
  #
@@ -102,7 +102,15 @@ module RunLoop
102
102
 
103
103
  # The hash method for this instance.
104
104
  def hash
105
- to_s.hash
105
+ str = [major, minor, patch].map do |str|
106
+ str ? str : "0"
107
+ end.join(".")
108
+
109
+ if pre
110
+ str = "#{str}.#{pre}"
111
+ end
112
+
113
+ str.hash
106
114
  end
107
115
 
108
116
  # Compare this version to another for equality.
@@ -158,25 +166,29 @@ module RunLoop
158
166
  def self.compare(a, b)
159
167
 
160
168
  if a.major != b.major
161
- return a.major > b.major ? 1 : -1
169
+ return a.major.to_i > b.major.to_i ? 1 : -1
162
170
  end
163
171
 
164
- if a.minor != b.minor
165
- return a.minor.to_i > b.minor.to_i ? 1 : -1
172
+ a_minor = a.minor ? a.minor.to_i : 0
173
+ b_minor = b.minor ? b.minor.to_i : 0
174
+ if a_minor != b_minor
175
+ return a_minor > b_minor.to_i ? 1 : -1
166
176
  end
167
177
 
168
- if a.patch != b.patch
169
- return a.patch.to_i > b.patch.to_i ? 1 : -1
178
+ a_patch = a.patch ? a.patch.to_i : 0
179
+ b_patch = b.patch ? b.patch.to_i : 0
180
+ if a_patch != b_patch
181
+ return a_patch.to_i > b_patch.to_i ? 1 : -1
170
182
  end
171
183
 
172
- return -1 if a.pre and (not a.pre_version) and b.pre_version
173
- return 1 if a.pre_version and b.pre and (not b.pre_version)
184
+ return -1 if a.pre && (!a.pre_version) && b.pre_version
185
+ return 1 if a.pre_version && b.pre && (!b.pre_version)
174
186
 
175
- return -1 if a.pre and (not b.pre)
176
- return 1 if (not a.pre) and b.pre
187
+ return -1 if a.pre && (!b.pre)
188
+ return 1 if (!a.pre) && b.pre
177
189
 
178
- return -1 if a.pre_version and (not b.pre_version)
179
- return 1 if (not a.pre_version) and b.pre_version
190
+ return -1 if a.pre_version && (!b.pre_version)
191
+ return 1 if (!a.pre_version) && b.pre_version
180
192
 
181
193
  if a.pre_version != b.pre_version
182
194
  return a.pre_version.to_i > b.pre_version.to_i ? 1 : -1
@@ -26,7 +26,15 @@ module RunLoop
26
26
  to_s
27
27
  end
28
28
 
29
- # Returns a version instance for Xcode 8.3 ; used to check for the
29
+ # Returns a version instance for Xcode 9.0; used to check for the
30
+ # availability of features and paths to various items on the filesystem
31
+ #
32
+ # @return [RunLoop::Version] 9.0
33
+ def v90
34
+ fetch_version(:v90)
35
+ end
36
+
37
+ # Returns a version instance for Xcode 8.3; used to check for the
30
38
  # availability of features and paths to various items on the filesystem
31
39
  #
32
40
  # @return [RunLoop::Version] 8.3
@@ -34,7 +42,7 @@ module RunLoop
34
42
  fetch_version(:v83)
35
43
  end
36
44
 
37
- # Returns a version instance for Xcode 8.2 ; used to check for the
45
+ # Returns a version instance for Xcode 8.2; used to check for the
38
46
  # availability of features and paths to various items on the filesystem
39
47
  #
40
48
  # @return [RunLoop::Version] 8.2
@@ -146,6 +154,13 @@ module RunLoop
146
154
  fetch_version(:v50)
147
155
  end
148
156
 
157
+ # Is the active Xcode version 9.0 or above?
158
+ #
159
+ # @return [Boolean] `true` if the current Xcode version is >= 9.0
160
+ def version_gte_90?
161
+ version >= v90
162
+ end
163
+
149
164
  # Is the active Xcode version 8.3 or above?
150
165
  #
151
166
  # @return [Boolean] `true` if the current Xcode version is >= 8.3
@@ -198,7 +198,8 @@ function portugueseBrazilLocalizations() {
198
198
  ["OK", /Deseja Ter Acesso às Suas Atividades de Movimento e Preparo Físico/],
199
199
  ["OK", /Deseja Ter Acesso às Contas do Twitter/],
200
200
  ["OK", /data available to nearby bluetooth devices/],
201
- ["OK", /[Dd]eseja [Ee]nviar-lhe [Nn]otificações/]
201
+ ["OK", /[Dd]eseja [Ee]nviar-lhe [Nn]otificações/],
202
+ ["Permitir", /Deseja Enviar Notificações/]
202
203
  ];
203
204
  }
204
205
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: run_loop
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.1
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karl Krukow
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-04-11 00:00:00.000000000 Z
12
+ date: 2017-08-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
@@ -212,47 +212,47 @@ dependencies:
212
212
  - !ruby/object:Gem::Version
213
213
  version: '4.3'
214
214
  - !ruby/object:Gem::Dependency
215
- name: guard-bundler
215
+ name: terminal-notifier-guard
216
216
  requirement: !ruby/object:Gem::Requirement
217
217
  requirements:
218
218
  - - "~>"
219
219
  - !ruby/object:Gem::Version
220
- version: '2.0'
220
+ version: '1.7'
221
221
  type: :development
222
222
  prerelease: false
223
223
  version_requirements: !ruby/object:Gem::Requirement
224
224
  requirements:
225
225
  - - "~>"
226
226
  - !ruby/object:Gem::Version
227
- version: '2.0'
227
+ version: '1.7'
228
228
  - !ruby/object:Gem::Dependency
229
- name: listen
229
+ name: guard-bundler
230
230
  requirement: !ruby/object:Gem::Requirement
231
231
  requirements:
232
- - - '='
232
+ - - "~>"
233
233
  - !ruby/object:Gem::Version
234
- version: 3.0.6
234
+ version: '2.0'
235
235
  type: :development
236
236
  prerelease: false
237
237
  version_requirements: !ruby/object:Gem::Requirement
238
238
  requirements:
239
- - - '='
239
+ - - "~>"
240
240
  - !ruby/object:Gem::Version
241
- version: 3.0.6
241
+ version: '2.0'
242
242
  - !ruby/object:Gem::Dependency
243
- name: growl
243
+ name: listen
244
244
  requirement: !ruby/object:Gem::Requirement
245
245
  requirements:
246
- - - "~>"
246
+ - - '='
247
247
  - !ruby/object:Gem::Version
248
- version: '1.0'
248
+ version: 3.0.6
249
249
  type: :development
250
250
  prerelease: false
251
251
  version_requirements: !ruby/object:Gem::Requirement
252
252
  requirements:
253
- - - "~>"
253
+ - - '='
254
254
  - !ruby/object:Gem::Version
255
- version: '1.0'
255
+ version: 3.0.6
256
256
  - !ruby/object:Gem::Dependency
257
257
  name: stub_env
258
258
  requirement: !ruby/object:Gem::Requirement
@@ -415,7 +415,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
415
415
  version: '0'
416
416
  requirements: []
417
417
  rubyforge_project:
418
- rubygems_version: 2.5.1
418
+ rubygems_version: 2.6.12
419
419
  signing_key:
420
420
  specification_version: 4
421
421
  summary: The bridge between Calabash iOS and Xcode command-line tools like instruments