testcentricity_mobile 4.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 +7 -0
- data/.yardopts +3 -0
- data/CHANGELOG.md +105 -0
- data/LICENSE.md +27 -0
- data/README.md +1795 -0
- data/lib/testcentricity_mobile/app_core/appium_connect_helper.rb +634 -0
- data/lib/testcentricity_mobile/app_core/screen_object.rb +413 -0
- data/lib/testcentricity_mobile/app_core/screen_objects_helper.rb +183 -0
- data/lib/testcentricity_mobile/app_core/screen_section.rb +607 -0
- data/lib/testcentricity_mobile/app_elements/alert.rb +152 -0
- data/lib/testcentricity_mobile/app_elements/app_element.rb +692 -0
- data/lib/testcentricity_mobile/app_elements/button.rb +10 -0
- data/lib/testcentricity_mobile/app_elements/checkbox.rb +56 -0
- data/lib/testcentricity_mobile/app_elements/image.rb +10 -0
- data/lib/testcentricity_mobile/app_elements/label.rb +10 -0
- data/lib/testcentricity_mobile/app_elements/list.rb +175 -0
- data/lib/testcentricity_mobile/app_elements/switch.rb +66 -0
- data/lib/testcentricity_mobile/app_elements/textfield.rb +51 -0
- data/lib/testcentricity_mobile/appium_server.rb +71 -0
- data/lib/testcentricity_mobile/data_objects/data_objects_helper.rb +100 -0
- data/lib/testcentricity_mobile/data_objects/environment.rb +416 -0
- data/lib/testcentricity_mobile/exception_queue_helper.rb +160 -0
- data/lib/testcentricity_mobile/utility_helpers.rb +48 -0
- data/lib/testcentricity_mobile/version.rb +3 -0
- data/lib/testcentricity_mobile/world_extensions.rb +61 -0
- data/lib/testcentricity_mobile.rb +99 -0
- metadata +317 -0
@@ -0,0 +1,607 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
module TestCentricity
|
4
|
+
class ScreenSection < BaseScreenSectionObject
|
5
|
+
include Test::Unit::Assertions
|
6
|
+
|
7
|
+
attr_reader :context, :name
|
8
|
+
attr_accessor :locator
|
9
|
+
attr_accessor :parent
|
10
|
+
attr_accessor :parent_list
|
11
|
+
attr_accessor :list_index
|
12
|
+
|
13
|
+
def initialize(name, parent, locator, context)
|
14
|
+
@name = name
|
15
|
+
@parent = parent
|
16
|
+
@locator = locator
|
17
|
+
@context = context
|
18
|
+
@parent_list = nil
|
19
|
+
@list_index = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_locator
|
23
|
+
if @locator.zero? && defined?(section_locator)
|
24
|
+
my_locator = section_locator
|
25
|
+
else
|
26
|
+
my_locator = @locator
|
27
|
+
end
|
28
|
+
locators = []
|
29
|
+
if @context == :section && !@parent.nil?
|
30
|
+
locators.push(@parent.get_locator)
|
31
|
+
end
|
32
|
+
|
33
|
+
if @parent_list.nil?
|
34
|
+
locators.push(my_locator)
|
35
|
+
else
|
36
|
+
locators.push(@parent_list.get_locator)
|
37
|
+
if @list_index.nil?
|
38
|
+
locators.push(my_locator)
|
39
|
+
else
|
40
|
+
item_objects = @parent_list.item_refs
|
41
|
+
if item_objects.nil?
|
42
|
+
list_key = my_locator.keys[0]
|
43
|
+
list_value = "#{my_locator.values[0]}[#{@list_index}]"
|
44
|
+
else
|
45
|
+
list_key = :object
|
46
|
+
list_value = item_objects[@list_index - 1]
|
47
|
+
end
|
48
|
+
locators.push( { list_key => list_value } )
|
49
|
+
end
|
50
|
+
end
|
51
|
+
locators
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_list_index(list, index = 1)
|
55
|
+
@parent_list = list unless list.nil?
|
56
|
+
@list_index = index
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_item_count
|
60
|
+
raise 'No parent list defined' if @parent_list.nil?
|
61
|
+
@parent_list.get_item_count
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_list_items
|
65
|
+
items = []
|
66
|
+
(1..get_item_count).each do |item|
|
67
|
+
set_list_index(nil, item)
|
68
|
+
begin
|
69
|
+
items.push(get_value)
|
70
|
+
rescue
|
71
|
+
scroll_into_view(@parent_list.scroll_mode)
|
72
|
+
items.push(get_value)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
items
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_object_type
|
79
|
+
:section
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_name
|
83
|
+
@name
|
84
|
+
end
|
85
|
+
|
86
|
+
def set_parent(parent)
|
87
|
+
@parent = parent
|
88
|
+
end
|
89
|
+
|
90
|
+
# Declare and instantiate a single generic UI Element for this screen section object.
|
91
|
+
#
|
92
|
+
# @param element_name [Symbol] name of UI object (as a symbol)
|
93
|
+
# @param locator [Hash] { locator_strategy: locator_identifier }
|
94
|
+
# The locator_strategy (a Symbol) specifies the selector strategy that Appium will use to find the UI element. Valid
|
95
|
+
# selectors are accessibility_id:, id:, name:, class:, xpath:, predicate: (iOS only), class_chain: (iOS only), and
|
96
|
+
# css: (WebViews in hybrid apps only).
|
97
|
+
# * The locator_identifier (a String) is the value or attribute that uniquely and unambiguously identifies the UI element.
|
98
|
+
#
|
99
|
+
# @example
|
100
|
+
# element :video_player, { accessibility_id: 'YouTube Video Player' }
|
101
|
+
#
|
102
|
+
def self.element(element_name, locator)
|
103
|
+
define_section_element(element_name, TestCentricity::AppElements::AppUIElement, locator)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Declare and instantiate a collection of generic UI Elements for this screen section object.
|
107
|
+
#
|
108
|
+
# @param element_hash [Hash] names of UI objects (as a Symbol) and locator Hash
|
109
|
+
# @example
|
110
|
+
# elements drop_down_field: { accessibility_id: 'drop_trigger' },
|
111
|
+
# settings_item: { accessibility_id: 'settings' },
|
112
|
+
# log_out_item: { accessibility_id: 'logout' }
|
113
|
+
#
|
114
|
+
def self.elements(element_hash)
|
115
|
+
element_hash.each_pair { |element_name, locator| element(element_name, locator) }
|
116
|
+
end
|
117
|
+
|
118
|
+
# Declare and instantiate a single button UI Element for this screen section object.
|
119
|
+
#
|
120
|
+
# @param element_name [Symbol] name of button object (as a symbol)
|
121
|
+
# @param locator [Hash] { locator_strategy: locator_identifier }
|
122
|
+
# @example
|
123
|
+
# button :video_play, { accessibility_id: 'video icon play' }
|
124
|
+
#
|
125
|
+
def self.button(element_name, locator)
|
126
|
+
define_section_element(element_name, TestCentricity::AppElements::AppButton, locator)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Declare and instantiate a collection of buttons for this screen section object.
|
130
|
+
#
|
131
|
+
# @param element_hash [Hash] names of buttons (as symbol) and locator Hash
|
132
|
+
# @example
|
133
|
+
# buttons video_back: { accessibility_id: 'video icon backward' },
|
134
|
+
# video_play: { accessibility_id: 'video icon play' },
|
135
|
+
# video_pause: { accessibility_id: 'video icon stop' },
|
136
|
+
# video_forward: { accessibility_id: 'video icon forward' }
|
137
|
+
#
|
138
|
+
def self.buttons(element_hash)
|
139
|
+
element_hash.each_pair { |element_name, locator| button(element_name, locator) }
|
140
|
+
end
|
141
|
+
|
142
|
+
# Declare and instantiate a single textfield UI Element for this screen section object.
|
143
|
+
#
|
144
|
+
# @param element_name [Symbol] name of textfield object (as a symbol)
|
145
|
+
# @param locator [Hash] { locator_strategy: locator_identifier }
|
146
|
+
# @example
|
147
|
+
# textfield :payee_name_field, { xpath: '//android.widget.EditText[@content-desc="Full Name* input field"]' }
|
148
|
+
# textfield :payee_name_field, { xpath: '//XCUIElementTypeTextField[@name="Full Name* input field"]' }
|
149
|
+
#
|
150
|
+
def self.textfield(element_name, locator)
|
151
|
+
define_section_element(element_name, TestCentricity::AppElements::AppTextField, locator)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Declare and instantiate a collection of textfields for this screen section object.
|
155
|
+
#
|
156
|
+
# @param element_hash [Hash] names of textfields (as symbol) and locator Hash
|
157
|
+
# @example
|
158
|
+
# textfields username_field: { accessibility_id: 'Username input field' },
|
159
|
+
# password_field: { accessibility_id: 'Password input field' }
|
160
|
+
#
|
161
|
+
def self.textfields(element_hash)
|
162
|
+
element_hash.each_pair { |element_name, locator| textfield(element_name, locator) }
|
163
|
+
end
|
164
|
+
|
165
|
+
# Declare and instantiate a single switch UI Element for this screen section object.
|
166
|
+
#
|
167
|
+
# @param element_name [Symbol] name of switch object (as a symbol)
|
168
|
+
# @param locator [Hash] { locator_strategy: locator_identifier }
|
169
|
+
# @example
|
170
|
+
# switch :debug_mode_switch, { accessibility_id: 'debug mode' }
|
171
|
+
#
|
172
|
+
def self.switch(element_name, locator)
|
173
|
+
define_section_element(element_name, TestCentricity::AppElements::AppSwitch, locator)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Declare and instantiate a collection of switches for this screen section object.
|
177
|
+
#
|
178
|
+
# @param element_hash [Hash] names of switches (as symbol) and locator Hash
|
179
|
+
# @example
|
180
|
+
# switches debug_mode_switch: { accessibility_id: 'debug mode' },
|
181
|
+
# metrics_switch: { accessibility_id: 'metrics' }
|
182
|
+
#
|
183
|
+
def self.switches(element_hash)
|
184
|
+
element_hash.each_pair { |element_name, locator| switch(element_name, locator) }
|
185
|
+
end
|
186
|
+
|
187
|
+
# Declare and instantiate a single checkbox UI Element for this screen section object.
|
188
|
+
#
|
189
|
+
# @param element_name [Symbol] name of checkbox object (as a symbol)
|
190
|
+
# @param locator [Hash] { locator_strategy: locator_identifier }
|
191
|
+
# @example
|
192
|
+
# checkbox :bill_address_check, { xpath: '//XCUIElementTypeOther[contains(@name, "billing checkbox")]'}
|
193
|
+
#
|
194
|
+
def self.checkbox(element_name, locator)
|
195
|
+
define_section_element(element_name, TestCentricity::AppElements::AppCheckBox, locator)
|
196
|
+
end
|
197
|
+
|
198
|
+
# Declare and instantiate a collection of checkboxes for this screen section object.
|
199
|
+
#
|
200
|
+
# @param element_hash [Hash] names of checkboxes (as symbol) and locator Hash
|
201
|
+
# @example
|
202
|
+
# checkboxes bill_address_check: { xpath: '//XCUIElementTypeOther[contains(@name, "billing checkbox")]'},
|
203
|
+
# is_gift_check: { accessibility_id: 'is a gift' }
|
204
|
+
#
|
205
|
+
def self.checkboxes(element_hash)
|
206
|
+
element_hash.each_pair { |element_name, locator| checkbox(element_name, locator) }
|
207
|
+
end
|
208
|
+
|
209
|
+
# Declare and instantiate a single label UI Element for this screen section object.
|
210
|
+
#
|
211
|
+
# @param element_name [Symbol] name of label object (as a symbol)
|
212
|
+
# @param locator [Hash] { locator_strategy: locator_identifier }
|
213
|
+
# @example
|
214
|
+
# label :header_label, { accessibility_id: 'container header' }
|
215
|
+
#
|
216
|
+
def self.label(element_name, locator)
|
217
|
+
define_section_element(element_name, TestCentricity::AppElements::AppLabel, locator)
|
218
|
+
end
|
219
|
+
|
220
|
+
# Declare and instantiate a collection of labels for this screen section object.
|
221
|
+
#
|
222
|
+
# @param element_hash [Hash] names of labels (as symbol) and locator Hash
|
223
|
+
# @example
|
224
|
+
# labels total_qty_value: { accessibility_id: 'total number' },
|
225
|
+
# total_price_value: { accessibility_id: 'total price' }
|
226
|
+
#
|
227
|
+
def self.labels(element_hash)
|
228
|
+
element_hash.each_pair { |element_name, locator| label(element_name, locator) }
|
229
|
+
end
|
230
|
+
|
231
|
+
# Declare and instantiate a single list UI Element for this screen section object.
|
232
|
+
#
|
233
|
+
# @param element_name [Symbol] name of list object (as a symbol)
|
234
|
+
# @param locator [Hash] { locator_strategy: locator_identifier }
|
235
|
+
# @example
|
236
|
+
# list :carousel_list, { accessibility_id: 'Carousel' }
|
237
|
+
#
|
238
|
+
def self.list(element_name, locator)
|
239
|
+
define_section_element(element_name, TestCentricity::AppElements::AppList, locator)
|
240
|
+
end
|
241
|
+
|
242
|
+
# Declare and instantiate a collection of lists for this screen section object.
|
243
|
+
#
|
244
|
+
# @param element_hash [Hash] names of lists (as symbol) and locator Hash
|
245
|
+
# @example
|
246
|
+
# lists product_grid: { xpath: '//android.widget.ScrollView/android.view.ViewGroup' },
|
247
|
+
# cart_list: { xpath: '//android.widget.ScrollView[@content-desc="cart screen"]' }
|
248
|
+
#
|
249
|
+
def self.lists(element_hash)
|
250
|
+
element_hash.each_pair { |element_name, locator| list(element_name, locator) }
|
251
|
+
end
|
252
|
+
|
253
|
+
# Declare and instantiate a single image UI Element for this screen section object.
|
254
|
+
#
|
255
|
+
# @param element_name [Symbol] name of image object (as a symbol)
|
256
|
+
# @param locator [Hash] { locator_strategy: locator_identifier }
|
257
|
+
# @example
|
258
|
+
# image :product_image, { xpath: '//XCUIElementTypeImage' }
|
259
|
+
#
|
260
|
+
def self.image(element_name, locator)
|
261
|
+
define_section_element(element_name, TestCentricity::AppElements::AppImage, locator)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Declare and instantiate a collection of images for this screen section object.
|
265
|
+
#
|
266
|
+
# @param element_hash [Hash] names of images (as symbol) and locator Hash
|
267
|
+
# @example
|
268
|
+
# images empty_cart_image: { accessibility_id: 'empty_cart' },
|
269
|
+
# logo_image: { accessibility_id: 'WebdriverIO logo' }
|
270
|
+
#
|
271
|
+
def self.images(element_hash)
|
272
|
+
element_hash.each_pair { |element_name, locator| image(element_name, locator) }
|
273
|
+
end
|
274
|
+
|
275
|
+
# Instantiate a single ScreenSection object within this ScreenSection object.
|
276
|
+
#
|
277
|
+
# @param section_name [Symbol] name of ScreenSection object (as a symbol)
|
278
|
+
# @param class_name [Class] Class name of ScreenSection object
|
279
|
+
# @example
|
280
|
+
# section :nav_menu, NavMenu
|
281
|
+
#
|
282
|
+
def self.section(section_name, obj, locator = 0)
|
283
|
+
define_section_element(section_name, obj, locator)
|
284
|
+
end
|
285
|
+
|
286
|
+
# Declare and instantiate a collection of ScreenSection objects for this ScreenSection object.
|
287
|
+
#
|
288
|
+
# @param element_hash [Hash] names of ScreenSections (as symbol) and class name
|
289
|
+
# @example
|
290
|
+
# sections product_grid_item: ProductGridItem,
|
291
|
+
# sort_by_menu: SortByMenu
|
292
|
+
#
|
293
|
+
def self.sections(section_hash)
|
294
|
+
section_hash.each_pair { |section_name, class_name| section(section_name, class_name) }
|
295
|
+
end
|
296
|
+
|
297
|
+
# Click on a screen Section object
|
298
|
+
#
|
299
|
+
# @example
|
300
|
+
# bar_chart_section.click
|
301
|
+
#
|
302
|
+
def click
|
303
|
+
section = find_section
|
304
|
+
section_not_found_exception(section)
|
305
|
+
section.click
|
306
|
+
end
|
307
|
+
|
308
|
+
# Tap on a screen Section object
|
309
|
+
#
|
310
|
+
# @example
|
311
|
+
# bar_chart_section.tap
|
312
|
+
#
|
313
|
+
def tap
|
314
|
+
section = find_section
|
315
|
+
section_not_found_exception(section)
|
316
|
+
driver.action
|
317
|
+
.click_and_hold(section)
|
318
|
+
.release
|
319
|
+
.perform
|
320
|
+
end
|
321
|
+
|
322
|
+
# Double-tap on a screen Section object
|
323
|
+
#
|
324
|
+
# @example
|
325
|
+
# bar_chart_section.double_tap
|
326
|
+
#
|
327
|
+
def double_tap
|
328
|
+
section = find_section
|
329
|
+
section_not_found_exception(section)
|
330
|
+
driver.action
|
331
|
+
.click_and_hold(section)
|
332
|
+
.release
|
333
|
+
.pause(duration: 0.2)
|
334
|
+
.click_and_hold(section)
|
335
|
+
.release
|
336
|
+
.perform
|
337
|
+
end
|
338
|
+
|
339
|
+
# Long press on a screen Section object
|
340
|
+
#
|
341
|
+
# @param duration [Float] duration of long press in seconds
|
342
|
+
# @example
|
343
|
+
# header_image.long_press(1.5)
|
344
|
+
#
|
345
|
+
def long_press(duration = 1)
|
346
|
+
section = find_section
|
347
|
+
section_not_found_exception(section)
|
348
|
+
driver.action
|
349
|
+
.click_and_hold(section)
|
350
|
+
.pause(duration: duration)
|
351
|
+
.release
|
352
|
+
.perform
|
353
|
+
end
|
354
|
+
|
355
|
+
# Scroll the screen Section object until it is visible. If scroll_mode is not specified, then vertical scrolling will
|
356
|
+
# be used.
|
357
|
+
#
|
358
|
+
# @param scroll_mode [Symbol] :vertical (default) or :horizontal
|
359
|
+
# @example
|
360
|
+
# carousel_item.scroll_into_view(scroll_mode = :horizontal)
|
361
|
+
#
|
362
|
+
def scroll_into_view(scroll_mode = :vertical)
|
363
|
+
return if visible?
|
364
|
+
obj = element
|
365
|
+
object_not_found_exception(obj)
|
366
|
+
driver.action.move_to(obj).perform
|
367
|
+
case scroll_mode
|
368
|
+
when :vertical
|
369
|
+
start_direction = :down
|
370
|
+
end_direction = :up
|
371
|
+
when :horizontal
|
372
|
+
start_direction = :right
|
373
|
+
end_direction = :left
|
374
|
+
else
|
375
|
+
raise "#{scroll_mode} is not a valid selector"
|
376
|
+
end
|
377
|
+
try_count = 8
|
378
|
+
direction = start_direction
|
379
|
+
while hidden?
|
380
|
+
swipe_gesture(direction, distance = 0.2)
|
381
|
+
try_count -= 1
|
382
|
+
if try_count.zero?
|
383
|
+
if direction == end_direction
|
384
|
+
break
|
385
|
+
else
|
386
|
+
direction = end_direction
|
387
|
+
try_count = 8
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
# Does screen Section object exists?
|
394
|
+
#
|
395
|
+
# @return [Boolean]
|
396
|
+
# @example
|
397
|
+
# navigation_toolbar.exists?
|
398
|
+
#
|
399
|
+
def exists?
|
400
|
+
section = find_section
|
401
|
+
section != nil
|
402
|
+
end
|
403
|
+
|
404
|
+
# Is screen Section object enabled?
|
405
|
+
#
|
406
|
+
# @return [Boolean]
|
407
|
+
# @example
|
408
|
+
# bar_chart_section.enabled?
|
409
|
+
#
|
410
|
+
def enabled?
|
411
|
+
section = find_section
|
412
|
+
section_not_found_exception(section)
|
413
|
+
section.enabled?
|
414
|
+
end
|
415
|
+
|
416
|
+
# Is screen Section object disabled (not enabled)?
|
417
|
+
#
|
418
|
+
# @return [Boolean]
|
419
|
+
# @example
|
420
|
+
# bar_chart_section.disabled?
|
421
|
+
#
|
422
|
+
def disabled?
|
423
|
+
section = find_section
|
424
|
+
section_not_found_exception(section)
|
425
|
+
section.enabled?
|
426
|
+
end
|
427
|
+
|
428
|
+
# Is screen Section object visible?
|
429
|
+
#
|
430
|
+
# @return [Boolean]
|
431
|
+
# @example
|
432
|
+
# navigation_toolbar.visible?
|
433
|
+
#
|
434
|
+
def visible?
|
435
|
+
section = find_section
|
436
|
+
return false if section.nil?
|
437
|
+
|
438
|
+
section.displayed?
|
439
|
+
end
|
440
|
+
|
441
|
+
# Is screen Section object hidden (not visible)?
|
442
|
+
#
|
443
|
+
# @return [Boolean]
|
444
|
+
# @example
|
445
|
+
# navigation_toolbar.hidden?
|
446
|
+
#
|
447
|
+
def hidden?
|
448
|
+
!visible?
|
449
|
+
end
|
450
|
+
|
451
|
+
# Wait until the screen Section object exists, or until the specified wait time has expired. If the wait time is nil,
|
452
|
+
# then the wait time will be Environ.default_max_wait_time.
|
453
|
+
#
|
454
|
+
# @param seconds [Integer or Float] wait time in seconds
|
455
|
+
# @example
|
456
|
+
# navigation_toolbar.wait_until_exists(1.5)
|
457
|
+
#
|
458
|
+
def wait_until_exists(seconds = nil, post_exception = true)
|
459
|
+
timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
|
460
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
461
|
+
wait.until { exists? }
|
462
|
+
rescue
|
463
|
+
if post_exception
|
464
|
+
raise "Could not find Section object '#{get_name}' (#{get_locator}) after #{timeout} seconds" unless exists?
|
465
|
+
else
|
466
|
+
exists?
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
# Wait until the screen Section object no longer exists, or until the specified wait time has expired. If the wait
|
471
|
+
# time is nil, then the wait time will be Environ.default_max_wait_time.
|
472
|
+
#
|
473
|
+
# @param seconds [Integer or Float] wait time in seconds
|
474
|
+
# @example
|
475
|
+
# navigation_toolbar.wait_until_gone(5)
|
476
|
+
#
|
477
|
+
def wait_until_gone(seconds = nil, post_exception = true)
|
478
|
+
timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
|
479
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
480
|
+
wait.until { !exists? }
|
481
|
+
rescue
|
482
|
+
if post_exception
|
483
|
+
raise "Section object '#{get_name}' (#{get_locator}) remained visible after #{timeout} seconds" if exists?
|
484
|
+
else
|
485
|
+
exists?
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
# Wait until the screen Section object is visible, or until the specified wait time has expired. If the wait time is nil,
|
490
|
+
# then the wait time will be Environ.default_max_wait_time.
|
491
|
+
#
|
492
|
+
# @param seconds [Integer or Float] wait time in seconds
|
493
|
+
# @example
|
494
|
+
# navigation_toolbar.wait_until_visible(1.5)
|
495
|
+
#
|
496
|
+
def wait_until_visible(seconds = nil, post_exception = true)
|
497
|
+
timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
|
498
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
499
|
+
wait.until { visible? }
|
500
|
+
rescue
|
501
|
+
if post_exception
|
502
|
+
raise "Could not find Section object '#{get_name}' (#{get_locator}) after #{timeout} seconds" unless visible?
|
503
|
+
else
|
504
|
+
visible?
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
# Wait until the screen Section object is hidden, or until the specified wait time has expired. If the wait time is nil,
|
509
|
+
# then the wait time will be Environ.default_max_wait_time.
|
510
|
+
#
|
511
|
+
# @param seconds [Integer or Float] wait time in seconds
|
512
|
+
# @example
|
513
|
+
# navigation_toolbar.wait_until_hidden(2)
|
514
|
+
#
|
515
|
+
def wait_until_hidden(seconds = nil, post_exception = true)
|
516
|
+
timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
|
517
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
518
|
+
wait.until { hidden? }
|
519
|
+
rescue
|
520
|
+
if post_exception
|
521
|
+
raise "Section object '#{get_name}' (#{get_locator}) remained visible after #{timeout} seconds" if visible?
|
522
|
+
else
|
523
|
+
visible?
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
# Return width of screen Section object.
|
528
|
+
#
|
529
|
+
# @return [Integer]
|
530
|
+
# @example
|
531
|
+
# button_width = my_button.width
|
532
|
+
#
|
533
|
+
def width
|
534
|
+
section = find_section
|
535
|
+
section_not_found_exception(section)
|
536
|
+
section.size.width
|
537
|
+
end
|
538
|
+
|
539
|
+
# Return height of screen Section object.
|
540
|
+
#
|
541
|
+
# @return [Integer]
|
542
|
+
# @example
|
543
|
+
# button_height = my_button.height
|
544
|
+
#
|
545
|
+
def height
|
546
|
+
section = find_section
|
547
|
+
section_not_found_exception(section)
|
548
|
+
section.size.height
|
549
|
+
end
|
550
|
+
|
551
|
+
# Return x coordinate of screen Section object's location.
|
552
|
+
#
|
553
|
+
# @return [Integer]
|
554
|
+
# @example
|
555
|
+
# button_x = my_button.x_loc
|
556
|
+
#
|
557
|
+
def x_loc
|
558
|
+
section = find_section
|
559
|
+
section_not_found_exception(section)
|
560
|
+
section.location.x
|
561
|
+
end
|
562
|
+
|
563
|
+
# Return y coordinate of screen Section object's location.
|
564
|
+
#
|
565
|
+
# @return [Integer]
|
566
|
+
# @example
|
567
|
+
# button_x = my_button.x_loc
|
568
|
+
#
|
569
|
+
def y_loc
|
570
|
+
section = find_section
|
571
|
+
section_not_found_exception(section)
|
572
|
+
section.location.y
|
573
|
+
end
|
574
|
+
|
575
|
+
private
|
576
|
+
|
577
|
+
def find_section
|
578
|
+
obj = nil
|
579
|
+
locators = get_locator
|
580
|
+
locators.each do |loc|
|
581
|
+
if obj.nil?
|
582
|
+
obj = find_element(loc.keys[0], loc.values[0])
|
583
|
+
puts "Found object #{loc}" if ENV['DEBUG']
|
584
|
+
else
|
585
|
+
obj = obj.find_element(loc.keys[0], loc.values[0])
|
586
|
+
puts "Found object #{loc}" if ENV['DEBUG']
|
587
|
+
end
|
588
|
+
end
|
589
|
+
obj
|
590
|
+
rescue
|
591
|
+
nil
|
592
|
+
end
|
593
|
+
|
594
|
+
def section_not_found_exception(obj)
|
595
|
+
raise ObjectNotFoundError.new("Section object '#{get_name}' (#{get_locator}) not found") unless obj
|
596
|
+
end
|
597
|
+
|
598
|
+
def self.define_section_element(element_name, obj, locator)
|
599
|
+
define_method(element_name) do
|
600
|
+
ivar_name = "@#{element_name}"
|
601
|
+
ivar = instance_variable_get(ivar_name)
|
602
|
+
return ivar if ivar
|
603
|
+
instance_variable_set(ivar_name, obj.new(element_name, self, locator, :section))
|
604
|
+
end
|
605
|
+
end
|
606
|
+
end
|
607
|
+
end
|