diff --git a/.travis.yml b/.travis.yml
index 8d194f4e6..7353abe77 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,7 @@
language: objective-c
before_script:
+ - script/ci/travis/instruments-auth.sh
- gem install json
- gem uninstall -Vax --force --no-abort-on-dependent calabash-cucumber
- gem uninstall -Vax --force --no-abort-on-dependent run_loop
@@ -9,9 +10,9 @@ before_script:
- script/ci/travis/bundle-install.rb
script:
- # Skip XTC run on all but 2.1.1 to avoid redundant testing. This is just a
+ # Skip XTC run on all but 2.1.2 to avoid redundant testing. This is just a
# smoke test to ensure a job can be validated; the ruby version is immaterial.
- - if [[ ( ! -z $XTC_API_TOKEN && `ruby -e 'print RUBY_VERSION'` == '2.1.1' ) ]]; then script/ci/travis/xtc-submit-ci.rb; fi
+ - if [[ ( ! -z $XTC_API_TOKEN && `ruby -e 'print RUBY_VERSION'` == '2.1.2' ) ]]; then script/ci/travis/xtc-submit-ci.rb; fi
- script/ci/travis/install-gem-ci.rb
- script/ci/travis/rspec-ci.rb
- script/ci/travis/cucumber-ci.rb --tags ~@no_ci
diff --git a/calabash-cucumber/lib/calabash-cucumber/actions/instruments_actions.rb b/calabash-cucumber/lib/calabash-cucumber/actions/instruments_actions.rb
index d70c927fd..94cffe086 100644
--- a/calabash-cucumber/lib/calabash-cucumber/actions/instruments_actions.rb
+++ b/calabash-cucumber/lib/calabash-cucumber/actions/instruments_actions.rb
@@ -121,17 +121,25 @@ def find_and_normalize(ui_query)
def normalize_rect_for_orientation!(orientation, rect)
orientation = orientation.to_sym
launcher = Calabash::Cucumber::Launcher.launcher
+
+ # Coordinate translations for orientation is handled in the server for iOS 8+
+ # https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICoordinateSpace_protocol/index.html
if launcher.ios_major_version.to_i >= 8
- return ## Orientation management changed in iOS 8:
- # ## https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICoordinateSpace_protocol/index.html
+ return
end
- dimensions = launcher.device.screen_dimensions
- if dimensions
- screen_size = {width: dimensions[:width]*dimensions[:sample]/dimensions[:scale],
- height: dimensions[:height]*dimensions[:sample]/dimensions[:scale]}
+
+ # We cannot use Device#screen_dimensions here because on iPads the height
+ # and width are the opposite of what we expect.
+ # @todo Move all coordinate/orientation translation into the server.
+ device = launcher.device
+ if device.ipad?
+ screen_size = { :width => 768, :height => 1024 }
+ elsif device.iphone_4in?
+ screen_size = { :width => 320, :height => 568 }
else
- screen_size = launcher.device.screen_size
+ screen_size = { :width => 320, :height => 480 }
end
+
case orientation
when :right
cx = rect['center_x']
@@ -150,5 +158,4 @@ def normalize_rect_for_orientation!(orientation, rect)
# no-op by design.
end
end
-
-end
\ No newline at end of file
+end
diff --git a/calabash-cucumber/lib/calabash-cucumber/device.rb b/calabash-cucumber/lib/calabash-cucumber/device.rb
index 07a51d4ba..f7b112bcd 100644
--- a/calabash-cucumber/lib/calabash-cucumber/device.rb
+++ b/calabash-cucumber/lib/calabash-cucumber/device.rb
@@ -220,6 +220,12 @@ def ios_major_version
version_hash(ios_version)[:major_version]
end
+ # Is this device running iOS 8?
+ # @return [Boolean] true if the major version of the OS is 8
+ def ios8?
+ ios_major_version.eql?('8')
+ end
+
# Is this device running iOS 7?
# @return [Boolean] true if the major version of the OS is 7
def ios7?
@@ -238,15 +244,13 @@ def ios5?
ios_major_version.eql?('5')
end
- # The screen size of the device.
+ # @deprecated 0.11.2 Replaced with screen_dimensions.
#
- # @note These values are not dynamically computed; they are constants.
- #
- # @note These values are for portrait or upside orientations
+ # The screen size of the device.
#
- # @return [Hash] representation of the screen size as a hash with keys
- # `:width` and `:height`
+ # @return [Hash] representation of the screen size
def screen_size
+ _deprecated('0.11.2', 'Replaced with screen_dimensions', :warn)
return screen_dimensions if screen_dimensions
return { :width => 768, :height => 1024 } if ipad?
return { :width => 320, :height => 568 } if iphone_4in?
diff --git a/calabash-cucumber/lib/calabash-cucumber/environment_helpers.rb b/calabash-cucumber/lib/calabash-cucumber/environment_helpers.rb
index 504284553..aed24ddfd 100644
--- a/calabash-cucumber/lib/calabash-cucumber/environment_helpers.rb
+++ b/calabash-cucumber/lib/calabash-cucumber/environment_helpers.rb
@@ -155,6 +155,18 @@ def ios7?
_OS_ENV.eql?(_canonical_os_version(:ios7)) || _default_device_or_create().ios7?
end
+ # Is the device under test running iOS 8?
+ #
+ # @note
+ # **WARNING:** The `OS` env variable has been deprecated and should
+ # never be set.
+ #
+ # @raise [RuntimeError] if the server cannot be reached
+ # @return [Boolean] true if device under test is running iOS 8
+ def ios8?
+ _default_device_or_create.ios8?
+ end
+
# Is the app that is being tested an iPhone app emulated on an iPad?
#
# @see Calabash::Cucumber::IPad
diff --git a/calabash-cucumber/lib/calabash-cucumber/launcher.rb b/calabash-cucumber/lib/calabash-cucumber/launcher.rb
index 0ba88bb32..8b7fcd90b 100644
--- a/calabash-cucumber/lib/calabash-cucumber/launcher.rb
+++ b/calabash-cucumber/lib/calabash-cucumber/launcher.rb
@@ -961,7 +961,7 @@ def server_version_from_bundle(app_bundle_path)
server_version = nil
exe_paths.each do |path|
- server_version_string = `strings "#{path}" | grep -E 'CALABASH VERSION'`.chomp!
+ server_version_string = `xcrun strings "#{path}" | grep -E 'CALABASH VERSION'`.chomp!
if server_version_string
server_version = server_version_string.split(' ').last
break
diff --git a/calabash-cucumber/lib/calabash-cucumber/uia.rb b/calabash-cucumber/lib/calabash-cucumber/uia.rb
index e30543ac5..98577d236 100644
--- a/calabash-cucumber/lib/calabash-cucumber/uia.rb
+++ b/calabash-cucumber/lib/calabash-cucumber/uia.rb
@@ -26,7 +26,13 @@ def uia(command, options={})
case run_loop[:uia_strategy]
when :preferences
res = http({:method => :post, :path => 'uia'}, {:command => command}.merge(options))
- res = JSON.parse(res)
+
+ begin
+ res = JSON.parse(res)
+ rescue TypeError, JSON::ParserError => _
+ raise "Could not parse response '#{res}'; the app has probably crashed"
+ end
+
if res['outcome'] != 'SUCCESS'
raise "uia action failed because: #{res['reason']}\n#{res['details']}"
end
@@ -234,13 +240,32 @@ def uia_type_string(string, opt_text_before='', escape=true)
indexes = string.enum_for(:scan, /\\/).map { Regexp.last_match.begin(0) }
indexes.reverse.each { |idx| string = string.insert(idx, '\\') }
end
- res = uia_handle_command(:typeString, string, opt_text_before)
- status = res['status']
- if status.eql?('error')
- value = res['value']
- raise "could not type '#{string}' - '#{value}'"
+ result = uia_handle_command(:typeString, string, opt_text_before)
+
+ # When 'status' == 'success', we get back result['value']. Sometimes,
+ # the 'value' key is not present in the result - in which case we assume
+ # success without error.
+ return if result.nil?
+
+ # Typing on UIWebViews returns result['value'] => ':nil'. There might
+ # be other cases where result is _not_ a Hash.
+ return unless result.is_a? Hash
+
+ # If there is no 'status' key, then we assume success. Syntax errors
+ # should be caught upstream.
+ # https://github.com/calabash/calabash-ios/issues/374
+ return unless result.has_key? 'status'
+
+ status = result['status']
+
+ # If status is not 'error' we punt. Should never happen.
+ return if status != 'error'
+
+ if result.has_key? 'value'
+ raise "Could not type '#{string}' - UIAutomation returned an error: '#{result['value']}'"
+ else
+ raise "Could not type '#{string}' - UIAutomation returned '#{result}'"
end
- status
end
# @!visibility private
@@ -385,8 +410,6 @@ def uia_result(s)
s
end
end
-
-
end
end
end
diff --git a/calabash-cucumber/lib/calabash-cucumber/version.rb b/calabash-cucumber/lib/calabash-cucumber/version.rb
index c35bbcee7..d5ccdb807 100644
--- a/calabash-cucumber/lib/calabash-cucumber/version.rb
+++ b/calabash-cucumber/lib/calabash-cucumber/version.rb
@@ -3,11 +3,11 @@ module Cucumber
# @!visibility public
# The Calabash iOS gem version.
- VERSION = '0.11.1'
+ VERSION = '0.11.2'
# @!visibility public
# The minimum required version of the calabash.framework or, for Xamarin
# users, the Calabash component.
- MIN_SERVER_VERSION = '0.11.1'
+ MIN_SERVER_VERSION = '0.11.2'
end
end
diff --git a/calabash-cucumber/spec/core_spec.rb b/calabash-cucumber/spec/core_spec.rb
index 55e5aec7b..c86a5f815 100644
--- a/calabash-cucumber/spec/core_spec.rb
+++ b/calabash-cucumber/spec/core_spec.rb
@@ -44,7 +44,7 @@ class CoreIncluded
end
describe 'Xcode regression' do
- xcode_installs = Resources.shared.alt_xcodes_gte_xc51_hash
+ xcode_installs = Resources.shared.alt_xcode_details_hash
if xcode_installs.empty?
it 'no alternative Xcode installs' do
expect(true).to be == true
@@ -80,7 +80,7 @@ class CoreIncluded
let(:core_instance) { CoreIncluded.new }
xctools = RunLoop::XCTools.new
- physical_devices = xctools.instruments :devices
+ physical_devices = Resources.shared.physical_devices_for_testing(xctools)
if physical_devices.empty?
it 'no devices attached to this computer' do
@@ -92,7 +92,7 @@ class CoreIncluded
end
else
physical_devices.each do |device|
- if device.version >= RunLoop::Version.new('8.0') and xctools.xcode_version < RunLoop::Version.new('6.0')
+ if Resources.shared.incompatible_xcode_ios_version(device.version, xctools.xcode_version)
it "Skipping #{device.name} iOS #{device.version} with Xcode #{version} - combination not supported" do
expect(true).to be == true
end
@@ -123,14 +123,15 @@ class CoreIncluded
let(:launcher) { Calabash::Cucumber::Launcher.new }
let(:core_instance) { CoreIncluded.new }
- xcode_installs = Resources.shared.alt_xcodes_gte_xc51_hash
- physical_devices = RunLoop::XCTools.new.instruments :devices
+ xcode_installs = Resources.shared.alt_xcode_details_hash
+ xctools = RunLoop::XCTools.new
+ physical_devices = Resources.shared.physical_devices_for_testing(xctools)
if not xcode_installs.empty? and Resources.shared.ideviceinstaller_available? and not physical_devices.empty?
xcode_installs.each do |install_hash|
version = install_hash[:version]
path = install_hash[:path]
physical_devices.each do |device|
- if device.version >= RunLoop::Version.new('8.0') and version < RunLoop::Version.new('6.0')
+ if Resources.shared.incompatible_xcode_ios_version(device.version, version)
it "Skipping #{device.name} iOS #{device.version} with Xcode #{version} - combination not supported" do
expect(true).to be == true
end
diff --git a/calabash-cucumber/spec/device_spec.rb b/calabash-cucumber/spec/device_spec.rb
new file mode 100644
index 000000000..bbf9054ac
--- /dev/null
+++ b/calabash-cucumber/spec/device_spec.rb
@@ -0,0 +1,20 @@
+describe Calabash::Cucumber::Device do
+
+ # noinspection RubyStringKeysInHashInspection
+ let(:simulator_data) { Resources.shared.server_version :simulator }
+ let(:endpoint) { 'http://localhost:37265' }
+
+ describe '#ios8?' do
+ it 'returns false when target is not iOS 8' do
+ device = Calabash::Cucumber::Device.new(endpoint, simulator_data)
+ expect(device.ios8?).to be == false
+ end
+
+ it 'returns true when target is iOS 8' do
+ simulator_data['iOS_version'] = '8.0'
+ device = Calabash::Cucumber::Device.new(endpoint, simulator_data)
+ expect(device.ios8?).to be == true
+ end
+ end
+
+end
diff --git a/calabash-cucumber/spec/environment_helpers_spec.rb b/calabash-cucumber/spec/environment_helpers_spec.rb
new file mode 100644
index 000000000..427968084
--- /dev/null
+++ b/calabash-cucumber/spec/environment_helpers_spec.rb
@@ -0,0 +1,32 @@
+module Calabash
+ module RspecTests
+ module EnvironmentHelpers
+ class TestObject
+ include Calabash::Cucumber::EnvironmentHelpers
+ end
+ end
+ end
+end
+
+describe Calabash::Cucumber::EnvironmentHelpers do
+
+ let(:simulator_data) { Resources.shared.server_version :simulator }
+ let(:endpoint) { 'http://localhost:37265' }
+ let(:test_obj) { Calabash::RspecTests::EnvironmentHelpers::TestObject.new }
+
+ describe 'ios8?' do
+ it 'returns true when device under test is iOS 8' do
+ simulator_data['iOS_version'] = '8.0'
+ device = Calabash::Cucumber::Device.new(endpoint, simulator_data)
+ expect(test_obj).to receive(:default_device).and_return(device)
+ expect(test_obj.ios8?).to be == true
+ end
+
+ it 'returns false when device under test is not iOS 8' do
+ simulator_data['iOS_version'] = '7.0'
+ device = Calabash::Cucumber::Device.new(endpoint, simulator_data)
+ expect(test_obj).to receive(:default_device).and_return(device)
+ expect(test_obj.ios8?).to be == false
+ end
+ end
+end
diff --git a/calabash-cucumber/spec/launcher_spec.rb b/calabash-cucumber/spec/launcher_spec.rb
index 1e6bca936..3b762f047 100644
--- a/calabash-cucumber/spec/launcher_spec.rb
+++ b/calabash-cucumber/spec/launcher_spec.rb
@@ -299,7 +299,7 @@ def args_for_reset_app_sandbox(sdk='7.1')
abp = Resources.shared.app_bundle_path :lp_simple_example
actual = launcher.server_version_from_bundle abp
expect(actual).not_to be == nil
- expect(RunLoop::Version.new(actual).to_s).to be == '0.11.1'
+ expect(RunLoop::Version.new(actual).to_s).to be == '0.11.2'
end
it 'and when there is a space is the path' do
@@ -309,7 +309,7 @@ def args_for_reset_app_sandbox(sdk='7.1')
abp = File.expand_path(File.join(dir, 'LPSimpleExample-cal.app'))
actual = launcher.server_version_from_bundle abp
expect(actual).not_to be == nil
- expect(RunLoop::Version.new(actual).to_s).to be == '0.11.1'
+ expect(RunLoop::Version.new(actual).to_s).to be == '0.11.2'
end
end
diff --git a/calabash-cucumber/spec/reset_app_sandbox_spec.rb b/calabash-cucumber/spec/reset_app_sandbox_spec.rb
index ec967e119..6058d2cb8 100644
--- a/calabash-cucumber/spec/reset_app_sandbox_spec.rb
+++ b/calabash-cucumber/spec/reset_app_sandbox_spec.rb
@@ -150,7 +150,7 @@ def path_to_containers(udid, simulator)
describe 'Xcode < 6' do
xcode_selected = Resources.shared.xcode_select_xcode_hash
- xcode_installs = Resources.shared.alt_xcodes_gte_xc51_hash + [xcode_selected]
+ xcode_installs = Resources.shared.alt_xcode_details_hash + [xcode_selected]
max_version = RunLoop::Version.new('5.1.1')
xcode5 = xcode_installs.delete_if { |hash| hash[:version] > max_version }.sample
if xcode5.nil?
@@ -212,7 +212,7 @@ def path_to_containers(udid, simulator)
describe 'Xcode >= 6.0' do
xcode_selected = Resources.shared.xcode_select_xcode_hash
- xcode_installs = Resources.shared.alt_xcodes_gte_xc51_hash + [xcode_selected]
+ xcode_installs = Resources.shared.alt_xcode_details_hash + [xcode_selected]
min_version = RunLoop::Version.new('6.0')
xcode_versions = xcode_installs.delete_if { |hash| hash[:version] < min_version }
if xcode_versions.empty?
@@ -224,34 +224,29 @@ def path_to_containers(udid, simulator)
describe "Xcode #{xcode6[:version]}" do
let(:helper) { Calabash::Rspec::ResetAppSandbox::Helper.new }
- if Resources.shared.travis_ci?
- it 'Skipping default simulator test on Travis CI; Simulator environment is not stable enough' do
- expect(true).to be == true
- end
- else
- it 'can reset the default simulator' do
- ENV['DEVELOPER_DIR'] = xcode6[:path]
- sim_control = RunLoop::SimControl.new
- helper.launch_and_stop_simulator(launcher, sim_control, 'simulator')
+ it 'can reset the default simulator' do
+ ENV['DEVELOPER_DIR'] = xcode6[:path]
+ sim_control = RunLoop::SimControl.new
+ helper.launch_and_stop_simulator(launcher, sim_control, 'simulator')
- target_simulator = helper.default_simulator_as_device(sim_control)
- udid = target_simulator.udid
+ target_simulator = helper.default_simulator_as_device(sim_control)
+ udid = target_simulator.udid
- app_bundles = helper.path_to_sim_app_bundles(udid, target_simulator)
- expect(File).to exist(app_bundles)
+ app_bundles = helper.path_to_sim_app_bundles(udid, target_simulator)
+ expect(File).to exist(app_bundles)
- installed_apps = helper.installed_apps(udid, target_simulator)
- expect(installed_apps).to include('LPSimpleExample-cal.app')
+ installed_apps = helper.installed_apps(udid, target_simulator)
+ expect(installed_apps).to include('LPSimpleExample-cal.app')
- launcher.reset_app_sandbox
+ launcher.reset_app_sandbox
- containers = helper.path_to_containers(udid, target_simulator)
- expect(File).not_to exist(containers)
- end
+ containers = helper.path_to_containers(udid, target_simulator)
+ expect(File).not_to exist(containers)
end
describe 'can reset a simulator if :udid option is passed' do
helper = Calabash::Rspec::ResetAppSandbox::Helper.new
+ ENV['DEVELOPER_DIR'] = xcode6[:path]
sim_control = RunLoop::SimControl.new
target_simulator = helper.random_core_simulator(sim_control)
instruments_launch_name = helper.instruments_launch_name(target_simulator)
@@ -276,6 +271,7 @@ def path_to_containers(udid, simulator)
describe 'respects the DEVICE_TARGET env var' do
helper = Calabash::Rspec::ResetAppSandbox::Helper.new
+ ENV['DEVELOPER_DIR'] = xcode6[:path]
sim_control = RunLoop::SimControl.new
target_simulator = helper.random_core_simulator(sim_control)
instruments_launch_name = helper.instruments_launch_name(target_simulator)
diff --git a/calabash-cucumber/spec/resources.rb b/calabash-cucumber/spec/resources.rb
index a94d352d5..92860b959 100644
--- a/calabash-cucumber/spec/resources.rb
+++ b/calabash-cucumber/spec/resources.rb
@@ -59,6 +59,12 @@ def device_for_mocking
'branch' => 'master',
'revision' => 'e494e30'
},
+ 'screen_dimensions' => {
+ 'scale' => 2,
+ 'width' => 640,
+ 'sample' => 1,
+ 'height' => 1136
+ },
'app_version' => '1.4.0',
'iOS_version' => '8.0',
'system' => 'x86_64',
@@ -67,9 +73,43 @@ def device_for_mocking
Calabash::Cucumber::Device.new(endpoint, version_data)
end
+ def server_version(device_or_simulator)
+ case device_or_simulator
+ when :device
+ {}
+ when :simulator
+ {
+ 'app_version' => '1.0',
+ 'outcome' => 'SUCCESS',
+ 'app_id' => 'com.xamarin.chou-cal',
+ 'simulator_device' => 'iPhone',
+ 'version' => '0.11.0',
+ 'app_name' => 'chou-cal',
+ 'iphone_app_emulated_on_ipad' => false,
+ '4inch' => true,
+ 'git' => {
+ 'remote_origin' => 'git@github.com:calabash/calabash-ios-server.git',
+ 'branch' => 'develop',
+ 'revision' => '652b20b'
+ },
+ 'screen_dimensions' => {
+ 'scale' => 2,
+ 'width' => 640,
+ 'sample' => 1,
+ 'height' => 1136
+ },
+ 'iOS_version' => '7.1',
+ 'system' => 'x86_64',
+ 'simulator' => 'CoreSimulator 110.2 - Device: iPhone 5 - Runtime: iOS 7.1 (11D167) - DeviceType: iPhone 5'
+ }
+ else
+ raise "expected '#{device_or_simulator}' to be one of #{[:simulator, :device]}"
+ end
+ end
+
def alt_xcode_install_paths
@alt_xcode_install_paths ||= lambda {
- min_xcode_version = RunLoop::Version.new('5.1')
+ min_xcode_version = RunLoop::Version.new('5.1.1')
Dir.glob('/Xcode/*/*.app/Contents/Developer').map do |path|
xcode_version = path[/(\d\.\d(\.\d)?)/, 0]
if RunLoop::Version.new(xcode_version) >= min_xcode_version
@@ -90,7 +130,7 @@ def xcode_select_xcode_hash
}.call
end
- def alt_xcodes_gte_xc51_hash
+ def alt_xcode_details_hash(skip_versions=[RunLoop::Version.new('6.0')])
@alt_xcodes_gte_xc51_hash ||= lambda {
ENV.delete('DEVELOPER_DIR')
xcode_select_path = RunLoop::XCTools.new.xcode_developer_dir
@@ -101,7 +141,9 @@ def alt_xcodes_gte_xc51_hash
version = RunLoop::XCTools.new.xcode_version
if path == xcode_select_path
nil
- elsif version >= RunLoop::Version.new('5.1')
+ elsif skip_versions.include?(version)
+ nil
+ elsif version >= RunLoop::Version.new('5.1.1')
{
:version => RunLoop::XCTools.new.xcode_version,
:path => path
@@ -213,4 +255,34 @@ def uninstall(udid, bundle_id, installer)
end
true
end
+
+ def incompatible_xcode_ios_version(device_version, xcode_version)
+ [(device_version >= RunLoop::Version.new('8.0') and xcode_version < RunLoop::Version.new('6.0')),
+ (device_version >= RunLoop::Version.new('8.1') and xcode_version < RunLoop::Version.new('6.1'))].any?
+ end
+
+ def idevice_id_bin_path
+ @idevice_id_bin_path ||= `which idevice_id`.chomp!
+ end
+
+ def idevice_id_available?
+ path = idevice_id_bin_path
+ path and File.exist? path
+ end
+
+ def physical_devices_for_testing(xcode_tools)
+ # Xcode 6 + iOS 8 - devices on the same network, whether development or not,
+ # appear when calling $ xcrun instruments -s devices. For the purposes of
+ # testing, we will only try to connect to devices that are connected via
+ # udid.
+ @physical_devices_for_testing ||= lambda {
+ devices = xcode_tools.instruments(:devices)
+ if idevice_id_available?
+ white_list = `#{idevice_id_bin_path} -l`.strip.split("\n")
+ devices.select { | device | white_list.include?(device.udid) }
+ else
+ devices
+ end
+ }.call
+ end
end
diff --git a/calabash-cucumber/spec/resources/LPSimpleExample-cal.ipa b/calabash-cucumber/spec/resources/LPSimpleExample-cal.ipa
index f121030d1..906faaabf 100644
Binary files a/calabash-cucumber/spec/resources/LPSimpleExample-cal.ipa and b/calabash-cucumber/spec/resources/LPSimpleExample-cal.ipa differ
diff --git a/calabash-cucumber/spec/resources/chou.app/Info.plist b/calabash-cucumber/spec/resources/chou.app/Info.plist
index 44b2b2467..b82df4245 100644
Binary files a/calabash-cucumber/spec/resources/chou.app/Info.plist and b/calabash-cucumber/spec/resources/chou.app/Info.plist differ
diff --git a/calabash-cucumber/spec/resources/chou.app/chou b/calabash-cucumber/spec/resources/chou.app/chou
index 4e06badfd..9c745c20d 100755
Binary files a/calabash-cucumber/spec/resources/chou.app/chou and b/calabash-cucumber/spec/resources/chou.app/chou differ
diff --git a/calabash-cucumber/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Info.plist b/calabash-cucumber/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Info.plist
index e2be495d1..8bfe7f5ad 100644
Binary files a/calabash-cucumber/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Info.plist and b/calabash-cucumber/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Info.plist differ
diff --git a/calabash-cucumber/spec/resources/enable-accessibility/LPSimpleExample-cal.app/LPSimpleExample-cal b/calabash-cucumber/spec/resources/enable-accessibility/LPSimpleExample-cal.app/LPSimpleExample-cal
index e10e012de..8723ee8f3 100755
Binary files a/calabash-cucumber/spec/resources/enable-accessibility/LPSimpleExample-cal.app/LPSimpleExample-cal and b/calabash-cucumber/spec/resources/enable-accessibility/LPSimpleExample-cal.app/LPSimpleExample-cal differ
diff --git a/calabash-cucumber/spec/uia_spec.rb b/calabash-cucumber/spec/uia_spec.rb
new file mode 100644
index 000000000..4f23172c1
--- /dev/null
+++ b/calabash-cucumber/spec/uia_spec.rb
@@ -0,0 +1,86 @@
+module Calabash
+ module RspecTests
+ module UIA
+ class TestObject
+ include Calabash::Cucumber::UIA
+ include Calabash::Cucumber::HTTPHelpers
+ end
+ end
+ end
+end
+
+describe Calabash::Cucumber::UIA do
+
+ let(:test_obj) { Calabash::RspecTests::UIA::TestObject.new }
+
+ describe 'uia_result' do
+ describe "when 'status' key is 'success' returns" do
+ it "value of the 'value' key when key exists" do
+ value = {:key => :value }
+ input = {'status' => 'success', 'value' => value, 'index' =>0}
+ expect(test_obj.send(:uia_result, input)).to be == value
+ end
+
+ it "empty hash when 'value' key does not exist" do
+ input = {'status' => 'success', 'index' =>0}
+ expect(test_obj.send(:uia_result, input)).to be == nil
+ end
+ end
+
+ describe "when 'status' key is not 'success' returns" do
+ it 'the argument it was passed' do
+ input = {'status' => 'error', 'value' => nil, 'index' =>0}
+ expect(test_obj.send(:uia_result, input)).to be == input
+ end
+ end
+ end
+
+ describe 'uia_type_string' do
+ describe 'does not raise an error' do
+ it "when :status == 'success' and :value is a hash" do
+ mocked_value = {}
+ expect(test_obj).to receive(:uia_handle_command).and_return(mocked_value)
+ expect { test_obj.uia_type_string 'foo' }.not_to raise_error
+ end
+
+ it "when :status == 'success' and :value is not a Hash" do
+ # Output from typing in UIWebViews.
+ mocked_value = ':nil'
+ expect(test_obj).to receive(:uia_handle_command).and_return(mocked_value)
+ expect { test_obj.uia_type_string 'foo' }.not_to raise_error
+ end
+
+ it "when :status != 'success' or 'error'" do
+ mocked_value = {'status' => 'unknown', 'value' => 'error message', 'index' =>0}
+ expect(test_obj).to receive(:uia_handle_command).and_return(mocked_value)
+ expect { test_obj.uia_type_string 'foo' }.not_to raise_error
+ end
+ end
+
+ describe "raises an error when :status == 'error'" do
+ it 'and result has a :value key' do
+ mocked_value = {'status' => 'error', 'value' => 'error message', 'index' =>0}
+ expect(test_obj).to receive(:uia_handle_command).and_return(mocked_value)
+ expect { test_obj.uia_type_string 'foo' }.to raise_error
+ end
+
+ it 'and result does not have a :value key' do
+ mocked_value = {'status' => 'error', 'index' =>0}
+ expect(test_obj).to receive(:uia_handle_command).and_return(mocked_value)
+ expect { test_obj.uia_type_string 'foo' }.to raise_error
+ end
+ end
+ end
+
+ describe 'uia' do
+ describe 'raises an error' do
+ it 'when http returns nil - simulates an app crash' do
+ launcher = Calabash::Cucumber::Launcher.new
+ launcher.run_loop = {:uia_strategy => :preferences}
+ expect(Calabash::Cucumber::Launcher).to receive(:launcher_if_used).and_return(launcher)
+ expect(test_obj).to receive(:http).and_return('')
+ expect { test_obj.uia('command') }.to raise_error
+ end
+ end
+ end
+end
diff --git a/calabash-cucumber/test/cucumber/LPSimpleExample-cal.app/Info.plist b/calabash-cucumber/test/cucumber/LPSimpleExample-cal.app/Info.plist
index e2be495d1..8bfe7f5ad 100644
Binary files a/calabash-cucumber/test/cucumber/LPSimpleExample-cal.app/Info.plist and b/calabash-cucumber/test/cucumber/LPSimpleExample-cal.app/Info.plist differ
diff --git a/calabash-cucumber/test/cucumber/LPSimpleExample-cal.app/LPSimpleExample-cal b/calabash-cucumber/test/cucumber/LPSimpleExample-cal.app/LPSimpleExample-cal
index aa776cc04..75a8d6890 100755
Binary files a/calabash-cucumber/test/cucumber/LPSimpleExample-cal.app/LPSimpleExample-cal and b/calabash-cucumber/test/cucumber/LPSimpleExample-cal.app/LPSimpleExample-cal differ
diff --git a/calabash-cucumber/test/xtc/chou-cal.ipa b/calabash-cucumber/test/xtc/chou-cal.ipa
index ec73360e3..d283ed735 100644
Binary files a/calabash-cucumber/test/xtc/chou-cal.ipa and b/calabash-cucumber/test/xtc/chou-cal.ipa differ
diff --git a/changelog/0.11.2.md b/changelog/0.11.2.md
new file mode 100644
index 000000000..c57a01501
--- /dev/null
+++ b/changelog/0.11.2.md
@@ -0,0 +1,31 @@
+## 0.11.2 Change log
+
+This is a bug-fix release.
+
+### Fixes
+
+#### #83 Fix Xcode 6.1 simulator preferences path
+
+* Touch gesture timeouts on Xcode 6.1 Simulators. #566 gem
+
+Thanks to all who reported. Another fantastic bug report from @JaniJegoroff.
+
+#### Other
+
+* Fix deserialization of boolean in filters. #84 server
+* Fix uia type string on iOS 8 webviews. #563 gem
+* Fix touch coordinates for iPads in landscape mode. #572 gem
+
+### Additions
+
+* Add ios8? to device and environment helpers #561 gem
+
+### Special Thanks
+
+To everyone creating issues and solutions.
+
+### Deprecated
+
+See https://github.com/calabash/calabash-ios/wiki/Deprecated
+
+* since 0.11.1 `Calabash::Device#screen_size` - Use `#screen_dimensions` instead.
diff --git a/script/ci/travis/com.apple.dt.instruments.process.analysis.plist b/script/ci/travis/com.apple.dt.instruments.process.analysis.plist
new file mode 100644
index 000000000..fb33b7663
--- /dev/null
+++ b/script/ci/travis/com.apple.dt.instruments.process.analysis.plist
@@ -0,0 +1,34 @@
+
+
+
+
+ allow-root
+
+ authenticate-user
+
+ class
+ user
+ comment
+ Rights for Instruments
+ created
+ 409022991.255041
+ group
+ admin
+ identifier
+ com.apple.dt.instruments.dtsecurity.xpc
+ modified
+ 409022991.255041
+ requirement
+ identifier "com.apple.dt.instruments.dtsecurity.xpc" and anchor apple
+ session-owner
+
+ shared
+
+ timeout
+ 36000
+ tries
+ 10000
+ version
+ 0
+
+
diff --git a/script/ci/travis/com.apple.dt.instruments.process.kill.plist b/script/ci/travis/com.apple.dt.instruments.process.kill.plist
new file mode 100644
index 000000000..5377e88b5
--- /dev/null
+++ b/script/ci/travis/com.apple.dt.instruments.process.kill.plist
@@ -0,0 +1,34 @@
+
+
+
+
+ allow-root
+
+ authenticate-user
+
+ class
+ user
+ comment
+ Rights for Instruments
+ created
+ 409022991.27266097
+ group
+ admin
+ identifier
+ com.apple.dt.instruments.dtsecurity.xpc
+ modified
+ 409022991.27266097
+ requirement
+ identifier "com.apple.dt.instruments.dtsecurity.xpc" and anchor apple
+ session-owner
+
+ shared
+
+ timeout
+ 5
+ tries
+ 10000
+ version
+ 0
+
+
diff --git a/script/ci/travis/instruments-auth.sh b/script/ci/travis/instruments-auth.sh
new file mode 100755
index 000000000..a0f90c661
--- /dev/null
+++ b/script/ci/travis/instruments-auth.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+SCRIPT_DIR="${PWD}/script/ci/travis"
+sudo security authorizationdb write com.apple.dt.instruments.process.analysis < $SCRIPT_DIR/com.apple.dt.instruments.process.analysis.plist
+sudo security authorizationdb write com.apple.dt.instruments.process.kill < $SCRIPT_DIR/com.apple.dt.instruments.process.kill.plist