watir 6.14.0 → 6.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +24 -6
  3. data/CHANGES.md +10 -0
  4. data/Gemfile +0 -2
  5. data/README.md +1 -1
  6. data/Rakefile +2 -2
  7. data/lib/watir.rb +2 -3
  8. data/lib/watir/adjacent.rb +2 -2
  9. data/lib/watir/alert.rb +5 -9
  10. data/lib/watir/attribute_helper.rb +2 -3
  11. data/lib/watir/browser.rb +5 -17
  12. data/lib/watir/capabilities.rb +11 -0
  13. data/lib/watir/cell_container.rb +2 -2
  14. data/lib/watir/container.rb +7 -8
  15. data/lib/watir/cookies.rb +2 -12
  16. data/lib/watir/element_collection.rb +2 -2
  17. data/lib/watir/elements/button.rb +2 -11
  18. data/lib/watir/elements/element.rb +43 -25
  19. data/lib/watir/elements/hidden.rb +1 -1
  20. data/lib/watir/elements/iframe.rb +7 -5
  21. data/lib/watir/elements/option.rb +2 -13
  22. data/lib/watir/elements/select.rb +6 -22
  23. data/lib/watir/elements/table.rb +2 -2
  24. data/lib/watir/exception.rb +1 -2
  25. data/lib/watir/generator/base/idl_sorter.rb +1 -1
  26. data/lib/watir/generator/base/spec_extractor.rb +2 -2
  27. data/lib/watir/generator/base/visitor.rb +1 -1
  28. data/lib/watir/generator/html/generator.rb +0 -1
  29. data/lib/watir/generator/html/spec_extractor.rb +1 -1
  30. data/lib/watir/generator/html/visitor.rb +1 -1
  31. data/lib/watir/generator/svg/spec_extractor.rb +1 -1
  32. data/lib/watir/generator/svg/visitor.rb +1 -1
  33. data/lib/watir/js_execution.rb +11 -0
  34. data/lib/watir/js_snippets.rb +1 -1
  35. data/lib/watir/js_snippets/elementObscured.js +14 -0
  36. data/lib/watir/js_snippets/selectedText.js +17 -0
  37. data/lib/watir/legacy_wait.rb +5 -5
  38. data/lib/watir/locators.rb +16 -5
  39. data/lib/watir/locators/anchor/selector_builder.rb +38 -0
  40. data/lib/watir/locators/button/locator.rb +14 -12
  41. data/lib/watir/locators/button/selector_builder.rb +0 -22
  42. data/lib/watir/locators/button/selector_builder/xpath.rb +67 -12
  43. data/lib/watir/locators/button/validator.rb +2 -1
  44. data/lib/watir/locators/cell/selector_builder.rb +0 -14
  45. data/lib/watir/locators/cell/selector_builder/xpath.rb +21 -0
  46. data/lib/watir/locators/element/locator.rb +60 -153
  47. data/lib/watir/locators/element/selector_builder.rb +103 -84
  48. data/lib/watir/locators/element/selector_builder/regexp_disassembler.rb +66 -0
  49. data/lib/watir/locators/element/selector_builder/xpath.rb +195 -82
  50. data/lib/watir/locators/element/selector_builder/xpath_support.rb +27 -0
  51. data/lib/watir/locators/element/validator.rb +2 -9
  52. data/lib/watir/locators/row/selector_builder.rb +5 -22
  53. data/lib/watir/locators/row/selector_builder/xpath.rb +53 -0
  54. data/lib/watir/locators/text_area/selector_builder.rb +1 -1
  55. data/lib/watir/locators/text_area/selector_builder/xpath.rb +19 -0
  56. data/lib/watir/locators/text_field/locator.rb +11 -8
  57. data/lib/watir/locators/text_field/selector_builder.rb +0 -23
  58. data/lib/watir/locators/text_field/selector_builder/xpath.rb +33 -4
  59. data/lib/watir/locators/text_field/validator.rb +4 -4
  60. data/lib/watir/radio_set.rb +5 -5
  61. data/lib/watir/row_container.rb +2 -2
  62. data/lib/watir/user_editable.rb +2 -2
  63. data/lib/watir/version.rb +1 -1
  64. data/lib/watir/wait.rb +24 -37
  65. data/lib/watir/window.rb +11 -8
  66. data/lib/watirspec/remote_server.rb +3 -1
  67. data/spec/locator_spec_helper.rb +1 -1
  68. data/spec/spec_helper.rb +25 -1
  69. data/spec/unit/anchor_locator_spec.rb +68 -0
  70. data/spec/unit/capabilities_spec.rb +27 -0
  71. data/spec/unit/element_locator_spec.rb +184 -101
  72. data/spec/unit/logger_spec.rb +5 -0
  73. data/spec/watirspec/adjacent_spec.rb +34 -34
  74. data/spec/watirspec/after_hooks_spec.rb +78 -35
  75. data/spec/watirspec/alert_spec.rb +10 -0
  76. data/spec/watirspec/browser_spec.rb +27 -1
  77. data/spec/watirspec/element_hidden_spec.rb +6 -0
  78. data/spec/watirspec/elements/button_spec.rb +5 -11
  79. data/spec/watirspec/elements/buttons_spec.rb +1 -1
  80. data/spec/watirspec/elements/checkbox_spec.rb +2 -15
  81. data/spec/watirspec/elements/date_time_field_spec.rb +6 -1
  82. data/spec/watirspec/elements/dd_spec.rb +0 -17
  83. data/spec/watirspec/elements/del_spec.rb +0 -14
  84. data/spec/watirspec/elements/div_spec.rb +0 -18
  85. data/spec/watirspec/elements/dl_spec.rb +0 -17
  86. data/spec/watirspec/elements/dt_spec.rb +0 -17
  87. data/spec/watirspec/elements/element_spec.rb +177 -17
  88. data/spec/watirspec/elements/elements_spec.rb +7 -6
  89. data/spec/watirspec/elements/em_spec.rb +0 -13
  90. data/spec/watirspec/elements/filefield_spec.rb +0 -11
  91. data/spec/watirspec/elements/form_spec.rb +6 -0
  92. data/spec/watirspec/elements/hn_spec.rb +0 -14
  93. data/spec/watirspec/elements/iframe_spec.rb +15 -0
  94. data/spec/watirspec/elements/ins_spec.rb +0 -14
  95. data/spec/watirspec/elements/labels_spec.rb +1 -1
  96. data/spec/watirspec/elements/li_spec.rb +0 -14
  97. data/spec/watirspec/elements/link_spec.rb +22 -14
  98. data/spec/watirspec/elements/links_spec.rb +13 -0
  99. data/spec/watirspec/elements/list_spec.rb +15 -0
  100. data/spec/watirspec/elements/ol_spec.rb +0 -14
  101. data/spec/watirspec/elements/option_spec.rb +0 -10
  102. data/spec/watirspec/elements/p_spec.rb +0 -14
  103. data/spec/watirspec/elements/pre_spec.rb +0 -14
  104. data/spec/watirspec/elements/radio_spec.rb +0 -14
  105. data/spec/watirspec/elements/select_list_spec.rb +0 -10
  106. data/spec/watirspec/elements/span_spec.rb +4 -15
  107. data/spec/watirspec/elements/strong_spec.rb +4 -15
  108. data/spec/watirspec/elements/table_nesting_spec.rb +1 -1
  109. data/spec/watirspec/elements/table_spec.rb +7 -0
  110. data/spec/watirspec/elements/text_field_spec.rb +10 -2
  111. data/spec/watirspec/elements/text_fields_spec.rb +1 -1
  112. data/spec/watirspec/elements/tr_spec.rb +1 -1
  113. data/spec/watirspec/elements/ul_spec.rb +0 -14
  114. data/spec/watirspec/html/closeable.html +8 -0
  115. data/spec/watirspec/html/forms_with_input_elements.html +28 -23
  116. data/spec/watirspec/html/nested_elements.html +9 -9
  117. data/spec/watirspec/html/obscured.html +34 -0
  118. data/spec/watirspec/html/tables.html +13 -13
  119. data/spec/watirspec/radio_set_spec.rb +5 -0
  120. data/spec/watirspec/selector_builder/button_spec.rb +254 -0
  121. data/spec/watirspec/selector_builder/cell_spec.rb +93 -0
  122. data/spec/watirspec/selector_builder/element_spec.rb +639 -0
  123. data/spec/watirspec/selector_builder/row_spec.rb +150 -0
  124. data/spec/watirspec/selector_builder/text_spec.rb +170 -0
  125. data/spec/watirspec/support/rspec_matchers.rb +6 -1
  126. data/spec/watirspec/user_editable_spec.rb +4 -0
  127. data/spec/watirspec/wait_spec.rb +65 -14
  128. data/spec/watirspec/window_switching_spec.rb +54 -1
  129. data/spec/watirspec_helper.rb +2 -0
  130. data/watir.gemspec +7 -1
  131. metadata +86 -8
  132. data/lib/watir/locators/text_area/locator.rb +0 -13
  133. data/lib/watir/xpath_support.rb +0 -18
