simctl 1.5.8 → 1.6.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: 23e929d60bc574b9e16e479b4754d40fa393cda0
4
- data.tar.gz: 06d72f6aca738f535b9517bdaacb3606ab17548b
3
+ metadata.gz: befe14fafe0f39d0393b7780baa319a46c6bf13a
4
+ data.tar.gz: 88c089c6d7da469fbca2024f8892861181bb09a6
5
5
  SHA512:
6
- metadata.gz: 37521cf964d7b1cc61c591beb0a77d2b0f0a54973d5a89ab10694aa9b7cb45329704d89064451ce22e36871bfb4296ca33c92b6894cb588c6cbf67fad43048d5
7
- data.tar.gz: 83480c3189051338b6d75fd8601847111a4bf61b1e9d94d9421ab27e6e47d44aece6ea47ff8713a3c81a7ab8ef4a81d807bcc1f78a068c576c77a5a9bdbf24c3
6
+ metadata.gz: e077e932fa6bb00962c6533a3d3656ecfe7e5917266d86c3cb8800b24fb4e81cfcf6311969e66a3cc6906685285cb0e121d52fc605e05a1e287420ff4f25a013
7
+ data.tar.gz: d489f60b57eea0d3b3b106e607c5231e1f4cf527e4b4edbd65081df9da559adeacdf4c92b836394cf279ef5ce2f51a7b9cbb5f85a4d4fc5770ffbadfcf29d871
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 1.6.0
2
+
3
+ * Breaking change: All `!` have been removed from method names
4
+ * Support spawning processes
5
+ * Add `device.ready?` method
6
+
1
7
  # 1.5.8
2
8
 
3
9
  * Support taking screenshots
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- simctl (1.5.8)
4
+ simctl (1.6.0)
5
5
  CFPropertyList
6
6
  naturally
7
7
 
data/README.md CHANGED
@@ -19,20 +19,20 @@ devicetype = SimCtl.devicetype(name: 'iPhone 5')
19
19
  device = SimCtl.create_device 'Unit Tests @ iPhone 5 9.3', devicetype, runtime
20
20
 
21
21
  # Launch a new Simulator.app instance
22
- device.launch!
22
+ device.launch
23
23
 
24
24
  # Wait for the device to be booted
25
- device.wait! {|d| d.state == :booted}
25
+ device.wait {|d| d.state == :booted}
26
26
 
27
27
  # Kill the Simulator.app instance again
28
- device.shutdown!
29
- device.kill!
28
+ device.shutdown
29
+ device.kill
30
30
 
31
31
  # Wait until it did shutdown
32
- device.wait! {|d| d.state == :shutdown}
32
+ device.wait {|d| d.state == :shutdown}
33
33
 
34
34
  # Delete the device
