testcentricity_web 4.3.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -11
  3. data/LICENSE.md +1 -1
  4. data/README.md +1931 -801
  5. data/lib/devices/devices.yml +144 -216
  6. data/lib/testcentricity_web/browser_helper.rb +33 -4
  7. data/lib/testcentricity_web/data_objects/environment.rb +96 -15
  8. data/lib/testcentricity_web/exception_queue_helper.rb +5 -6
  9. data/lib/testcentricity_web/version.rb +1 -1
  10. data/lib/testcentricity_web/web_core/page_object.rb +53 -49
  11. data/lib/testcentricity_web/web_core/page_objects_helper.rb +20 -11
  12. data/lib/testcentricity_web/web_core/page_section.rb +31 -34
  13. data/lib/testcentricity_web/web_core/webdriver_helper.rb +416 -288
  14. data/lib/testcentricity_web/web_elements/audio.rb +6 -4
  15. data/lib/testcentricity_web/web_elements/button.rb +7 -4
  16. data/lib/testcentricity_web/web_elements/checkbox.rb +149 -147
  17. data/lib/testcentricity_web/web_elements/file_field.rb +38 -36
  18. data/lib/testcentricity_web/web_elements/image.rb +75 -70
  19. data/lib/testcentricity_web/web_elements/label.rb +6 -4
  20. data/lib/testcentricity_web/web_elements/link.rb +15 -13
  21. data/lib/testcentricity_web/web_elements/list.rb +171 -169
  22. data/lib/testcentricity_web/web_elements/media.rb +384 -379
  23. data/lib/testcentricity_web/web_elements/radio.rb +135 -133
  24. data/lib/testcentricity_web/web_elements/range.rb +16 -29
  25. data/lib/testcentricity_web/web_elements/select_list.rb +247 -245
  26. data/lib/testcentricity_web/web_elements/table.rb +575 -573
  27. data/lib/testcentricity_web/web_elements/textfield.rb +143 -139
  28. data/lib/testcentricity_web/web_elements/ui_element.rb +1171 -0
  29. data/lib/testcentricity_web/web_elements/video.rb +39 -37
  30. data/lib/testcentricity_web/world_extensions.rb +37 -4
  31. data/lib/testcentricity_web.rb +4 -23
  32. metadata +27 -79
  33. data/lib/testcentricity_web/web_elements/ui_elements_helper.rb +0 -1148