@@ -45,7 +45,14 @@ module Watir
45
45
  #
46
46
 
47
47
  def exists?
48
- return false if located? && stale?
48
+ if located? && stale?
49
+ Watir.logger.deprecate 'Checking `#exists? == false` to determine a stale element',
50
+ '`#stale? == true`',
51
+ reference: 'http://watir.com/staleness-changes',
52
+ ids: [:stale_exists]
53
+ # TODO: Change this to `reset!` after removing deprecation
54
+ return false
55
+ end
49
56
 
50
57
  assert_exists
51
58
  true
@@ -246,15 +253,13 @@ module Watir
246
253
  end
247
254
 
248
255
  #
249
- # Returns value of the element.
256
+ # Returns list of class values.
250
257
  #
251
- # @return [String]
258
+ # @return [Array]
252
259
  #
253
260
 
254
- def value
255
- attribute_value('value') || ''
256
- rescue Selenium::WebDriver::Error::InvalidElementStateError
257
- ''
261
+ def classes
262
+ class_name.split
258
263
  end
259
264
 
260
265
  #
@@ -448,7 +453,7 @@ module Watir
448
453
  Watir.logger.warn msg, ids: [:visible_element]
449
454
  displayed = display_check
450
455
  if displayed.nil? && display_check
451
- Watir.logger.deprecate 'Checking `#present? == false` to determine a stale element',
456
+ Watir.logger.deprecate 'Checking `#visible? == false` to determine a stale element',
452
457
  '`#stale? == true`',
