testa_appium_driver 0.1.3 → 0.1.7
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/.gitignore +2 -2
- data/.idea/deployment.xml +10 -2
- data/.idea/inspectionProfiles/Project_Default.xml +8 -8
- data/.idea/runConfigurations/Android_Test.xml +41 -41
- data/.idea/runConfigurations.xml +10 -0
- data/.idea/sshConfigs.xml +3 -0
- data/.idea/webServers.xml +7 -0
- data/.rspec +3 -3
- data/.rubocop.yml +13 -13
- data/CHANGELOG.md +5 -5
- data/CODE_OF_CONDUCT.md +102 -102
- data/Gemfile +12 -12
- data/LICENSE.txt +21 -21
- data/README.md +18 -5
- data/Rakefile +12 -12
- data/bin/console +17 -17
- data/bin/setup +8 -8
- data/lib/testa_appium_driver/android/class_selectors.rb +101 -16
- data/lib/testa_appium_driver/android/driver.rb +19 -1
- data/lib/testa_appium_driver/android/locator.rb +22 -7
- data/lib/testa_appium_driver/android/scroll_actions/uiautomator_scroll_actions.rb +0 -14
- data/lib/testa_appium_driver/common/constants.rb +1 -0
- data/lib/testa_appium_driver/common/helpers.rb +5 -1
- data/lib/testa_appium_driver/common/locator/scroll_actions.rb +152 -58
- data/lib/testa_appium_driver/common/locator.rb +160 -25
- data/lib/testa_appium_driver/common/scroll_actions/w3c_scroll_actions.rb +14 -36
- data/lib/testa_appium_driver/common/scroll_actions.rb +30 -8
- data/lib/testa_appium_driver/common/selenium_element.rb +2 -2
- data/lib/testa_appium_driver/driver.rb +99 -29
- data/lib/testa_appium_driver/ios/driver.rb +14 -0
- data/lib/testa_appium_driver/ios/locator.rb +10 -5
- data/lib/testa_appium_driver/ios/type_selectors.rb +0 -13
- data/lib/testa_appium_driver/version.rb +5 -5
- data/testa_appium_driver.gemspec +1 -1
- data/testa_appium_driver.iml +39 -5
- metadata +7 -6
@@ -2,6 +2,7 @@ module TestaAppiumDriver
|
|
2
2
|
#noinspection RubyTooManyMethodsInspection
|
3
3
|
class Locator
|
4
4
|
|
5
|
+
# performs a long tap on the retrieved element
|
5
6
|
# @param [Float] duration in seconds
|
6
7
|
def long_tap(duration = LONG_TAP_DURATION)
|
7
8
|
action_builder = @driver.action
|
@@ -15,173 +16,254 @@ module TestaAppiumDriver
|
|
15
16
|
@driver.perform_actions [f1]
|
16
17
|
end
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
|
20
|
+
# scrolls to the start of the scrollable containers and scrolls to the end,
|
21
|
+
# everytime a locator element is found the given block is executed
|
22
|
+
# @return [Array<Selenium::WebDriver::Element>]
|
23
|
+
def each(top: nil, bottom: nil, right: nil, left: nil, direction: nil, &block)
|
24
|
+
deadzone = _process_deadzone(top, bottom, right, left)
|
20
25
|
raise "Each can only be performed on multiple elements locator" if @single
|
21
26
|
deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
|
22
27
|
sa = ScrollActions.new(@scrollable_locator,
|
23
28
|
locator: self,
|
24
29
|
deadzone: deadzone,
|
25
30
|
default_scroll_strategy: @default_scroll_strategy)
|
26
|
-
|
31
|
+
if direction.nil?
|
32
|
+
sa.each(&block)
|
33
|
+
else
|
34
|
+
sa.send("each_#{direction}", &block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# scrolls down from the current page view (without prior scrolling to the top) and
|
39
|
+
# everytime a locator element is found the given block is executed
|
40
|
+
# @return [Array<Selenium::WebDriver::Element>]
|
41
|
+
def each_down(top: nil, bottom: nil, right: nil, left: nil, &block)
|
42
|
+
each(top: top, bottom: bottom, right: right, left: left, direction: :down, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
# scrolls up from the current page view (without prior scrolling to the bottom) and
|
46
|
+
# everytime a locator element is found the given block is executed
|
47
|
+
# @return [Array<Selenium::WebDriver::Element>]
|
48
|
+
def each_up(top: nil, bottom: nil, right: nil, left: nil, &block)
|
49
|
+
each(top: top, bottom: bottom, right: right, left: left, direction: :up, &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
# scrolls right from the current page view (without prior scrolling to the left) and
|
53
|
+
# everytime a locator element is found the given block is executed
|
54
|
+
# @return [Array<Selenium::WebDriver::Element>]
|
55
|
+
def each_right(top: nil, bottom: nil, right: nil, left: nil, &block)
|
56
|
+
each(top: top, bottom: bottom, right: right, left: left, direction: :right, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
# scrolls left from the current page view (without prior scrolling to the right) and
|
60
|
+
# everytime a locator element is found the given block is executed
|
61
|
+
# @return [Array<Selenium::WebDriver::Element>]
|
62
|
+
def each_left(top: nil, bottom: nil, right: nil, left: nil, &block)
|
63
|
+
each(top: top, bottom: bottom, right: right, left: left, direction: :left, &block)
|
27
64
|
end
|
28
65
|
|
29
66
|
|
30
67
|
# Aligns element (by default) on top of the scrollable container, if the element does not exists it will scroll to find it
|
68
|
+
# The element is aligned if the the distance from the top/bottom/right/left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
|
69
|
+
# If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
|
70
|
+
# The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
|
31
71
|
# @return [TestaAppiumDriver::Locator]
|
32
|
-
def align(with = :top,
|
72
|
+
def align(with = :top, top: nil, bottom: nil, right: nil, left: nil, scroll_to_find: false)
|
33
73
|
deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
|
34
74
|
sa = ScrollActions.new(@scrollable_locator,
|
35
75
|
locator: self,
|
36
76
|
deadzone: deadzone,
|
37
|
-
default_scroll_strategy: @default_scroll_strategy
|
38
|
-
|
39
|
-
sa.align(with)
|
77
|
+
default_scroll_strategy: @default_scroll_strategy)
|
78
|
+
sa.align(with, scroll_to_find)
|
40
79
|
self
|
41
80
|
end
|
42
81
|
|
43
82
|
# Aligns element on top of the scrollable container, if the element does not exists it will scroll to find it
|
83
|
+
# The element is aligned if the the distance from the top of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
|
84
|
+
# If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
|
85
|
+
# The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
|
44
86
|
# @return [TestaAppiumDriver::Locator]
|
45
|
-
def align_top(
|
46
|
-
align(:top,
|
87
|
+
def align_top(top: nil, bottom: nil, right: nil, left: nil)
|
88
|
+
align(:top, top: top, bottom: bottom, right: right, left: left)
|
47
89
|
end
|
48
90
|
|
49
91
|
# Aligns element on bottom of the scrollable container, if the element does not exists it will scroll to find it
|
92
|
+
# The element is aligned if the the distance from the bottom of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
|
93
|
+
# If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
|
94
|
+
# The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
|
50
95
|
# @return [TestaAppiumDriver::Locator]
|
51
|
-
def align_bottom(
|
52
|
-
align(:bottom,
|
96
|
+
def align_bottom(top: nil, bottom: nil, right: nil, left: nil)
|
97
|
+
align(:bottom, top: top, bottom: bottom, right: right, left: left)
|
53
98
|
end
|
54
99
|
|
55
100
|
# Aligns element on left of the scrollable container, if the element does not exists it will scroll to find it
|
101
|
+
# The element is aligned if the the distance from the left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
|
102
|
+
# If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
|
103
|
+
# The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
|
56
104
|
# @return [TestaAppiumDriver::Locator]
|
57
|
-
def align_left(
|
58
|
-
align(:left,
|
105
|
+
def align_left(top: nil, bottom: nil, right: nil, left: nil)
|
106
|
+
align(:left, top: top, bottom: bottom, right: right, left: left)
|
59
107
|
end
|
60
108
|
|
61
109
|
# Aligns element on right of the scrollable container, if the element does not exists it will scroll to find it
|
110
|
+
# The element is aligned if the the distance from the right of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
|
111
|
+
# If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
|
112
|
+
# The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
|
62
113
|
# @return [TestaAppiumDriver::Locator]
|
63
|
-
def align_right(
|
64
|
-
align(:right,
|
114
|
+
def align_right(top: nil, bottom: nil, right: nil, left: nil)
|
115
|
+
align(:right, top: top, bottom: bottom, right: right, left: left)
|
65
116
|
end
|
66
117
|
|
67
118
|
# Aligns element (by default) on top of the scrollable container, if the element does not exists it raise an exception
|
119
|
+
# The element is aligned if the the distance from the top/bottom/right/left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
|
120
|
+
# If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
|
121
|
+
# The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
|
68
122
|
# @return [TestaAppiumDriver::Locator]
|
69
|
-
def align!(with = :top,
|
70
|
-
align(with,
|
123
|
+
def align!(with = :top, top: nil, bottom: nil, right: nil, left: nil)
|
124
|
+
align(with, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
|
71
125
|
end
|
72
126
|
|
73
127
|
# Aligns element on top of the scrollable container, if the element does not exists it raise an exception
|
128
|
+
# The element is aligned if the the distance from the top of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
|
129
|
+
# If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
|
130
|
+
# The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
|
74
131
|
# @return [TestaAppiumDriver::Locator]
|
75
|
-
def align_top!(
|
76
|
-
align(:top,
|
132
|
+
def align_top!(top: nil, bottom: nil, right: nil, left: nil)
|
133
|
+
align(:top, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
|
77
134
|
end
|
78
135
|
|
79
136
|
# Aligns element on bottom of the scrollable container, if the element does not exists it raise an exception
|
137
|
+
# The element is aligned if the the distance from the bottom of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
|
138
|
+
# If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
|
139
|
+
# The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
|
80
140
|
# @return [TestaAppiumDriver::Locator]
|
81
|
-
def align_bottom!(
|
82
|
-
align(:bottom,
|
141
|
+
def align_bottom!(top: nil, bottom: nil, right: nil, left: nil)
|
142
|
+
align(:bottom, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
|
83
143
|
end
|
84
144
|
|
85
145
|
# Aligns element on left of the scrollable container, if the element does not exists it raise an exception
|
146
|
+
# The element is aligned if the the distance from the left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
|
147
|
+
# If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
|
148
|
+
# The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
|
86
149
|
# @return [TestaAppiumDriver::Locator]
|
87
|
-
def align_left!(
|
88
|
-
align(:left,
|
150
|
+
def align_left!(top: nil, bottom: nil, right: nil, left: nil)
|
151
|
+
align(:left, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
|
89
152
|
end
|
90
153
|
|
91
154
|
# Aligns element on right of the scrollable container, if the element does not exists it raise an exception
|
155
|
+
# The element is aligned if the the distance from the right of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
|
156
|
+
# If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
|
157
|
+
# The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
|
92
158
|
# @return [TestaAppiumDriver::Locator]
|
93
|
-
def align_right!(
|
94
|
-
align(:right,
|
159
|
+
def align_right!(top: nil, bottom: nil, right: nil, left: nil)
|
160
|
+
align(:right, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
|
95
161
|
end
|
96
162
|
|
97
163
|
|
98
164
|
# First scrolls to the beginning of the scrollable container and then scrolls down until element is found or end is reached
|
99
165
|
# @return [TestaAppiumDriver::Locator]
|
100
|
-
def scroll_to(
|
166
|
+
def scroll_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil, direction: nil)
|
101
167
|
if direction
|
102
|
-
_scroll_dir_to(
|
168
|
+
_scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, direction)
|
103
169
|
else
|
104
|
-
_scroll_to(
|
170
|
+
_scroll_to(_process_deadzone(top, bottom, right, left), max_scrolls)
|
105
171
|
end
|
106
172
|
end
|
107
173
|
|
108
174
|
|
109
175
|
# Scrolls down until element is found or end is reached
|
110
176
|
# @return [TestaAppiumDriver::Locator]
|
111
|
-
def scroll_down_to(
|
112
|
-
_scroll_dir_to(
|
177
|
+
def scroll_down_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
|
178
|
+
_scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :down)
|
113
179
|
end
|
114
180
|
|
115
181
|
# Scrolls up until element is found or end is reached
|
116
182
|
# @return [TestaAppiumDriver::Locator]
|
117
|
-
def scroll_up_to(
|
118
|
-
_scroll_dir_to(
|
183
|
+
def scroll_up_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
|
184
|
+
_scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :up)
|
119
185
|
end
|
120
186
|
|
121
187
|
# Scrolls right until element is found or end is reached
|
122
188
|
# @return [TestaAppiumDriver::Locator]
|
123
|
-
def scroll_right_to(
|
124
|
-
_scroll_dir_to(
|
189
|
+
def scroll_right_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
|
190
|
+
_scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :right)
|
125
191
|
end
|
126
192
|
|
127
193
|
|
128
194
|
# Scrolls left until element is found or end is reached
|
129
195
|
# @return [TestaAppiumDriver::Locator]
|
130
|
-
def scroll_left_to(
|
131
|
-
_scroll_dir_to(
|
196
|
+
def scroll_left_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
|
197
|
+
_scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :left)
|
132
198
|
end
|
133
199
|
|
134
200
|
# Scrolls to the start of the scrollable container (top on vertical container, left on horizontal)
|
135
201
|
# @return [TestaAppiumDriver::Locator]
|
136
|
-
def scroll_to_start(
|
137
|
-
_scroll_to_start_or_end(:start,
|
202
|
+
def scroll_to_start(top: nil, bottom: nil, right: nil, left: nil)
|
203
|
+
_scroll_to_start_or_end(:start, _process_deadzone(top, bottom, right, left))
|
138
204
|
end
|
139
205
|
|
140
206
|
# Scrolls to the end of the scrollable container (bottom on vertical container, right on horizontal)
|
141
207
|
# @return [TestaAppiumDriver::Locator]
|
142
|
-
def scroll_to_end(
|
143
|
-
_scroll_to_start_or_end(:end,
|
208
|
+
def scroll_to_end(top: nil, bottom: nil, right: nil, left: nil)
|
209
|
+
_scroll_to_start_or_end(:end, _process_deadzone(top, bottom, right, left))
|
144
210
|
end
|
145
211
|
|
146
212
|
|
147
213
|
# @return [TestaAppiumDriver::Locator]
|
148
|
-
def page_down(
|
149
|
-
_page(:down,
|
214
|
+
def page_down(top: nil, bottom: nil, right: nil, left: nil)
|
215
|
+
_page(:down, _process_deadzone(top, bottom, right, left))
|
150
216
|
end
|
151
217
|
|
152
218
|
# @return [TestaAppiumDriver::Locator]
|
153
|
-
def page_up(
|
154
|
-
_page(:up,
|
219
|
+
def page_up(top: nil, bottom: nil, right: nil, left: nil)
|
220
|
+
_page(:up, _process_deadzone(top, bottom, right, left))
|
155
221
|
end
|
156
222
|
|
157
223
|
# @return [TestaAppiumDriver::Locator]
|
158
|
-
def page_left(
|
159
|
-
_page(:left,
|
224
|
+
def page_left(top: nil, bottom: nil, right: nil, left: nil)
|
225
|
+
_page(:left, _process_deadzone(top, bottom, right, left))
|
160
226
|
end
|
161
227
|
|
162
228
|
# @return [TestaAppiumDriver::Locator]
|
163
|
-
def page_right(
|
164
|
-
_page(:right,
|
229
|
+
def page_right(top: nil, bottom: nil, right: nil, left: nil)
|
230
|
+
_page(:right, _process_deadzone(top, bottom, right, left))
|
165
231
|
end
|
166
232
|
|
167
233
|
# @return [TestaAppiumDriver::Locator]
|
168
|
-
def fling_down(
|
169
|
-
_fling(:down,
|
234
|
+
def fling_down(top: nil, bottom: nil, right: nil, left: nil)
|
235
|
+
_fling(:down, _process_deadzone(top, bottom, right, left))
|
170
236
|
end
|
171
237
|
|
172
238
|
# @return [TestaAppiumDriver::Locator]
|
173
|
-
def fling_up(
|
174
|
-
_fling(:up,
|
239
|
+
def fling_up(top: nil, bottom: nil, right: nil, left: nil)
|
240
|
+
_fling(:up, _process_deadzone(top, bottom, right, left))
|
175
241
|
end
|
176
242
|
|
177
243
|
# @return [TestaAppiumDriver::Locator]
|
178
|
-
def fling_left(
|
179
|
-
_fling(:left,
|
244
|
+
def fling_left(top: nil, bottom: nil, right: nil, left: nil)
|
245
|
+
_fling(:left, _process_deadzone(top, bottom, right, left))
|
180
246
|
end
|
181
247
|
|
182
248
|
# @return [TestaAppiumDriver::Locator]
|
183
|
-
def fling_right(
|
184
|
-
_fling(:right,
|
249
|
+
def fling_right(top: nil, bottom: nil, right: nil, left: nil)
|
250
|
+
_fling(:right, _process_deadzone(top, bottom, right, left))
|
251
|
+
end
|
252
|
+
|
253
|
+
def drag_up_by(amount)
|
254
|
+
drag_by(amount, direction: :top)
|
255
|
+
end
|
256
|
+
|
257
|
+
def drag_down_by(amount)
|
258
|
+
drag_by(amount, direction: :bottom)
|
259
|
+
end
|
260
|
+
|
261
|
+
def drag_left_by(amount)
|
262
|
+
drag_by(amount, direction: :left)
|
263
|
+
end
|
264
|
+
|
265
|
+
def drag_right_by(amount)
|
266
|
+
drag_by(amount, direction: :right)
|
185
267
|
end
|
186
268
|
|
187
269
|
|
@@ -232,6 +314,18 @@ module TestaAppiumDriver
|
|
232
314
|
|
233
315
|
|
234
316
|
private
|
317
|
+
def _process_deadzone(top, bottom, right, left)
|
318
|
+
deadzone = nil
|
319
|
+
if !top.nil? || !bottom.nil? || !right.nil? || !left.nil?
|
320
|
+
deadzone = {}
|
321
|
+
deadzone[:top] = top unless top.nil?
|
322
|
+
deadzone[:bottom] = bottom unless bottom.nil?
|
323
|
+
deadzone[:right] = right unless right.nil?
|
324
|
+
deadzone[:left] = left unless left.nil?
|
325
|
+
end
|
326
|
+
deadzone
|
327
|
+
end
|
328
|
+
|
235
329
|
def _drag_to(x, y)
|
236
330
|
sa = ScrollActions.new(@scrollable_locator,
|
237
331
|
locator: self,
|
@@ -239,6 +333,8 @@ module TestaAppiumDriver
|
|
239
333
|
sa.drag_to(x, y)
|
240
334
|
self
|
241
335
|
end
|
336
|
+
|
337
|
+
|
242
338
|
def _page(direction, deadzone)
|
243
339
|
deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
|
244
340
|
sa = ScrollActions.new(@scrollable_locator,
|
@@ -266,7 +362,6 @@ module TestaAppiumDriver
|
|
266
362
|
sa = ScrollActions.new(@scrollable_locator,
|
267
363
|
locator: self,
|
268
364
|
deadzone: deadzone,
|
269
|
-
direction: :left,
|
270
365
|
default_scroll_strategy: @default_scroll_strategy)
|
271
366
|
if type == :start
|
272
367
|
sa.scroll_to_start
|
@@ -293,7 +388,6 @@ module TestaAppiumDriver
|
|
293
388
|
locator: self,
|
294
389
|
deadzone: deadzone,
|
295
390
|
max_scrolls: max_scrolls,
|
296
|
-
direction: direction,
|
297
391
|
default_scroll_strategy: @default_scroll_strategy)
|
298
392
|
|
299
393
|
sa.send("scroll_#{direction}_to")
|
@@ -17,6 +17,8 @@ module TestaAppiumDriver
|
|
17
17
|
attr_accessor :last_selector_adjacent
|
18
18
|
attr_accessor :can_use_id_strategy
|
19
19
|
|
20
|
+
attr_accessor :image_selector
|
21
|
+
|
20
22
|
attr_accessor :from_element
|
21
23
|
attr_accessor :scroll_orientation
|
22
24
|
attr_accessor :scroll_deadzone
|
@@ -25,6 +27,8 @@ module TestaAppiumDriver
|
|
25
27
|
attr_accessor :default_find_strategy
|
26
28
|
attr_accessor :default_scroll_strategy
|
27
29
|
|
30
|
+
attr_accessor :index_for_multiple
|
31
|
+
|
28
32
|
|
29
33
|
# locator parameters are:
|
30
34
|
# single: true or false
|
@@ -38,12 +42,22 @@ module TestaAppiumDriver
|
|
38
42
|
def initialize(driver, from_element, params = {})
|
39
43
|
# @type [TestaAppiumDriver::Driver]
|
40
44
|
@driver = driver
|
45
|
+
@index_for_multiple = nil
|
46
|
+
@image_selector = nil
|
41
47
|
|
42
48
|
params, selectors = extract_selectors_from_params(params)
|
43
49
|
single = params[:single]
|
44
50
|
|
45
51
|
@single = single
|
46
52
|
|
53
|
+
if selectors[:image].nil?
|
54
|
+
if from_element.instance_of?(TestaAppiumDriver::Locator) && !from_element.image_selector.nil?
|
55
|
+
raise "Cannot chain non-image selectors to image selectors"
|
56
|
+
end
|
57
|
+
else
|
58
|
+
handle_image_selector(selectors, params)
|
59
|
+
end
|
60
|
+
|
47
61
|
selectors[:id] = selectors[:name] unless selectors[:name].nil?
|
48
62
|
if from_element.instance_of?(Selenium::WebDriver::Element)
|
49
63
|
@xpath_selector = "//*" # to select current element
|
@@ -57,7 +71,8 @@ module TestaAppiumDriver
|
|
57
71
|
@default_find_strategy = params[:default_find_strategy]
|
58
72
|
@default_scroll_strategy = params[:default_scroll_strategy]
|
59
73
|
|
60
|
-
|
74
|
+
|
75
|
+
@can_use_id_strategy = is_only_id_selector?(selectors)
|
61
76
|
if @can_use_id_strategy
|
62
77
|
if @driver.device == :android
|
63
78
|
@can_use_id_strategy = resolve_id(selectors[:id])
|
@@ -76,32 +91,70 @@ module TestaAppiumDriver
|
|
76
91
|
end
|
77
92
|
|
78
93
|
|
94
|
+
|
95
|
+
|
96
|
+
def is_only_id_selector?(selectors)
|
97
|
+
# since, name and id is the same thing for iOS,
|
98
|
+
if @driver.device == :android
|
99
|
+
selectors.keys.count == 1 && !selectors[:id].nil?
|
100
|
+
else
|
101
|
+
# if it iOS we assign the name to id
|
102
|
+
selectors.keys.count == 2 && !selectors[:id].nil? && selectors[:id] == selectors[:name]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
|
79
107
|
# method missing is used to fetch the element before executing additional commands like click, send_key, count
|
80
108
|
def method_missing(method, *args, &block)
|
81
|
-
execute.send(method, *args, &block)
|
109
|
+
r = execute.send(method, *args, &block)
|
110
|
+
@driver.invalidate_cache
|
111
|
+
r
|
82
112
|
end
|
83
113
|
|
84
114
|
|
85
115
|
# @param [Boolean] skip_cache if true it will skip cache check and store
|
86
116
|
# @param [Selenium::WebDriver::Element] force_cache_element, for internal use where we have already the element, and want to execute custom locator methods on it
|
87
117
|
# @return [Selenium::WebDriver::Element, Array]
|
88
|
-
def execute(skip_cache: false, force_cache_element: nil)
|
118
|
+
def execute(skip_cache: false, force_cache_element: nil, ignore_implicit_wait: false)
|
89
119
|
return force_cache_element unless force_cache_element.nil?
|
90
120
|
# if we are looking for current element, then return from_element
|
91
121
|
# for example when we have driver.element.elements[1].click
|
92
122
|
# elements[2] will be resolved with xpath because we are looking for multiple elements from element
|
93
123
|
# and since we are looking for instance 2, [](instance) method will return new "empty locator"
|
94
124
|
# we are executing click on that "empty locator" so we have to return the instance 2 of elements for the click
|
95
|
-
if @xpath_selector == "
|
125
|
+
if @xpath_selector == "//*[1]" && !@from_element.nil? && @image_selector.nil?
|
126
|
+
return @from_element if @from_element.instance_of?(Selenium::WebDriver::Element)
|
127
|
+
return @from_element.execute(skip_cache: skip_cache, force_cache_element: force_cache_element, ignore_implicit_wait: ignore_implicit_wait) if @from_element.instance_of?(TestaAppiumDriver::Locator)
|
96
128
|
return @from_element
|
97
129
|
end
|
98
130
|
|
99
131
|
|
100
132
|
|
101
|
-
strategy, selector = strategy_and_selector
|
102
133
|
|
103
134
|
|
104
|
-
|
135
|
+
|
136
|
+
r = @driver.execute(@from_element, @single, strategies_and_selectors, skip_cache, ignore_implicit_wait)
|
137
|
+
r = r[@index_for_multiple] if !@index_for_multiple.nil? && !@single
|
138
|
+
r
|
139
|
+
end
|
140
|
+
|
141
|
+
def when_exists(timeout = nil, &block)
|
142
|
+
timeout = @driver.get_timeouts["implicit"] / 1000 if timeout.nil?
|
143
|
+
found = false
|
144
|
+
begin
|
145
|
+
wait_until_exists(timeout)
|
146
|
+
found = true
|
147
|
+
rescue
|
148
|
+
#ignored
|
149
|
+
end
|
150
|
+
if found
|
151
|
+
if block_given? # block is given
|
152
|
+
block.call(self) # use call to execute the block
|
153
|
+
else # the value of block_argument becomes nil if you didn't give a block
|
154
|
+
# block was not given
|
155
|
+
end
|
156
|
+
end
|
157
|
+
self
|
105
158
|
end
|
106
159
|
|
107
160
|
|
@@ -109,12 +162,8 @@ module TestaAppiumDriver
|
|
109
162
|
# @return [TestaAppiumDriver::Locator]
|
110
163
|
def wait_until_exists(timeout = nil)
|
111
164
|
timeout = @driver.get_timeouts["implicit"] / 1000 if timeout.nil?
|
112
|
-
|
113
|
-
until
|
114
|
-
raise "wait until exists timeout exceeded" if start_time + timeout < Time.now.to_f
|
115
|
-
sleep EXISTS_WAIT
|
116
|
-
end
|
117
|
-
self
|
165
|
+
args = {timeout: timeout}
|
166
|
+
_wait(:until, args)
|
118
167
|
end
|
119
168
|
|
120
169
|
|
@@ -122,28 +171,31 @@ module TestaAppiumDriver
|
|
122
171
|
# @return [TestaAppiumDriver::Locator]
|
123
172
|
def wait_while_exists(timeout = nil)
|
124
173
|
timeout = @driver.get_timeouts["implicit"] / 1000 if timeout.nil?
|
125
|
-
|
126
|
-
while
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
174
|
+
args = {timeout: timeout}
|
175
|
+
_wait(:while, args)
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
def wait_while(timeout = nil, args = {})
|
180
|
+
args[:timeout] = timeout
|
181
|
+
_wait(:while, args)
|
182
|
+
end
|
183
|
+
|
184
|
+
def wait_until(timeout = nil, args = {})
|
185
|
+
args[:timeout] = timeout
|
186
|
+
_wait(:until, args)
|
131
187
|
end
|
132
188
|
|
133
189
|
|
134
190
|
# all timeouts are disabled before check, and enabled after check
|
135
191
|
# @return [boolean] true if it exists in the page regardless if visible or not
|
136
192
|
def exists?
|
137
|
-
@driver.disable_wait_for_idle
|
138
|
-
@driver.disable_implicit_wait
|
139
193
|
found = true
|
140
194
|
begin
|
141
|
-
execute(skip_cache: true)
|
195
|
+
execute(skip_cache: true, ignore_implicit_wait: true)
|
142
196
|
rescue StandardError
|
143
197
|
found = false
|
144
198
|
end
|
145
|
-
@driver.enable_implicit_wait
|
146
|
-
@driver.enable_wait_for_idle
|
147
199
|
found
|
148
200
|
end
|
149
201
|
|
@@ -177,7 +229,8 @@ module TestaAppiumDriver
|
|
177
229
|
locator.can_use_id_strategy = false
|
178
230
|
locator
|
179
231
|
else
|
180
|
-
from_element = self.
|
232
|
+
from_element = self.dup
|
233
|
+
from_element.index_for_multiple = instance
|
181
234
|
params = {}.merge({single: true, scrollable_locator: @scrollable_locator})
|
182
235
|
#params[:strategy] = FIND_STRATEGY_XPATH
|
183
236
|
#params[:strategy_reason] = "retrieved instance of a array"
|
@@ -214,7 +267,8 @@ module TestaAppiumDriver
|
|
214
267
|
xpath: @xpath_selector,
|
215
268
|
scrollable: @scrollable_locator.nil? ? nil : @scrollable_locator.to_s,
|
216
269
|
scroll_orientation: @scroll_orientation,
|
217
|
-
resolved:
|
270
|
+
resolved: strategies_and_selectors,
|
271
|
+
index_for_multiple: @index_for_multiple
|
218
272
|
}
|
219
273
|
end
|
220
274
|
|
@@ -399,6 +453,51 @@ module TestaAppiumDriver
|
|
399
453
|
|
400
454
|
private
|
401
455
|
|
456
|
+
def _wait(type, args)
|
457
|
+
interval = EXISTS_WAIT
|
458
|
+
interval = args[:interval] unless args[:interval].nil?
|
459
|
+
|
460
|
+
message = "wait #{type} exists timeout exceeded"
|
461
|
+
message = args[:message] unless args[:message].nil?
|
462
|
+
|
463
|
+
if args[:timeout].nil?
|
464
|
+
timeout = @driver.get_timeouts["implicit"] / 1000
|
465
|
+
else
|
466
|
+
timeout = args[:timeout]
|
467
|
+
end
|
468
|
+
|
469
|
+
args.delete(:message)
|
470
|
+
args.delete(:interval)
|
471
|
+
args.delete(:timeout)
|
472
|
+
|
473
|
+
|
474
|
+
|
475
|
+
start_time = Time.now.to_f
|
476
|
+
if type == :while
|
477
|
+
while exists? && _attributes_match(args)
|
478
|
+
raise message if start_time + timeout < Time.now.to_f
|
479
|
+
sleep interval
|
480
|
+
end
|
481
|
+
else
|
482
|
+
until exists? && _attributes_match(args)
|
483
|
+
raise message if start_time + timeout < Time.now.to_f
|
484
|
+
sleep interval
|
485
|
+
end
|
486
|
+
end
|
487
|
+
self
|
488
|
+
end
|
489
|
+
|
490
|
+
def _attributes_match(attributes)
|
491
|
+
all_match = true
|
492
|
+
attributes.each do |key, value|
|
493
|
+
unless attribute(key) == value
|
494
|
+
all_match = false
|
495
|
+
break
|
496
|
+
end
|
497
|
+
end
|
498
|
+
all_match
|
499
|
+
end
|
500
|
+
|
402
501
|
#noinspection RubyNilAnalysis
|
403
502
|
def perform_driver_method(name, *args)
|
404
503
|
elements = execute
|
@@ -413,6 +512,42 @@ module TestaAppiumDriver
|
|
413
512
|
locator.single = false unless single # switching from single result to multiple
|
414
513
|
locator.xpath_selector += hash_to_xpath(@driver.device, selectors, single)
|
415
514
|
end
|
515
|
+
|
516
|
+
|
517
|
+
def handle_image_selector(selectors, params)
|
518
|
+
image_match_threshold = 0.4
|
519
|
+
image_match_threshold = params[:imageMatchThreshold] unless params[:imageMatchThreshold].nil?
|
520
|
+
image_match_threshold = params[:threshold] unless params[:threshold].nil?
|
521
|
+
fix_image_find_screenshot_dims = true
|
522
|
+
fix_image_find_screenshot_dims = params[:fixImageFindScreenshotDims] unless params[:fixImageFindScreenshotDims].nil?
|
523
|
+
fix_image_template_size = false
|
524
|
+
fix_image_template_size = params[:fixImageTemplateSize] unless params[:fixImageTemplateSize].nil?
|
525
|
+
fix_image_template_scale = false
|
526
|
+
fix_image_template_scale = params[:fixImageTemplateScale] unless params[:fixImageTemplateScale].nil?
|
527
|
+
default_image_template_scale = 1.0
|
528
|
+
default_image_template_scale = params[:defaultImageTemplateScale] unless params[:defaultImageTemplateScale].nil?
|
529
|
+
check_for_image_element_staleness = true
|
530
|
+
check_for_image_element_staleness = params[:checkForImageElementStaleness] unless params[:checkForImageElementStaleness].nil?
|
531
|
+
auto_update_image_element_position = false
|
532
|
+
auto_update_image_element_position = params[:autoUpdateImageElementPosition] unless params[:autoUpdateImageElementPosition].nil?
|
533
|
+
image_element_tap_strategy = "w3cActions"
|
534
|
+
image_element_tap_strategy = params[:imageElementTapStrategy] unless params[:imageElementTapStrategy].nil?
|
535
|
+
get_matched_image_result = false
|
536
|
+
get_matched_image_result = params[:getMatchedImageResult] unless params[:getMatchedImageResult].nil?
|
537
|
+
|
538
|
+
@image_selector = {
|
539
|
+
image: selectors[:image],
|
540
|
+
imageMatchThreshold: image_match_threshold,
|
541
|
+
fixImageFindScreenshotDims: fix_image_find_screenshot_dims,
|
542
|
+
fixImageTemplateSize: fix_image_template_size,
|
543
|
+
fixImageTemplateScale: fix_image_template_scale,
|
544
|
+
defaultImageTemplateScale: default_image_template_scale,
|
545
|
+
checkForImageElementStaleness: check_for_image_element_staleness,
|
546
|
+
autoUpdateImageElementPosition: auto_update_image_element_position,
|
547
|
+
imageElementTapStrategy: image_element_tap_strategy,
|
548
|
+
getMatchedImageResult: get_matched_image_result,
|
549
|
+
}
|
550
|
+
end
|
416
551
|
end
|
417
552
|
|
418
553
|
end
|