simctl 1.5.8 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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