appium_lib 0.0.30 → 0.3.0
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.
- checksums.yaml +8 -8
- data/Rakefile +15 -7
- data/appium_lib.gemspec +3 -3
- data/docs.md +7 -5
- data/lib/appium_lib.rb +34 -6
- data/lib/appium_lib/android/element/alert.rb +43 -0
- data/lib/appium_lib/android/element/generic.rb +94 -0
- data/lib/appium_lib/android/element/textfield.rb +43 -0
- data/lib/appium_lib/android/helper.rb +120 -0
- data/lib/appium_lib/android/patch.rb +10 -0
- data/lib/appium_lib/common/element/button.rb +83 -0
- data/lib/appium_lib/common/element/text.rb +44 -0
- data/lib/appium_lib/common/element/window.rb +9 -0
- data/lib/appium_lib/common/helper.rb +140 -0
- data/lib/appium_lib/common/patch.rb +83 -0
- data/lib/appium_lib/common/version.rb +6 -0
- data/lib/appium_lib/driver.rb +265 -0
- data/lib/appium_lib/ios/element/alert.rb +56 -0
- data/lib/appium_lib/ios/element/generic.rb +170 -0
- data/lib/appium_lib/ios/element/textfield.rb +90 -0
- data/lib/appium_lib/ios/helper.rb +103 -0
- data/lib/appium_lib/ios/patch.rb +15 -0
- data/readme.md +10 -3
- data/release_notes.md +8 -0
- metadata +19 -15
- data/lib/appium_lib/console.rb +0 -254
- data/lib/appium_lib/element/android/alert.rb +0 -45
- data/lib/appium_lib/element/android/generic.rb +0 -88
- data/lib/appium_lib/element/android/textfield.rb +0 -44
- data/lib/appium_lib/element/button.rb +0 -83
- data/lib/appium_lib/element/ios/alert.rb +0 -49
- data/lib/appium_lib/element/ios/generic.rb +0 -140
- data/lib/appium_lib/element/ios/textfield.rb +0 -93
- data/lib/appium_lib/element/text.rb +0 -43
- data/lib/appium_lib/element/window.rb +0 -12
- data/lib/appium_lib/helper.rb +0 -278
- data/lib/appium_lib/patch.rb +0 -90
- data/lib/appium_lib/version.rb +0 -4
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YmE2MWU3M2FmMDI5OWVkNzQ3Mzk5ZjAzMjdkODcxNGFiNmIzNzI1Yw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDdiZGM4MjAzZjU3OTQ4MTAxZjJiNjg2MTdmNzEzNjFlN2U5ZjMxMw==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NDk5OWIyNjgzYzg3M2NiNmE2OGJiZmI3MDM5YTM5NDg4MmNiYTE0Nzg2YTlj
|
10
|
+
MGEyZTA0NTdjZjYyYWQxMGE2ZjY4MDkyOWE1NzRkYTFjZTQ0MWU3NTcwMGI1
|
11
|
+
NzAyZmQ4ODhkYzBkMmFiM2RkYzQ0MjlhNDA3NGYxNWJlOWNiNzI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NjU2M2Q2NWE0MWY4NTg5NTAwNzFjYzcyYjg0NjNhYzU2YTNlZDI4MTFjY2Nm
|
14
|
+
YTIzMTFmZGZhMTA4YTc4MDIyZmZkMGY0ZDczZWIyMjdiZTk4ZjM5MTRlOWI1
|
15
|
+
NThkMjVjZjU2MTAxODhhYTQyNmM4MTZjNDFlOTU1M2IwYjhlYjg=
|
data/Rakefile
CHANGED
@@ -1,12 +1,13 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require 'rubygems'
|
2
3
|
require 'rake'
|
3
4
|
require 'date'
|
4
5
|
|
5
6
|
# Defines gem name.
|
6
|
-
def repo_name; 'appium_lib'
|
7
|
-
def gh_name; 'ruby_lib'
|
8
|
-
def version_file; "lib/#{repo_name}/version.rb"
|
9
|
-
def version_rgx; /VERSION = '([^']+)'/m
|
7
|
+
def repo_name; 'appium_lib' end # ruby_lib published as appium_lib
|
8
|
+
def gh_name; 'ruby_lib' end # the name as used on github.com
|
9
|
+
def version_file; "lib/#{repo_name}/common/version.rb" end
|
10
|
+
def version_rgx; /VERSION = '([^']+)'/m end
|
10
11
|
|
11
12
|
def version
|
12
13
|
@version = @version || File.read(version_file).match(version_rgx)[1]
|
@@ -79,9 +80,16 @@ desc 'Build a new gem (same as gem task)'
|
|
79
80
|
task :build => :gem do
|
80
81
|
end
|
81
82
|
|
83
|
+
desc 'Uninstall gem'
|
84
|
+
task :uninstall do
|
85
|
+
cmd = "gem uninstall -aIx #{repo_name}"
|
86
|
+
puts cmd
|
87
|
+
# rescue on gem not installed error.
|
88
|
+
begin; `cmd`; rescue; end
|
89
|
+
end
|
90
|
+
|
82
91
|
desc 'Install gem'
|
83
|
-
task :install => :gem do
|
84
|
-
`gem uninstall -aIx #{repo_name}`
|
92
|
+
task :install => [ :gem, :uninstall ] do
|
85
93
|
sh "gem install --no-rdoc --no-ri #{repo_name}-#{version}.gem"
|
86
94
|
end
|
87
95
|
|
@@ -112,7 +120,7 @@ task :notes do
|
|
112
120
|
data =`git log --pretty=oneline #{pairs[a]}`
|
113
121
|
new_data = ''
|
114
122
|
data.split("\n").each do |line|
|
115
|
-
hex = line.match(/[a-zA-Z0-9]+/)[0]
|
123
|
+
hex = line.match(/[a-zA-Z0-9]+/)[0]
|
116
124
|
# use first 7 chars to match GitHub
|
117
125
|
new_data += "- [#{hex[0...7]}](https://github.com/appium/#{gh_name}/commit/#{hex}) #{line.gsub(hex, '').strip}\n"
|
118
126
|
end
|
data/appium_lib.gemspec
CHANGED
@@ -8,15 +8,15 @@ end
|
|
8
8
|
|
9
9
|
add_to_path 'lib'
|
10
10
|
|
11
|
-
require 'appium_lib/version'
|
11
|
+
require 'appium_lib/common/version'
|
12
12
|
|
13
13
|
Gem::Specification.new do |s|
|
14
14
|
# 1.8.x is not supported
|
15
15
|
s.required_ruby_version = '>= 1.9.3'
|
16
16
|
|
17
17
|
s.name = 'appium_lib'
|
18
|
-
s.version =
|
19
|
-
s.date =
|
18
|
+
s.version = Appium::VERSION
|
19
|
+
s.date = Appium::DATE
|
20
20
|
s.license = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
21
21
|
s.description = s.summary = 'Ruby lib for use with Appium'
|
22
22
|
s.description += '.' # avoid identical warning
|
data/docs.md
CHANGED
@@ -14,7 +14,9 @@
|
|
14
14
|
- [mechanic names of elements](https://github.com/jaykz52/mechanic/blob/8c490e1d225f384847e47ffdafb47cc2248bb96c/src/mechanic-core.js#L28)
|
15
15
|
- [All methods supported by Appium](https://github.com/appium/appium/wiki/JSON-Wire-Protocol:-Supported-Methods)
|
16
16
|
- [Appium's mobile gesture docs](https://github.com/appium/appium/wiki/Automating-mobile-gestures)
|
17
|
-
|
17
|
+
|
18
|
+
--
|
19
|
+
|
18
20
|
Example use of Appium's mobile gesture.
|
19
21
|
|
20
22
|
> @driver.execute_script 'mobile: tap', :x => 0, :y => 500
|
@@ -31,7 +33,6 @@ textfield | UIATextField
|
|
31
33
|
secure | UIASecureTextField
|
32
34
|
text | UIAStaticText
|
33
35
|
|
34
|
-
|
35
36
|
--
|
36
37
|
|
37
38
|
#### generic
|
@@ -45,6 +46,7 @@ iOS uses accessibility label with a fallback to text.
|
|
45
46
|
- `(Array<Element>) names(name)` Returns all elements containing name.
|
46
47
|
- `(Element) text(text)` Returns the first element containing text.
|
47
48
|
- `(Array<Element>) texts(text)` Returns all elements containing text.
|
49
|
+
|
48
50
|
--
|
49
51
|
|
50
52
|
#### alert
|
@@ -152,7 +154,7 @@ s.value == password('hello'.length)
|
|
152
154
|
`execute_script 'UIATarget.localTarget().frontMostApp().buttons()[0].tap()'`
|
153
155
|
|
154
156
|
See [app.js](https://github.com/appium/appium/blob/master/app/uiauto/appium/app.js#L3) for more au methods.
|
155
|
-
Note that raw UIAutomation commands are not
|
157
|
+
Note that raw UIAutomation commands are not officially supported.
|
156
158
|
|
157
159
|
Advanced au.
|
158
160
|
|
@@ -214,7 +216,7 @@ at_exit do
|
|
214
216
|
# $driver.session_id
|
215
217
|
ID = $driver.send(:bridge).session_id
|
216
218
|
driver_quit
|
217
|
-
|
219
|
+
|
218
220
|
if !SAUCE_USERNAME.nil? && !SAUCE_ACCESS_KEY.nil?
|
219
221
|
URL = "https://#{SAUCE_USERNAME}:#{SAUCE_ACCESS_KEY}@saucelabs.com/rest/v1/#{SAUCE_USERNAME}/jobs/#{ID}"
|
220
222
|
|
@@ -228,4 +230,4 @@ at_exit do
|
|
228
230
|
end
|
229
231
|
end
|
230
232
|
end
|
231
|
-
```
|
233
|
+
```
|
data/lib/appium_lib.rb
CHANGED
@@ -1,10 +1,38 @@
|
|
1
|
-
|
2
|
-
path = path ? "../#{path}/" : '..'
|
3
|
-
path = File.expand_path path, file
|
1
|
+
# encoding: utf-8
|
4
2
|
|
5
|
-
|
3
|
+
$last_driver = nil
|
4
|
+
|
5
|
+
# Invoke top level methods on last created Appium driver.
|
6
|
+
def self.method_missing method, *args, &block
|
7
|
+
raise "driver is nil. called #{method}" if $last_driver == nil
|
8
|
+
|
9
|
+
has_args = ! args.empty?
|
10
|
+
has_block = ! block.nil?
|
11
|
+
|
12
|
+
# method with no params
|
13
|
+
if ! has_args && ! has_block
|
14
|
+
$last_driver.send method
|
15
|
+
# method with only arg params
|
16
|
+
elsif has_args && ! has_block
|
17
|
+
$last_driver.send method, *args
|
18
|
+
# method with only block param
|
19
|
+
elsif ! has_args && has_block
|
20
|
+
$last_driver.send method, block
|
21
|
+
# method with arg + block
|
22
|
+
elsif has_args && has_block
|
23
|
+
$last_driver.send method, *args, block
|
24
|
+
end
|
6
25
|
end
|
7
26
|
|
8
|
-
|
27
|
+
module Appium
|
28
|
+
def self.add_to_path file, path=false
|
29
|
+
path = path ? "../#{path}/" : '..'
|
30
|
+
path = File.expand_path path, file
|
9
31
|
|
10
|
-
|
32
|
+
$:.unshift path unless $:.include? path
|
33
|
+
end
|
34
|
+
|
35
|
+
add_to_path __FILE__
|
36
|
+
|
37
|
+
require 'appium_lib/driver'
|
38
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Appium::Android
|
3
|
+
# Tap the alert button identified by value.
|
4
|
+
# @param value [Integer, String] either an integer index of the button or the button's name
|
5
|
+
# @return [void]
|
6
|
+
def alert_click value
|
7
|
+
button(value).click
|
8
|
+
end
|
9
|
+
|
10
|
+
# Get the alert message text.
|
11
|
+
# @return [String]
|
12
|
+
def alert_text
|
13
|
+
get_page
|
14
|
+
end
|
15
|
+
|
16
|
+
# Accept the alert.
|
17
|
+
# The last button is considered "accept."
|
18
|
+
# @return [void]
|
19
|
+
def alert_accept
|
20
|
+
last_button.click
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get the text of the alert's accept button.
|
24
|
+
# The last button is considered "accept."
|
25
|
+
# @return [String]
|
26
|
+
def alert_accept_text
|
27
|
+
last_button.text
|
28
|
+
end
|
29
|
+
|
30
|
+
# Dismiss the alert.
|
31
|
+
# The first button is considered "dismiss."
|
32
|
+
# @return [void]
|
33
|
+
def alert_dismiss
|
34
|
+
first_button.click
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get the text of the alert's dismiss button.
|
38
|
+
# The first button is considered "dismiss."
|
39
|
+
# @return [String]
|
40
|
+
def alert_dismiss_text
|
41
|
+
first_button.text
|
42
|
+
end
|
43
|
+
end # module Appium::Android
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Appium::Android
|
3
|
+
=begin
|
4
|
+
name, names, text, text should match substring and case insensitive.
|
5
|
+
|
6
|
+
In Android //* is used to find partial case insensitive text matches.
|
7
|
+
//* is not currently implemented in iOS.
|
8
|
+
|
9
|
+
find_element :name by default uses a partial case insensitive match.
|
10
|
+
On iOS the default is an exact name match.
|
11
|
+
=end
|
12
|
+
|
13
|
+
=begin
|
14
|
+
// iOS version
|
15
|
+
// https://github.com/appium/ruby_lib/blob/37bb4e90b29e5adb4438b287b6387a504c94b5c4/lib/appium_lib/element/ios/generic.rb#L23
|
16
|
+
var search = "name contains[c] '#{text}' || label contains[c] '#{text}' || value contains[c] '#{text}'";
|
17
|
+
var a = w.secureTextFields().firstWithPredicate(search);
|
18
|
+
if ( isNil(a) ) {
|
19
|
+
a = w.textFields().firstWithPredicate(search);
|
20
|
+
if ( isNil(a) ) {
|
21
|
+
a = w.buttons().firstWithPredicate(search);
|
22
|
+
if ( isNil(a) ) {
|
23
|
+
a = w.elements().firstWithPredicate(search);
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
Android considers both a textfield and a secure textfield to be "EditText".
|
29
|
+
Name (the content desc) is searched first and then we search for value (text).
|
30
|
+
There's no label in Android.
|
31
|
+
|
32
|
+
Android buttons have different class names (android.widget.Button, android.widget.ImageButton)
|
33
|
+
so we consider the element a button if the class name contains the word button.
|
34
|
+
|
35
|
+
After looking for textfields and buttons, then we search all elements. Find will return
|
36
|
+
the first element that matches.
|
37
|
+
=end
|
38
|
+
def find val
|
39
|
+
# s.className('android.widget.EditText').descriptionContains(value);
|
40
|
+
args = [ [4, 'android.widget.EditText'], [7, val] ],
|
41
|
+
# s.className('android.widget.EditText').textContains(value);
|
42
|
+
[ [4, 'android.widget.EditText'], [3, val] ],
|
43
|
+
|
44
|
+
# s.className('android.widget.Button').descriptionContains(value);
|
45
|
+
[ [4, 'android.widget.Button'], [7, val] ],
|
46
|
+
# s.className('android.widget.Button').textContains(value);
|
47
|
+
[ [4, 'android.widget.Button'], [3, val] ],
|
48
|
+
|
49
|
+
# s.className('android.widget.ImageButton').descriptionContains(value);
|
50
|
+
[ [4, 'android.widget.ImageButton'], [7, val] ],
|
51
|
+
# s.className('android.widget.ImageButton').textContains(value);
|
52
|
+
[ [4, 'android.widget.ImageButton'], [3, val] ],
|
53
|
+
|
54
|
+
# s.descriptionContains(value);
|
55
|
+
[ [7, val] ],
|
56
|
+
# s.textContains(value);
|
57
|
+
[ [3, val] ]
|
58
|
+
mobile :find, args
|
59
|
+
end
|
60
|
+
|
61
|
+
# Return the first element matching text.
|
62
|
+
# @param text [String] the text to search for
|
63
|
+
# @return [Element] the first matching element
|
64
|
+
def text text
|
65
|
+
# Return the first element matching selector.
|
66
|
+
# s.textContains(value)
|
67
|
+
mobile :find, [ [ [3, text] ] ]
|
68
|
+
end
|
69
|
+
|
70
|
+
# Return all elements matching text.
|
71
|
+
# @param text [String] the text to search for
|
72
|
+
# @return [Array<Element>] all matching elements
|
73
|
+
def texts text
|
74
|
+
@driver.find_elements :xpath, "//*[contains(@text, '#{text}')]"
|
75
|
+
end
|
76
|
+
|
77
|
+
# Return the first element matching name.
|
78
|
+
# on Android name is content description
|
79
|
+
# on iOS name is the accessibility label or the text.
|
80
|
+
# @param name [String] the name to search for
|
81
|
+
# @return [Element] the first matching element
|
82
|
+
def name name
|
83
|
+
@driver.find_element :name, name
|
84
|
+
end
|
85
|
+
|
86
|
+
# Return all elements matching name.
|
87
|
+
# on Android name is content description
|
88
|
+
# on iOS name is the accessibility label or the text.
|
89
|
+
# @param name [String] the name to search for
|
90
|
+
# @return [Array<Element>] all matching elements
|
91
|
+
def names name
|
92
|
+
@driver.find_elements :name, name
|
93
|
+
end
|
94
|
+
end # module Appium::Android
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Appium::Android
|
3
|
+
# UIATextField methods
|
4
|
+
|
5
|
+
# Get an array of textfield texts.
|
6
|
+
# @return [Array<String>]
|
7
|
+
def textfields
|
8
|
+
find_eles_attr :textfield, :text
|
9
|
+
end
|
10
|
+
|
11
|
+
# Get an array of textfield elements.
|
12
|
+
# @return [Array<Textfield>]
|
13
|
+
def e_textfields
|
14
|
+
find_eles :textfield
|
15
|
+
end
|
16
|
+
|
17
|
+
# Get the first textfield element.
|
18
|
+
# @return [Textfield]
|
19
|
+
def first_textfield
|
20
|
+
first_ele :textfield
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get the last textfield element.
|
24
|
+
# @return [Textfield]
|
25
|
+
def last_textfield
|
26
|
+
last_ele :textfield
|
27
|
+
end
|
28
|
+
|
29
|
+
# Get the first textfield that matches text.
|
30
|
+
# @param text [String, Integer] the text to match exactly. If int then the textfield at that index is returned.
|
31
|
+
# @return [Textfield]
|
32
|
+
def textfield text
|
33
|
+
return ele_index :textfield, text if text.is_a? Numeric
|
34
|
+
find_ele_by_text :textfield, text
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get the first textfield that includes text.
|
38
|
+
# @param text [String] the text the textfield must include
|
39
|
+
# @return [Textfield]
|
40
|
+
def textfield_include text
|
41
|
+
find_ele_by_text_include :textfield, text
|
42
|
+
end
|
43
|
+
end # module Appium::Android
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Appium::Android
|
3
|
+
# Returns an array of android classes that match the tag name
|
4
|
+
def tag_name_to_android tag_name
|
5
|
+
tag_name = tag_name.to_s.downcase.strip
|
6
|
+
|
7
|
+
def prefix *tags
|
8
|
+
tags.map!{ |tag| "android.widget.#{tag}" }
|
9
|
+
end
|
10
|
+
# note that 'secure' is not an allowed tag name on android
|
11
|
+
# because android can't tell what a secure textfield is
|
12
|
+
# they're all edittexts.
|
13
|
+
|
14
|
+
# must match names in AndroidElementClassMap (Appium's Java server)
|
15
|
+
case tag_name
|
16
|
+
when 'button'
|
17
|
+
prefix 'Button', 'ImageButton'
|
18
|
+
when 'text'
|
19
|
+
prefix 'TextView'
|
20
|
+
when 'list'
|
21
|
+
prefix 'ListView'
|
22
|
+
when 'window', 'frame'
|
23
|
+
prefix 'FrameLayout'
|
24
|
+
when 'grid'
|
25
|
+
prefix 'GridView'
|
26
|
+
when 'relative'
|
27
|
+
prefix 'RelativeLayout'
|
28
|
+
when 'linear'
|
29
|
+
prefix 'LinearLayout'
|
30
|
+
when 'textfield'
|
31
|
+
prefix 'EditText'
|
32
|
+
else
|
33
|
+
raise "Invalid tag name #{tag_name}"
|
34
|
+
end # return result of case
|
35
|
+
end
|
36
|
+
|
37
|
+
# on android, assume the attr is name (which falls back to text).
|
38
|
+
def find_eles_attr tag_name
|
39
|
+
=begin
|
40
|
+
sel1 = [ [4, 'android.widget.Button'], [100] ]
|
41
|
+
sel2 = [ [4, 'android.widget.ImageButton'], [100] ]
|
42
|
+
|
43
|
+
args = [ 'all', sel1, sel2 ]
|
44
|
+
|
45
|
+
mobile :find, args
|
46
|
+
=end
|
47
|
+
array = ['all']
|
48
|
+
|
49
|
+
tag_name_to_android(tag_name).each do |name|
|
50
|
+
# sel.className(name).getStringAttribute("name")
|
51
|
+
array.push [ [4, name], [100] ]
|
52
|
+
end
|
53
|
+
|
54
|
+
mobile :find, array
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# Android only.
|
59
|
+
def get_inspect
|
60
|
+
def run node
|
61
|
+
r = []
|
62
|
+
|
63
|
+
run_internal = lambda do |node|
|
64
|
+
if node.kind_of? Array
|
65
|
+
node.each { |node| run_internal.call node }
|
66
|
+
return
|
67
|
+
end
|
68
|
+
|
69
|
+
keys = node.keys
|
70
|
+
return if keys.empty?
|
71
|
+
|
72
|
+
obj = {}
|
73
|
+
obj.merge!( { desc: node['@content-desc'] } ) if keys.include?('@content-desc') && !node['@content-desc'].empty?
|
74
|
+
obj.merge!( { text: node['@text'] } ) if keys.include?('@text') && !node['@text'].empty?
|
75
|
+
obj.merge!( { class: node['@class'] } ) if keys.include?('@class') && !obj.empty?
|
76
|
+
|
77
|
+
r.push obj if !obj.empty?
|
78
|
+
run_internal.call node['node'] if keys.include?('node')
|
79
|
+
end
|
80
|
+
|
81
|
+
run_internal.call node
|
82
|
+
r
|
83
|
+
end
|
84
|
+
|
85
|
+
json = JSON.parse(@driver.page_source)
|
86
|
+
node = json['hierarchy']
|
87
|
+
results = run node
|
88
|
+
|
89
|
+
out = ''
|
90
|
+
results.each { |e|
|
91
|
+
out += e[:class].split('.').last + "\n"
|
92
|
+
|
93
|
+
out += " class: #{e[:class]}\n"
|
94
|
+
if e[:text] == e[:desc]
|
95
|
+
out += " text, name: #{e[:text]}\n" unless e[:text].nil?
|
96
|
+
else
|
97
|
+
out += " text: #{e[:text]}\n" unless e[:text].nil?
|
98
|
+
out += " name: #{e[:desc]}\n" unless e[:desc].nil?
|
99
|
+
end
|
100
|
+
}
|
101
|
+
out
|
102
|
+
end
|
103
|
+
|
104
|
+
# Android only. Intended for use with console.
|
105
|
+
# Inspects and prints the current page.
|
106
|
+
def page
|
107
|
+
puts get_inspect
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
|
111
|
+
# JavaScript code from https://github.com/appium/appium/blob/master/app/android.js
|
112
|
+
#
|
113
|
+
# Math.round((duration * 1000) / 200)
|
114
|
+
# (.20 * 1000) / 200 = 1
|
115
|
+
#
|
116
|
+
# We want steps to be exactly 1. If it's zero then a tap is used instead of a swipe.
|
117
|
+
def fast_duration
|
118
|
+
0.20
|
119
|
+
end
|
120
|
+
end # module Appium::Android
|