453
458
  reference: 'http://watir.com/staleness-changes',
454
459
  ids: [:stale_visible]
@@ -490,6 +495,21 @@ module Watir
490
495
  false
491
496
  end
492
497
 
498
+ #
499
+ # Returns true if the element's center point is covered by a non-descendant element.
500
+ #
501
+ # @return [Boolean]
502
+ #
503
+
504
+ def obscured?
505
+ element_call do
506
+ return true unless present?
507
+
508
+ scroll_into_view
509
+ execute_js(:elementObscured, self)
510
+ end
511
+ end
512
+
493
513
  #
494
514
  # Returns given style property of this element.
495
515
  #
@@ -557,7 +577,7 @@ module Watir
557
577
  #
558
578
 
559
579
  def stale?
560
- raise Watir::Exception::Error, 'Can not check staleness of unused element' unless @element
580
+ raise Error, 'Can not check staleness of unused element' unless @element
561
581
 
562
582
  ensure_context
563
583
  stale_in_context?
@@ -581,6 +601,7 @@ module Watir
581
601
  def locate
582
602
  ensure_context
583
603
  locate_in_context
604
+ self
584
605
  end
585
606
 
586
607
  #
@@ -627,7 +648,7 @@ module Watir
627
648
  begin
628
649
  @query_scope.wait_for_exists unless @query_scope.is_a? Browser
629
650
  wait_until(&:exists?)
630
- rescue Watir::Wait::TimeoutError
651
+ rescue Wait::TimeoutError
631
652
  msg = "timed out after #{Watir.default_timeout} seconds, waiting for #{inspect} to be located"
632
653
  raise unknown_exception, msg
633
654
  end
@@ -639,8 +660,8 @@ module Watir
639
660
 
640
661
  begin
641
662
  @query_scope.wait_for_present unless @query_scope.is_a? Browser
642
- wait_until_present
643
- rescue Watir::Wait::TimeoutError
663
+ wait_until(&:present?)
664
+ rescue Wait::TimeoutError
644
665
  msg = "element located, but timed out after #{Watir.default_timeout} seconds, " \
645
666
  "waiting for #{inspect} to be present"
646
667
  raise unknown_exception, msg
@@ -651,11 +672,12 @@ module Watir
651
672
  return assert_enabled unless Watir.relaxed_locate?
652
673
 
653
674
  wait_for_exists