35
- device.delete!
35
+ device.delete
36
36
  ```
37
37
 
38
38
  ## License (MIT)
@@ -17,7 +17,7 @@ module SimCtl
17
17
  device = Executor.execute(command_for('create', Shellwords.shellescape(name), devicetype.identifier, runtime.identifier)) do |identifier|
18
18
  device(udid: identifier)
19
19
  end
20
- device.wait! {|d| d.state == :shutdown && File.exists?(d.path.device_plist)}
20
+ device.wait {|d| d.state == :shutdown && File.exists?(d.path.device_plist)}
21
21
  device
22
22
  end
23
23
  end
@@ -14,10 +14,10 @@ module SimCtl
14
14
  # @return [SimCtl::List] a list of all deleted SimCtl::Device objects
15
15
  def delete_all_devices
16
16
  list_devices.each do |device|
17
- device.kill!
18
- device.shutdown! if device.state != :shutdown
19
- device.wait! {|d| d.state == :shutdown}
20
- device.delete!
17
+ device.kill
18
+ device.shutdown if device.state != :shutdown
19
+ device.wait {|d| d.state == :shutdown}
20
+ device.delete
21
21
  end
22
22
  end
23
23
  end
@@ -12,7 +12,7 @@ module SimCtl
12
12
  # * display: Can be main or tv for iOS, tv for tvOS and main for watchOS
13
13
  # @return [void]
14
14
  def screenshot(device, file, opts={})
15
- unless XcodeVersion.gte? '8.2'
15
+ unless Xcode::Version.gte? '8.2'
16
16
  raise UnsupportedCommandError.new('Needs at least Xcode 8.2')
17
17
  end
18
18
  optional_args = opts.map {|k,v| "--#{k}=#{Shellwords.shellescape(v)}"}
@@ -3,9 +3,7 @@ require 'shellwords'
3
3
  module SimCtl
4
4
  class Command
5
5
  module Launch
6
- LAUNCH_APP_COMMAND = 'xcrun simctl launch'
7
6
  SUPPORTED_SCALE = [1.0, 0.75, 0.5, 0.25]
8
- XCODE_HOME = `xcode-select -p`.chomp
9
7
 
10
8
  # Launches a Simulator instance with the given device
11
9
  #
@@ -23,7 +21,7 @@ module SimCtl
23
21
  }
24
22
  args.merge!({ '-DeviceSetPath' => Shellwords.shellescape(SimCtl.device_set_path) }) unless SimCtl.device_set_path.nil?
25
23
  args = args.merge(opts).zip.flatten.join(' ')
26
- command = "open -Fgn #{XCODE_HOME}/Applications/Simulator.app --args #{args}"
24
+ command = "open -Fgn #{Xcode::Path.home}/Applications/Simulator.app --args #{args}"
27
25
  system command
28
26
  end
29
27
 
@@ -11,16 +11,16 @@ module SimCtl
11
11
  def reset_device(name, device_type, runtime)
12
12
  begin
13
13
  list_devices.where(name: name, os: runtime.name).each do |device|
14
- device.kill!
15
- device.shutdown! if device.state != :shutdown
16
- device.wait! {|d| d.state == :shutdown}
17
- device.delete!
14
+ device.kill
15
+ device.shutdown if device.state != :shutdown
16
+ device.wait {|d| d.state == :shutdown}
17
+ device.delete
18
18
  end
19
19
  rescue Exception => exception
20
20
  yield exception if block_given?
21
21
  end
22
22
  device = create_device name, device_type, runtime
23
- device.wait! {|d| d.state == :shutdown}
23
+ device.wait {|d| d.state == :shutdown}
24
24
  device
25
25
  end
26
26
  end
@@ -0,0 +1,19 @@
1
+ require 'shellwords'
2
+
3
+ module SimCtl
4
+ class Command
5
+ module Spawn
6
+ # Spawn a process on a device
7
+ #
8
+ # @param device [SimCtl::Device] the device to spawn a process on
9
+ # @param path [String] path to executable
10
+ # @param args [Array] arguments for the executable
11
+ # @return [String] standard output the spawned process generated
12
+ def spawn(device, path, args=[], opts={})
13
+ Executor.execute(command_for('spawn', device.udid, Shellwords.shellescape(path), *args.map{|a| Shellwords.shellwords(a)})) do |output|
14
+ output
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -11,6 +11,7 @@ require 'simctl/command/openurl'
11
11
  require 'simctl/command/rename'
12
12
  require 'simctl/command/reset'
13
13
  require 'simctl/command/shutdown'
14
+ require 'simctl/command/spawn'
14
15
  require 'simctl/command/uninstall'
15
16
  require 'simctl/executor'
16
17
  require 'shellwords'
@@ -32,6 +33,7 @@ module SimCtl
32
33
  include SimCtl::Command::Rename
33
34
  include SimCtl::Command::Reset
34
35
  include SimCtl::Command::Shutdown
36
+ include SimCtl::Command::Spawn
35
37
  include SimCtl::Command::Uninstall
36
38
 
37
39
  def device_set_path=(device_set_path)
data/lib/simctl/device.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'cfpropertylist'
2
2
  require 'ostruct'
3
+ require 'simctl/device_launchctl'
3
4
  require 'simctl/device_path'
4
5
  require 'simctl/device_settings'
5
6
  require 'simctl/object'
@@ -9,17 +10,24 @@ module SimCtl
9
10
  class Device < Object
10
11
  attr_reader :availability, :name, :os, :state, :udid
11
12
 
13
+ # Returns true/false if the device is available
14
+ #
15
+ # @return [Bool]
16
+ def available?
17
+ availability !~ /unavailable/i
18
+ end
19
+
12
20
  # Boots the device
13
21
  #
14
22
  # @return [void]
15
- def boot!
23
+ def boot
16
24
  SimCtl.boot_device(self)
17
25
  end
18
26
 
19
27
  # Deletes the device
20
28
  #
21
29
  # @return [void]
22
- def delete!
30
+ def delete
23
31
  SimCtl.delete_device(self)
24
32
  end
25
33
 
@@ -33,7 +41,7 @@ module SimCtl
33
41
  # Erases the device
34
42
  #
35
43
  # @return [void]
36
- def erase!
44
+ def erase
37
45
  SimCtl.erase_device(self)
38
46
  end
39
47
 
@@ -41,7 +49,7 @@ module SimCtl
41
49
  #
42
50
  # @param path Absolute path to the app that should be installed
43
51
  # @return [void]
44
- def install!(path)
52
+ def install(path)
45
53
  SimCtl.install_app(self, path)
46
54
  end
47
55
 
@@ -49,31 +57,38 @@ module SimCtl
49
57
  #
50
58
  # @param app_id App identifier of the app that should be uninstalled
51
59
  # @return [void]
52
- def uninstall!(app_id)
60
+ def uninstall(app_id)
53
61
  SimCtl.uninstall_app(self, app_id)
54
62
  end
55
63
 
56
64
  # Kills the device
57
65
  #
58
66
  # @return [void]
59
- def kill!
67
+ def kill
60
68
  SimCtl.kill_device(self)
61
69
  end
62
70
 
63
71
  # Launches the Simulator
64
72
  #
65
73
  # @return [void]
66
- def launch!(scale=1.0, opts={})
74
+ def launch(scale=1.0, opts={})
67
75
  SimCtl.launch_device(self, scale, opts)
68
76
  end
69
77
 
78
+ # Returns the launchctl object
79
+ #
80
+ # @ return [SimCtl::DeviceLaunchctl]
81
+ def launchctl
82
+ @launchctl ||= DeviceLaunchctl.new(self)
83
+ end
84
+
70
85
  # Launches an app in the given device
71
86
  #
72
87
  # @param opts [Hash] options hash - `{ wait_for_debugger: true/false }`
73
88
  # @param identifier [String] the app identifier
74
89
  # @param args [Array] optional launch arguments
75
90
  # @return [void]
76
- def launch_app!(identifier, args=[], opts={})
91
+ def launch_app(identifier, args=[], opts={})
77
92
  SimCtl.launch_app(self, identifier, args, opts)
78
93
  end
79
94
 
@@ -81,18 +96,31 @@ module SimCtl
81
96
  #
82
97
  # @param url [String] The url to be opened on the device
83
98
  # @return [void]
84
- def open_url!(url)
99
+ def open_url(url)
85
100
  SimCtl.open_url(self, url)
86
101
  end
87
102
 
88
103
  def path
89
- @path ||= DevicePath.new(udid)
104
+ @path ||= DevicePath.new(self)
105
+ end
106
+
107
+ # Returns true/false if the device is ready
108
+ # Uses [SimCtl::DeviceLaunchctl] to look for certain services being running.
109
+ #
110
+ # Unfortunately the 'booted' state does not mean the Simulator is ready for
111
+ # installing or launching applications.
112
+ #
113
+ # @return [Bool]
114
+ def ready?
115
+ # TODO: Should look for different services depending on device type (iphone/ipad, tv, watch)
116
+ running_services = launchctl.list.reject {|service| service.pid.to_i == 0 }.map {|service| service.name}
117
+ (required_services_for_ready - running_services).empty?
90
118
  end
91
119
 
92
120
  # Reloads the device information
93
121
  #
94
122
  # @return [void]
95
- def reload!
123
+ def reload
96
124
  device = SimCtl.device(udid: udid)
97
125
  device.instance_variables.each do |ivar|
98
126
  instance_variable_set(ivar, device.instance_variable_get(ivar))
@@ -102,7 +130,7 @@ module SimCtl
102
130
  # Renames the device
103
131
  #
104
132
  # @return [void]
105
- def rename!(name)
133
+ def rename(name)
106
134
  SimCtl.rename_device(self, name)
107
135
  @name = name
108
136
  end
@@ -110,7 +138,7 @@ module SimCtl
110
138
  # Resets the device
111
139
  #
112
140
  # @return [void]
113
- def reset!
141
+ def reset
114
142
  SimCtl.reset_device name, devicetype, runtime
115
143
  end
116
144
 
@@ -128,7 +156,7 @@ module SimCtl
128
156
  # * type: Can be png, tiff, bmp, gif, jpeg (default is png)
129
157
  # * display: Can be main or tv for iOS, tv for tvOS and main for watchOS
130
158
  # @return [void]
131
- def screenshot!(file, opts={})
159
+ def screenshot(file, opts={})
132
160
  SimCtl.screenshot(self, file, opts)
133
161
  end
134
162
 
@@ -142,10 +170,19 @@ module SimCtl
142
170
  # Shuts down the runtime
143
171
  #
144
172
  # @return [void]
145
- def shutdown!
173
+ def shutdown
146
174
  SimCtl.shutdown_device(self)
147
175
  end
148
176
 
177
+ # Spawn a process on a device
178
+ #
179
+ # @param path [String] path to executable
180
+ # @param args [Array] arguments for the executable
181
+ # @return [void]
182
+ def spawn(path, args=[], opts={})
183
+ SimCtl.spawn(self, path, args, opts)
184
+ end
185
+
149
186
  # Returns the state of the device
150
187
  #
151
188
  # @return [sym]
@@ -156,13 +193,13 @@ module SimCtl
156
193
  # Reloads the device until the given block returns true
157
194
  #
158
195
  # @return [void]
159
- def wait!(timeout=SimCtl.default_timeout)
196
+ def wait(timeout=SimCtl.default_timeout)
160
197
  Timeout::timeout(timeout) do
161
198
  loop do
162
199
  break if yield SimCtl.device(udid: udid)
163
200
  end
164
201
  end
165
- reload!
202
+ reload
166
203
  end
167
204
 
168
205
  def ==(other)
@@ -171,11 +208,56 @@ module SimCtl
171
208
  other.udid == udid
172
209
  end
173
210
 
211
+ def method_missing(method_name, *args, &block)
212
+ if method_name[-1] == '!'
213
+ new_method_name = method_name.to_s.chop.to_sym
214
+ if respond_to?(new_method_name)
215
+ warn "[#{Kernel.caller.first}] `#{method_name}` is deprecated. Please use `#{new_method_name}` instead."
216
+ return send(new_method_name, &block)
217
+ end
218
+ end
219
+ super
220
+ end
221
+
174
222
  private
