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