654
- return if [Input, Button, Select, Option].none? { |c| is_a? c }
675
+ return unless [Input, Button, Select, Option].any? { |c| is_a? c } || @content_editable
676
+ return if enabled?
655
677
 
656
678
  begin
657
679
  wait_until(&:enabled?)
658
- rescue Watir::Wait::TimeoutError
680
+ rescue Wait::TimeoutError
659
681
  raise_disabled
660
682
  end
661
683
  end
@@ -666,12 +688,12 @@ module Watir
666
688
  raise_writable unless !respond_to?(:readonly?) || !readonly?
667
689
  end
668
690
 
691
+ return if !respond_to?(:readonly?) || !readonly?
692
+
669
693
  begin
670
694
  wait_until { !respond_to?(:readonly?) || !readonly? }
671
- rescue Watir::Wait::TimeoutError
672
- message = "element present and enabled, but timed out after #{Watir.default_timeout} seconds, " \
673
- "waiting for #{inspect} to not be readonly"
674
- raise ObjectReadOnlyException, message
695
+ rescue Wait::TimeoutError
696
+ raise_writable
675
697
  end
676
698
  end
677
699
 
@@ -696,7 +718,7 @@ module Watir
696
718
  private
697
719
 
698
720
  def unknown_exception
699
- Watir::Exception::UnknownObjectException
721
+ UnknownObjectException
700
722
  end
701
723
 
702
724
  def raise_writable
@@ -721,16 +743,12 @@ module Watir
721
743
  self.class
722
744
  end
723
745
 
724
- def attribute?(attribute_name)
725
- !attribute_value(attribute_name).nil?
726
- end
727
-
728
746
  def assert_enabled
729
747
  raise ObjectDisabledException, "object is disabled #{inspect}" unless element_call { @element.enabled? }
730
748
  end
731
749
 
732
750
  def assert_is_element(obj)
733
- raise TypeError, "execpted Watir::Element, got #{obj.inspect}:#{obj.class}" unless obj.is_a? Watir::Element
751
+ raise TypeError, "execpted Watir::Element, got #{obj.inspect}:#{obj.class}" unless obj.is_a? Element
734
752
  end
735
753
 
736
754
  # Removes duplication in #present? & #visible? and makes setting deprecation notice easier
@@ -777,7 +795,7 @@ module Watir
777
795
  raise_disabled unless %i[wait_for_present wait_for_enabled wait_for_writable].include?(precondition)
778
796
  retry
779
797
  rescue Selenium::WebDriver::Error::NoSuchWindowError
780
- raise Exception::NoMatchingWindowFoundException, 'browser window was closed'
798
+ raise NoMatchingWindowFoundException, 'browser window was closed'
781
799
  ensure
782
800
  Watir.logger.info "<- `Completed #{inspect}##{caller}`"
783
801
  Wait.timer.reset! unless already_locked
@@ -5,7 +5,7 @@ module Watir
5
5
  end
6
6
 
7
7
  def click
8
- raise Watir::Exception::ObjectDisabledException, 'click is not available on the hidden field element'
8
+ raise ObjectDisabledException, 'click is not available on the hidden field element'
9
9
  end
10
10
  end
11
11
 
@@ -45,7 +45,7 @@ module Watir
45
45
  #
46
46
 
47
47
  def execute_script(script, *args)
48
- args.map! { |e| e.is_a?(Watir::Element) ? e.wd : e }
48
+ args.map! { |e| e.is_a?(Element) ? e.wd : e }
49
49
  returned = driver.execute_script(script, *args)
50
50
 
51
51
  browser.wrap_elements_in(self, returned)
@@ -77,7 +77,7 @@ module Watir
77
77
  private
78
78
 
79
79
  def unknown_exception
80
- Watir::Exception::UnknownFrameException
80
+ UnknownFrameException
81
81
  end
82
82
  end # IFrame
83
83
 
@@ -105,6 +105,8 @@ module Watir
105
105
  #
106
106
 
107
107
  class FramedDriver
108
+ include Exception
109
+
108
110
  def initialize(element, browser)
109
111
  @element = element
110
112
  @browser = browser
@@ -125,15 +127,15 @@ module Watir
125
127
  @driver.switch_to.frame @element
126
128
  @browser.default_context = false
127
129
  rescue Selenium::WebDriver::Error::NoSuchFrameError => e
