appium_lib 0.24.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +17 -8
- data/android_tests/Gemfile +1 -0
- data/android_tests/LICENSE-2.0.txt +202 -0
- data/android_tests/Rakefile +61 -0
- data/android_tests/api.apk +0 -0
- data/android_tests/appium.txt +3 -0
- data/android_tests/flaky.txt +1 -0
- data/android_tests/lib/android/specs/android/dynamic.rb +5 -0
- data/android_tests/lib/android/specs/android/element/alert.rb +41 -0
- data/android_tests/lib/android/specs/android/element/button.rb +55 -0
- data/android_tests/lib/android/specs/android/element/generic.rb +48 -0
- data/android_tests/lib/android/specs/android/element/text.rb +39 -0
- data/android_tests/lib/android/specs/android/element/textfield.rb +60 -0
- data/android_tests/lib/android/specs/android/helper.rb +80 -0
- data/android_tests/lib/android/specs/android/patch.rb +14 -0
- data/android_tests/lib/android/specs/common/device.rb +117 -0
- data/android_tests/lib/android/specs/common/element/window.rb +9 -0
- data/android_tests/lib/android/specs/common/helper.rb +112 -0
- data/android_tests/lib/android/specs/common/patch.rb +69 -0
- data/android_tests/lib/android/specs/common/version.rb +9 -0
- data/android_tests/lib/android/specs/driver.rb +174 -0
- data/android_tests/lib/format.rb +49 -0
- data/android_tests/lib/run.rb +72 -0
- data/android_tests/readme.md +27 -0
- data/appium_lib.gemspec +8 -5
- data/docs/android_docs.md +1052 -716
- data/docs/ios_docs.md +657 -834
- data/docs_gen/make_docs.rb +1 -3
- data/ios_tests/Gemfile +1 -0
- data/ios_tests/LICENSE-2.0.txt +202 -0
- data/ios_tests/Rakefile +47 -0
- data/ios_tests/UICatalog.app.zip +0 -0
- data/ios_tests/UICatalog.app/12-6AM.png +0 -0
- data/ios_tests/UICatalog.app/12-6PM.png +0 -0
- data/ios_tests/UICatalog.app/6-12AM.png +0 -0
- data/ios_tests/UICatalog.app/6-12PM.png +0 -0
- data/ios_tests/UICatalog.app/Default-568h@2x.png +0 -0
- data/ios_tests/UICatalog.app/Default@2x.png +0 -0
- data/ios_tests/UICatalog.app/Info.plist +0 -0
- data/ios_tests/UICatalog.app/PkgInfo +1 -0
- data/ios_tests/UICatalog.app/UIButton_custom.png +0 -0
- data/ios_tests/UICatalog.app/UICatalog +0 -0
- data/ios_tests/UICatalog.app/blueButton.png +0 -0
- data/ios_tests/UICatalog.app/bookmarkImage.png +0 -0
- data/ios_tests/UICatalog.app/bookmarkImageHighlighted.png +0 -0
- data/ios_tests/UICatalog.app/divider.png +0 -0
- data/ios_tests/UICatalog.app/en.lproj/AlertsViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/ButtonsViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/ControlsViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/ImagesViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/Localizable.strings +0 -0
- data/ios_tests/UICatalog.app/en.lproj/MainWindow.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/PickerViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/SearchBarController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/SegmentViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/TextFieldController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/TextViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/ToolbarViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/TransitionViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/WebViewController.nib +0 -0
- data/ios_tests/UICatalog.app/orangeslide.png +0 -0
- data/ios_tests/UICatalog.app/scene1.jpg +0 -0
- data/ios_tests/UICatalog.app/scene2.jpg +0 -0
- data/ios_tests/UICatalog.app/scene3.jpg +0 -0
- data/ios_tests/UICatalog.app/scene4.jpg +0 -0
- data/ios_tests/UICatalog.app/scene5.jpg +0 -0
- data/ios_tests/UICatalog.app/searchBarBackground.png +0 -0
- data/ios_tests/UICatalog.app/segment_check.png +0 -0
- data/ios_tests/UICatalog.app/segment_search.png +0 -0
- data/ios_tests/UICatalog.app/segment_tools.png +0 -0
- data/ios_tests/UICatalog.app/segmentedBackground.png +0 -0
- data/ios_tests/UICatalog.app/slider_ball.png +0 -0
- data/ios_tests/UICatalog.app/toolbarBackground.png +0 -0
- data/ios_tests/UICatalog.app/whiteButton.png +0 -0
- data/ios_tests/UICatalog.app/yellowslide.png +0 -0
- data/ios_tests/appium.txt +3 -0
- data/ios_tests/flaky.txt +1 -0
- data/ios_tests/lib/format.rb +25 -0
- data/ios_tests/lib/ios/specs/common/element/window.rb +15 -0
- data/ios_tests/lib/ios/specs/common/helper.rb +204 -0
- data/ios_tests/lib/ios/specs/common/patch.rb +50 -0
- data/ios_tests/lib/ios/specs/common/version.rb +17 -0
- data/ios_tests/lib/ios/specs/device/device.rb +82 -0
- data/ios_tests/lib/ios/specs/device/multi_touch.rb +12 -0
- data/ios_tests/lib/ios/specs/device/touch_actions.rb +15 -0
- data/ios_tests/lib/ios/specs/driver.rb +203 -0
- data/ios_tests/lib/ios/specs/ios/element/alert.rb +48 -0
- data/ios_tests/lib/ios/specs/ios/element/button.rb +58 -0
- data/ios_tests/lib/ios/specs/ios/element/generic.rb +35 -0
- data/ios_tests/lib/ios/specs/ios/element/text.rb +54 -0
- data/ios_tests/lib/ios/specs/ios/element/textfield.rb +123 -0
- data/ios_tests/lib/ios/specs/ios/helper.rb +27 -0
- data/ios_tests/lib/ios/specs/ios/patch.rb +30 -0
- data/ios_tests/lib/run.rb +106 -0
- data/ios_tests/readme.md +30 -0
- data/ios_tests/upload/sauce_storage.rb +64 -0
- data/ios_tests/upload/upload.rb +6 -0
- data/lib/appium_lib.rb +4 -14
- data/lib/appium_lib/android/dynamic.rb +30 -32
- data/lib/appium_lib/android/element/alert.rb +34 -33
- data/lib/appium_lib/android/element/button.rb +91 -0
- data/lib/appium_lib/android/element/generic.rb +51 -146
- data/lib/appium_lib/android/element/text.rb +54 -0
- data/lib/appium_lib/android/element/textfield.rb +46 -41
- data/lib/appium_lib/android/helper.rb +248 -417
- data/lib/appium_lib/android/mobile_methods.rb +17 -0
- data/lib/appium_lib/android/patch.rb +9 -8
- data/lib/appium_lib/awesome_print/ostruct.rb +33 -0
- data/lib/appium_lib/common/element/window.rb +9 -8
- data/lib/appium_lib/common/helper.rb +182 -243
- data/lib/appium_lib/common/patch.rb +65 -79
- data/lib/appium_lib/common/version.rb +2 -3
- data/lib/appium_lib/device/device.rb +339 -0
- data/lib/appium_lib/device/multi_touch.rb +94 -0
- data/lib/appium_lib/device/touch_actions.rb +142 -0
- data/lib/appium_lib/driver.rb +217 -306
- data/lib/appium_lib/ios/element/alert.rb +16 -92
- data/lib/appium_lib/ios/element/button.rb +55 -0
- data/lib/appium_lib/ios/element/generic.rb +27 -160
- data/lib/appium_lib/ios/element/text.rb +54 -0
- data/lib/appium_lib/ios/element/textfield.rb +78 -65
- data/lib/appium_lib/ios/helper.rb +300 -190
- data/lib/appium_lib/ios/mobile_methods.rb +17 -0
- data/lib/appium_lib/ios/patch.rb +55 -41
- data/lib/appium_lib/logger.rb +13 -0
- data/lib/appium_lib/rails/duplicable.rb +116 -0
- data/readme.md +6 -1
- data/release_notes.md +118 -0
- metadata +170 -12
- data/lib/appium_lib/common/element/button.rb +0 -83
- data/lib/appium_lib/common/element/text.rb +0 -61
@@ -0,0 +1,17 @@
|
|
1
|
+
module Appium
|
2
|
+
module Android
|
3
|
+
class << self
|
4
|
+
# @!method uiautomator_find
|
5
|
+
# find_element/s can be used with a [UISelector](http://developer.android.com/tools/help/uiautomator/UiSelector.html).
|
6
|
+
#
|
7
|
+
# ```ruby
|
8
|
+
# find_elements :uiautomator, 'new UiSelector().clickable(true)'
|
9
|
+
# ```
|
10
|
+
def extended(mod)
|
11
|
+
Selenium::WebDriver::SearchContext.class_eval do
|
12
|
+
Selenium::WebDriver::SearchContext::FINDERS[:uiautomator] = '-android uiautomator'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end # class << self
|
16
|
+
end # module Android
|
17
|
+
end # module Appium
|
@@ -1,10 +1,10 @@
|
|
1
|
-
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
module Appium
|
2
|
+
module Android
|
3
|
+
# @private
|
4
|
+
# class_eval inside a method because class Selenium::WebDriver::Element
|
5
|
+
# will trigger as soon as the file is required. in contrast a method
|
6
|
+
# will trigger only when invoked.
|
7
|
+
def patch_webdriver_element
|
8
8
|
Selenium::WebDriver::Element.class_eval do
|
9
9
|
# Cross platform way of entering text into a textfield
|
10
10
|
def type text
|
@@ -12,4 +12,5 @@ module Appium::Android
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
|
-
end
|
15
|
+
end # Android
|
16
|
+
end # Appium
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Enable OpenStruct support in awesome print
|
2
|
+
# Code from @marshallshen https://github.com/michaeldv/awesome_print/pull/145
|
3
|
+
#
|
4
|
+
# Copyright (c) 2010-2013 Michael Dvorkin
|
5
|
+
#
|
6
|
+
# Awesome Print is freely distributable under the terms of MIT license.
|
7
|
+
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
8
|
+
#------------------------------------------------------------------------------
|
9
|
+
|
10
|
+
if defined?(OpenStruct)
|
11
|
+
module AwesomePrint
|
12
|
+
module OpenStruct
|
13
|
+
def self.included(base)
|
14
|
+
base.send :alias_method, :cast_without_ostruct, :cast
|
15
|
+
base.send :alias_method, :cast, :cast_with_ostruct
|
16
|
+
end
|
17
|
+
|
18
|
+
def cast_with_ostruct(object, type)
|
19
|
+
cast = cast_without_ostruct(object, type)
|
20
|
+
if (defined?(::OpenStruct)) && (object.is_a?(::OpenStruct))
|
21
|
+
cast = :open_struct_instance
|
22
|
+
end
|
23
|
+
cast
|
24
|
+
end
|
25
|
+
|
26
|
+
def awesome_open_struct_instance(object)
|
27
|
+
"#{object.class} #{awesome_hash(object.marshal_dump)}"
|
28
|
+
end
|
29
|
+
end # module OpenStruct
|
30
|
+
end # module AwesomePrint
|
31
|
+
|
32
|
+
AwesomePrint::Formatter.send(:include, AwesomePrint::OpenStruct)
|
33
|
+
end
|
@@ -1,9 +1,10 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# UIAWindow methods
|
3
|
-
module Appium
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
2
|
+
module Appium
|
3
|
+
module Common
|
4
|
+
# Get the window's size
|
5
|
+
def window_size
|
6
|
+
return nil if @driver.nil?
|
7
|
+
@driver.manage.window.size
|
8
|
+
end
|
9
|
+
end # module Common
|
10
|
+
end # module Appium
|
@@ -1,271 +1,210 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# Generic helper methods not specific
|
3
2
|
# to a particular tag name
|
4
|
-
module Appium
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
3
|
+
module Appium
|
4
|
+
module Common
|
5
|
+
# json and ap are required for the source method.
|
6
|
+
require 'json'
|
7
|
+
require 'ap' # awesome print
|
8
|
+
require 'timeout' # for wait
|
9
|
+
|
10
|
+
# iOS .name returns the accessibility attribute if it's set. if not set, the string value is used.
|
11
|
+
# Android .name returns the accessibility attribute and nothing if it's not set.
|
12
|
+
#
|
13
|
+
# .text should be cross platform so prefer that over name, unless both
|
14
|
+
# Android and iOS have proper accessibility attributes.
|
15
|
+
# .text and .value should be the same so use .text over .value.
|
16
|
+
#
|
17
|
+
# secure class_name is iOS only because it can't be implemented using uiautomator for Android.
|
18
|
+
#
|
19
|
+
# find_element :text doesn't work so use XPath to find by text.
|
20
|
+
|
21
|
+
# Check every 0.5 seconds to see if block.call doesn't raise an exception.
|
22
|
+
# if .call raises an exception then it will be tried again.
|
23
|
+
# if .call doesn't raise an exception then it will stop waiting.
|
24
|
+
#
|
25
|
+
# Example: wait { name('back').click }
|
26
|
+
#
|
27
|
+
# Give up after 30 seconds.
|
28
|
+
# @param max_wait [Integer] the maximum time in seconds to wait for.
|
29
|
+
# Note that max wait 0 means infinity.
|
30
|
+
# @param interval [Float] the time in seconds to wait after calling the block
|
31
|
+
# @param block [Block] the block to call
|
32
|
+
# @return [Object] the result of block.call
|
33
|
+
def wait max_wait=30, interval=0.5, &block
|
34
|
+
max_wait = 1 if max_wait <= 0
|
35
|
+
result = nil
|
36
|
+
timeout max_wait do
|
37
|
+
until (
|
38
|
+
begin
|
39
|
+
result = block.call || true
|
40
|
+
rescue Exception
|
41
|
+
end)
|
42
|
+
sleep interval
|
43
|
+
end
|
39
44
|
end
|
45
|
+
result
|
40
46
|
end
|
41
|
-
result
|
42
|
-
end
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# Check every 0.5 seconds to see if block.call returns true. nil is considered a failure.
|
50
|
-
# Give up after 30 seconds.
|
51
|
-
# @param max_wait [Integer] the maximum time in seconds to wait for
|
52
|
-
# @param interval [Float] the time in seconds to wait after calling the block
|
53
|
-
# @param block [Block] the block to call
|
54
|
-
# @return [Object] the result of block.call
|
55
|
-
def wait_true max_wait=30, interval=0.5, &block
|
56
|
-
max_wait = 1 if max_wait <= 0
|
57
|
-
result = nil
|
58
|
-
timeout max_wait do
|
59
|
-
until (result = begin; block.call; rescue; end)
|
60
|
-
sleep interval
|
48
|
+
# Return block.call and ignore any exceptions.
|
49
|
+
def ignore &block
|
50
|
+
begin
|
51
|
+
block.call
|
52
|
+
rescue Exception
|
61
53
|
end
|
62
54
|
end
|
63
|
-
result
|
64
|
-
end
|
65
|
-
|
66
|
-
# Navigate back.
|
67
|
-
# @return [void]
|
68
|
-
def back
|
69
|
-
@driver.navigate.back
|
70
|
-
end
|
71
|
-
|
72
|
-
# For Sauce Labs reporting. Returns the current session id.
|
73
|
-
def session_id
|
74
|
-
@driver.session_id
|
75
|
-
end
|
76
|
-
|
77
|
-
# Returns the first element that matches the provided xpath.
|
78
|
-
#
|
79
|
-
# @param xpath_str [String] the XPath string
|
80
|
-
# @return [Element]
|
81
|
-
def xpath xpath_str
|
82
|
-
find_element :xpath, xpath_str
|
83
|
-
end
|
84
|
-
|
85
|
-
# Returns all elements that match the provided xpath.
|
86
|
-
#
|
87
|
-
# @param xpath_str [String] the XPath string
|
88
|
-
# @return [Array<Element>]
|
89
|
-
def xpaths xpath_str
|
90
|
-
find_elements :xpath, xpath_str
|
91
|
-
end
|
92
|
-
|
93
|
-
# Get the element of type tag_name at matching index.
|
94
|
-
# @param tag_name [String] the tag name to find
|
95
|
-
# @param index [Integer] the index
|
96
|
-
# @return [Element] the found element of type tag_name
|
97
|
-
def ele_index tag_name, index
|
98
|
-
# XPath index starts at 1.
|
99
|
-
raise "#{index} is not a valid xpath index. Must be >= 1" if index <= 0
|
100
|
-
find_element :xpath, "//#{tag_name}[#{index}]"
|
101
|
-
end
|
102
55
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
@
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
# Get the first tag by attribute that exactly matches value.
|
127
|
-
# @param tag [String] the tag name to match
|
128
|
-
# @param attr [String] the attribute to compare
|
129
|
-
# @param value [String] the value of the attribute that the element must include
|
130
|
-
# @return [Element] the element of type tag who's attribute includes value
|
131
|
-
def find_ele_by_attr_include tag, attr, value
|
132
|
-
@driver.find_element :xpath, %Q(#{tag}[contains(@#{attr}, '#{value}')])
|
133
|
-
end
|
134
|
-
|
135
|
-
# Get tags by attribute that include value.
|
136
|
-
# @param tag [String] the tag name to match
|
137
|
-
# @param attr [String] the attribute to compare
|
138
|
-
# @param value [String] the value of the attribute that the element must include
|
139
|
-
# @return [Array<Element>] the elements of type tag who's attribute includes value
|
140
|
-
def find_eles_by_attr_include tag, attr, value
|
141
|
-
@driver.find_elements :xpath, %Q(#{tag}[contains(@#{attr}, '#{value}')])
|
142
|
-
end
|
56
|
+
# Check every 0.5 seconds to see if block.call returns a truthy value.
|
57
|
+
# Note this isn't a strict boolean true, any truthy value is accepted.
|
58
|
+
# false and nil are considered failures.
|
59
|
+
# Give up after 30 seconds.
|
60
|
+
# @param max_wait [Integer] the maximum time in seconds to wait for
|
61
|
+
# @param interval [Float] the time in seconds to wait after calling the block
|
62
|
+
# @param block [Block] the block to call
|
63
|
+
# @return [Object] the result of block.call
|
64
|
+
def wait_true max_wait=30, interval=0.5, &block
|
65
|
+
max_wait = 1 if max_wait <= 0
|
66
|
+
result = nil
|
67
|
+
timeout max_wait do
|
68
|
+
until (
|
69
|
+
begin
|
70
|
+
result = block.call
|
71
|
+
rescue Exception
|
72
|
+
end)
|
73
|
+
sleep interval
|
74
|
+
end
|
75
|
+
end
|
76
|
+
result
|
77
|
+
end
|
143
78
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
def find_ele_by_text_include tag, text
|
150
|
-
find_ele_by_attr_include tag, :text, text
|
151
|
-
end
|
79
|
+
# Navigate back.
|
80
|
+
# @return [void]
|
81
|
+
def back
|
82
|
+
@driver.navigate.back
|
83
|
+
end
|
152
84
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
# element.attribute(:text).include? text
|
158
|
-
def find_eles_by_text_include tag, text
|
159
|
-
find_eles_by_attr_include tag, :text, text
|
160
|
-
end
|
85
|
+
# For Sauce Labs reporting. Returns the current session id.
|
86
|
+
def session_id
|
87
|
+
@driver.session_id
|
88
|
+
end
|
161
89
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
90
|
+
# Returns the first element that matches the provided xpath.
|
91
|
+
#
|
92
|
+
# @param xpath_str [String] the XPath string
|
93
|
+
# @return [Element]
|
94
|
+
def xpath xpath_str
|
95
|
+
find_element :xpath, xpath_str
|
96
|
+
end
|
169
97
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
98
|
+
# Returns all elements that match the provided xpath.
|
99
|
+
#
|
100
|
+
# @param xpath_str [String] the XPath string
|
101
|
+
# @return [Array<Element>]
|
102
|
+
def xpaths xpath_str
|
103
|
+
find_elements :xpath, xpath_str
|
104
|
+
end
|
176
105
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
106
|
+
# Prints xml of the current page
|
107
|
+
# @return [void]
|
108
|
+
def source
|
109
|
+
doc = Nokogiri::XML(@driver.page_source) do |config|
|
110
|
+
config.options = Nokogiri::XML::ParseOptions::NOBLANKS | Nokogiri::XML::ParseOptions::NONET
|
111
|
+
end
|
112
|
+
puts doc.to_xml indent: 2
|
113
|
+
end
|
182
114
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
115
|
+
# Returns XML string for the current page
|
116
|
+
# Same as driver.page_source
|
117
|
+
# @return [String]
|
118
|
+
def get_source
|
119
|
+
@driver.page_source
|
120
|
+
end
|
189
121
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
def find_name name
|
195
|
-
find_element :name, name
|
196
|
-
end
|
122
|
+
# @private
|
123
|
+
# http://nokogiri.org/Nokogiri/XML/SAX.html
|
124
|
+
class CountElements < Nokogiri::XML::SAX::Document
|
125
|
+
attr_reader :result
|
197
126
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
# @return [Array<Element>]
|
202
|
-
def find_names name
|
203
|
-
find_elements :name, name
|
204
|
-
end
|
127
|
+
def initialize
|
128
|
+
reset
|
129
|
+
end
|
205
130
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
# @return [Element]
|
210
|
-
def tag tag_name
|
211
|
-
find_element :tag_name, tag_name
|
212
|
-
end
|
131
|
+
def reset
|
132
|
+
@result = Hash.new 0
|
133
|
+
end
|
213
134
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
def tags tag_name
|
219
|
-
find_elements :tag_name, tag_name
|
220
|
-
end
|
135
|
+
# http://nokogiri.org/Nokogiri/XML/SAX/Document.html
|
136
|
+
def start_element name, attrs = []
|
137
|
+
@result[name] += 1
|
138
|
+
end
|
221
139
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
140
|
+
def formatted_result
|
141
|
+
message = ''
|
142
|
+
sorted = @result.sort_by { |element, count| count }.reverse
|
143
|
+
sorted.each do |element, count|
|
144
|
+
message += "#{count}x #{element}\n"
|
145
|
+
end
|
146
|
+
message.strip
|
147
|
+
end
|
148
|
+
end # class CountElements
|
227
149
|
|
228
|
-
|
150
|
+
# Returns a string of class counts.
|
151
|
+
def get_page_class
|
152
|
+
parser = @count_elements_parser ||= Nokogiri::XML::SAX::Parser.new(CountElements.new)
|
229
153
|
|
230
|
-
|
231
|
-
|
232
|
-
y = opts.fetch :y, 0
|
154
|
+
parser.document.reset
|
155
|
+
parser.parse get_source
|
233
156
|
|
234
|
-
|
235
|
-
|
236
|
-
end
|
157
|
+
parser.document.formatted_result
|
158
|
+
end
|
237
159
|
|
238
|
-
|
239
|
-
|
240
|
-
|
160
|
+
# Count all classes on screen and print to stdout.
|
161
|
+
# Useful for appium_console.
|
162
|
+
def page_class
|
163
|
+
puts get_page_class
|
164
|
+
nil
|
165
|
+
end
|
241
166
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
167
|
+
# Converts pixel values to window relative values
|
168
|
+
#
|
169
|
+
# ```ruby
|
170
|
+
# px_to_window_rel x: 50, y: 150
|
171
|
+
# ```
|
172
|
+
def px_to_window_rel opts={}
|
173
|
+
w = $driver.window_size
|
174
|
+
x = opts.fetch :x, 0
|
175
|
+
y = opts.fetch :y, 0
|
176
|
+
|
177
|
+
OpenStruct.new(x: "#{x.to_f} / #{w.width.to_f}",
|
178
|
+
y: "#{y.to_f} / #{w.height.to_f}")
|
179
|
+
end
|
249
180
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
lazy_load_strings
|
255
|
-
@strings_xml.select { |key, value| value.downcase.include? target.downcase }
|
256
|
-
end
|
181
|
+
# @private
|
182
|
+
def lazy_load_strings
|
183
|
+
@strings_xml ||= app_strings
|
184
|
+
end
|
257
185
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
186
|
+
# Search strings.xml's values for target.
|
187
|
+
# @param target [String] the target to search for in strings.xml values
|
188
|
+
# @return [Array]
|
189
|
+
def xml_keys target
|
190
|
+
lazy_load_strings
|
191
|
+
@strings_xml.select { |key, value| key.downcase.include? target.downcase }
|
192
|
+
end
|
265
193
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
194
|
+
# Search strings.xml's keys for target.
|
195
|
+
# @param target [String] the target to search for in strings.xml keys
|
196
|
+
# @return [Array]
|
197
|
+
def xml_values target
|
198
|
+
lazy_load_strings
|
199
|
+
@strings_xml.select { |key, value| value.downcase.include? target.downcase }
|
200
|
+
end
|
270
201
|
|
271
|
-
|
202
|
+
# Resolve id in strings.xml and return the value.
|
203
|
+
# @param id [String] the id to resolve
|
204
|
+
# @return [String]
|
205
|
+
def resolve_id id
|
206
|
+
lazy_load_strings
|
207
|
+
@strings_xml[id]
|
208
|
+
end
|
209
|
+
end # module Common
|
210
|
+
end # module Appium
|