lib/calabash-android/operations.rb in calabash-android-0.1.0 vs lib/calabash-android/operations.rb in calabash-android-0.2.0.pre2

- old
+ new

@@ -1,10 +1,12 @@ require 'json' +require 'net/http' require 'rubygems' require 'json' require 'socket' require 'timeout' +require 'calabash-android/helpers' module Calabash module Android module Operations @@ -13,23 +15,11 @@ def log(message) $stdout.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")} - #{message}" if (ARGV.include? "-v" or ARGV.include? "--verbose") end def take_screenshot - path = ENV["SCREENSHOT_PATH_PREFIX"] || "results" - FileUtils.mkdir_p path unless File.exist? path - filename_prefix = FeatureNameMemory.feature_name.gsub(/\s+/, '_').downcase - begin - Timeout.timeout(30) do - file_name = "#{path}/#{filename_prefix}_#{StepCounter.step_line}.png" - log "Taking screenshoot to #{file_name} from device: #{ENV['ADB_DEVICE_ARG']}" - system("java -jar #{File.dirname(__FILE__)}/lib/screenShotTaker.jar #{file_name} #{ENV['ADB_DEVICE_ARG']}") - log "Screenshot stored in: #{file_name}" - end - rescue Timeout::Error - raise Exception, "take_screenshot timed out" - end + Device.default_device.take_screenshot end def macro(txt) if self.respond_to?:step step(txt) @@ -37,35 +27,27 @@ Then(txt) end end def performAction(action, *arguments) - log "Action: #{action} - Params: #{arguments.join(', ')}" + Device.default_device.perform_action(action, *arguments) + end - action = {"command" => action, "arguments" => arguments} + def install_app(app_path) + Device.default_device.install_app(app_path) + end - Timeout.timeout(300) do - begin - @@client.send(action.to_json + "\n", 0) #force_encoding('UTF-8') seems to be missing from JRuby - result = @@client.readline - rescue Exception => e - log "Error communicating with test server: #{e}" - raise e - end - log "Result:'" + result.strip + "'" - raise "Empty result from TestServer" if result.chomp.empty? - result = JSON.parse(result) - if not result["success"] then - take_screenshot - raise result["message"].to_s - end - return result - end - rescue Timeout::Error - raise Exception, "Step timed out" + def uninstall_apps + Device.default_device.uninstall_app(ENV["TEST_PACKAGE_NAME"]) + Device.default_device.uninstall_app(ENV["PACKAGE_NAME"]) end + def start_test_server_in_background + Device.default_device.start_test_server_in_background() + end + + def wait_for(timeout, &block) begin Timeout::timeout(timeout) do until block.call sleep 0.3 @@ -91,62 +73,190 @@ def ni raise "Not yet implemented." end - - ##adb - def adb_command - if is_windows? - %Q("#{ENV["ANDROID_HOME"]}\\platform-tools\\adb.exe" #{ENV["ADB_DEVICE_ARG"]}) - else - %Q(#{ENV["ANDROID_HOME"]}/platform-tools/adb #{ENV["ADB_DEVICE_ARG"]}) - end - end - def is_windows? ENV["OS"] == "Windows_NT" end ### ### app life cycle def connect_to_test_server - log `#{adb_command} forward tcp:#{ENV["TEST_SERVER_PORT"]} tcp:7101` - - end_time = Time.now + 60 - begin - Timeout.timeout(10) do - @@client = TCPSocket.open('127.0.0.1',ENV["TEST_SERVER_PORT"]) - @@client.send("Ping!\n",0) - log "Got '#{@@client.readline.strip}' from testserver" - end - rescue Exception => e - log "Got exception:#{e}. Retrying!" - sleep(1) - retry unless Time.now > end_time - end + puts "Explicit calls to connect_to_test_server should be removed." + puts "Please take a look in your hooks file for calls to this methods." + puts "(Hooks are stored in features/support)" end def disconnect_from_test_server - log "Closing connection to test" - @@client.close + puts "Explicit calls to disconnect_from_test_server should be removed." + puts "Please take a look in your hooks file for calls to this methods." + puts "(Hooks are stored in features/support)" end + class Device + @@default_device = nil + def self.default_device + unless @@default_device + @@default_device = Device.new(ENV["ADB_DEVICE_ARG"], ENV["TEST_SERVER_PORT"], ENV["APP_PATH"], ENV["TEST_APP_PATH"]) + end + @@default_device + end - ##location - def set_gps_coordinates_from_location(location) - require 'geocoder' - results = Geocoder.search(location) - raise Exception, "Got no results for #{location}" if results.empty? + def make_default_device + @@default_device = self + end - best_result = results.first - set_gps_coordinates(best_result.latitude, best_result.longitude) - end + def initialize(serial, server_port, app_path, test_server_path) + @serial = serial + @server_port = server_port + @app_path = app_path + @test_server_path = test_server_path - def set_gps_coordinates(latitude, longitude) - performAction('set_gps_coordinates', latitude, longitude) + puts "#{adb_command} forward tcp:b#{server_port} tcp:7102" + log `#{adb_command} forward tcp:#{server_port} tcp:7102` +=begin + begin + Timeout::timeout(15) do + puts http("/ping") + end + rescue Timeout::Error + msg = "Unable to make connection to Calabash Test Server at http://127.0.0.1:#{@server_port}/\n" + msg << "Please check the logcat output for more info about what happened\n" + raise msg + end +=end + end + + def reinstall_apps() + uninstall_app(package_name(@app_path)) + install_app(@app_path) + uninstall_app(package_name(@test_server_path)) + install_app(@test_server_path) + end + + def install_app(app_path) + cmd = "#{adb_command} install #{app_path}" + log "Installing: #{app_path}" + result = `#{cmd}` + if result.include? "Success" + log "Success" + else + log "#Failure" + log "'#{cmd}' said:" + log result.strip + raise "Could not install app #{app_path}: #{result.strip}" + end + end + + def uninstall_app(package_name) + log "Uninstalling: #{package_name}" + log `#{adb_command} uninstall #{package_name}` + end + + def perform_action(action, *arguments) + log "Action: #{action} - Params: #{arguments.join(', ')}" + + params = {"command" => action, "arguments" => arguments} + + Timeout.timeout(300) do + begin + result = http("/", params) + rescue Exception => e + log "Error communicating with test server: #{e}" + raise e + end + log "Result:'" + result.strip + "'" + raise "Empty result from TestServer" if result.chomp.empty? + result = JSON.parse(result) + if not result["success"] then + take_screenshot + raise result["message"].to_s + end + return result + end + rescue Timeout::Error + raise Exception, "Step timed out" + end + + def http(path, data = {}) + begin + http = Net::HTTP.new "127.0.0.1", @server_port + resp, data = http.post(path, "command=#{data.to_json}", {}) + data + rescue EOFError + sleep 0.5 + retry + end + end + + def take_screenshot + path = ENV["SCREENSHOT_PATH_PREFIX"] || "results" + FileUtils.mkdir_p path unless File.exist? path + filename_prefix = FeatureNameMemory.feature_name.gsub(/\s+/, '_').downcase + begin + Timeout.timeout(30) do + file_name = "#{path}/#{filename_prefix}_#{StepCounter.step_line}.png" + log "Taking screenshoot to #{file_name} from device: #{@serial}" + system("java -jar #{File.dirname(__FILE__)}/lib/screenShotTaker.jar #{file_name} #{device_args}") + log "Screenshot stored in: #{file_name}" + end + rescue Timeout::Error + raise Exception, "take_screenshot timed out" + end + end + + def adb_command + if is_windows? + %Q("#{ENV["ANDROID_HOME"]}\\platform-tools\\adb.exe" #{device_args}) + else + %Q(#{ENV["ANDROID_HOME"]}/platform-tools/adb #{device_args}) + end + end + + def device_args + if @serial + "-s #{@serial}" + else + "" + end + end + + def is_windows? + ENV["OS"] == "Windows_NT" + end + + def start_test_server_in_background + test_server_package = package_name(@test_server_path) + cmd = "#{adb_command} shell am instrument -w -e class sh.calaba.instrumentationbackend.InstrumentationBackend #{test_server_package}/sh.calaba.instrumentationbackend.CalabashInstrumentationTestRunner" + log "Starting test server using:" + log cmd + if is_windows? + system(%Q(start /MIN cmd /C #{cmd})) + else + `#{cmd} 1>&2 &` + end + end + + def log(message) + $stdout.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")} - #{message}" if (ARGV.include? "-v" or ARGV.include? "--verbose") + end + + ##location + def set_gps_coordinates_from_location(location) + require 'geocoder' + results = Geocoder.search(location) + raise Exception, "Got no results for #{location}" if results.empty? + + best_result = results.first + set_gps_coordinates(best_result.latitude, best_result.longitude) + end + + def set_gps_coordinates(latitude, longitude) + perform_action('set_gps_coordinates', latitude, longitude) + end end def label(uiquery) @@ -164,10 +274,9 @@ end def html(q) query(q).map {|e| e['html']} end - def set_text(uiquery, txt) raise "Currently queries are only supported for webviews" unless uiquery.start_with? "webView" uiquery.slice!(0, "webView".length)