honeydew 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. data/.gitignore +21 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +17 -0
  7. data/android-server/.gitignore +4 -0
  8. data/android-server/pom.xml +215 -0
  9. data/android-server/repo/com/google/android/uiautomator/4.1.1.4/_maven.repositories +4 -0
  10. data/android-server/repo/com/google/android/uiautomator/4.1.1.4/uiautomator-4.1.1.4.jar +0 -0
  11. data/android-server/repo/com/google/android/uiautomator/4.1.1.4/uiautomator-4.1.1.4.pom +9 -0
  12. data/android-server/repo/com/jayway/maven/plugins/android/generation2/android-maven-plugin/3.5.2-SNAPSHOT/android-maven-plugin-3.5.2-SNAPSHOT.jar +0 -0
  13. data/android-server/repo/com/jayway/maven/plugins/android/generation2/android-maven-plugin/3.5.2-SNAPSHOT/android-maven-plugin-3.5.2-SNAPSHOT.pom +56 -0
  14. data/android-server/repo/com/jayway/maven/plugins/android/generation2/android-maven-plugin/3.5.2-SNAPSHOT/maven-metadata-local.xml +24 -0
  15. data/android-server/repo/commons-jxpath/commons-jxpath/1.4-SNAPSHOT/_maven.repositories +4 -0
  16. data/android-server/repo/commons-jxpath/commons-jxpath/1.4-SNAPSHOT/commons-jxpath-1.4-SNAPSHOT.jar +0 -0
  17. data/android-server/repo/commons-jxpath/commons-jxpath/1.4-SNAPSHOT/commons-jxpath-1.4-SNAPSHOT.pom +9 -0
  18. data/android-server/repo/commons-jxpath/commons-jxpath/1.4-SNAPSHOT/maven-metadata-local.xml +24 -0
  19. data/android-server/repo/commons-jxpath/commons-jxpath/maven-metadata-local.xml +11 -0
  20. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/Action.java +65 -0
  21. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/ActionsExecutor.java +73 -0
  22. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/Command.java +16 -0
  23. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/Result.java +36 -0
  24. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/TestRunner.java +26 -0
  25. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/Click.java +20 -0
  26. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/ClickAndWaitForNewWindow.java +20 -0
  27. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/DumpWindowHierarchy.java +28 -0
  28. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/HasSettingsMenuItem.java +23 -0
  29. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/InspectOptionInSettingsMenu.java +32 -0
  30. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/IsButtonPresent.java +23 -0
  31. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/IsChildCountEqualTo.java +26 -0
  32. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/IsElementWithNestedTextPresent.java +24 -0
  33. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/IsOptionInSettingsMenuDisabled.java +9 -0
  34. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/IsOptionInSettingsMenuEnabled.java +9 -0
  35. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/IsTextPresent.java +19 -0
  36. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/LaunchApp.java +25 -0
  37. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/LaunchHome.java +19 -0
  38. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/LongClick.java +20 -0
  39. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/PressBack.java +19 -0
  40. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/PressEnter.java +19 -0
  41. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/SelectFromAppsList.java +24 -0
  42. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/SelectMenuInSettings.java +22 -0
  43. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/SetText.java +27 -0
  44. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/SetTextByIndex.java +25 -0
  45. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/SetTextByLabel.java +28 -0
  46. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/Unlock.java +31 -0
  47. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/actions/WakeUp.java +24 -0
  48. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/httpd/NanoHTTPD.java +1100 -0
  49. data/android-server/src/main/java/com/uiautomator_cucumber/android_server/httpd/RemoteCommandReceiver.java +64 -0
  50. data/example/Gemfile +5 -0
  51. data/example/Rakefile +9 -0
  52. data/example/features/example.feature +10 -0
  53. data/example/features/step_definitions/honeydew_steps.rb +1 -0
  54. data/example/features/support/hooks.rb +4 -0
  55. data/honeydew.gemspec +28 -0
  56. data/honeydew.iml +28 -0
  57. data/lib/honeydew/cucumber.rb +4 -0
  58. data/lib/honeydew/device.rb +79 -0
  59. data/lib/honeydew/device_actions.rb +151 -0
  60. data/lib/honeydew/device_commands.rb +84 -0
  61. data/lib/honeydew/device_matchers.rb +52 -0
  62. data/lib/honeydew/dsl.rb +9 -0
  63. data/lib/honeydew/hooks.rb +0 -0
  64. data/lib/honeydew/step_definitions.rb +75 -0
  65. data/lib/honeydew/version.rb +3 -0
  66. data/lib/honeydew.rb +72 -0
  67. data/lib/tasks/honeydew.rake +7 -0
  68. data/spec/honeydew/device_matchers_spec.rb +58 -0
  69. data/spec/honeydew/device_spec.rb +66 -0
  70. data/spec/spec_helper.rb +39 -0
  71. data/todo.md +9 -0
  72. metadata +232 -0