@@ -1,1148 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test/unit'
4
-
5
- Capybara::Node::Element.class_eval do
6
- def click_at(x, y)
7
- right = x - (native.size.width / 2)
8
- top = y - (native.size.height / 2)
9
- driver.browser.action.move_to(native).move_by(right.to_i, top.to_i).click.perform
10
- end
11
-
12
- def hover_at(x, y)
13
- right = x - (native.size.width / 2)
14
- top = y - (native.size.height / 2)
15
- driver.browser.action.move_to(native).move_by(right.to_i, top.to_i).perform
16
- end
17
-
18
- def get_width
19
- native.size.width
20
- end
21
-
22
- def get_height
23
- native.size.height
24
- end
25
-
26
- def get_x
27
- native.location.x
28
- end
29
-
30
- def get_y
31
- native.location.y
32
- end
33
-
34
- def displayed?
35
- native.displayed?
36
- end
37
- end
38
-
39
-
40
- module TestCentricity
41
- class UIElement
42
- include Capybara::DSL
43
- include Test::Unit::Assertions
44
-
45
- attr_reader :parent, :locator, :context, :type, :name
46
- attr_accessor :alt_locator, :locator_type, :original_style
47
- attr_accessor :base_object
48
-
49
- XPATH_SELECTORS = ['//', '[@', '[contains(']
50
- CSS_SELECTORS = %w[# :nth-child( :first-child :last-child :nth-of-type( :first-of-type :last-of-type ^= $= *= :contains(]
51
-
52
- def initialize(name, parent, locator, context)
53
- @name = name
54
- @parent = parent
55
- @locator = locator
56
- @context = context
57
- @type = nil
58
- @alt_locator = nil
59
- @original_style = nil
60
- set_locator_type
61
- end
62
-
63
- def set_locator_type(locator = nil)
64
- locator = @locator if locator.nil?
65
- is_xpath = XPATH_SELECTORS.any? { |selector| locator.include?(selector) }
66
- is_css = CSS_SELECTORS.any? { |selector| locator.include?(selector) }
67
- @locator_type = if is_xpath && !is_css
68
- :xpath
69
- elsif is_css && !is_xpath
70
- :css
71
- elsif !is_css && !is_xpath
72
- :css
73
- else
74
- :css
75
- end
76
- end
77
-
78
- def get_locator_type
79
- @locator_type
80
- end
81
-
82
- def get_object_type
83
- if @type
84
- @type
85
- else
86
- obj, type = find_element
87
- object_not_found_exception(obj, type)
88
- if obj.tag_name
89
- obj.tag_name
90
- elsif obj.native.attribute('type')
91
- obj.native.attribute('type')
92
- end
93
- end
94
- end
95
-
96
- def get_locator
97
- @locator
98
- end
99
-
100
- def get_name
101
- @name
102
- end
103
-
104
- def set_alt_locator(temp_locator)
105
- @alt_locator = temp_locator
106
- end
107
-
108
- def clear_alt_locator
109
- @alt_locator = nil
110
- end
111
-
112
- # Click on an object
113
- #
114
- # @example
115
- # basket_link.click
116
- #
117
- def click
118
- obj, type = find_element
119
- object_not_found_exception(obj, type)
120
- begin
121
- obj.click
122
- rescue StandardError
123
- obj.click_at(10, 10)
124
- end
125
- end
126
-
127
- # Double-click on an object
128
- #
129
- # @example
130
- # file_image.double_click
131
- #
132
- def double_click
133
- obj, type = find_element
134
- object_not_found_exception(obj, type)
135
- page.driver.browser.action.double_click(obj.native).perform
136
- end
137
-
138
- # Right-click on an object
139
- #
140
- # @example
141
- # basket_item_image.right_click
142
- #
143
- def right_click
144
- obj, type = find_element
145
- object_not_found_exception(obj, type)
146
- page.driver.browser.action.context_click(obj.native).perform
147
- end
148
-
149
- # Click at a specific location within an object
150
- #
151
- # @param x [Integer] X offset
152
- # @param y [Integer] Y offset
153
- # @example
154
- # basket_item_image.click_at(10, 10)
155
- #
156
- def click_at(x, y)
157
- obj, = find_element
158
- raise "UI #{object_ref_message} not found" unless obj
159
- obj.click_at(x, y)
160
- end
161
-
162
- # Scroll the object to its top, middle, or bottom
163
- #
164
- # @param position [Symbol] :top, :bottom, :center
165
- # @example
166
- # cue_list.scroll_to(:bottom)
167
- #
168
- def scroll_to(position)
169
- obj, type = find_element
170
- object_not_found_exception(obj, type)
171
- page.scroll_to(obj, align: position)
172
- end
173
-
174
- def set(value)
175
- obj, type = find_element
176
- object_not_found_exception(obj, type)
177
- obj.set(value)
178
- end
179
-
180
- # Send keystrokes to this object.
181
- #
182
- # @param keys [String] keys
183
- # @example
184
- # comment_field.send_keys(:enter)
185
- #
186
- def send_keys(*keys)
187
- obj, type = find_element
188
- object_not_found_exception(obj, type)
189
- obj.send_keys(*keys)
190
- end
191
-
192
- # Does UI object exists?
193
- #
194
- # @return [Boolean]
195
- # @example
196
- # basket_link.exists?
197
- #
198
- def exists?(visible = true)
199
- obj, = find_object(visible)
200
- !obj.nil?
201
- end
202
-
203
- # Is UI object visible?
204
- #
205
- # @return [Boolean]
206
- # @example
207
- # remember_me_checkbox.visible?
208
- #
209
- def visible?
210
- obj, type = find_element
211
- exists = obj
212
- invisible = false
213
- if type == :css
214
- Capybara.using_wait_time 0.1 do
215
- # is object itself hidden with .ui-helper-hidden class?
216
- self_hidden = page.has_css?("#{@locator}.ui-helper-hidden")
217
- # is parent of object hidden, thus hiding the object?
218
- parent_hidden = page.has_css?(".ui-helper-hidden > #{@locator}")
219
- # is grandparent of object, or any other ancestor, hidden?
220
- other_ancestor_hidden = page.has_css?(".ui-helper-hidden * #{@locator}")
221
- # if any of the above conditions are true, then object is invisible
222
- invisible = self_hidden || parent_hidden || other_ancestor_hidden
223
- end
224
- else
225
- invisible = !obj.visible? if exists
226
- end
227
- # the object is visible if it exists and it is not invisible
228
- if exists && !invisible
229
- true
230
- else
231
- false
232
- end
233
- end
234
-
235
- # Is UI object hidden (not visible)?
236
- #
237
- # @return [Boolean]
238
- # @example
239
- # remember_me_checkbox.hidden?
240
- #
241
- def hidden?
242
- !visible?
243
- end
244
-
245
- # Is UI object enabled?
246
- #
247
- # @return [Boolean]
248
- # @example
249
- # login_button.enabled?
250
- #
251
- def enabled?
252
- !disabled?
253
- end
254
-
255
- # Is UI object disabled (not enabled)?
256
- #
257
- # @return [Boolean]
258
- # @example
259
- # login_button.disabled?
260
- #
261
- def disabled?
262
- obj, type = find_element
263
- object_not_found_exception(obj, type)
264
- obj.disabled?
265
- end
266
-
267
- # Is UI object's required attribute set?
268
- #
269
- # @return [Boolean]
270
- # @example
271
- # first_name_field.required?
272
- #
273
- def required?
274
- obj, type = find_element
275
- object_not_found_exception(obj, type)
276
- state = get_attribute(:required)
277
- state.boolean? ? state : state == 'true'
278
- end
279
-
280
- # Is UI object obscured (not currently in viewport and not clickable)?
281
- #
282
- # @return [Boolean]
283
- # @example
284
- # buy_now_button.obscured?
285
- #
286
- def obscured?
287
- obj, type = find_element
288
- object_not_found_exception(obj, type)
289
- obj.obscured?
290
- end
291
-
292
- # Does UI object have the current focus?
293
- #
294
- # @return [Boolean]
295
- # @example
296
- # first_name_field.focused?
297
- #
298
- def focused?
299
- obj, type = find_element(visible = :all)
300
- object_not_found_exception(obj, type)
301
- focused_obj = page.driver.browser.switch_to.active_element
302
- focused_obj == obj.native
303
- end
304
-
305
- # Return a human readable representation of the UI element
306
- #
307
- # @return [String]
308
- # @example
309
- # buy_now_button.inspect
310
- #
311
- def inspect
312
- obj, type = find_element
313
- object_not_found_exception(obj, type)
314
- obj.inspect
315
- end
316
-
317
- # Wait until the object exists, or until the specified wait time has expired. If the wait time is nil, then the wait
318
- # time will be Capybara.default_max_wait_time.
319
- #
320
- # @param seconds [Integer or Float] wait time in seconds
321
- # @example
322
- # run_button.wait_until_exists(0.5)
323
- #
324
- def wait_until_exists(seconds = nil, post_exception = true)
325
- timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
326
- wait = Selenium::WebDriver::Wait.new(timeout: timeout)
327
- wait.until { exists? }
328
- rescue StandardError
329
- if post_exception
330
- raise "Could not find UI #{object_ref_message} after #{timeout} seconds" unless exists?
331
- else
332
- exists?
333
- end
334
- end
335
-
336
- # Wait until the object no longer exists, or until the specified wait time has expired. If the wait time is nil, then
337
- # the wait time will be Capybara.default_max_wait_time.
338
- #
339
- # @param seconds [Integer or Float] wait time in seconds
340
- # @example
341
- # logout_button.wait_until_gone(5)
342
- #
343
- def wait_until_gone(seconds = nil, post_exception = true)
344
- timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
345
- wait = Selenium::WebDriver::Wait.new(timeout: timeout)
346
- wait.until { !exists? }
347
- rescue StandardError
348
- if post_exception
349
- raise "UI #{object_ref_message} remained visible after #{timeout} seconds" if exists?
350
- else
351
- exists?
352
- end
353
- end
354
-
355
- # Wait until the object is visible, or until the specified wait time has expired. If the wait time is nil, then the
356
- # wait time will be Capybara.default_max_wait_time.
357
- #
358
- # @param seconds [Integer or Float] wait time in seconds
359
- # @example
360
- # run_button.wait_until_visible(0.5)
361
- #
362
- def wait_until_visible(seconds = nil, post_exception = true)
363
- timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
364
- wait = Selenium::WebDriver::Wait.new(timeout: timeout)
365
- wait.until { visible? }
366
- rescue StandardError
367
- if post_exception
368
- raise "Could not find UI #{object_ref_message} after #{timeout} seconds" unless visible?
369
- else
370
- visible?
371
- end
372
- end
373
-
374
- # Wait until the object is hidden, or until the specified wait time has expired. If the wait time is nil, then the
375
- # wait time will be Capybara.default_max_wait_time.
376
- #
377
- # @param seconds [Integer or Float] wait time in seconds
378
- # @example
379
- # run_button.wait_until_hidden(10)
380
- #
381
- def wait_until_hidden(seconds = nil, post_exception = true)
382
- timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
383
- wait = Selenium::WebDriver::Wait.new(timeout: timeout)
384
- wait.until { hidden? }
385
- rescue StandardError
386
- if post_exception
387
- raise "UI #{object_ref_message} remained visible after #{timeout} seconds" if visible?
388
- else
389
- visible?
390
- end
391
- end
392
-
393
- # Wait until the object is enabled, or until the specified wait time has expired. If the wait time is nil, then the
394
- # wait time will be Capybara.default_max_wait_time.
395
- #
396
- # @param seconds [Integer or Float] wait time in seconds
397
- # @example
398
- # run_button.wait_until_enabled(10)
399
- #
400
- def wait_until_enabled(seconds = nil, post_exception = true)
401
- timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
402
- wait = Selenium::WebDriver::Wait.new(timeout: timeout)
403
- wait.until { enabled? }
404
- rescue StandardError
405
- if post_exception
406
- raise "UI #{object_ref_message} remained disabled after #{timeout} seconds" unless enabled?
407
- else
408
- enabled?
409
- end
410
- end
411
-
412
- # Wait until the object is no longer in a busy state, or until the specified wait time has expired. If the wait time
413
- # is nil, then the wait time will be Capybara.default_max_wait_time.
414
- #
415
- # @param seconds [Integer or Float] wait time in seconds
416
- # @example
417
- # login_button.wait_while_busy(10)
418
- #
419
- def wait_while_busy(seconds = nil, post_exception = true)
420
- timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
421
- wait = Selenium::WebDriver::Wait.new(timeout: timeout)
422
- wait.until { aria_busy? }
423
- rescue StandardError
424
- if post_exception
425
- raise "UI #{object_ref_message} remained in busy state after #{timeout} seconds" if aria_busy?
426
- else
427
- aria_busy?
428
- end
429
- end
430
-
431
- # Wait until the object's value equals the specified value, or until the specified wait time has expired. If the wait
432
- # time is nil, then the wait time will be Capybara.default_max_wait_time.
433
- #
434
- # @param value [String or Hash] value expected or comparison hash
435
- # @param seconds [Integer or Float] wait time in seconds
436
- # @example
437
- # card_authorized_label.wait_until_value_is('Card authorized', 5)
438
- # or
439
- # total_weight_field.wait_until_value_is({ greater_than: '250' }, 5)
440
- #
441
- def wait_until_value_is(value, seconds = nil, post_exception = true)
442
- timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
443
- wait = Selenium::WebDriver::Wait.new(timeout: timeout)
444
- wait.until { compare(value, get_value) }
445
- rescue StandardError
446
- if post_exception
447
- raise "Value of UI #{object_ref_message} failed to equal '#{value}' after #{timeout} seconds" unless get_value == value
448
- else
449
- get_value == value
450
- end
451
- end
452
-
453
- # Wait until the object's value changes to a different value, or until the specified wait time has expired. If the
454
- # wait time is nil, then the wait time will be Capybara.default_max_wait_time.
455
- #
456
- # @param seconds [Integer or Float] wait time in seconds
457
- # @example
458
- # basket_grand_total_label.wait_until_value_changes(5)
459
- #
460
- def wait_until_value_changes(seconds = nil, post_exception = true)
461
- value = get_value
462
- timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
463
- wait = Selenium::WebDriver::Wait.new(timeout: timeout)
464
- wait.until { get_value != value }
465
- rescue StandardError
466
- if post_exception
467
- raise "Value of UI #{object_ref_message} failed to change from '#{value}' after #{timeout} seconds" if get_value == value
468
- else
469
- get_value == value
470
- end
471
- end
472
-
473
- # Return the number of occurrences of an object with an ambiguous locator that evaluates to multiple UI elements.
474
- #
475
- # @param visible [Boolean, Symbol] Only find elements with the specified visibility:
476
- # * true - only finds visible elements.
477
- # * false - finds invisible _and_ visible elements.
478
- # * :all - same as false; finds visible and invisible elements.
479
- # * :hidden - only finds invisible elements.
480
- # * :visible - same as true; only finds visible elements.
481
- # @example
482
- # num_uploads = upload_progress_bars.count(:all)
483
- #
484
- def count(visible = true)
485
- obj_locator = @alt_locator.nil? ? @locator : @alt_locator
486
- page.all(@locator_type, obj_locator, wait: 0.01, visible: visible, minimum: 0).count
487
- end
488
-
489
- # Return width of object.
490
- #
491
- # @return [Integer]
492
- # @example
493
- # button_width = my_button.width
494
- #
495
- def width
496
- obj, type = find_element(visible = false)
497
- object_not_found_exception(obj, type)
498
- obj.get_width
499
- end
500
-
501
- # Return height of object.
502
- #
503
- # @return [Integer]
504
- # @example
505
- # button_height = my_button.height
506
- #
507
- def height
508
- obj, type = find_element(visible = false)
509
- object_not_found_exception(obj, type)
510
- obj.get_height
511
- end
512
-
513
- # Return x coordinate of object's location.
514
- #
515
- # @return [Integer]
516
- # @example
517
- # button_x = my_button.x
518
- #
519
- def x
520
- obj, type = find_element(visible = false)
521
- object_not_found_exception(obj, type)
522
- obj.get_x
523
- end
524
-
525
- # Return y coordinate of object's location.
526
- #
527
- # @return [Integer]
528
- # @example
529
- # button_y = my_button.y
530
- #
531
- def y
532
- obj, type = find_element(visible = false)
533
- object_not_found_exception(obj, type)
534
- obj.get_y
535
- end
536
-
537
- # Return UI object's title property
538
- #
539
- # @return [String]
540
- # @example
541
- # buy_now_button.title
542
- #
543
- def title
544
- get_attribute(:title)
545
- end
546
-
547
- # Is UI object displayed in browser window?
548
- #
549
- # @return [Boolean]
550
- # @example
551
- # basket_link.displayed??
552
- #
553
- def displayed?
554
- obj, type = find_element(visible = false)
555
- object_not_found_exception(obj, type)
556
- obj.displayed?
557
- end
558
-
559
- def get_value(visible = true)
560
- obj, type = find_element(visible)
561
- object_not_found_exception(obj, type)
562
- text = case obj.tag_name.downcase
563
- when 'input', 'select', 'textarea'
564
- obj.value
565
- else
566
- obj.text
567
- end
568
- text.gsub(/[[:space:]]+/, ' ').strip unless text.nil?
569
- end
570
-
571
- alias get_caption get_value
572
- alias caption get_value
573
- alias value get_value
574
-
575
- def verify_value(expected, enqueue = false)
576
- actual = get_value
577
- enqueue ?
578
- ExceptionQueue.enqueue_assert_equal(expected.strip, actual.strip, "Expected UI #{object_ref_message}") :
579
- assert_equal(expected.strip, actual.strip, "Expected UI #{object_ref_message} to display '#{expected}' but found '#{actual}'")
580
- end
581
-
582
- alias verify_caption verify_value
583
-
584
- # Hover the cursor over an object
585
- #
586
- # @param visible [Boolean, Symbol] Only find elements with the specified visibility:
587
- # * true - only finds visible elements.
588
- # * false - finds invisible _and_ visible elements.
589
- # * :all - same as false; finds visible and invisible elements.
590
- # * :hidden - only finds invisible elements.
591
- # * :visible - same as true; only finds visible elements.
592
- # @example
593
- # basket_link.hover
594
- #
595
- def hover(visible = true)
596
- obj, type = find_element(visible)
597
- object_not_found_exception(obj, type)
598
- obj.hover
599
- end
600
-
601
- # Hover at a specific location within an object
602
- #
603
- # @param x [Integer] X offset
604
- # @param y [Integer] Y offset
605
- # @param visible [Boolean, Symbol] Only find elements with the specified visibility:
606
- # * true - only finds visible elements.
607
- # * false - finds invisible _and_ visible elements.
608
- # * :all - same as false; finds visible and invisible elements.
609
- # * :hidden - only finds invisible elements.
610
- # * :visible - same as true; only finds visible elements.
611
- # @example
612
- # timeline_bar.hover_at(100, 5)
613
- #
614
- def hover_at(x, y, visible = true)
615
- obj, = find_element(visible)
616
- raise "UI #{object_ref_message} not found" unless obj
617
- obj.hover_at(x, y)
618
- end
619
-
620
- def drag_by(right_offset, down_offset)
621
- obj, type = find_element
622
- object_not_found_exception(obj, type)
623
- page.driver.browser.action.click_and_hold(obj.native).perform
624
- sleep(1)
625
- obj.drag_by(right_offset, down_offset)
626
- end
627
-
628
- def drag_and_drop(target, right_offset = nil, down_offset = nil)
629
- source, type = find_element
630
- object_not_found_exception(source, type)
631
- page.driver.browser.action.click_and_hold(source.native).perform
632
- sleep(1)
633
- target_drop, = target.find_element
634
- page.driver.browser.action.move_to(target_drop.native, right_offset.to_i, down_offset.to_i).release.perform
635
- end
636
-
637
- # Highlight an object with a 3 pixel wide, red dashed border for the specified wait time.
638
- # If wait time is zero, then the highlight will remain until the page is refreshed
639
- #
640
- # @param duration [Integer or Float] wait time in seconds
641
- # @example
642
- # error_message.highlight(3)
643
- #
644
- def highlight(duration = 1)
645
- obj, type = find_element
646
- object_not_found_exception(obj, type)
647
- # store original style so it can be reset later
648
- @original_style = obj.native.attribute('style')
649
- # style element with red border
650
- page.execute_script(
651
- 'arguments[0].setAttribute(arguments[1], arguments[2])',
652
- obj,
653
- 'style',
654
- 'border: 3px solid red; border-style: dashed;'
655
- )
656
- # keep element highlighted for duration and then revert to original style
657
- if duration.positive?
658
- sleep duration
659
- page.execute_script(
660
- 'arguments[0].setAttribute(arguments[1], arguments[2])',
661
- obj,
662
- 'style',
663
- @original_style
664
- )
665
- end
666
- end
667
-
668
- # Restore a highlighted object's original style
669
- #
670
- # @example
671
- # store_link.unhighlight
672
- #
673
- def unhighlight
674
- obj, type = find_element
675
- object_not_found_exception(obj, type)
676
- return if @original_style.nil?
677
- page.execute_script(
678
- 'arguments[0].setAttribute(arguments[1], arguments[2])',
679
- obj,
680
- 'style',
681
- @original_style
682
- )
683
- end
684
-
685
- # Return UI object's style property
686
- #
687
- # @return [String]
688
- # @example
689
- # buy_now_button.style
690
- #
691
- def style
692
- get_attribute('style')
693
- end
694
-
695
- # Return state of UI object's role property
696
- #
697
- # @return [String]
698
- # @example
699
- # buy_now_button.role
700
- #
701
- def role
702
- get_attribute('role')
703
- end
704
-
705
- # Return state of UI object's tabindex property
706
- #
707
- # @return [String]
708
- # @example
709
- # buy_now_button.tabindex
710
- #
711
- def tabindex
712
- get_attribute('tabindex')
713
- end
714
-
715
- # Return state of UI object's aria-label property
716
- #
717
- # @return [String]
718
- # @example
719
- # buy_now_button.aria_label
720
- #
721
- def aria_label
722
- get_attribute('aria-label')
723
- end
724
-
725
- # Return state of UI object's aria-labelledby property
726
- #
727
- # @return [String]
728
- # @example
729
- # buy_now_button.aria_labelledby
730
- #
731
- def aria_labelledby
732
- get_attribute('aria-labelledby')
733
- end
734
-
735
- # Return state of UI object's aria-describedby property
736
- #
737
- # @return [String]
738
- # @example
739
- # buy_now_button.aria_describedby
740
- #
741
- def aria_describedby
742
- get_attribute('aria-describedby')
743
- end
744
-
745
- # Return state of UI object's aria-live property
746
- #
747
- # @return [String]
748
- # @example
749
- # properties_list.aria_live
750
- #
751
- def aria_live
752
- get_attribute('aria-live')
753
- end
754
-
755
- # Return state of UI object's aria-sort property
756
- #
757
- # @return [String]
758
- # @example
759
- # name_column.aria_sort
760
- #
761
- def aria_sort
762
- get_attribute('aria-sort')
763
- end
764
-
765
- # Return state of UI object's aria-rowcount property
766
- #
767
- # @return [Integer]
768
- # @example
769
- # user_grid.aria_rowcount
770
- #
771
- def aria_rowcount
772
- get_attribute('aria-rowcount')
773
- end
774
-
775
- # Return state of UI object's aria-colcount property
776
- #
777
- # @return [Integer]
778
- # @example
779
- # user_grid.aria_colcount
780
- #
781
- def aria_colcount
782
- get_attribute('aria-colcount')
783
- end
784
-
785
- # Return state of UI object's aria-valuemax property
786
- #
787
- # @return [Integer]
788
- # @example
789
- # volume_slider.aria_valuemax
790
- #
791
- def aria_valuemax
792
- get_attribute('aria-valuemax')
793
- end
794
-
795
- # Return state of UI object's aria-valuemin property
796
- #
797
- # @return [Integer]
798
- # @example
799
- # volume_slider.aria_valuemin
800
- #
801
- def aria_valuemin
802
- get_attribute('aria-valuemin')
803
- end
804
-
805
- # Return state of UI object's aria-valuenow property
806
- #
807
- # @return [Integer]
808
- # @example
809
- # volume_slider.aria_valuenow
810
- #
811
- def aria_valuenow
812
- get_attribute('aria-valuenow')
813
- end
814
-
815
- # Return state of UI object's aria-valuetext property
816
- #
817
- # @return [Integer]
818
- # @example
819
- # volume_slider.aria_valuetext
820
- #
821
- def aria_valuetext
822
- get_attribute('aria-valuetext')
823
- end
824
-
825
- # Return state of UI object's aria-orientation property
826
- #
827
- # @return [Integer]
828
- # @example
829
- # volume_slider.aria_orientation
830
- #
831
- def aria_orientation
832
- get_attribute('aria-orientation')
833
- end
834
-
835
- # Return state of UI object's aria-keyshortcuts property
836
- #
837
- # @return [Integer]
838
- # @example
839
- # play_button.aria_keyshortcuts
840
- #
841
- def aria_keyshortcuts
842
- get_attribute('aria-keyshortcuts')
843
- end
844
-
845
- # Return state of UI object's aria-roledescription property
846
- #
847
- # @return [Integer]
848
- # @example
849
- # editor_button.aria_roledescription
850
- #
851
- def aria_roledescription
852
- get_attribute('aria-roledescription')
853
- end
854
-
855
- # Return state of UI object's aria-autocomplete property
856
- #
857
- # @return [Integer]
858
- # @example
859
- # email_field.aria_autocomplete
860
- #
861
- def aria_autocomplete
862
- get_attribute('aria-autocomplete')
863
- end
864
-
865
- # Return state of UI object's aria-controls property
866
- #
867
- # @return [Integer]
868
- # @example
869
- # video_menu.aria_controls
870
- #
871
- def aria_controls
872
- get_attribute('aria-controls')
873
- end
874
-
875
- # Return state of UI object's aria-disabled property
876
- #
877
- # @return [Boolean]
878
- # @example
879
- # buy_now_button.aria_disabled?
880
- #
881
- def aria_disabled?
882
- state = get_attribute('aria-disabled')
883
- state.boolean? ? state : state == 'true'
884
- end
885
-
886
- # Return state of UI object's aria-selected property
887
- #
888
- # @return [Boolean]
889
- # @example
890
- # nutrition_info_tab.aria_selected?
891
- #
892
- def aria_selected?
893
- state = get_attribute('aria-selected')
894
- state.boolean? ? state : state == 'true'
895
- end
896
-
897
- # Return state of UI object's aria-hidden property
898
- #
899
- # @return [Boolean]
900
- # @example
901
- # nutrition_info_tab.aria_hidden?
902
- #
903
- def aria_hidden?
904
- state = get_attribute('aria-hidden')
905
- state.boolean? ? state : state == 'true'
906
- end
907
-
908
- # Return state of UI object's aria-expanded property
909
- #
910
- # @return [Boolean]
911
- # @example
912
- # catalog_tree.aria_expanded?
913
- #
914
- def aria_expanded?
915
- state = get_attribute('aria-expanded')
916
- state.boolean? ? state : state == 'true'
917
- end
918
-
919
- # Return state of UI object's aria-required property
920
- #
921
- # @return [Boolean]
922
- # @example
923
- # home_phone_field.aria_required?
924
- #
925
- def aria_required?
926
- state = get_attribute('aria-required')
927
- state.boolean? ? state : state == 'true'
928
- end
929
-
930
- # Return state of UI object's aria-invalid property
931
- #
932
- # @return [Boolean]
933
- # @example
934
- # home_phone_field.aria_invalid?
935
- #
936
- def aria_invalid?
937
- state = get_attribute('aria-invalid')
938
- state.boolean? ? state : state == 'true'
939
- end
940
-
941
- # Return state of UI object's aria-checked property
942
- #
943
- # @return [Boolean]
944
- # @example
945
- # allow_new_users_checkbox.aria_checked?
946
- #
947
- def aria_checked?
948
- state = get_attribute('aria-checked')
949
- state.boolean? ? state : state == 'true'
950
- end
951
-
952
- # Return state of UI object's aria-haspopup property
953
- #
954
- # @return [Boolean]
955
- # @example
956
- # user_avatar.aria_haspopup?
957
- #
958
- def aria_haspopup?
959
- state = get_attribute('aria-haspopup')
960
- state.boolean? ? state : state == 'true'
961
- end
962
-
963
- # Return state of UI object's aria-pressed property
964
- #
965
- # @return [Boolean]
966
- # @example
967
- # option1_button.aria_pressed?
968
- #
969
- def aria_pressed?
970
- state = get_attribute('aria-pressed')
971
- state.boolean? ? state : state == 'true'
972
- end
973
-
974
- # Return state of UI object's aria-readonly property
975
- #
976
- # @return [Boolean]
977
- # @example
978
- # home_phone_field.aria_readonly?
979
- #
980
- def aria_readonly?
981
- state = get_attribute('aria-readonly')
982
- state.boolean? ? state : state == 'true'
983
- end
984
-
985
- # Return state of UI object's aria-busy property
986
- #
987
- # @return [Boolean]
988
- # @example
989
- # home_phone_field.aria_busy?
990
- #
991
- def aria_busy?
992
- state = get_attribute('aria-busy')
993
- state.boolean? ? state : state == 'true'
994
- end
995
-
996
- # Return state of UI object's aria-modal property
997
- #
998
- # @return [Boolean]
999
- # @example
1000
- # add_user_modal.aria_modal?
1001
- #
1002
- def aria_modal?
1003
- state = get_attribute('aria-modal')
1004
- state.boolean? ? state : state == 'true'
1005
- end
1006
-
1007
- # Return state of UI object's aria-multiline property
1008
- #
1009
- # @return [Boolean]
1010
- # @example
1011
- # description_field.aria_multiline?
1012
- #
1013
- def aria_multiline?
1014
- state = get_attribute('aria-multiline')
1015
- state.boolean? ? state : state == 'true'
1016
- end
1017
-
1018
- # Return state of UI object's aria-multiselectable property
1019
- #
1020
- # @return [Boolean]
1021
- # @example
1022
- # channels_select.aria_multiselectable?
1023
- #
1024
- def aria_multiselectable?
1025
- state = get_attribute('aria-multiselectable')
1026
- state.boolean? ? state : state == 'true'
1027
- end
1028
-
1029
- # Return state of UI object's contenteditable property
1030
- #
1031
- # @return [Boolean]
1032
- # @example
1033
- # description_field.content_editable?
1034
- #
1035
- def content_editable?
1036
- state = get_attribute('contenteditable')
1037
- state.boolean? ? state : state == 'true'
1038
- end
1039
-
1040
- # Return crossorigin property
1041
- #
1042
- # @return crossorigin value
1043
- # @example
1044
- # with_creds = media_player.crossorigin == 'use-credentials'
1045
- #
1046
- def crossorigin
1047
- obj, = find_element
1048
- object_not_found_exception(obj, @type)
1049
- obj.native.attribute('crossorigin')
1050
- end
1051
-
1052
- def get_attribute(attrib)
1053
- obj, type = find_element(visible = false)
1054
- object_not_found_exception(obj, type)
1055
- obj[attrib]
1056
- end
1057
-
1058
- def get_native_attribute(attrib)
1059
- obj, type = find_element(visible = false)
1060
- object_not_found_exception(obj, type)
1061
- obj.native.attribute(attrib)
1062
- end
1063
-
1064
- def find_element(visible = true)
1065
- wait = Selenium::WebDriver::Wait.new(timeout: Capybara.default_max_wait_time)
1066
- wait.until { find_object(visible) }
1067
- end
1068
-
1069
- private
1070
-
1071
- def find_object(visible = true)
1072
- obj_locator = @alt_locator.nil? ? @locator : @alt_locator
1073
- parent_section = @context == :section && !@parent.get_locator.nil?
1074
- tries ||= parent_section ? 2 : 1
1075
- if parent_section && tries == 2
1076
- parent_locator = @parent.get_locator
1077
- parent_locator = parent_locator.tr('|', ' ')
1078
- parent_locator_type = @parent.get_locator_type
1079
- obj = page.find(parent_locator_type, parent_locator, visible: :all, wait: 0.01).find(@locator_type, obj_locator, wait: 0.01, visible: visible)
1080
- else
1081
- obj = page.find(@locator_type, obj_locator, wait: 0.01, visible: visible)
1082
- end
1083
- [obj, @locator_type]
1084
- rescue StandardError
1085
- retry if (tries -= 1).positive?
1086
- [nil, nil]
1087
- end
1088
-
1089
- def object_not_found_exception(obj, obj_type)
1090
- locator = @alt_locator.nil? ? @locator : @alt_locator
1091
- object_type = obj_type.nil? ? 'Object' : obj_type
1092
- raise ObjectNotFoundError, "#{object_type} named '#{@name}' (#{locator}) not found" unless obj
1093
- end
1094
-
1095
- def invalid_object_type_exception(obj, obj_type)
1096
- unless obj.tag_name == obj_type || obj.native.attribute('type') == obj_type
1097
- locator = @alt_locator.nil? ? @locator : @alt_locator
1098
- raise "#{locator} is not a #{obj_type} element"
1099
- end
1100
- end
1101
-
1102
- def object_ref_message
1103
- "object '#{get_name}' (#{get_locator})"
1104
- end
1105
-
1106
- def compare(expected, actual)
1107
- if expected.is_a?(Hash) && expected.length == 1
1108
- expected.each do |key, value|
1109
- case key
1110
- when :lt, :less_than
1111
- actual < value
1112
- when :lt_eq, :less_than_or_equal
1113
- actual <= value
1114
- when :gt, :greater_than
1115
- actual > value
1116
- when :gt_eq, :greater_than_or_equal
1117
- actual >= value
1118
- when :starts_with
1119
- actual.start_with?(value)
1120
- when :ends_with
1121
- actual.end_with?(value)
1122
- when :contains
1123
- actual.include?(value)
1124
- when :not_contains, :does_not_contain
1125
- !actual.include?(value)
1126
- when :not_equal
1127
- actual != value
1128
- end
1129
- end
1130
- else
1131
- expected == actual
1132
- end
1133
- end
1134
-
1135
- def find_component(component, component_name)
1136
- begin
1137
- element = @base_object.find(:css, component, visible: :all, minimum: 0, wait: 1)
1138
- rescue
1139
- begin
1140
- element = page.find(:css, component, visible: :all, minimum: 0, wait: 2)
1141
- rescue
1142
- raise "Component #{component_name} (#{component}) for #{@type} named '#{@name}' (#{locator}) not found"
1143
- end
1144
- end
1145
- element
1146
- end
1147
- end
1148
- end