175
223
 
176
224
  def plist
177
225
  @plist ||= OpenStruct.new(CFPropertyList.native_types(CFPropertyList::List.new(file: path.device_plist).value))
178
226
  end
179
227
 
228
+ def required_services_for_ready
229
+ case runtime.type
230
+ when :tvos, :watchos
231
+ if Xcode::Version.gte? '8.0'
232
+ [
233
+ 'com.apple.mobileassetd',
234
+ 'com.apple.nsurlsessiond',
235
+ ]
236
+ else
237
+ [
238
+ 'com.apple.mobileassetd',
239
+ 'com.apple.networkd',
240
+ ]
241
+ end
242
+ when :ios
243
+ if Xcode::Version.gte? '8.0'
244
+ [
245
+ 'com.apple.SimulatorBridge',
246
+ 'com.apple.SpringBoard',
247
+ 'com.apple.backboardd',
248
+ 'com.apple.medialibraryd',
249
+ 'com.apple.mobile.installd',
250
+ ]
251
+ else
252
+ [
253
+ 'com.apple.SimulatorBridge',
254
+ 'com.apple.SpringBoard',
255
+ 'com.apple.mobile.installd',
256
+ ]
257
+ end
258
+ else
259
+ []
260
+ end
261
+ end
180
262
  end