128
- raise Exception::UnknownFrameException, e.message
130
+ raise UnknownFrameException, e.message
129
131
  end
130
132
 
131
133
  def wd
132
134
  @element
133
135
  end
134
136
 
135
- def respond_to_missing?(meth)
136
- @driver.respond_to?(meth) || @element.respond_to?(meth)
137
+ def respond_to_missing?(meth, _include_private = false)
138
+ @driver.respond_to?(meth) || @element.respond_to?(meth) || super
137
139
  end
138
140
 
139
141
  def method_missing(meth, *args, &blk)
@@ -46,24 +46,13 @@ module Watir
46
46
  #
47
47
  # Returns the text of option.
48
48
  #
49
- # Note that the text is either one of the following respectively:
50
- # * label attribute
51
- # * text attribute
52
- # * inner element text
49
+ # getAttribute atom pulls the text value if the label does not exist
53
50
  #
54
51
  # @return [String]
55
52
  #
56
53
 
57
54
  def text
58
- # A little unintuitive - we'll return the 'label' or 'text' attribute if
59
- # they exist, otherwise the inner text of the element
60
-
61
- %i[label text].each do |a|
62
- val = attribute_value(a)
63
- return val unless val.nil?
64
- end
65
-
66
- super
55
+ attribute_value(:label)
67
56
  end
68
57
  end # Option
69
58
  end # Watir
@@ -1,13 +1,11 @@
1
1
  module Watir
2
2
  class Select < HTMLElement
3
- include Watir::Exception
4
-
5
3
  #
6
4
  # Clears all selected options.
7
5
  #
8
6
 
9
7
  def clear
10
- raise Error, 'you can only clear multi-selects' unless multiple?
8
+ raise Exception::Error, 'you can only clear multi-selects' unless multiple?
11
9
 
12
10
  selected_options.each(&:click)
13
11
  end
@@ -146,13 +144,11 @@ module Watir
146
144
  def select_by(str_or_rx)
147
145
  found = find_options(:value, str_or_rx)
148
146
 
149
- if found && found.size > 1
147
+ if found.size > 1
150
148
  Watir.logger.deprecate 'Selecting Multiple Options with #select', '#select_all',
151
149
  ids: [:select_by]
152
150
  end
153
- return select_matching(found) if found&.any?
154
-
155
- raise NoValueFoundException, "#{str_or_rx.inspect} not found in select list"
151
+ select_matching(found)
156
152
  end
157
153
 
158
154
  def select_by!(str_or_rx, number)
@@ -189,7 +185,7 @@ module Watir
189
185
  next unless what.is_a?(String) ? value == what : value =~ what
190
186
  return true if opt.enabled?
191
187
 
192
- raise Watir::Exception::ObjectDisabledException, "option matching #{what} by #{how} on #{inspect} is disabled"
188
+ raise ObjectDisabledException, "option matching #{what} by #{how} on #{inspect} is disabled"
193
189
  end
194
190
  false
195
191
  end
@@ -199,9 +195,7 @@ module Watir
199
195
 
200
196
  found = find_options :text, str_or_rx
201
197
 
202
- return select_matching(found) if found
203
-
204
- raise NoValueFoundException, "#{str_or_rx.inspect} not found in select list"
198
+ select_matching(found)
205
199
  end
206
200
 
207
201
  def find_options(how, str_or_rx)
@@ -216,6 +210,7 @@ module Watir
216
210
  raise TypeError, "expected String or Regexp, got #{str_or_rx.inspect}:#{str_or_rx.class}"
217
211
  end
218
212
  end
213
+ # TODO: Remove conditional when remove relaxed_locate toggle
219
214
  return @found unless @found.empty?
220
215
 
221
216
  raise NoValueFoundException, "#{str_or_rx.inspect} not found in select list"
@@ -228,17 +223,6 @@ module Watir
228
223
  elements.each { |e| e.click unless e.selected? }
229
224
  elements.first.exist? ? elements.first.text : ''
230
225
  end
231
-
232
- def matches_regexp?(how, element, exp)
233
- case how
234
- when :text
235
- element.text =~ exp || element.label =~ exp
236
- when :value
237
- element.value =~ exp
238
- else
239
- raise Error, "unknown how: #{how.inspect}"
240
- end
241
- end
242
226
  end # Select
243
227
 
244
228
  module Container
@@ -27,7 +27,7 @@ module Watir
27
27
 
