require 'calabash-cucumber/utils/logging' require 'calabash-cucumber/device' module Calabash module Cucumber # This module provides methods for interaction with UIAutomation's # record-and-playback features. # # @note # In iOS 7, the record-and-playback feature was dropped from UIAutomation. # As such, using the record-and-playback API is not recommended. # # @note # We expect that this module will be deprecated once iOS 6 testing is no # longer supported. module PlaybackHelpers include Calabash::Cucumber::Logging # @!visibility private DATA_PATH = File.expand_path(File.dirname(__FILE__)) # @!visibility private def recording_name_for(recording_name, os, device) #noinspection RubyControlFlowConversionInspection if !recording_name.end_with? '.base64' "#{recording_name}_#{os}_#{device}.base64" else recording_name end end # @!visibility private def load_recording(recording, rec_dir) directories = playback_file_directories(rec_dir) directories.each { |dir| path = "#{dir}/#{recording}" if File.exists?(path) return File.read(path) end } nil end # @!visibility private def playback_file_directories (rec_dir) # rec_dir is either ENV['PLAYBACK_DIR'] or ./features/playback [File.expand_path(rec_dir), "#{Dir.pwd}", "#{Dir.pwd}/features", "#{Dir.pwd}/features/playback", "#{DATA_PATH}/resources/"].uniq end # @!visibility private def load_playback_data(recording_name, options={}) device = options['DEVICE'] || ENV['DEVICE'] || 'iphone' # Xcode 7/iOS 9 - Playback file not found for rotation #837 # As of iOS 7 and Xcode 5.1.1, the only part of the playback API that # is being used is the rotation API. We've incorrectly been using # iPhone recordings for iPad rotations. The iPhone recordings are # working, so I am not inclined to make any dramatic changes. if device != 'iphone' || device != 'ipad' device = 'iphone' end major = Calabash::Cucumber::Launcher.launcher.ios_major_version unless major raise < :post, :raw => true, :path => 'play'}, post_data) res = JSON.parse(res) if res['outcome'] != 'SUCCESS' raise "playback failed because: #{res['reason']}\n#{res['details']}" end res['results'] end # Plays back a recording but interpolates it first. # @param [String] recording the filename of the recording # @param [Hash] options can control the behavior of the recording def interpolate(recording, options={}) data = load_playback_data(recording) post_data = %Q|{"events":"#{data}"| post_data<< %Q|,"start":"#{escape_quotes(options[:start])}"| if options[:start] post_data<< %Q|,"end":"#{escape_quotes(options[:end])}"| if options[:end] post_data<< %Q|,"offset_start":#{options[:offset_start].to_json}| if options[:offset_start] post_data<< %Q|,"offset_end":#{options[:offset_end].to_json}| if options[:offset_end] post_data << '}' res = http({:method => :post, :raw => true, :path => 'interpolate'}, post_data) res = JSON.parse(res) if res['outcome'] != 'SUCCESS' raise "interpolate failed because: #{res['reason']}\n#{res['details']}" end res['results'] end # Begins a recording. def record_begin http({:method => :post, :path => 'record'}, {:action => :start}) end # Ends a recording and saves it. # @param [String] file_name where to save the recording. def record_end(file_name) res = http({:method => :post, :path => 'record'}, {:action => :stop}) File.open('_recording.plist', 'wb') do |f| f.write res end device = ENV['DEVICE'] || 'iphone' major = Calabash::Cucumber::Launcher.launcher.ios_major_version unless major raise < '#{rec_dir}/#{file_name}'" end end end end