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 +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/README.md +6 -6
- data/lib/simctl/command/create.rb +1 -1
- data/lib/simctl/command/delete.rb +4 -4
- data/lib/simctl/command/io.rb +1 -1
- data/lib/simctl/command/launch.rb +1 -3
- data/lib/simctl/command/reset.rb +5 -5
- data/lib/simctl/command/spawn.rb +19 -0
- data/lib/simctl/command.rb +2 -0
- data/lib/simctl/device.rb +99 -17
- data/lib/simctl/device_launchctl.rb +23 -0
- data/lib/simctl/device_path.rb +34 -6
- data/lib/simctl/device_settings.rb +2 -2
- data/lib/simctl/runtime.rb +5 -1
- data/lib/simctl/version.rb +1 -1
- data/lib/simctl/xcode/path.rb +17 -0
- data/lib/simctl/xcode/version.rb +13 -0
- data/lib/simctl.rb +2 -1
- data/spec/simctl/device_interaction_spec.rb +61 -26
- data/spec/simctl/list_spec.rb +4 -4
- data/spec/simctl/readme_spec.rb +6 -6
- data/spec/spec_helper.rb +2 -0
- metadata +6 -3
- data/lib/simctl/xcode_version.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: befe14fafe0f39d0393b7780baa319a46c6bf13a
|
4
|
+
data.tar.gz: 88c089c6d7da469fbca2024f8892861181bb09a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e077e932fa6bb00962c6533a3d3656ecfe7e5917266d86c3cb8800b24fb4e81cfcf6311969e66a3cc6906685285cb0e121d52fc605e05a1e287420ff4f25a013
|
7
|
+
data.tar.gz: d489f60b57eea0d3b3b106e607c5231e1f4cf527e4b4edbd65081df9da559adeacdf4c92b836394cf279ef5ce2f51a7b9cbb5f85a4d4fc5770ffbadfcf29d871
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
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
|
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
|
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
|
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
|
19
|
-
device.wait
|
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
|
data/lib/simctl/command/io.rb
CHANGED
@@ -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
|
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 #{
|
24
|
+
command = "open -Fgn #{Xcode::Path.home}/Applications/Simulator.app --args #{args}"
|
27
25
|
system command
|
28
26
|
end
|
29
27
|
|
data/lib/simctl/command/reset.rb
CHANGED
@@ -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
|
16
|
-
device.wait
|
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
|
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
|
data/lib/simctl/command.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
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
|
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(
|
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
|
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
|
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
|
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
|
data/lib/simctl/device_path.rb
CHANGED
@@ -1,19 +1,47 @@
|
|
1
1
|
module SimCtl
|
2
2
|
class DevicePath
|
3
|
-
|
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
|
6
|
-
@
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
36
|
+
def update_hardware_keyboard(enabled)
|
37
37
|
edit_plist(path.preferences_plist) do |plist|
|
38
38
|
plist['AutomaticMinimizationEnabled'] = enabled
|
39
39
|
end
|
data/lib/simctl/runtime.rb
CHANGED
@@ -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?
|
data/lib/simctl/version.rb
CHANGED
@@ -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
|
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/
|
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
|
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
|
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
|
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
|
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
|
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
|
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::
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
data/spec/simctl/list_spec.rb
CHANGED
@@ -77,13 +77,13 @@ RSpec.describe SimCtl do
|
|
77
77
|
end
|
78
78
|
|
79
79
|
it 'finds the latest runtime' do
|
80
|
-
if SimCtl::
|
80
|
+
if SimCtl::Xcode::Version.gte?('8.2')
|
81
81
|
expect(SimCtl::Runtime.latest(:ios).version).to be == '10.2'
|
82
|
-
elsif SimCtl::
|
82
|
+
elsif SimCtl::Xcode::Version.gte?('8.1')
|
83
83
|
expect(SimCtl::Runtime.latest(:ios).version).to be == '10.1'
|
84
|
-
elsif SimCtl::
|
84
|
+
elsif SimCtl::Xcode::Version.gte?('8.0')
|
85
85
|
expect(SimCtl::Runtime.latest(:ios).version).to be == '10.0'
|
86
|
-
elsif SimCtl::
|
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
|
data/spec/simctl/readme_spec.rb
CHANGED
@@ -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
|
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
|
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
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.
|
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-
|
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/
|
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
|
data/lib/simctl/xcode_version.rb
DELETED