28
28
  def hashes
29
29
  all_rows = rows.locate
30
- header_row = all_rows.first || raise(Exception::Error, 'no rows in table')
30
+ header_row = all_rows.first || raise(Error, 'no rows in table')
31
31
 
32
32
  all_rows.entries[1..-1].map do |row|
33
33
  cell_size_check(header_row, row)
@@ -69,7 +69,7 @@ module Watir
69
69
 
70
70
  index = cell_row.selector[:index]
71
71
  row_id = index ? "row at index #{index - 1}" : 'designated row'
72
- raise Exception::Error, "#{row_id} has #{row_size} cells, while header row has #{header_size}"
72
+ raise Error, "#{row_id} has #{row_size} cells, while header row has #{header_size}"
73
73
  end
74
74
  end # Table
75
75
  end # Watir
@@ -7,9 +7,8 @@ module Watir
7
7
  class ObjectDisabledException < Error; end
8
8
  class ObjectReadOnlyException < Error; end
9
9
  class NoValueFoundException < Error; end
10
- class UnknownCellException < Error; end
11
10
  class NoMatchingWindowFoundException < Error; end
12
11
  class UnknownFrameException < Error; end
13
- class UnknownRowException < Error; end
12
+ class LocatorException < Error; end
14
13
  end # Exception
15
14
  end # Watir
@@ -2,7 +2,7 @@ require 'tsort'
2
2
 
3
3
  module Watir
4
4
  module Generator
5
- module Base
5
+ class Base
6
6
  class IDLSorter
7
7
  include TSort
8
8
 
@@ -1,6 +1,6 @@
1
1
  module Watir
2
2
  module Generator
3
- module Base
3
+ class Base
4
4
  class SpecExtractor
5
5
  IDL_SELECTOR = "//pre[contains(@class, 'idl')]".freeze
6
6
 
@@ -49,7 +49,7 @@ module Watir
49
49
  private
50
50
 
51
51
  def download_and_parse
52
- URI.open(@uri) { |io| @doc = Nokogiri.HTML(io) }
52
+ File.open(@uri) { |io| @doc = Nokogiri.HTML(io) }
53
53
  end
54
54
 
55
55
  def extract_idl_parts
@@ -1,6 +1,6 @@
1
1
  module Watir
2
2
  module Generator
3
- module Base
3
+ class Base
4
4
  class Visitor < WebIDL::RubySexpVisitor
5
5
  STRING_TYPES = ['WindowProxy', 'ValidityState', 'TimeRanges', 'Location',
6
6
  'Any', 'TimedTrackArray', 'TimedTrack', 'TextTrackArray', 'TextTrack',
@@ -4,7 +4,6 @@ module Watir
4
4
  private
5
5
 
6
6
  def ignored_tags
7
- # ignore the link element for now
8
7
  %w[link]
9
8
  end
10
9
 
@@ -1,6 +1,6 @@
1
1
  module Watir
2
2
  module Generator
3
- module HTML
3
+ class HTML
4
4
  class SpecExtractor < Base::SpecExtractor
5
5
  private
6
6
 
@@ -1,6 +1,6 @@
1
1
  module Watir
2
2
  module Generator
3
- module HTML
3
+ class HTML
4
4
  class Visitor < Base::Visitor
5
5
  def classify_regexp
6
6
  /^HTML(.+)Element$/
@@ -1,6 +1,6 @@
1
1
  module Watir
2
2
  module Generator
3
- module SVG
3
+ class SVG
4
4
  class SpecExtractor < Base::SpecExtractor
5
5
  private
6
6
 
@@ -1,6 +1,6 @@
1
1
  module Watir
2
2
  module Generator
3
- module SVG
3
+ class SVG
4
4
  class Visitor < Base::Visitor
5
5
  def classify_regexp
6
6
  /^SVG(.+)Element$/
@@ -148,5 +148,16 @@ module Watir
148
148
  def select_text(str)
149
149
  element_call { execute_js :selectText, @element, str }
150
150
  end
151
+
152
+ #
153
+ # Selects text on page (as if dragging clicked mouse across provided text).
154
+ #
155
+ # @example
156
+ # browser.li(id: 'non_link_1').selected_text
157
+ #
158
+
159
+ def selected_text
160
+ element_call { execute_js :selectedText }
161
+ end
151
162
  end # JSExecution
152
163
  end # Watir