honeydew 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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