181
263
  end
@@ -0,0 +1,23 @@
1
+ require 'ostruct'
2
+
3
+ module SimCtl
4
+ class DeviceLaunchctl
5
+ def initialize(device)
6
+ @device = device
7
+ end
8
+
9
+ def list
10
+ fields = [:pid, :status, :name]
11
+ device
12
+ .spawn(device.path.launchctl, ['list'])
13
+ .split("\n")
14
+ .drop(1)
15
+ .map {|item| Hash[fields.zip(item.split("\t"))] }
16
+ .map {|item| OpenStruct.new(item) }
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :device
22
+ end
23
+ end
@@ -1,19 +1,47 @@
1
1
  module SimCtl
2
2
  class DevicePath
3
- attr_reader :device_plist, :global_preferences_plist, :home, :preferences_plist
3
+ def initialize(device)
4
+ @device = device
5
+ end
6
+
7
+ def device_plist
8
+ @device_plist ||= File.join(home, 'device.plist')
9
+ end
10
+
11
+ def global_preferences_plist
12
+ @global_preferences_plist ||= File.join(home, 'data/Library/Preferences/.GlobalPreferences.plist')
13
+ end
14
+
15
+ def home
16
+ @home ||= File.join(device_set_path, device.udid)
17
+ end
4
18
 
