Skip to content

Commit

Permalink
Merge pull request #26 from bbc/reboot
Browse files Browse the repository at this point in the history
Add reboot and screenshot options
  • Loading branch information
Asimk21 authored Apr 18, 2017
2 parents 292f71e + e17a1c5 commit e077e87
Show file tree
Hide file tree
Showing 15 changed files with 208 additions and 44 deletions.
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--color
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
language: ruby
rvm:
- 2.2

script: bundle exec rspec
28 changes: 14 additions & 14 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
device_api-ios (1.0.6)
device_api-ios (1.1.0)
device_api (>= 1.0, < 2.0)
ios-devices (>= 0.2)
ox (>= 2.1.0)
Expand All @@ -10,29 +10,29 @@ GEM
remote: https://rubygems.org/
specs:
device_api (1.0.2)
diff-lcs (1.2.5)
diff-lcs (1.3)
ios-devices (0.2.1)
ox (2.4.9)
rspec (3.3.0)
rspec-core (~> 3.3.0)
rspec-expectations (~> 3.3.0)
rspec-mocks (~> 3.3.0)
rspec-core (3.3.2)
rspec-support (~> 3.3.0)
rspec-expectations (3.3.1)
rspec (3.5.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.3.0)
rspec-mocks (3.3.2)
rspec-support (~> 3.5.0)
rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.3.0)
rspec-support (3.3.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)

PLATFORMS
ruby

DEPENDENCIES
device_api-ios!
rspec
rspec (~> 3.5)

BUNDLED WITH
1.14.3
4 changes: 2 additions & 2 deletions device_api-ios.gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = 'device_api-ios'
s.version = '1.0.7'
s.version = '1.1.0'
s.date = Time.now.strftime("%Y-%m-%d")
s.summary = 'IOS Device Management API'
s.description = 'iOS implementation of DeviceAPI'
Expand All @@ -12,5 +12,5 @@ Gem::Specification.new do |s|
s.add_runtime_dependency 'device_api', '>=1.0', '<2.0'
s.add_runtime_dependency 'ios-devices', '>=0.2'
s.add_runtime_dependency 'ox', '>=2.1.0'
s.add_development_dependency 'rspec'
s.add_development_dependency 'rspec', '~> 3.5'
end
17 changes: 8 additions & 9 deletions lib/device_api/ios.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,18 @@ module IOS

# Returns an array of connected iOS devices
def self.devices
IDevice.devices.map do |d|
if d.keys.first
DeviceAPI::IOS::Device.new(serial: d.keys.first, display: d.values.flatten.first, state: 'ok')
end
devs = IDevice.devices
devs.keys.map do |serial|
DeviceAPI::IOS::Device.new(qualifier: serial, display: devs[serial], state: 'ok')
end
end

# Retrieve a Device object by serial ID
def self.device(serial)
if serial.to_s.empty?
raise DeviceAPI::BadSerialString.new("Serial was '#{ serial.nil? ? 'nil' : serial }'")
def self.device(qualifier)
if qualifier.to_s.empty?
raise DeviceAPI::BadSerialString.new("Serial was '#{ qualifier.nil? ? 'nil' : qualifier }'")
end
DeviceAPI::IOS::Device.new(serial: serial, state: 'device')
DeviceAPI::IOS::Device.new(qualifier: qualifier, state: 'device')
end
end
end
end
25 changes: 24 additions & 1 deletion lib/device_api/ios/device.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
require 'device_api/ios/device'
require 'device_api/ios/idevice'
require 'device_api/ios/idevicename'
require 'device_api/ios/idevicescreenshot'
require 'device_api/ios/idevicediagnostics'
require 'ios/devices'

# DeviceAPI - an interface to allow for automation of devices
Expand All @@ -10,8 +12,14 @@ module DeviceAPI
module IOS
# Namespace for the Device object.
class Device < DeviceAPI::Device
attr_accessor :qualifier
def self.create options = {}
self.new(options)
end

def initialize(options = {})
@serial = options[:serial]
@qualifier = options[:qualifier]
@serial = options[:serial] || options[:qualifier]
@state = options[:state]
end

