honeydew 0.12.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +79 -8
- data/Rakefile +2 -2
- data/examples/cucumber/Gemfile +5 -0
- data/{example → examples/cucumber}/Rakefile +0 -0
- data/{example → examples/cucumber}/features/example.feature +0 -0
- data/{example → examples/cucumber}/features/step_definitions/honeydew_steps.rb +0 -0
- data/examples/rspec/spec/browse_spec.rb +16 -0
- data/examples/rspec/spec/spec_helper.rb +6 -0
- data/honeydew.gemspec +17 -17
- data/honeydew.iml +12 -18
- data/lib/honeydew.rb +1 -72
- data/lib/honeydew/device.rb +79 -44
- data/lib/honeydew/device_actions.rb +32 -100
- data/lib/honeydew/device_commands.rb +36 -23
- data/lib/honeydew/device_matchers.rb +29 -22
- data/lib/honeydew/dsl.rb +1 -1
- data/lib/honeydew/honeydew.rb +82 -0
- data/lib/honeydew/version.rb +1 -1
- data/{android-server → server}/.gitignore +0 -0
- data/{android-server → server}/pom.xml +16 -6
- data/{android-server → server}/repo/com/google/android/uiautomator/4.1.1.4/_maven.repositories +0 -0
- data/{android-server → server}/repo/com/google/android/uiautomator/4.1.1.4/uiautomator-4.1.1.4.jar +0 -0
- data/{android-server → server}/repo/com/google/android/uiautomator/4.1.1.4/uiautomator-4.1.1.4.pom +0 -0
- data/{android-server → 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
- data/{android-server → server}/repo/com/jayway/maven/plugins/android/generation2/android-maven-plugin/3.5.2-SNAPSHOT/android-maven-plugin-3.5.2-SNAPSHOT.pom +0 -0
- data/{android-server → server}/repo/com/jayway/maven/plugins/android/generation2/android-maven-plugin/3.5.2-SNAPSHOT/maven-metadata-local.xml +0 -0
- data/{android-server → server}/repo/commons-jxpath/commons-jxpath/1.4-SNAPSHOT/_maven.repositories +0 -0
- data/{android-server → server}/repo/commons-jxpath/commons-jxpath/1.4-SNAPSHOT/commons-jxpath-1.4-SNAPSHOT.jar +0 -0
- data/{android-server → server}/repo/commons-jxpath/commons-jxpath/1.4-SNAPSHOT/commons-jxpath-1.4-SNAPSHOT.pom +0 -0
- data/{android-server → server}/repo/commons-jxpath/commons-jxpath/1.4-SNAPSHOT/maven-metadata-local.xml +0 -0
- data/{android-server → server}/repo/commons-jxpath/commons-jxpath/maven-metadata-local.xml +0 -0
- data/server/repo/fi/iki/elonen/nanohttpd-webserver/2.0.3/nanohttpd-webserver-2.0.3.jar +0 -0
- data/server/repo/fi/iki/elonen/nanohttpd-webserver/2.0.3/nanohttpd-webserver-2.0.3.pom +9 -0
- data/server/repo/fi/iki/elonen/nanohttpd-webserver/maven-metadata-local.xml +12 -0
- data/server/repo/fi/iki/elonen/nanohttpd/2.0.3/nanohttpd-2.0.3.jar +0 -0
- data/server/repo/fi/iki/elonen/nanohttpd/2.0.3/nanohttpd-2.0.3.pom +9 -0
- data/server/repo/fi/iki/elonen/nanohttpd/maven-metadata-local.xml +12 -0
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/Action.java +13 -6
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/ActionsExecutor.java +3 -2
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/Command.java +6 -1
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/Result.java +7 -7
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/TestRunner.java +14 -6
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/Click.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/ClickAndWaitForNewWindow.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/DumpWindowHierarchy.java +5 -5
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/HasSettingsMenuItem.java +4 -5
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/InspectOptionInSettingsMenu.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/IsButtonPresent.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/IsChildCountEqualTo.java +4 -4
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/IsElementWithNestedTextPresent.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/IsOptionInSettingsMenuDisabled.java +1 -1
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/IsOptionInSettingsMenuEnabled.java +1 -1
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/IsTextPresent.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/LaunchApp.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/LaunchHome.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/LongClick.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/PressBack.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/PressEnter.java +4 -4
- data/server/src/main/java/com/amplify/honeydew_server/actions/ScrollToTextByIndex.java +27 -0
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/SelectFromAppsList.java +4 -4
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/SelectMenuInSettings.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/SetText.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/SetTextByIndex.java +2 -2
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/SetTextByLabel.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/Unlock.java +3 -3
- data/{android-server/src/main/java/com/uiautomator_cucumber/android_server → server/src/main/java/com/amplify/honeydew_server}/actions/WakeUp.java +4 -4
- data/server/src/main/java/com/amplify/honeydew_server/httpd/RemoteCommandReceiver.java +66 -0
- data/spec/honeydew/device_matchers_spec.rb +21 -42
- data/spec/honeydew/device_spec.rb +38 -36
- data/spec/spec_helper.rb +2 -25
- metadata +93 -92
- data/android-server/src/main/java/com/uiautomator_cucumber/android_server/httpd/NanoHTTPD.java +0 -1100
- data/android-server/src/main/java/com/uiautomator_cucumber/android_server/httpd/RemoteCommandReceiver.java +0 -64
- data/example/Gemfile +0 -5
- data/example/features/support/hooks.rb +0 -4
- data/lib/honeydew/hooks.rb +0 -0
- data/lib/honeydew/step_definitions.rb +0 -75
- data/lib/tasks/honeydew.rake +0 -7
- data/todo.md +0 -9
data/.rspec
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
--color
|
2
|
-
--format
|
2
|
+
--format documentation
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,24 +1,95 @@
|
|
1
1
|
# Honeydew
|
2
2
|
|
3
|
-
|
3
|
+
NOTE: Honeydew is currently in alpha and is not quite ready for use.
|
4
|
+
|
5
|
+
Honeydew is a Ruby driver for UIAutomator which enables automated testing of
|
6
|
+
Android devices.
|
4
7
|
|
5
8
|
## Installation
|
6
9
|
|
7
|
-
|
10
|
+
Install the honeydew gem:
|
11
|
+
|
12
|
+
$ gem install honeydew
|
13
|
+
|
14
|
+
Or if you're using Bundler, add honeydew to your Gemfile:
|
8
15
|
|
9
16
|
gem 'honeydew'
|
10
17
|
|
11
|
-
|
18
|
+
You'll need to have the Android SDK installed, ANDROID_HOME set correctly as
|
19
|
+
well as Maven.
|
12
20
|
|
13
|
-
|
21
|
+
## Using Honeydew
|
14
22
|
|
15
|
-
|
23
|
+
In typical operation, Honeydew connects to the first Android device connected
|
24
|
+
to your system which has debugging enabled. You can send commands to this
|
25
|
+
device like so:
|
16
26
|
|
17
|
-
|
27
|
+
``` ruby
|
28
|
+
Honeydew.current_device.launch_home
|
29
|
+
Honeydew.
|
30
|
+
```
|
31
|
+
|
32
|
+
If you want to interact with multiple Android devices at the same time, you can
|
33
|
+
create separate device instances by specifying their serial IDS. You can get
|
34
|
+
the serial IDs of all android devices connected to your system with the ``adb
|
35
|
+
devices -l``` command, e.g:
|
36
|
+
|
37
|
+
$ adb devices -l
|
38
|
+
List of devices attached
|
39
|
+
|
40
|
+
Once you have the serial ID of a device you wish to control, create a device
|
41
|
+
object for it:
|
42
|
+
|
43
|
+
``` ruby
|
44
|
+
nexus = Honeydew::Device.new ''
|
45
|
+
```
|
46
|
+
|
47
|
+
Then you can begin issuing commands:
|
48
|
+
|
49
|
+
``` ruby
|
50
|
+
nexus.click_text 'Android Air-Hockey'
|
51
|
+
if nexus.has_text? 'New Game'
|
52
|
+
nexus.click_button 'New Game'
|
53
|
+
...
|
54
|
+
```
|
55
|
+
|
56
|
+
## Using Honeydew with RSpec
|
57
|
+
|
58
|
+
Honeydew comes with a DSL that can be used in RSpec as well as matchers for use
|
59
|
+
with RSpec.
|
60
|
+
|
61
|
+
## Using Honeydew with Cucumber
|
62
|
+
|
63
|
+
If you're using Cucumber, Honeydew comes with a DSL that can ease the creation
|
64
|
+
of device related steps. Firstly require the honeydew cucumber files:
|
65
|
+
|
66
|
+
``` ruby
|
67
|
+
require 'honeydew/cucumber'
|
68
|
+
```
|
69
|
+
|
70
|
+
This adds the Honeydew DSL to World so you can interact with the device in your
|
71
|
+
steps like so:
|
72
|
+
|
73
|
+
``` ruby
|
74
|
+
using_device :teacher_tablet
|
75
|
+
teacher_tablet.launch_settings
|
76
|
+
```
|
77
|
+
|
78
|
+
## Controlling Android Devices
|
79
|
+
|
80
|
+
Honeydew provides a number of methods for interacting with an Android device.
|
81
|
+
|
82
|
+
## Thanks
|
18
83
|
|
19
|
-
|
84
|
+
Honeydew is sponsored by [Amplify](http://www.amplify.com/) and was created by
|
85
|
+
[Selvakumar Natesan](https://github.com/selvakn) and [Christopher
|
86
|
+
Rex](https://github.com/christopher-rex) of
|
87
|
+
[ThoughtWorks](http://www.thoughtworks.com/).
|
20
88
|
|
21
|
-
|
89
|
+
Additional thanks to [Shyam Vala](https://github.com/shyamvala), [Premanand
|
90
|
+
Chandrasekaran](https://github.com/premanandc) and [John
|
91
|
+
Barker](https://github.com/excepttheweasel/) for multi device support, testing
|
92
|
+
and a little bit of polish.
|
22
93
|
|
23
94
|
## Contributing
|
24
95
|
|
data/Rakefile
CHANGED
@@ -11,7 +11,7 @@ task :build_android_server do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def android_server_path
|
14
|
-
File.absolute_path(File.join(File.dirname(__FILE__), '
|
14
|
+
File.absolute_path(File.join(File.dirname(__FILE__), 'server'))
|
15
15
|
end
|
16
16
|
|
17
|
-
task :build => [:spec, :build_android_server]
|
17
|
+
task :build => [:spec, :build_android_server]
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Browser' do
|
4
|
+
before do
|
5
|
+
use_device :my_tablet
|
6
|
+
end
|
7
|
+
|
8
|
+
context 'surfing the web' do
|
9
|
+
it 'launches hacker news' do
|
10
|
+
my_tablet.launch_home
|
11
|
+
my_tablet.click_text 'Chrome'
|
12
|
+
my_tablet.fill_in 'Search, or say Google', with: 'http://news.ycombinator.com'
|
13
|
+
expect(my_tablet).to have_text 'Hacker News'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/honeydew.gemspec
CHANGED
@@ -4,25 +4,25 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'honeydew/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'honeydew'
|
8
8
|
spec.version = Honeydew::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.
|
12
|
-
spec.
|
13
|
-
|
9
|
+
spec.authors = ['Selvakumar Natesan', 'Christopher Rex', 'Shyam Vala', 'John Barker']
|
10
|
+
spec.email = ['scmp-team@amplify.com', 'jbarker@amplify.com']
|
11
|
+
spec.summary = 'Ruby DSL for controlling Android devices'
|
12
|
+
spec.description = <<-EOF
|
13
|
+
Honeydew is a Ruby driver for UIAutomator which enables automated testing of
|
14
|
+
Android devices.
|
15
|
+
EOF
|
14
16
|
|
15
|
-
spec.files = `git ls-files`.split($/) + Dir[
|
16
|
-
spec.
|
17
|
-
spec.
|
18
|
-
spec.require_paths = ["lib"]
|
17
|
+
spec.files = `git ls-files`.split($/) + Dir["server/target/honeydew-server-#{Honeydew::VERSION}*.jar"]
|
18
|
+
spec.test_files = spec.files.grep(/spec/)
|
19
|
+
spec.require_paths = ['lib']
|
19
20
|
|
20
|
-
spec.
|
21
|
-
spec.
|
22
|
-
spec.add_development_dependency "rspec"
|
21
|
+
spec.add_dependency('activesupport')
|
22
|
+
spec.add_dependency('json')
|
23
23
|
|
24
|
-
spec.
|
25
|
-
spec.
|
26
|
-
spec.
|
27
|
-
spec.
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'rspec'
|
27
|
+
spec.add_development_dependency 'simplecov'
|
28
28
|
end
|
data/honeydew.iml
CHANGED
@@ -1,28 +1,22 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
2
|
<module type="RUBY_MODULE" version="4">
|
3
|
+
<component name="FacetManager">
|
4
|
+
<facet type="RailsFacetType" name="Ruby on Rails">
|
5
|
+
<configuration>
|
6
|
+
<RAILS_FACET_CONFIG_ID NAME="RAILS_FACET_SUPPORT_REMOVED" VALUE="false" />
|
7
|
+
<RAILS_FACET_CONFIG_ID NAME="RAILS_TESTS_SOURCES_PATCHED" VALUE="true" />
|
8
|
+
<RAILS_FACET_CONFIG_ID NAME="RAILS_FACET_APPLICATION_ROOT" VALUE="$MODULE_DIR$" />
|
9
|
+
</configuration>
|
10
|
+
</facet>
|
11
|
+
</component>
|
3
12
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
4
13
|
<exclude-output />
|
5
14
|
<content url="file://$MODULE_DIR$">
|
6
|
-
<sourceFolder url="file://$MODULE_DIR$/
|
15
|
+
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
16
|
+
<sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
|
7
17
|
</content>
|
8
|
-
<orderEntry type="
|
18
|
+
<orderEntry type="inheritedJdk" />
|
9
19
|
<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
20
|
</component>
|
27
21
|
</module>
|
28
22
|
|
data/lib/honeydew.rb
CHANGED
@@ -1,72 +1 @@
|
|
1
|
-
require '
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'restclient'
|
4
|
-
require 'active_support/core_ext'
|
5
|
-
|
6
|
-
require "honeydew/version"
|
7
|
-
require "honeydew/device"
|
8
|
-
|
9
|
-
module Honeydew
|
10
|
-
class Configuration
|
11
|
-
attr_accessor :port, :timeout
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
@port = 7120
|
15
|
-
@timeout = 5.seconds
|
16
|
-
end
|
17
|
-
|
18
|
-
def obtain_new_port
|
19
|
-
@port.tap { @port += 1 }
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class <<self
|
24
|
-
attr_accessor :config
|
25
|
-
|
26
|
-
def config
|
27
|
-
return @config if @config
|
28
|
-
configure
|
29
|
-
@config
|
30
|
-
end
|
31
|
-
|
32
|
-
def configure
|
33
|
-
@config ||= Configuration.new
|
34
|
-
yield(@config) if block_given?
|
35
|
-
end
|
36
|
-
|
37
|
-
def attached_devices
|
38
|
-
`adb devices`.split("\n").drop(1).collect {|line| line.split[0].chomp}
|
39
|
-
end
|
40
|
-
|
41
|
-
def default_device_serial
|
42
|
-
attached_devices.first
|
43
|
-
end
|
44
|
-
|
45
|
-
def default_device
|
46
|
-
@default_device ||= device[default_device_serial]
|
47
|
-
end
|
48
|
-
|
49
|
-
def current_device
|
50
|
-
@current_device ||= default_device
|
51
|
-
end
|
52
|
-
|
53
|
-
def using_device(serial, &block)
|
54
|
-
original_device = current_device
|
55
|
-
use_device(serial).tap do |device|
|
56
|
-
device.instance_eval(&block) if block_given?
|
57
|
-
end
|
58
|
-
ensure
|
59
|
-
@current_device = original_device
|
60
|
-
end
|
61
|
-
|
62
|
-
def use_device(serial)
|
63
|
-
@current_device = device[serial]
|
64
|
-
end
|
65
|
-
|
66
|
-
def device
|
67
|
-
@devices ||= Hash.new do |hash, serial|
|
68
|
-
hash[serial] = Device.new(serial) if attached_devices.include?(serial)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
1
|
+
require 'honeydew/honeydew'
|
data/lib/honeydew/device.rb
CHANGED
@@ -1,79 +1,114 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
require 'honeydew/device_matchers'
|
4
|
+
require 'honeydew/device_actions'
|
3
5
|
|
4
6
|
module Honeydew
|
5
7
|
class Device
|
6
8
|
include Honeydew::DeviceActions
|
7
9
|
include Honeydew::DeviceMatchers
|
8
10
|
|
11
|
+
ServerTimeoutError = Class.new(Timeout::Error)
|
12
|
+
ActionFailedError = Class.new(Timeout::Error)
|
13
|
+
FinderTimeout = Class.new(Timeout::Error)
|
14
|
+
|
9
15
|
attr_reader :serial, :port
|
10
16
|
|
11
17
|
def initialize(serial)
|
12
|
-
|
13
|
-
|
18
|
+
@serial = serial
|
19
|
+
|
20
|
+
unless Honeydew.attached_devices.include?(@serial)
|
21
|
+
raise ArgumentError, "No device with serial #{@serial} attached"
|
14
22
|
end
|
23
|
+
|
15
24
|
@port = Honeydew.config.obtain_new_port
|
16
|
-
|
17
|
-
start_uiautomator_server
|
25
|
+
start_honeydew_server
|
18
26
|
end
|
19
27
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
28
|
+
def using_timeout timeout
|
29
|
+
old_timeout = Honeydew.config.timeout
|
30
|
+
Honeydew.config.timeout = timeout
|
31
|
+
yield
|
32
|
+
ensure
|
33
|
+
Honeydew.config.timeout = old_timeout
|
25
34
|
end
|
26
35
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
36
|
+
private
|
37
|
+
|
38
|
+
def perform_assertion action, arguments = {}, options = {}
|
39
|
+
ensure_device_ready
|
40
|
+
|
41
|
+
log "performing assertion #{action} with arguments #{arguments}"
|
42
|
+
Timeout.timeout Honeydew.config.timeout.to_i, FinderTimeout do
|
43
|
+
begin
|
44
|
+
send_command action, arguments
|
45
|
+
rescue ActionFailedError
|
46
|
+
sleep 0.3
|
47
|
+
retry
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
rescue FinderTimeout
|
32
52
|
end
|
33
53
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
54
|
+
def perform_action action, arguments = {}, options = {}
|
55
|
+
ensure_device_ready
|
56
|
+
|
57
|
+
log "performing action #{action} with arguments #{arguments}"
|
58
|
+
send_command action, arguments
|
39
59
|
end
|
40
60
|
|
41
|
-
def
|
42
|
-
|
61
|
+
def send_command action, arguments
|
62
|
+
uri = device_endpoint('/command')
|
63
|
+
|
64
|
+
request = Net::HTTP::Post.new uri.path
|
65
|
+
request.set_form_data action: action, arguments: arguments.to_json.to_s
|
66
|
+
|
67
|
+
response = Net::HTTP.start(uri.hostname, uri.port) do |http|
|
68
|
+
http.read_timeout = Honeydew.config.server_timeout
|
69
|
+
http.request request
|
70
|
+
end
|
71
|
+
|
72
|
+
case response
|
73
|
+
when Net::HTTPOK
|
74
|
+
true
|
75
|
+
when Net::HTTPRequestedRangeNotSatisfiable
|
76
|
+
raise ActionFailedError.new response.body
|
77
|
+
else
|
78
|
+
raise "honeydew-server failed to process command, response: #{response.value}"
|
79
|
+
end
|
43
80
|
end
|
44
81
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
82
|
+
def log message
|
83
|
+
return unless Honeydew.config.debug
|
84
|
+
STDERR.puts "Device #{serial}: #{message}"
|
48
85
|
end
|
49
|
-
private
|
50
86
|
|
51
|
-
def
|
87
|
+
def ensure_device_ready
|
52
88
|
@device_ready ||= begin
|
53
|
-
|
89
|
+
wait_for_honeydew_server
|
54
90
|
true
|
55
91
|
end
|
56
92
|
end
|
57
93
|
|
58
|
-
def
|
59
|
-
|
60
|
-
retriable :on => [RestClient::ServerBrokeConnection, Errno::ECONNRESET, Errno::ECONNREFUSED], :interval => 0.3, :tries => 30 do
|
61
|
-
RestClient.head device_endpoint
|
62
|
-
end
|
94
|
+
def timeout_server_operation &block
|
95
|
+
Timeout.timeout(Honeydew.config.server_timeout.to_i, ServerTimeoutError, &block)
|
63
96
|
end
|
64
97
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
tries -= 1
|
70
|
-
if tries > 0
|
71
|
-
sleep options[:interval]
|
72
|
-
retry
|
73
|
-
else
|
74
|
-
raise
|
98
|
+
def wait_for_honeydew_server
|
99
|
+
log 'waiting for honeydew-server to respond'
|
100
|
+
timeout_server_operation do
|
101
|
+
sleep 0.1 until honeydew_server_alive?
|
75
102
|
end
|
103
|
+
log 'honeydew-server is alive and awaiting commands'
|
104
|
+
|
105
|
+
rescue ServerTimeoutError
|
106
|
+
raise 'timed out waiting for honeydew-server to respond'
|
76
107
|
end
|
77
108
|
|
109
|
+
def honeydew_server_alive?
|
110
|
+
Net::HTTP.get_response(device_endpoint('/status')).code.to_i == 200
|
111
|
+
rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::ENETRESET, EOFError
|
112
|
+
end
|
78
113
|
end
|
79
114
|
end
|