5
- def initialize(udid)
6
- @home = File.join(device_set_path, udid)
7
- @device_plist = File.join(@home, 'device.plist')
8
- @global_preferences_plist = File.join(@home, 'data/Library/Preferences/.GlobalPreferences.plist')
9
- @preferences_plist = File.join(@home, 'data/Library/Preferences/com.apple.Preferences.plist')
19
+ def launchctl
20
+ @launchctl ||= File.join(runtime_root, 'bin/launchctl')
21
+ end
22
+
23
+ def preferences_plist
24
+ @preferences_plist ||= File.join(home, 'data/Library/Preferences/com.apple.Preferences.plist')
10
25
  end
11
26
 
12
27
  private
13
28
 
29
+ attr_reader :device
30
+
14
31
  def device_set_path
15
32
  return SimCtl.device_set_path unless SimCtl.device_set_path.nil?
16
33
  File.join(ENV['HOME'], 'Library/Developer/CoreSimulator/Devices')
17
34
  end
35
+
36
+ def locate_runtime_root
37
+ "/Library/Developer/CoreSimulator/Profiles/Runtimes/#{device.runtime.name}.simruntime/Contents/Resources/RuntimeRoot".tap do |path|
38
+ return path if File.exists?(path)
39
+ end
40
+ Xcode::Path.sdk_root
41
+ end
42
+
43
+ def runtime_root
44
+ @runtime_root ||= locate_runtime_root
45
+ end
18
46
  end
19
47
  end
@@ -11,7 +11,7 @@ module SimCtl
11
11
  # Disables the keyboard helpers
12
12
  #
13
13
  # @return [void]
14
- def disable_keyboard_helpers!
14
+ def disable_keyboard_helpers
15
15
  edit_plist(path.preferences_plist) do |plist|
