appium_lib 0.24.1 → 1.0.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 +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
|