Expand Down Expand Up @@ -49,6 +57,12 @@ def device_class
get_prop('DeviceClass')
end

# Capture screenshot on device
def screenshot(args = {})
args[:device_id] = serial
IDeviceScreenshot.capture(args)
end

# Get the IMEI number of the device
# @return (String) IMEI number of current device
def imei
Expand Down Expand Up @@ -109,6 +123,15 @@ def list_installed_packages
IDeviceInstaller.list_installed_packages(serial)
end

# Reboot the device
def reboot
restart
end

def restart
IDeviceDiagnostics.restart(serial)
end

private

def get_prop(key)
Expand Down
10 changes: 5 additions & 5 deletions lib/device_api/ios/idevice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ def self.devices
raise IDeviceCommandError.new(result.stderr) if result.exit != 0

lines = result.stdout.split("\n")
results = []
results = {}

lines.each do |ln|
if /[0-9a-zA-Z].*/.match(ln)
results.push(ln => execute_with_timeout_and_retry("ideviceinfo -u #{ln} -k DeviceName").stdout.split("\n"))
results[ln] = execute_with_timeout_and_retry("ideviceinfo -u #{ln} -k DeviceName").stdout.strip
end
end
results
Expand All @@ -31,8 +31,8 @@ def self.devices
def self.trusted?(device_id)
result = execute("ideviceinfo -u '#{device_id}'")

return true if result.exit == 0 && !result.stdout.split("\n")[0].match('Usage')
false
lines = result.stdout.split("\n")
result.exit == 0 and lines.length > 0 and not lines[0].match('Usage')
end

# Returns a Hash containing properties of the specified device using idevice_id.
Expand Down Expand Up @@ -66,4 +66,4 @@ def initialize(msg)
end

end
end
end
19 changes: 19 additions & 0 deletions lib/device_api/ios/idevicediagnostics.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# DeviceAPI - an interface to allow for automation of devices
module DeviceAPI
# iOS component of DeviceAPI
module IOS
# Namespace for all methods encapsulating idevicename calls
class IDeviceDiagnostics < Execution

# Reboot the device
def self.reboot(device_id)
self.restart(device_id)
end

def self.restart(device_id)
result = execute("idevicediagnostics restart -u #{device_id}")
end

end
end
end
23 changes: 23 additions & 0 deletions lib/device_api/ios/idevicescreenshot.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# DeviceAPI - an interface to allow for automation of devices
module DeviceAPI
# iOS component of DeviceAPI
module IOS
# Namespace for all methods encapsulating idevicescreenshot calls
class IDeviceScreenshot < Execution

# Take a screenshot of the device based on the provided UUID
# @param filename for the output file
def self.capture(args)
result = execute("idevicescreenshot #{args[:filename]} -u #{args[:device_id]}")
raise IDeviceScreenshotError.new(result.stderr) if result.exit != 0
end
end

# Error class for the IDeviceScreenshot class
class IDeviceScreenshotError < StandardError
def initialize(msg)
super(msg)
end
end
end
end
7 changes: 7 additions & 0 deletions spec/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
The directory structure mirrors the directory structure of the `lib` directory.
For example:

| Module/Class | Lib File | Spec file |
|---|---|---
| `DeviceAPI::IOS` | `lib/device_api/ios.rb` | `spec/lib/device_api/ios_spec.rb` |
| `DeviceAPI::IOS:IDevice` | `lib/device_api/ios/idevice.rb` | `spec/lib/device_api/ios/idevice_spec.rb` |
25 changes: 25 additions & 0 deletions spec/lib/device_api/ios/device_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require 'device_api/ios/device'

RSpec.describe DeviceAPI::IOS::Device do
describe '.create' do
it 'creates an instance of DeviceAPI::IOS::Device' do
expect(DeviceAPI::IOS::Device.create({qualifier: '12345'})).to be_a DeviceAPI::IOS::Device
end

it 'sets the serial to be the qualifier' do
expect(DeviceAPI::IOS::Device.create({qualifier: '12345'}).serial).to eq '12345'
end

it 'uses serial to override the qualifer if it is set' do
expect(DeviceAPI::IOS::Device.create({qualifier: '12345', serial: '98765'}).serial).to eq '98765'
end