@@ -0,0 +1,64 @@
1
+ package com.uiautomator_cucumber.android_server.httpd;
2
+
3
+ import android.util.Log;
4
+ import com.google.gson.Gson;
5
+ import com.uiautomator_cucumber.android_server.ActionsExecutor;
6
+ import com.uiautomator_cucumber.android_server.Command;
7
+ import com.uiautomator_cucumber.android_server.Result;
8
+
9
+ import java.io.File;
10
+ import java.io.IOException;
11
+ import java.util.Properties;
12
+
13
+ public class RemoteCommandReceiver extends NanoHTTPD {
14
+ private static final String MIME_JSON = "application/json";
15
+ private static final String TAG = "RemoteCommandReceiver";
16
+ private final Gson gson;
17
+ private final ActionsExecutor actionsExecutor;
18
+ private boolean running = true;
19
+
20
+ public RemoteCommandReceiver(ActionsExecutor actionsExecutor) throws IOException, InterruptedException {
21
+ super(7120, new File("/"));
22
+ Log.d(TAG, "Listening on HTTP port 7120. Kill test to stop");
23
+ this.gson = new Gson();
24
+ this.actionsExecutor = actionsExecutor;
25
+ while (running) {
26
+ Thread.sleep(5000);
27
+ }
28
+ }
29
+
30
+ @Override
31
+ public Response serve(String uri, String method, Properties header, Properties params, Properties files) {
32
+ log(uri, method, params);
33
+
34
+ Result result = tryPerformingControlAction(method, uri);
35
+ if (result == null) {
36
+ result = performActionOnDevice(params);
37
+ }
38
+ return new Response(HTTP_OK, MIME_JSON, gson.toJson(result));
39
+ }
40
+
41
+ @Override
42
+ public void stop() {
43
+ super.stop();
44
+ this.running = false;
45
+ }
46
+
47
+ private Result performActionOnDevice(Properties params) {
48
+ return actionsExecutor.execute(gson.fromJson((String) params.get("command"), Command.class));
49
+ }
50
+
51
+ private Result tryPerformingControlAction(String method, String uri) {
52
+ if (uri.equalsIgnoreCase("/terminate")) {
53
+ stop();
54
+ return Result.OK;
55
+ } else if(method.equalsIgnoreCase("HEAD")) {
56
+ return Result.OK;
57
+ }
58
+ return null;
59
+ }
60
+
61
+ private void log(String uri, String method, Properties params) {
62
+ Log.d(TAG, String.format("Processing uri: %s, method: %s, params: %s", uri, method, params));
63
+ }
64
+ }
data/example/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'honeydew', :path => File.join(File.dirname(__FILE__), '..')
4
+ gem 'cucumber'
5
+ gem 'rake'
data/example/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.require
4
+
5
+ require 'cucumber/rake/task'
6
+
7
+ Cucumber::Rake::Task.new(:features) do |t|
8
+ t.cucumber_opts = "features --color --format pretty"
9
+ end
@@ -0,0 +1,10 @@
1
+ @honeydew
2
+ Feature: Example demonstrating honeydew
3
+ Scenario: Perform addition using calculator
4
+ When I launch app "Calculator"
5
+ Then I long press the element with description "square root"
6
+ Then I press the "6" button
7
+ Then I press the "2" button
8
+ Then I press the "5" button
9
+ And I press the "=" button
10
+ Then I wait up to 2 seconds for "25" to appear in edit text
@@ -0,0 +1 @@
1
+ require 'honeydew/step_definitions'
@@ -0,0 +1,4 @@
1
+ require 'honeydew'
2
+ Before("@honeydew") do |scenario|
3
+ Honeydew.start_uiautomator_server
4
+ end
data/honeydew.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'honeydew/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "honeydew"
8
+ spec.version = Honeydew::VERSION
9
+ spec.authors = ["Selva", "Christopher Rex"]
10
+ spec.email = ["scmp-team@amplify.com"]
11
+ spec.description = %q{Automated functional testing on Android with uiautomator and cucumber}
12
+ spec.summary = %q{Automated functional testing on Android with uiautomator and cucumber}
13
+ spec.homepage = ""
14
+
15
+ spec.files = `git ls-files`.split($/) + Dir['android-server/target/*.jar']
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.3"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rspec"
23
+
24
+ spec.add_dependency("cucumber")
25
+ spec.add_dependency("json")
26
+ spec.add_dependency("rest-client")
27
+ spec.add_dependency("activesupport")
28
+ end
data/honeydew.iml ADDED
@@ -0,0 +1,28 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="RUBY_MODULE" version="4">
3
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
4
+ <exclude-output />
5
+ <content url="file://$MODULE_DIR$">
6
+ <sourceFolder url="file://$MODULE_DIR$/android-server/src" isTestSource="false" />
7
+ </content>
8
+ <orderEntry type="jdk" jdkName="RVM: jruby-1.7.3" jdkType="JRUBY_SDK" />
9
+ <orderEntry type="sourceFolder" forTests="false" />
10
+ <orderEntry type="library" scope="PROVIDED" name="activesupport (v3.2.13, RVM: jruby-1.7.3) [gem]" level="application" />
11
+ <orderEntry type="library" scope="PROVIDED" name="builder (v3.2.0, RVM: jruby-1.7.3) [gem]" level="application" />
12
+ <orderEntry type="library" scope="PROVIDED" name="bundler (v1.3.5, RVM: jruby-1.7.3) [gem]" level="application" />
13
+ <orderEntry type="library" scope="PROVIDED" name="cucumber (v1.3.1, RVM: jruby-1.7.3) [gem]" level="application" />
14
+ <orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.2.4, RVM: jruby-1.7.3) [gem]" level="application" />
15
+ <orderEntry type="library" scope="PROVIDED" name="gherkin (v2.12.0, RVM: jruby-1.7.3) [gem]" level="application" />
16
+ <orderEntry type="library" scope="PROVIDED" name="i18n (v0.6.1, RVM: jruby-1.7.3) [gem]" level="application" />
17
+ <orderEntry type="library" scope="PROVIDED" name="json (v1.7.7, RVM: jruby-1.7.3) [gem]" level="application" />
18
+ <orderEntry type="library" scope="PROVIDED" name="mime-types (v1.23, RVM: jruby-1.7.3) [gem]" level="application" />
19
+ <orderEntry type="library" scope="PROVIDED" name="multi_json (v1.7.3, RVM: jruby-1.7.3) [gem]" level="application" />
20
+ <orderEntry type="library" scope="PROVIDED" name="rake (v10.0.4, RVM: jruby-1.7.3) [gem]" level="application" />
21
+ <orderEntry type="library" scope="PROVIDED" name="rest-client (v1.6.7, RVM: jruby-1.7.3) [gem]" level="application" />
22
+ <orderEntry type="library" scope="PROVIDED" name="rspec (v2.13.0, RVM: jruby-1.7.3) [gem]" level="application" />
23
+ <orderEntry type="library" scope="PROVIDED" name="rspec-core (v2.13.1, RVM: jruby-1.7.3) [gem]" level="application" />
24
+ <orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v2.13.0, RVM: jruby-1.7.3) [gem]" level="application" />
25
+ <orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v2.13.1, RVM: jruby-1.7.3) [gem]" level="application" />
26
+ </component>
27
+ </module>
28
+
@@ -0,0 +1,4 @@
1
+ require 'honeydew'
2
+ require 'honeydew/dsl'
3
+
4
+ World(Honeydew::DSL)
@@ -0,0 +1,79 @@
1
+ require "honeydew/device_matchers"
2
+ require "honeydew/device_actions"
3
+
4
+ module Honeydew
5
+ class Device
6
+ include Honeydew::DeviceActions
7
+ include Honeydew::DeviceMatchers
8
+
9
+ attr_reader :serial, :port
10
+
11
+ def initialize(serial)
12
+ if serial.to_s.empty?
13
+ raise ArgumentError, 'HoneyDew: Invalid serial or no device connected'
14
+ end
15
+ @port = Honeydew.config.obtain_new_port
16
+ @serial = serial
17
+ start_uiautomator_server
18
+ end
19
+
20
+ def contains_textview_text?(text, timeout = Honeydew.config.timeout)
21
+ response = has_textview_text? text, timeout
22
+ response['success']
23
+ rescue
24
+ false
25
+ end
26
+
27
+ def contains_element_with_description?(description, timeout = Honeydew.config.timeout)
28
+ response = has_element_with_description? description, timeout
29
+ response['success']
30
+ rescue
31
+ false
32
+ end
33
+
34
+ def contains_button?(text, timeout = Honeydew.config.timeout)
35
+ response = has_button? text, timeout
36
+ response['success']
37
+ rescue
38
+ false
39
+ end
40
+
41
+ def is_app_installed?(package_name)
42
+ has_app_installed?(package_name)
43
+ end
44
+
45
+ def clear_directory(directory)
46
+ all_files_in_directory_path = [directory.chomp('/'), '/*'].join
47
+ adb "shell rm -r #{all_files_in_directory_path}"
48
+ end
49
+ private
50
+
51
+ def ensure_tablet_ready
52
+ @device_ready ||= begin
53
+ wait_for_android_server
54
+ true
55
+ end
56
+ end
57
+
58
+ def wait_for_android_server
59
+ log 'Waiting for server to come up'
60
+ retriable :on => [RestClient::ServerBrokeConnection, Errno::ECONNRESET, Errno::ECONNREFUSED], :interval => 0.3, :tries => 30 do
61
+ RestClient.head device_endpoint
62
+ end
63
+ end
64
+
65
+ def retriable(options, &block)
66
+ tries = options[:tries]
67
+ yield
68
+ rescue *[*options[:on]]
69
+ tries -= 1
70
+ if tries > 0
71
+ sleep options[:interval]
72
+ retry
73
+ else
74
+ raise
75
+ end
76
+ end
77
+
78
+ end
79
+ end
@@ -0,0 +1,151 @@
1
+ require "honeydew/device_commands"
2
+
3
+ module Honeydew
4
+ module DeviceActions
5
+ include Honeydew::DeviceCommands
6
+
7
+ def click_button(button_text)
8
+ perform_action :action => 'click', :arguments => {:text => button_text, :type => 'Button'}
9
+ end
10
+
11
+ def click_button_and_wait(button_text)
12
+ perform_action :action => 'click_and_wait_for_new_window', :arguments => {:text => button_text, :type => 'Button'}
13
+ end
14
+
15
+ def click_text(text)
16
+ perform_action :action => 'click', :arguments => {:text => text, :type => 'TextView'}
17
+ end
18
+
19
+ def click_text_and_wait(text)
20
+ perform_action :action => 'click_and_wait_for_new_window', :arguments => {:text => text, :type => 'TextView'}
21
+ end
22
+
23
+ def click_element(element_description)
24
+ perform_action :action => 'click', :arguments => {:description => element_description}
25
+ end
26
+
27
+ def click_element_and_wait(element_description)
28
+ perform_action :action => 'click_and_wait_for_new_window', :arguments => {:description => element_description}
29
+ end
30
+
31
+ def fill_in field_description, options = {with: ''}
32
+ perform_action :action => 'set_text', :arguments => {:description => field_description, :text => options[:with]}
33
+ end
34
+
35
+ def fill_in_by_label field_label, options = {with: ''}
36
+ perform_action :action => 'set_text_by_label', :arguments => {:label => field_label, :text => options[:with]}
37
+ end
38
+
39
+ def fill_in_by_index index, options = {with: ''}
40
+ perform_action :action => 'set_text_by_index', :arguments => {:index => index, :text => options[:with]}
41
+ end
42
+
43
+ def launch_home
44
+ perform_action :action => 'launch_home'
45
+ end
46
+
47
+ def launch_settings_app(app_name)
48
+ perform_action :action => 'select_from_apps_list', :arguments => {:appName => app_name}
49
+ end
50
+
51
+ def launch_application(application_name)
52
+ perform_action :action => 'launch_app', :arguments => {:appName => application_name}, :attempts => 3
53
+ end
54
+
55
+ def long_click_element(element_description)
56
+ perform_action :action => 'long_click', :arguments => {:description => element_description}
57
+ end
58
+
59
+ def launch_settings_item(item_name)
60
+ perform_action :action => 'select_menu_in_settings', :arguments => {:menuName => item_name}
61
+ end
62
+
63
+
64
+ def press_back
65
+ perform_action :action => 'press_back'
66
+ end
67
+
68
+ def press_enter
69
+ perform_action :action => 'press_enter'
70
+ end
71
+
72
+ def unlock
73
+ perform_action :action => 'unlock'
74
+ end
75
+
76
+ def wake_up
77
+ perform_action :action => 'wake_up'
78
+ end
79
+
80
+ def perform_action(options)
81
+ ensure_tablet_ready
82
+
83
+ command = options.slice(:action, :arguments)
84
+ timeout = options[:retry_until]
85
+ attempts = options[:attempts]
86
+
87
+ response =
88
+ if timeout
89
+ retry_until_timeout(timeout, command)
90
+ elsif attempts
91
+ retry_until_success(attempts, command)
92
+ else
93
+ execute_command(command)
94
+ end
95
+ log_action(command, response)
96
+ raise "Device: #{serial} :Action #{options} failed." unless response['success']
97
+ response
98
+ end
99
+
100
+ private
101
+
102
+ def retry_until_success(attempts, command)
103
+ completed = false
104
+ response = nil
105
+ tries = 0
106
+ until completed || (tries >= attempts) do
107
+ response = execute_command(command)
108
+ completed = response['success']
109
+ return response if completed
110
+ tries += 1
111
+ sleep 1
112
+ end
113
+ log_action(command, response)
114
+ raise "Device: #{serial} : All #{attempts} attempts failed while performing #{command[:action]}, with arguments: #{command[:arguments]}"
115
+ end
116
+
117
+ def retry_until_timeout(timeout, command)
118
+ completed = false
119
+ response = nil
120
+ Timeout.timeout(timeout.to_i) do
121
+ until completed do
122
+ sleep 1
123
+ response = execute_command(command)
124
+ completed = response['success']
125
+ end
126
+ end
127
+ return response
128
+ rescue Timeout::Error
129
+ log_action(command, response)
130
+ raise "Device: #{serial} :Timeout while performing #{command[:action]}, with arguments: #{command[:arguments]}"
131
+ end
132
+
133
+ def execute_command(command)
134
+ response = RestClient.get(device_endpoint, :params => stringify_keys(:command => command))
135
+ JSON.parse(response)
136
+ end
137
+
138
+ def log_action(command, response)
139
+ log "Device: #{serial} : executing command: #{command}"
140
+ log "Device: #{serial} : responded with: #{response}"
141
+ end
142
+
143
+ def stringify_keys(options)
144
+ JSON.parse(options.to_json)
145
+ end
146
+
147
+ def log(message)
148
+ puts message
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,84 @@
1
+ module Honeydew
2
+ module DeviceCommands
3
+
4
+ def device_endpoint
5
+ "http://127.0.0.1:#{port}"
6
+ end
7
+
8
+ def dump_window_hierarchy(local_path)
9
+ path_in_device = perform_action(:action => 'dump_window_hierarchy')['description']
10
+ adb "pull #{path_in_device} #{local_path}"
11
+ end
12
+
13
+ def take_screenshot(local_path)
14
+ path_in_device = '/data/local/tmp/honeydew.png'
15
+ adb "shell /system/bin/screencap -p #{path_in_device}"
16
+ adb "pull #{path_in_device} #{local_path}"
17
+ end
18
+
19
+ def start_uiautomator_server
20
+ forwarding_port
21
+ terminate_uiautomator_server
22
+ log "Device: #{serial} : Starting server on the device"
23
+ start_automation_server
24
+ end
25
+
26
+ def terminate_uiautomator_server
27
+ log 'Terminating server'
28
+ RestClient.get("#{device_endpoint}/terminate")
29
+ rescue
30
+ # Swallow
31
+ end
32
+
33
+ def automation_test_jar_name
34
+ "android-server-0.0.1-SNAPSHOT.jar"
35
+ end
36
+
37
+ def automation_server_jar_path
38
+ File.absolute_path(File.join(File.dirname(__FILE__), "../../android-server/target/#{automation_test_jar_name}"))
39
+ end
40
+
41
+ def start_automation_server
42
+ Thread.new do
43
+ adb "push #{automation_server_jar_path} /data/local/tmp"
44
+ adb "shell uiautomator runtest #{automation_test_jar_name} -c com.uiautomator_cucumber.android_server.TestRunner"
45
+ log "Device: #{serial} initiated the start of automation server"
46
+ end
47
+ at_exit do
48
+ terminate_uiautomator_server
49
+ end
50
+ end
51
+
52
+ def forwarding_port
53
+ log "Device: #{serial} : Forwarding port #{port} to device"
54
+ adb "forward tcp:#{port} tcp:7120"
55
+ end
56
+
57
+ def uninstall_app(package_name)
58
+ adb "uninstall #{package_name}"
59
+ end
60
+
61
+ def install_app(apk_location)
62
+ adb "install #{apk_location}"
63
+ end
64
+
65
+ def clear_app_data(package_name)
66
+ adb "shell pm clear #{package_name}"
67
+ end
68
+
69
+ def reboot
70
+ adb 'reboot'
71
+ end
72
+
73
+ def launch_settings
74
+ adb 'shell am start -n com.android.settings/com.android.settings.Settings'
75
+ end
76
+
77
+ def adb(command)
78
+ adb_command = "adb -s #{serial} #{command}"
79
+ log "Device: #{serial} :Executing '#{adb_command}'"
80
+ `#{adb_command}`.tap { raise 'ADB command failed' unless $?.success? }
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,52 @@
1
+ module Honeydew
2
+ module DeviceMatchers
3
+
4
+ def has_text?(text, timeout = Honeydew.config.timeout)
5
+ perform_action :action => 'is_text_present', :arguments => {:text => text}, :retry_until => timeout
6
+ end
7
+
8
+ def has_element_with_description?(description, timeout = Honeydew.config.timeout)
9
+ perform_action :action => 'is_text_present', :arguments => {:description => description}, :retry_until => timeout
10
+ end
11
+
12
+ def has_edit_text?(text, timeout = Honeydew.config.timeout)
13
+ perform_action :action => 'is_text_present', :arguments => {:text => text, :type => 'EditText'}, :retry_until => timeout
14
+ end
15
+
16
+ def has_textview_text?(text, timeout = Honeydew.config.timeout)
17
+ perform_action :action => 'is_text_present', :arguments => {:text => text, :type => 'TextView'}, :retry_until => timeout
18
+ end
19
+
20
+ def has_textview_with_text_and_description?(text, description, timeout=Honeydew.config.timeout)
21
+ perform_action :action => 'is_text_present', :arguments => {:text => text, :description => description, :type => 'TextView'}, :retry_until => timeout
22
+ end
23
+
24
+ def has_button?(button_text, timeout = Honeydew.config.timeout)
25
+ perform_action(:action => 'is_button_present', :arguments => {:text => button_text}, :retry_until => timeout)
26
+ end
27
+
28
+ def has_child_count?(parent_element_description, child_element_description, child_count, timeout = Honeydew.config.timeout)
29
+ perform_action(:action => 'is_child_count_equal_to', :arguments => {:parent_description => parent_element_description, :child_description => child_element_description, :child_count => child_count}, :retry_until => timeout)
30
+ end
31
+
32
+ def has_element_with_nested_text?(parent_description, child_text, timeout = Honeydew.config.timeout)
33
+ perform_action(:action => 'is_element_with_nested_text_present', :arguments => {:parent_description => parent_description, :child_text => child_text}, :retry_until => timeout)
34
+ end
35
+
36
+ def has_app_installed?(package_name)
37
+ adb('shell pm list packages').include?(package_name)
38
+ end
39
+
40
+ def is_option_in_setting_enabled?(item_name, option_names)
41
+ perform_action :action => 'is_option_in_settings_menu_enabled', :arguments => {:menuName => item_name, :optionNames => option_names}
42
+ end
43
+
44
+ def is_option_in_setting_disabled?(item_name, option_names)
45
+ perform_action :action => 'is_option_in_settings_menu_disabled', :arguments => {:menuName => item_name, :optionNames => option_names}
46
+ end
47
+
48
+ def has_settings_menu_item?(item_name, timeout = 10)
49
+ perform_action(:action => 'has_settings_menu_item', :arguments => {:menuName => item_name}, :retry_until => timeout)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,9 @@
1
+ module Honeydew
2
+ module DSL
3
+ def use_device(name, serial)
4
+ define_singleton_method name.to_sym do |*args, &block|
5
+ Honeydew.using_device(serial, &block)
6
+ end
7
+ end
8
+ end
9
+ end
File without changes
@@ -0,0 +1,75 @@
1
+ Given /^I unlock$/ do
2
+ Honeydew.current_device.unlock
3
+ end
4
+
5
+ Given /^I launch app "(.*?)"$/ do |app_name|
6
+ Honeydew.current_device.launch_application app_name
7
+ end
8
+
9
+ Given /^I launch home$/ do
10
+ Honeydew.current_device.launch_home
11
+ end
12
+
13
+ When /^I press back$/ do
14
+ Honeydew.current_device.press_back
15
+ end
16
+
17
+ Given /^I select "(.*?)" in the Settings view$/ do |menu_item|
18
+ Honeydew.current_device.launch_settings_item menu_item
19
+ end
20
+
21
+ Given /^I select app "(.*?)" from the Apps list in the Settings view$/ do |app_name|
22
+ Honeydew.current_device.launch_settings_app app_name
23
+ end
24
+
25
+ Given /^I should see text containing "(.*?)"$/ do |expected_text|
26
+ Honeydew.current_device.should have_textview_text expected_text
27
+ end
28
+
29
+ Given /^I enter text "(.*?)" into field with description "(.*?)"$/ do |text, field_description|
30
+ Honeydew.current_device.fill_in field_description, with: text
31
+ end
32
+
33
+ Given /^I press the "(.*?)" button$/ do |button_text|
34
+ Honeydew.current_device.click_button button_text
35
+ end
36
+
37
+ Given /^I press the "(.*?)" text$/ do |text|
38
+ Honeydew.current_device.click_text text
39
+ end
40
+
41
+ Given /^I press the element with description "(.*?)"$/ do |element_description|
42
+ Honeydew.current_device.click_element element_description
43
+ end
44
+
45
+ Given /^I long press the element with description "(.*?)"$/ do |element_description|
46
+ Honeydew.current_device.long_click_element element_description
47
+ end
48
+
49
+ When /^I wait up to (\d+) seconds for "(.*?)" to appear$/ do |timeout, text|
50
+ Honeydew.current_device.should have_textview_text text, timeout
51
+ end
52
+
53
+ When /^I wait up to (\d+) seconds for "(.*?)" to appear in edit text$/ do |timeout, text|
54
+ Honeydew.current_device.should have_edit_text text, timeout
55
+ end
56
+
57
+ Given /I uninstall the app "(.*?)" using ADB$/ do |pacakge_name|
58
+ Honeydew.current_device.uninstall_app pacakge_name
59
+ end
60
+
61
+ Given /I install the app "(.*?)" using ADB$/ do |apk_location|
62
+ Honeydew.current_device.install_app apk_location
63
+ end
64
+
65
+ Given /I reboot the device using ADB$/ do
66
+ Honeydew.current_device.reboot
67
+ end
68
+
69
+ Then /I see the app "(.*?)" installed using ADB$/ do |package_name|
70
+ Honeydew.current_device.should have_app_installed package_name
71
+ end
72
+
73
+ Then /I should see a button "(.*?)" with (package|description) as "(.*?)"$/ do |button_text, condition, package_name|
74
+ Honeydew.current_device.should have_button button_text
75
+ end
@@ -0,0 +1,3 @@
1
+ module Honeydew
2
+ VERSION = "0.1.4"
3
+ end