require 'calabash-cucumber/environment_helpers' require 'calabash-cucumber/query_helpers' require 'calabash-cucumber/http_helpers' require 'calabash-cucumber/failure_helpers' require 'calabash-cucumber/uia' module Calabash module Cucumber module IPad class Emulation include Calabash::Cucumber::FailureHelpers include Calabash::Cucumber::HTTPHelpers include Calabash::Cucumber::QueryHelpers include Calabash::Cucumber::UIA # NOTE to maintainers - when adding a localization, please notice that # the keys and values are semantically reversed. # # you should read the hash as: # # :emulated_1x #=> what button is showing when the app is emulated at 2X? # :emulated_2x #=> what button is showing when the app is emulated at 1X? IPAD_1X_2X_BUTTON_LABELS = { :en => {:emulated_1x => '2X', :emulated_2x => '1X'} } attr_reader :scale attr_reader :lang_code @button_names_hash = nil def initialize (lang_code=:en) @button_names_hash = IPAD_1X_2X_BUTTON_LABELS[lang_code] if @button_names_hash.nil? raise "could not find 1X/2X buttons for language code '#{lang_code}'" end @lang_code = lang_code @scale = _internal_ipad_emulation_scale end def tap_ipad_scale_button key = @scale name = @button_names_hash[key] res = uia_call_windows([:view, {:marked => "#{name}"}], :tap) # ':nil' is a very strange success return value... if res.is_a?(Hash) or res != ':nil' screenshot_and_raise "could not touch scale button '#{name}' - '#{res['value']}'" end end private def _internal_ipad_emulation_scale hash = @button_names_hash val = nil hash.values.each do |button_name| res = uia_call_windows([:view, {:marked => "#{button_name}"}], :name) if res == button_name val = button_name break end end if val.nil? raise "could not find iPad scale button with '#{hash.values}'" end if val == hash[:emulated_1x] :emulated_1x elsif val == hash[:emulated_2x] :emulated_2x else raise "unrecognized emulation scale '#{val}'" end end end # ensures that iPhone apps emulated on an iPad are displayed at +scale+. # # starting in iOS 7, iPhone apps emulated on the iPad always launch at 2x. # calabash cannot currently interact with such apps in 2x mode (trust us, # we've tried). # # +scale+ must be one of { +:emulated_1x+ | +:emulated_2x+ } # # is it is recommended that clients call this convenience method: # # +ensure_ipad_emulation_1x+ #=> ensures the app is displayed in 1x mode # # takes these optional arguments # # :lang_code #=> a language code for matching the name of the 'scale' button # :wait_after_touch #=> how long to wait after the 'scale' button is touched # # the default values are: # # :lang_code => :en # :wait_after_touch => 0.4 # # +IMPORTANT+ if this is not an iphone app emulated on a ipad, then calling # this function has no effect. # # raises an exception if: # * the app was +not+ launched with Instruments i.e. there is no run_loop # * an invalid +scale+ is passed # * an unknown language code is passed # * the 'scale' button cannot be touched def ensure_ipad_emulation_scale(scale, opts={}) return unless iphone_app_emulated_on_ipad? unless uia_available? raise 'this function requires the app be launched with instruments' end allowed = [:emulated_1x, :emulated_2x] unless allowed.include?(scale) raise "'#{scale}' is not one of '#{allowed}' allowed args" end default_opts = {:lang_code => :en, :wait_after_touch => 0.4} merged_opts = default_opts.merge(opts) obj = Emulation.new(merged_opts[:lang_code]) actual_scale = obj.scale if actual_scale != scale obj.tap_ipad_scale_button end sleep(merged_opts[:wait_after_touch]) end # ensures that iPhone apps emulated on an iPad are displayed at +1X+. # # here is an example of how to use this function in your +Before+ launch # hooks: # # Before do |scenario| # @calabash_launcher = Calabash::Cucumber::Launcher.new # unless @calabash_launcher.calabash_no_launch? # @calabash_launcher.relaunch # @calabash_launcher.calabash_notify(self) # # ensure emulated apps are at 1x # ensure_ipad_emulation_1x # end # # do other stuff to prepare the test environment # end # # takes these optional arguments # # :lang_code #=> a language code for matching the name of the 'scale' button # :wait_after_touch #=> how long to wait after the 'scale' button is touched # # the default values are: # # :lang_code => :en # :wait_after_touch => 0.4 # # +IMPORTANT+ if this is not an iphone app emulated on a ipad, then calling # this function has no effect. # # raises an exception if: # * the app was +not+ launched with Instruments i.e. there is no run_loop # * an unknown language code is passed # * the 'scale' button cannot be touched def ensure_ipad_emulation_1x(opts={}) ensure_ipad_emulation_scale(:emulated_1x, opts) end private # ensures iPhone apps running on an iPad are emulated at 2X # # you should never need to call this function - calabash cannot interact # with iPhone apps emulated on the iPad in 2x mode. def _ensure_ipad_emulation_2x(opts={}) ensure_ipad_emulation_scale(:emulated_2x, opts) end end end end