Class: Capybara::Playwright::Node
- Inherits:
-
Driver::Node
- Object
- Driver::Node
- Capybara::Playwright::Node
show all
- Defined in:
- lib/capybara/playwright/node.rb
Overview
Selector and checking methods are derived from twapole/apparition Action methods (click, select_option, …) uses playwright.
ref:
selenium: https://github.com/teamcapybara/capybara/blob/master/lib/capybara/selenium/node.rb
apparition: https://github.com/twalpole/apparition/blob/master/lib/capybara/apparition/node.rb
Defined Under Namespace
Modules: UpdateValueJS
Classes: Checkbox, ClickOptions, DateInput, DateTimeInput, FileUpload, JSValueInput, NotActionableError, RadioButton, SendKeys, Settable, StaleReferenceError, TextInput, TimeInput
Constant Summary
collapse
- SCROLL_POSITIONS =
{
top: '0',
bottom: 'el.scrollHeight',
center: '(el.scrollHeight - el.clientHeight)/2'
}.freeze
Instance Method Summary
collapse
-
#==(other) ⇒ Object
-
#[](name) ⇒ Object
-
#all_text ⇒ Object
-
#checked? ⇒ Boolean
-
#click(keys = [], **options) ⇒ Object
-
#disabled? ⇒ Boolean
-
#double_click(keys = [], **options) ⇒ Object
-
#drag_to(element, **options) ⇒ Object
-
#drop(*args) ⇒ Object
-
#find_css(query, **options) ⇒ Object
-
#find_xpath(query, **options) ⇒ Object
-
#hover ⇒ Object
-
#initialize(driver, page, element) ⇒ Node
constructor
-
#inspect ⇒ Object
-
#multiple? ⇒ Boolean
-
#obscured? ⇒ Boolean
-
#path ⇒ Object
-
#readonly? ⇒ Boolean
-
#rect ⇒ Object
-
#right_click(keys = [], **options) ⇒ Object
-
#scroll_by(x, y) ⇒ Object
-
#scroll_to(element, location, position = nil) ⇒ Object
-
#select_option ⇒ Object
-
#selected? ⇒ Boolean
-
#send_keys(*args) ⇒ Object
-
#set(value, **options) ⇒ Object
-
#style(styles) ⇒ Object
-
#tag_name ⇒ Object
-
#trigger(event) ⇒ Object
-
#unselect_option ⇒ Object
-
#value ⇒ Object
-
#visible? ⇒ Boolean
-
#visible_text ⇒ Object
Constructor Details
#initialize(driver, page, element) ⇒ Node
Returns a new instance of Node.
67
68
69
70
71
|
# File 'lib/capybara/playwright/node.rb', line 67
def initialize(driver, page, element)
super(driver, element)
@page = page
@element = element
end
|
Instance Method Details
#==(other) ⇒ Object
816
817
818
819
820
|
# File 'lib/capybara/playwright/node.rb', line 816
def ==(other)
return false unless other.is_a?(Node)
@element.evaluate('(self, other) => self == other', arg: other.element)
end
|
#[](name) ⇒ Object
137
138
139
140
141
|
# File 'lib/capybara/playwright/node.rb', line 137
def [](name)
assert_element_not_stale
property(name) || attribute(name)
end
|
#all_text ⇒ Object
104
105
106
107
108
109
110
111
112
113
|
# File 'lib/capybara/playwright/node.rb', line 104
def all_text
assert_element_not_stale
text = @element.text_content
text.to_s.gsub(/[\u200b\u200e\u200f]/, '')
.gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ')
.gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
.gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
.tr("\u00a0", ' ')
end
|
#checked? ⇒ Boolean
734
735
736
|
# File 'lib/capybara/playwright/node.rb', line 734
def checked?
@element.evaluate('el => !!el.checked')
end
|
#click(keys = [], **options) ⇒ Object
343
344
345
346
|
# File 'lib/capybara/playwright/node.rb', line 343
def click(keys = [], **options)
click_options = ClickOptions.new(@element, keys, options, capybara_default_wait_time)
@element.click(**click_options.as_params)
end
|
#disabled? ⇒ Boolean
742
743
744
745
746
747
748
749
750
751
752
|
# File 'lib/capybara/playwright/node.rb', line 742
def disabled?
@element.evaluate(" function(el) {\n const xpath = 'parent::optgroup[@disabled] | \\\n ancestor::select[@disabled] | \\\n parent::fieldset[@disabled] | \\\n ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]';\n return el.disabled || document.evaluate(xpath, el, null, XPathResult.BOOLEAN_TYPE, null).booleanValue\n }\n JAVASCRIPT\nend\n")
|
#double_click(keys = [], **options) ⇒ Object
355
356
357
358
|
# File 'lib/capybara/playwright/node.rb', line 355
def double_click(keys = [], **options)
click_options = ClickOptions.new(@element, keys, options, capybara_default_wait_time)
@element.dblclick(**click_options.as_params)
end
|
#drag_to(element, **options) ⇒ Object
607
608
609
|
# File 'lib/capybara/playwright/node.rb', line 607
def drag_to(element, **options)
raise NotImplementedError
end
|
#drop(*args) ⇒ Object
611
612
613
|
# File 'lib/capybara/playwright/node.rb', line 611
def drop(*args)
raise NotImplementedError
end
|
#find_css(query, **options) ⇒ Object
830
831
832
833
834
835
836
|
# File 'lib/capybara/playwright/node.rb', line 830
def find_css(query, **options)
assert_element_not_stale
@element.query_selector_all(query).map do |el|
Node.new(@driver, @page, el)
end
end
|
#find_xpath(query, **options) ⇒ Object
822
823
824
825
826
827
828
|
# File 'lib/capybara/playwright/node.rb', line 822
def find_xpath(query, **options)
assert_element_not_stale
@element.query_selector_all("xpath=#{query}").map do |el|
Node.new(@driver, @page, el)
end
end
|
#hover ⇒ Object
603
604
605
|
# File 'lib/capybara/playwright/node.rb', line 603
def hover
@element.hover(timeout: capybara_default_wait_time)
end
|
#inspect ⇒ Object
812
813
814
|
# File 'lib/capybara/playwright/node.rb', line 812
def inspect
%(#<#{self.class} tag="#{tag_name}" path="#{path}">)
end
|
#multiple? ⇒ Boolean
758
759
760
|
# File 'lib/capybara/playwright/node.rb', line 758
def multiple?
@element.evaluate('el => el.multiple')
end
|
#obscured? ⇒ Boolean
730
731
732
|
# File 'lib/capybara/playwright/node.rb', line 730
def obscured?
@element.capybara_obscured?
end
|
#path ⇒ Object
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
|
# File 'lib/capybara/playwright/node.rb', line 774
def path
assert_element_not_stale
@element.evaluate(" (el) => {\n var xml = document;\n var xpath = '';\n var pos, tempitem2;\n if (el.getRootNode && el.getRootNode() instanceof ShadowRoot) {\n return \"(: Shadow DOM element - no XPath :)\";\n };\n while(el !== xml.documentElement) {\n pos = 0;\n tempitem2 = el;\n while(tempitem2) {\n if (tempitem2.nodeType === 1 && tempitem2.nodeName === el.nodeName) { // If it is ELEMENT_NODE of the same name\n pos += 1;\n }\n tempitem2 = tempitem2.previousSibling;\n }\n if (el.namespaceURI != xml.documentElement.namespaceURI) {\n xpath = \"*[local-name()='\"+el.nodeName+\"' and namespace-uri()='\"+(el.namespaceURI===null?'':el.namespaceURI)+\"'][\"+pos+']'+'/'+xpath;\n } else {\n xpath = el.nodeName.toUpperCase()+\"[\"+pos+\"]/\"+xpath;\n }\n el = el.parentNode;\n }\n xpath = '/'+xml.documentElement.nodeName.toUpperCase()+'/'+xpath;\n xpath = xpath.replace(/\\\\/$/, '');\n return xpath;\n }\n JAVASCRIPT\nend\n")
|
#readonly? ⇒ Boolean
754
755
756
|
# File 'lib/capybara/playwright/node.rb', line 754
def readonly?
!@element.editable?
end
|
#rect ⇒ Object
762
763
764
765
766
767
768
769
770
771
772
|
# File 'lib/capybara/playwright/node.rb', line 762
def rect
assert_element_not_stale
@element.evaluate(" function(el){\n const rects = [...el.getClientRects()]\n const rect = rects.find(r => (r.height && r.width)) || el.getBoundingClientRect();\n return rect.toJSON();\n }\n JAVASCRIPT\nend\n")
|
#right_click(keys = [], **options) ⇒ Object
348
349
350
351
352
353
|
# File 'lib/capybara/playwright/node.rb', line 348
def right_click(keys = [], **options)
click_options = ClickOptions.new(@element, keys, options, capybara_default_wait_time)
params = click_options.as_params
params[:button] = 'right'
@element.click(**params)
end
|
615
616
617
618
619
620
621
622
623
624
625
626
627
628
|
# File 'lib/capybara/playwright/node.rb', line 615
def scroll_by(x, y)
js = " (el, [x, y]) => {\n if (el.scrollBy){\n el.scrollBy(x, y);\n } else {\n el.scrollTop = el.scrollTop + y;\n el.scrollLeft = el.scrollLeft + x;\n }\n }\n JAVASCRIPT\n\n @element.evaluate(js, arg: [x, y])\nend\n"
|
630
631
632
633
634
635
636
637
638
639
640
641
|
# File 'lib/capybara/playwright/node.rb', line 630
def scroll_to(element, location, position = nil)
if element.is_a? Capybara::Playwright::Node
scroll_element_to_location(element, location)
elsif location.is_a? Symbol
scroll_to_location(location)
else
scroll_to_coords(*position)
end
self
end
|
#select_option ⇒ Object
316
317
318
319
320
321
322
323
324
325
326
327
|
# File 'lib/capybara/playwright/node.rb', line 316
def select_option
return false if disabled?
select_element = parent_select_element
if select_element.evaluate('el => el.multiple')
selected_options = select_element.query_selector_all('option:checked')
selected_options << @element
select_element.select_option(element: selected_options, timeout: capybara_default_wait_time)
else
select_element.select_option(element: @element, timeout: capybara_default_wait_time)
end
end
|
#selected? ⇒ Boolean
738
739
740
|
# File 'lib/capybara/playwright/node.rb', line 738
def selected?
@element.evaluate('el => !!el.selected')
end
|
#send_keys(*args) ⇒ Object
436
437
438
|
# File 'lib/capybara/playwright/node.rb', line 436
def send_keys(*args)
SendKeys.new(@element, args).execute
end
|
#set(value, **options) ⇒ Object
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
|
# File 'lib/capybara/playwright/node.rb', line 174
def set(value, **options)
settable_class =
case tag_name
when 'input'
case attribute('type')
when 'radio'
RadioButton
when 'checkbox'
Checkbox
when 'file'
FileUpload
when 'date'
DateInput
when 'time'
TimeInput
when 'datetime-local'
DateTimeInput
when 'color'
JSValueInput
when 'range'
JSValueInput
else
TextInput
end
when 'textarea'
TextInput
else
if @element.editable?
TextInput
else
raise NotSupportedByDriverError
end
end
settable_class.new(@element, capybara_default_wait_time).set(value, **options)
rescue ::Playwright::TimeoutError => err
raise NotActionableError.new(err)
end
|
#style(styles) ⇒ Object
166
167
168
169
170
|
# File 'lib/capybara/playwright/node.rb', line 166
def style(styles)
raise NotImplementedError
end
|
#tag_name ⇒ Object
694
695
696
|
# File 'lib/capybara/playwright/node.rb', line 694
def tag_name
@tag_name ||= @element.evaluate('e => e.tagName.toLowerCase()')
end
|
#trigger(event) ⇒ Object
808
809
810
|
# File 'lib/capybara/playwright/node.rb', line 808
def trigger(event)
@element.dispatch_event(event)
end
|
#unselect_option ⇒ Object
329
330
331
332
333
334
335
336
337
|
# File 'lib/capybara/playwright/node.rb', line 329
def unselect_option
if parent_select_element.evaluate('el => el.multiple')
return false if disabled?
@element.evaluate('el => el.selected = false')
else
raise Capybara::UnselectNotAllowed, 'Cannot unselect option from single select box.'
end
end
|
#value ⇒ Object
152
153
154
155
156
157
158
159
160
161
162
163
164
|
# File 'lib/capybara/playwright/node.rb', line 152
def value
assert_element_not_stale
if tag_name == 'select' && @element.evaluate('el => el.multiple')
@element.query_selector_all('option:checked').map do |option|
option.evaluate('el => el.value')
end
else
@element.evaluate('el => el.value')
end
end
|
#visible? ⇒ Boolean
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
|
# File 'lib/capybara/playwright/node.rb', line 698
def visible?
@element.evaluate(" function(el) {\n if (el.tagName == 'AREA'){\n const map_name = document.evaluate('./ancestor::map/@name', el, null, XPathResult.STRING_TYPE, null).stringValue;\n el = document.querySelector(`img[usemap='\#${map_name}']`);\n if (!el){\n return false;\n }\n }\n var forced_visible = false;\n while (el) {\n const style = window.getComputedStyle(el);\n if (style.visibility == 'visible')\n forced_visible = true;\n if ((style.display == 'none') ||\n ((style.visibility == 'hidden') && !forced_visible) ||\n (parseFloat(style.opacity) == 0)) {\n return false;\n }\n var parent = el.parentElement;\n if (parent && (parent.tagName == 'DETAILS') && !parent.open && (el.tagName != 'SUMMARY')) {\n return false;\n }\n el = parent;\n }\n return true;\n }\n JAVASCRIPT\nend\n")
|
#visible_text ⇒ Object
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
# File 'lib/capybara/playwright/node.rb', line 115
def visible_text
assert_element_not_stale
return '' unless visible?
text = @element.evaluate(" function(el){\n if (el.nodeName == 'TEXTAREA'){\n return el.textContent;\n } else if (el instanceof SVGElement) {\n return el.textContent;\n } else {\n return el.innerText;\n }\n }\n JAVASCRIPT\n text.to_s.gsub(/\\A[[:space:]&&[^\\u00a0]]+/, '')\n .gsub(/[[:space:]&&[^\\u00a0]]+\\z/, '')\n .gsub(/\\n+/, \"\\n\")\n .tr(\"\\u00a0\", ' ')\nend\n")
|