16
16
  %w(
17
17
  KeyboardAllowPaddle
@@ -33,7 +33,7 @@ module SimCtl
33
33
  #
34
34
  # @param enabled value to replace
35
35
  # @return [vod]
36
- def update_hardware_keyboard!(enabled)
36
+ def update_hardware_keyboard(enabled)
37
37
  edit_plist(path.preferences_plist) do |plist|
38
38
  plist['AutomaticMinimizationEnabled'] = enabled
39
39
  end
@@ -3,7 +3,11 @@ require 'simctl/object'
3
3
 
4
4
  module SimCtl
5
5
  class Runtime < Object
6
- attr_reader :availability, :buildversion, :identifier, :name, :version
6
+ attr_reader :availability, :buildversion, :identifier, :name, :type, :version
7
+
8
+ def type
9
+ @type ||= name.split("\s").first.downcase.to_sym
10
+ end
7
11
 
8
12
  def ==(other)
9
13
  return false if other.nil?
@@ -1,3 +1,3 @@
1
1
  module SimCtl
2
- VERSION = '1.5.8'
2
+ VERSION = '1.6.0'
3
3
  end
@@ -0,0 +1,17 @@
1
+ module SimCtl
2
+ module Xcode
3
+ class Path
4
+ HOME=`xcode-select -p`.chomp
5
+
6
+ class << self
7
+ def home
8
+ HOME
9
+ end
10
+
11
+ def sdk_root
12
+ File.join(HOME, 'Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk')
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module SimCtl
2
+ module Xcode
3
+ class Version
4
+ VERSION = Gem::Version.new(`xcodebuild -version`.scan(/Xcode (\S+)/).flatten.first)
5
+
6
+ class << self
7
+ def gte?(version)
8
+ VERSION >= Gem::Version.new(version)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/simctl.rb CHANGED
@@ -3,7 +3,8 @@ require 'simctl/device'
3
3
  require 'simctl/device_type'
4
4
  require 'simctl/list'
5
5
  require 'simctl/runtime'
6
- require 'simctl/xcode_version'
6
+ require 'simctl/xcode/path'
7
+ require 'simctl/xcode/version'
7
8
 
8
9
  module SimCtl
9
10
  class UnsupportedCommandError < StandardError; end
@@ -7,13 +7,13 @@ RSpec.describe SimCtl, order: :defined do
7
7
  @devicetype = SimCtl.devicetype(name: 'iPhone 5')
8
8
  @runtime = SimCtl::Runtime.latest(:ios)
9
9
  @device = SimCtl.create_device @name, @devicetype, @runtime
10
- @device.wait! {|d| d.state == :shutdown}
10
+ @device.wait {|d| d.state == :shutdown}
11
11
  end
12
12
 
13
13
  after(:all) do
14
- with_rescue { @device.kill! }
15
- with_rescue { @device.wait! {|d| d.state == :shutdown} }
16
- with_rescue { @device.delete! }
14
+ with_rescue { @device.kill }
15
+ with_rescue { @device.wait {|d| d.state == :shutdown} }
16
+ with_rescue { @device.delete }
17
17
  end
18
18
 
19
19
  describe 'creating a device' do
@@ -54,13 +54,31 @@ RSpec.describe SimCtl, order: :defined do
54
54
  it 'state is shutdown' do
55
55
  expect(@device.state).to be == :shutdown
56
56
  end
57
+
58
+ describe '#path' do
59
+ it 'has a device plist' do
60
+ expect(File).to exist(@device.path.device_plist)
61
+ end
62
+
63
+ it 'has a global preferences plist' do
64
+ expect(File).to exist(@device.path.global_preferences_plist)
65
+ end
66
+
67
+ it 'has a home' do
68
+ expect(File).to exist(@device.path.home)
69
+ end
70
+
71
+ it 'has a launchctl' do
72
+ expect(File).to exist(@device.path.launchctl)
73
+ end
74
+ end
57
75
  end
58
76
 
59
77
  describe 'device settings' do
60
78
  describe 'update hardware keyboard' do
61
79
  it 'creates the preferences plist' do
62
80
  File.delete(@device.path.preferences_plist) if File.exists?(@device.path.preferences_plist)
63
- @device.settings.update_hardware_keyboard!(false)
81
+ @device.settings.update_hardware_keyboard(false)
64
82
  expect(File).to exist(@device.path.preferences_plist)
65
83
  end
66
84
  end
@@ -68,7 +86,7 @@ RSpec.describe SimCtl, order: :defined do
68
86
  describe 'disable keyboard helpers' do
69
87
  it 'creates the preferences plist' do
70
88
  File.delete(@device.path.preferences_plist) if File.exists?(@device.path.preferences_plist)
71
- @device.settings.disable_keyboard_helpers!
89
+ @device.settings.disable_keyboard_helpers
72
90
  expect(File).to exist(@device.path.preferences_plist)
73
91
  end
74
92
  end
@@ -106,7 +124,7 @@ RSpec.describe SimCtl, order: :defined do
106
124
 
107
125
  describe 'renaming the device' do
108
126
  it 'renames the device' do
109
- @device.rename!('new name')
127
+ @device.rename('new name')
110
128
  expect(@device.name).to be == 'new name'
111
129
  expect(SimCtl.device(udid: @device.udid).name).to be == 'new name'
112
130
  end
@@ -114,63 +132,75 @@ RSpec.describe SimCtl, order: :defined do
114
132
 
115
133
  describe 'erasing the device' do
116
134
  it 'erases the device' do
117
- @device.erase!
135
+ @device.erase
118
136
  end
119
137
  end
120
138
 
121
139
  describe 'launching the device' do
122
140
  it 'launches the device' do
123
- @device.launch!
124
- @device.wait!{|d| d.state == :booted}
141
+ @device.launch
142
+ @device.wait {|d| d.state == :booted}
125
143
  expect(@device.state).to be == :booted
126
144
  end
145
+
146
+ it 'is ready' do
147
+ @device.wait {|d| d.ready?}
148
+ expect(@device).to be_ready
149
+ end
127
150
  end
128
151
 
129
152
  describe 'launching a system app' do
130
153
  it 'launches Safari' do
131
- @device.launch_app!('com.apple.mobilesafari')
154
+ @device.launch_app('com.apple.mobilesafari')
132
155
  end
133
156
  end
134
157
 
135
158
  describe 'taking a screenshot' do
136
- if SimCtl::XcodeVersion.gte? '8.2'
159
+ if SimCtl::Xcode::Version.gte? '8.2'
137
160
  it 'takes a screenshot' do
138
161
  file = File.join(Dir.mktmpdir, 'screenshot.png')
139
- @device.screenshot!(file)
162
+ @device.screenshot(file)
140
163
  expect(File).to exist(file)
141
164
  end
142
165
  else
143
166
  it 'raises exception' do
144
- expect { @device.screenshot!('/tmp/foo.png') }.to raise_error SimCtl::UnsupportedCommandError
167
+ expect { @device.screenshot('/tmp/foo.png') }.to raise_error SimCtl::UnsupportedCommandError
145
168
  end
146
169
  end
147
170
  end
148
171
 
172
+ describe 'spawning a process' do
173
+ it 'spawns launchctl list' do
174
+ output = @device.spawn(@device.path.launchctl, ['list'])
175
+ expect(output.length).to be > 0
176
+ end
177
+ end
178
+
149
179
  describe 'installing an app' do
150
180
  before(:all) do
151
181
  system 'cd spec/SampleApp && xcodebuild -sdk iphonesimulator >/dev/null 2>&1'
152
182
  end
153
183
 
154
184
  it 'installs SampleApp' do
155
- @device.install!('spec/SampleApp/build/Release-iphonesimulator/SampleApp.app')
185
+ @device.install('spec/SampleApp/build/Release-iphonesimulator/SampleApp.app')
156
186
  end
157
187
  end
158
188
 
159
189
  describe 'launching an app' do
160
190
  it 'launches SampleApp' do
161
- @device.launch_app!('com.github.plu.simctl.SampleApp')
191
+ @device.launch_app('com.github.plu.simctl.SampleApp')
162
192
  end
163
193
  end
164
194
 
165
195
  describe 'uninstall an app' do
166
196
  it 'uninstalls SampleApp' do
167
- @device.uninstall!('com.github.plu.simctl.SampleApp')
197
+ @device.uninstall('com.github.plu.simctl.SampleApp')
168
198
  end
169
199
  end
170
200
 
171
201
  describe 'opening a url' do
172
202
  it 'opens some url' do
173
- @device.open_url!('https://www.github.com')
203
+ @device.open_url('https://www.github.com')
174
204
  end
175
205
  end
176
206
 
@@ -180,8 +210,8 @@ RSpec.describe SimCtl, order: :defined do
180
210
  end
181
211
 
182
212
  it 'kills the device' do
183
- @device.kill!
184
- @device.wait!{|d| d.state == :shutdown}
213
+ @device.kill
214
+ @device.wait {|d| d.state == :shutdown}
185
215
  end
186
216
 
187
217
  it 'state is shutdown' do
@@ -195,14 +225,19 @@ RSpec.describe SimCtl, order: :defined do
195
225
  end
196
226
 
197
227
  it 'boots the device' do
198
- @device.boot!
199
- @device.wait! {|d| d.state == :booted}
228
+ @device.boot
229
+ @device.wait {|d| d.state == :booted}
200
230
  expect(@device.state).to be == :booted
201
231
  end
202
232
 
203
233
  it 'state is booted' do
204
234
  expect(@device.state).to be == :booted
205
235
  end
236
+
237
+ it 'is ready' do
238
+ @device.wait {|d| d.ready?}
239
+ expect(@device).to be_ready
240
+ end
206
241
  end
207
242
 
208
243
  describe 'shutting down the device' do
@@ -211,8 +246,8 @@ RSpec.describe SimCtl, order: :defined do
211
246
  end
212
247
 
213
248
  it 'shuts down the device' do
214
- @device.shutdown!
215
- @device.wait!{|d| d.state == :shutdown}
249
+ @device.shutdown
250
+ @device.wait {|d| d.state == :shutdown}
216
251
  end
217
252
 
218
253
  it 'state is shutdown' do
@@ -222,7 +257,7 @@ RSpec.describe SimCtl, order: :defined do
222
257
 
223
258
  describe 'resetting the device' do
224
259
  it 'deletes the old device and creates a new one' do
225
- new_device = @device.reset!
260
+ new_device = @device.reset
226
261
  expect(new_device.name).to be == @device.name
227
262
  expect(new_device.devicetype).to be == @device.devicetype
228
263
  expect(new_device.runtime).to be == @device.runtime
@@ -235,7 +270,7 @@ RSpec.describe SimCtl, order: :defined do
235
270
  describe 'deleting the device' do
236
271
  it 'deletes the device' do
237
272
  device = SimCtl.create_device @name, @devicetype, @runtime
238
- device.delete!
273
+ device.delete
239
274
  expect(SimCtl.device(udid: @device.udid)).to be_nil
240
275
  end
241
276
  end
@@ -77,13 +77,13 @@ RSpec.describe SimCtl do
77
77
  end
78
78
 
79
79
  it 'finds the latest runtime' do
80
- if SimCtl::XcodeVersion.gte?('8.2')
80
+ if SimCtl::Xcode::Version.gte?('8.2')
81
81
  expect(SimCtl::Runtime.latest(:ios).version).to be == '10.2'
82
- elsif SimCtl::XcodeVersion.gte?('8.1')
82
+ elsif SimCtl::Xcode::Version.gte?('8.1')
83
83
  expect(SimCtl::Runtime.latest(:ios).version).to be == '10.1'
84
- elsif SimCtl::XcodeVersion.gte?('8.0')
84
+ elsif SimCtl::Xcode::Version.gte?('8.0')
85
85
  expect(SimCtl::Runtime.latest(:ios).version).to be == '10.0'
86
- elsif SimCtl::XcodeVersion.gte?('7.3')
86
+ elsif SimCtl::Xcode::Version.gte?('7.3')
87
87
  expect(SimCtl::Runtime.latest(:ios).version).to be == '9.3'
88
88
  end
89
89
  end
@@ -12,19 +12,19 @@ RSpec.describe SimCtl do
12
12
  device = SimCtl.create_device 'Unit Tests @ iPhone 5 9.3', devicetype, runtime
13
13
 
14
14
  # Launch a new Simulator.app instance
15
- device.launch!
15
+ device.launch
16
16
 
17
17
  # Wait for the device to be booted
18
- device.wait! {|d| d.state == :booted}
18
+ device.wait {|d| d.state == :booted}
19
19
 
20
20
  # Kill the Simulator.app instance again
21
- device.shutdown!
22
- device.kill!
21
+ device.shutdown
22
+ device.kill
23
23
 
24
24
  # Wait until it did shutdown
25
- device.wait! {|d| d.state == :shutdown}
25
+ device.wait {|d| d.state == :shutdown}
26
26
 
27
27
  # Delete the device
28
- device.delete!
28
+ device.delete
29
29
  end
30
30
  end
data/spec/spec_helper.rb CHANGED
@@ -10,6 +10,8 @@ require File.dirname(__FILE__) + '/../lib/simctl.rb'
10
10
 
11
11
  if ENV['TRAVIS']
12
12
  SimCtl.default_timeout = 300
13
+ else
14
+ SimCtl.default_timeout = 60
13
15
  end
14
16
 
15
17
  unless ENV['CUSTOM_DEVICE_SET_PATH'] == 'false'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simctl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.8
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johannes Plunien
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-22 00:00:00.000000000 Z
11
+ date: 2016-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coveralls
@@ -111,8 +111,10 @@ files:
111
111
  - lib/simctl/command/rename.rb
112
112
  - lib/simctl/command/reset.rb
113
113
  - lib/simctl/command/shutdown.rb
114
+ - lib/simctl/command/spawn.rb
114
115
  - lib/simctl/command/uninstall.rb
115
116
  - lib/simctl/device.rb
117
+ - lib/simctl/device_launchctl.rb
116
118
  - lib/simctl/device_path.rb
117
119
  - lib/simctl/device_settings.rb
118
120
  - lib/simctl/device_type.rb
@@ -121,7 +123,8 @@ files:
121
123
  - lib/simctl/object.rb
122
124
  - lib/simctl/runtime.rb
123
125
  - lib/simctl/version.rb
124
- - lib/simctl/xcode_version.rb
126
+ - lib/simctl/xcode/path.rb
127
+ - lib/simctl/xcode/version.rb
125
128
  - simctl.gemspec
126
129
  - spec/SampleApp/.gitignore
127
130
  - spec/SampleApp/SampleApp.xcodeproj/project.pbxproj
@@ -1,11 +0,0 @@
1
- module SimCtl
2
- module XcodeVersion
3
- VERSION = Gem::Version.new(`xcodebuild -version`.scan(/Xcode (\S+)/).flatten.first)
4
-
5
- class << self
6
- def gte?(version)
7
- return VERSION >= Gem::Version.new(version)
8
- end
9
- end
10
- end
11
- end