it 'sets the qualifier' do
expect(DeviceAPI::IOS::Device.create({qualifier: '12345'}).qualifier).to eq '12345'
end

it 'does not override the qualifier with the serial' do
expect(DeviceAPI::IOS::Device.create({qualifier: '12345', serial: '98765'}).qualifier).to eq '12345'
end
end
end
49 changes: 49 additions & 0 deletions spec/lib/device_api/ios/idevice_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require 'device_api/ios/idevice'

RSpec.describe DeviceAPI::IOS::IDevice do
describe '.devices' do
it 'detects devices attached to device' do
allow(Open3).to receive(:capture3).with('idevice_id -l').and_return( [ "12345678\n23451234\n", '', Struct.new(:exitstatus).new(0) ] )
allow(Open3).to receive(:capture3).with('ideviceinfo -u 12345678 -k DeviceName').and_return( [ "Device-1\n", '', Struct.new(:exitstatus).new(0) ] )
allow(Open3).to receive(:capture3).with('ideviceinfo -u 23451234 -k DeviceName').and_return( [ "Device-2\n", '', Struct.new(:exitstatus).new(0) ] )

expect(DeviceAPI::IOS::IDevice.devices).to match(
{
'12345678' => 'Device-1',
'23451234' => 'Device-2'
}
)
end

it 'detects an empty list of devices' do
allow(Open3).to receive(:capture3).with('idevice_id -l').and_return( [ '', '', Struct.new(:exitstatus).new(0) ] )

expect(DeviceAPI::IOS::IDevice.devices).to match({})
end
end

describe '#trusted?' do
it 'reports a connected device as trusted' do
allow(Open3).to receive(:capture3).with("ideviceinfo -u '00000001'").and_return( [ "ActivationState: Activated\nActivationStateAcknowledged: true\nBasebandActivationTicketVersion: V2\nBasebandCertId: 2\n", '', Struct.new(:exitstatus).new(0) ] )
expect(DeviceAPI::IOS::IDevice.trusted?('00000001')).to be_truthy
end

it 'reports a connected device as not trusted' do
allow(Open3).to receive(:capture3).with("ideviceinfo -u '00000001'").and_return( [ '', "ERROR: Could not connect to lockdownd, error code -19\n", Struct.new(:exitstatus).new(255) ] )
expect(DeviceAPI::IOS::IDevice.trusted?('00000001')).to be_falsey
end

it 'reports a not connected device as not trusted' do
# So apparently calling ideviceinfo with an unknown id results in a success
allow(Open3).to receive(:capture3).with("ideviceinfo -u '00000001'").and_return( [ "Usage: ideviceinfo [OPTIONS]\nShow information about a connected device.\n\n -d, --debug enable communication debugging\n", '', Struct.new(:exitstatus).new(0) ] )
expect(DeviceAPI::IOS::IDevice.trusted?('00000001')).to be_falsey
end

it 'reports a success with no output as not trusted' do
# This is unlikely but can occur
# Possibly due to a race condition
allow(Open3).to receive(:capture3).with("ideviceinfo -u '00000001'").and_return( [ '', '', Struct.new(:exitstatus).new(0) ] )
expect(DeviceAPI::IOS::IDevice.trusted?('00000001')).to be_falsey
end
end
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require 'device_api/ios/ideviceinstaller'

describe DeviceAPI::IOS::IDeviceInstaller do
RSpec.describe DeviceAPI::IOS::IDeviceInstaller do
describe '.list_installed_packages' do
it 'returns a list of installed apps' do
output = <<end
Expand Down Expand Up @@ -94,4 +94,4 @@
expect(result).to eq(false)
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'device_api/execution'
require 'device_api/ios/ipaddress'

describe DeviceAPI::IOS::IPAddress do
RSpec.describe DeviceAPI::IOS::IPAddress do

describe '.address' do
it 'gets the correct IP Address' do
Expand Down Expand Up @@ -32,4 +32,4 @@
expect(ip_address).to eq('10.10.1.80')
end
end
end
end
Loading

0 comments on commit e077e87

Please sign in to comment.