lib/simctl/device.rb in simctl-1.5.8 vs lib/simctl/device.rb in simctl-1.6.0
- old
+ new
@@ -1,27 +1,35 @@
require 'cfpropertylist'
require 'ostruct'
+require 'simctl/device_launchctl'
require 'simctl/device_path'
require 'simctl/device_settings'
require 'simctl/object'
require 'timeout'
module SimCtl
class Device < Object
attr_reader :availability, :name, :os, :state, :udid
+ # Returns true/false if the device is available
+ #
+ # @return [Bool]
+ def available?
+ availability !~ /unavailable/i
+ end
+
# Boots the device
#
# @return [void]
- def boot!
+ def boot
SimCtl.boot_device(self)
end
# Deletes the device
#
# @return [void]
- def delete!
+ def delete
SimCtl.delete_device(self)
end
# Returns the device type
#
@@ -31,88 +39,108 @@
end
# Erases the device
#
# @return [void]
- def erase!
+ def erase
SimCtl.erase_device(self)
end
# Installs an app on a device
#
# @param path Absolute path to the app that should be installed
# @return [void]
- def install!(path)
+ def install(path)
SimCtl.install_app(self, path)
end
# Uninstall an app from a device
#
# @param app_id App identifier of the app that should be uninstalled
# @return [void]
- def uninstall!(app_id)
+ def uninstall(app_id)
SimCtl.uninstall_app(self, app_id)
end
# Kills the device
#
# @return [void]
- def kill!
+ def kill
SimCtl.kill_device(self)
end
# Launches the Simulator
#
# @return [void]
- def launch!(scale=1.0, opts={})
+ def launch(scale=1.0, opts={})
SimCtl.launch_device(self, scale, opts)
end
+ # Returns the launchctl object
+ #
+ # @ return [SimCtl::DeviceLaunchctl]
+ def launchctl
+ @launchctl ||= DeviceLaunchctl.new(self)
+ end
+
# Launches an app in the given device
#
# @param opts [Hash] options hash - `{ wait_for_debugger: true/false }`
# @param identifier [String] the app identifier
# @param args [Array] optional launch arguments
# @return [void]
- def launch_app!(identifier, args=[], opts={})
+ def launch_app(identifier, args=[], opts={})
SimCtl.launch_app(self, identifier, args, opts)
end
# Opens the url on the device
#
# @param url [String] The url to be opened on the device
# @return [void]
- def open_url!(url)
+ def open_url(url)
SimCtl.open_url(self, url)
end
def path
- @path ||= DevicePath.new(udid)
+ @path ||= DevicePath.new(self)
end
+ # Returns true/false if the device is ready
+ # Uses [SimCtl::DeviceLaunchctl] to look for certain services being running.
+ #
+ # Unfortunately the 'booted' state does not mean the Simulator is ready for
+ # installing or launching applications.
+ #
+ # @return [Bool]
+ def ready?
+ # TODO: Should look for different services depending on device type (iphone/ipad, tv, watch)
+ running_services = launchctl.list.reject {|service| service.pid.to_i == 0 }.map {|service| service.name}
+ (required_services_for_ready - running_services).empty?
+ end
+
# Reloads the device information
#
# @return [void]
- def reload!
+ def reload
device = SimCtl.device(udid: udid)
device.instance_variables.each do |ivar|
instance_variable_set(ivar, device.instance_variable_get(ivar))
end
end
# Renames the device
#
# @return [void]
- def rename!(name)
+ def rename(name)
SimCtl.rename_device(self, name)
@name = name
end
# Resets the device
#
# @return [void]
- def reset!
+ def reset
SimCtl.reset_device name, devicetype, runtime
end
# Resets the runtime
#
@@ -126,11 +154,11 @@
# @param file Path where the screenshot should be saved to
# @param opts Optional hash that supports two keys:
# * type: Can be png, tiff, bmp, gif, jpeg (default is png)
# * display: Can be main or tv for iOS, tv for tvOS and main for watchOS
# @return [void]
- def screenshot!(file, opts={})
+ def screenshot(file, opts={})
SimCtl.screenshot(self, file, opts)
end
# Returns the settings object
#
@@ -140,42 +168,96 @@
end
# Shuts down the runtime
#
# @return [void]
- def shutdown!
+ def shutdown
SimCtl.shutdown_device(self)
end
+ # Spawn a process on a device
+ #
+ # @param path [String] path to executable
+ # @param args [Array] arguments for the executable
+ # @return [void]
+ def spawn(path, args=[], opts={})
+ SimCtl.spawn(self, path, args, opts)
+ end
+
# Returns the state of the device
#
# @return [sym]
def state
@state.downcase.to_sym
end
# Reloads the device until the given block returns true
#
# @return [void]
- def wait!(timeout=SimCtl.default_timeout)
+ def wait(timeout=SimCtl.default_timeout)
Timeout::timeout(timeout) do
loop do
break if yield SimCtl.device(udid: udid)
end
end
- reload!
+ reload
end
def ==(other)
return false if other.nil?
return false unless other.kind_of? Device
other.udid == udid
end
+ def method_missing(method_name, *args, &block)
+ if method_name[-1] == '!'
+ new_method_name = method_name.to_s.chop.to_sym
+ if respond_to?(new_method_name)
+ warn "[#{Kernel.caller.first}] `#{method_name}` is deprecated. Please use `#{new_method_name}` instead."
+ return send(new_method_name, &block)
+ end
+ end
+ super
+ end
+
private
def plist
@plist ||= OpenStruct.new(CFPropertyList.native_types(CFPropertyList::List.new(file: path.device_plist).value))
end
+ def required_services_for_ready
+ case runtime.type
+ when :tvos, :watchos
+ if Xcode::Version.gte? '8.0'
+ [
+ 'com.apple.mobileassetd',
+ 'com.apple.nsurlsessiond',
+ ]
+ else
+ [
+ 'com.apple.mobileassetd',
+ 'com.apple.networkd',
+ ]
+ end
+ when :ios
+ if Xcode::Version.gte? '8.0'
+ [
+ 'com.apple.SimulatorBridge',
+ 'com.apple.SpringBoard',
+ 'com.apple.backboardd',
+ 'com.apple.medialibraryd',
+ 'com.apple.mobile.installd',
+ ]
+ else
+ [
+ 'com.apple.SimulatorBridge',
+ 'com.apple.SpringBoard',
+ 'com.apple.mobile.installd',
+ ]
+ end
+ else
+ []
+ end
+ end
end
end