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, DragTo, 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
-
#shadow_root ⇒ 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.
70
71
72
73
74
|
# File 'lib/capybara/playwright/node.rb', line 70
def initialize(driver, page, element)
super(driver, element)
@page = page
@element = element
end
|
Instance Method Details
#==(other) ⇒ Object
934
935
936
937
938
|
# File 'lib/capybara/playwright/node.rb', line 934
def ==(other)
return false unless other.is_a?(Node)
@element.evaluate('(self, other) => self == other', arg: other.element)
end
|
#[](name) ⇒ Object
144
145
146
147
148
|
# File 'lib/capybara/playwright/node.rb', line 144
def [](name)
assert_element_not_stale {
property(name) || attribute(name)
}
end
|
#all_text ⇒ Object
111
112
113
114
115
116
117
118
119
120
|
# File 'lib/capybara/playwright/node.rb', line 111
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
837
838
839
840
841
|
# File 'lib/capybara/playwright/node.rb', line 837
def checked?
assert_element_not_stale {
@element.evaluate('el => !!el.checked')
}
end
|
#click(keys = [], **options) ⇒ Object
364
365
366
367
|
# File 'lib/capybara/playwright/node.rb', line 364
def click(keys = [], **options)
click_options = ClickOptions.new(@element, keys, options, capybara_default_wait_time)
@element.click(**click_options.as_params)
end
|
#disabled? ⇒ Boolean
849
850
851
852
853
854
855
856
857
858
859
|
# File 'lib/capybara/playwright/node.rb', line 849
def disabled?
@element.evaluate(<<~JAVASCRIPT)
function(el) {
const xpath = 'parent::optgroup[@disabled] | \
ancestor::select[@disabled] | \
parent::fieldset[@disabled] | \
ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]';
return el.disabled || document.evaluate(xpath, el, null, XPathResult.BOOLEAN_TYPE, null).booleanValue
}
JAVASCRIPT
end
|
#double_click(keys = [], **options) ⇒ Object
376
377
378
379
|
# File 'lib/capybara/playwright/node.rb', line 376
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
638
639
640
|
# File 'lib/capybara/playwright/node.rb', line 638
def drag_to(element, **options)
DragTo.new(@page, @element, element.element, options).execute
end
|
#drop(*args) ⇒ Object
712
713
714
|
# File 'lib/capybara/playwright/node.rb', line 712
def drop(*args)
raise NotImplementedError
end
|
#find_css(query, **options) ⇒ Object
948
949
950
951
952
953
954
|
# File 'lib/capybara/playwright/node.rb', line 948
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
940
941
942
943
944
945
946
|
# File 'lib/capybara/playwright/node.rb', line 940
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
634
635
636
|
# File 'lib/capybara/playwright/node.rb', line 634
def hover
@element.hover(timeout: capybara_default_wait_time)
end
|
#inspect ⇒ Object
930
931
932
|
# File 'lib/capybara/playwright/node.rb', line 930
def inspect
%(#<#{self.class} tag="#{tag_name}" path="#{path}">)
end
|
#multiple? ⇒ Boolean
865
866
867
|
# File 'lib/capybara/playwright/node.rb', line 865
def multiple?
@element.evaluate('el => el.multiple')
end
|
#obscured? ⇒ Boolean
833
834
835
|
# File 'lib/capybara/playwright/node.rb', line 833
def obscured?
@element.capybara_obscured?
end
|
#path ⇒ Object
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
|
# File 'lib/capybara/playwright/node.rb', line 881
def path
assert_element_not_stale {
@element.evaluate(<<~JAVASCRIPT)
(el) => {
var xml = document;
var xpath = '';
var pos, tempitem2;
if (el.getRootNode && el.getRootNode() instanceof ShadowRoot) {
return "(: Shadow DOM element - no XPath :)";
};
while(el !== xml.documentElement) {
pos = 0;
tempitem2 = el;
while(tempitem2) {
if (tempitem2.nodeType === 1 && tempitem2.nodeName === el.nodeName) { // If it is ELEMENT_NODE of the same name
pos += 1;
}
tempitem2 = tempitem2.previousSibling;
}
if (el.namespaceURI != xml.documentElement.namespaceURI) {
xpath = "*[local-name()='"+el.nodeName+"' and namespace-uri()='"+(el.namespaceURI===null?'':el.namespaceURI)+"']["+pos+']'+'/'+xpath;
} else {
xpath = el.nodeName.toUpperCase()+"["+pos+"]/"+xpath;
}
el = el.parentNode;
}
xpath = '/'+xml.documentElement.nodeName.toUpperCase()+'/'+xpath;
xpath = xpath.replace(/\\/$/, '');
return xpath;
}
JAVASCRIPT
}
end
|
#readonly? ⇒ Boolean
861
862
863
|
# File 'lib/capybara/playwright/node.rb', line 861
def readonly?
!@element.editable?
end
|
#rect ⇒ Object
869
870
871
872
873
874
875
876
877
878
879
|
# File 'lib/capybara/playwright/node.rb', line 869
def rect
assert_element_not_stale {
@element.evaluate(<<~JAVASCRIPT)
function(el){
const rects = [...el.getClientRects()]
const rect = rects.find(r => (r.height && r.width)) || el.getBoundingClientRect();
return rect.toJSON();
}
JAVASCRIPT
}
end
|
#right_click(keys = [], **options) ⇒ Object
369
370
371
372
373
374
|
# File 'lib/capybara/playwright/node.rb', line 369
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
|
716
717
718
719
720
721
722
723
724
725
726
727
728
729
|
# File 'lib/capybara/playwright/node.rb', line 716
def scroll_by(x, y)
js = <<~JAVASCRIPT
(el, [x, y]) => {
if (el.scrollBy){
el.scrollBy(x, y);
} else {
el.scrollTop = el.scrollTop + y;
el.scrollLeft = el.scrollLeft + x;
}
}
JAVASCRIPT
@element.evaluate(js, arg: [x, y])
end
|
731
732
733
734
735
736
737
738
739
740
741
742
|
# File 'lib/capybara/playwright/node.rb', line 731
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
337
338
339
340
341
342
343
344
345
346
347
348
|
# File 'lib/capybara/playwright/node.rb', line 337
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
843
844
845
846
847
|
# File 'lib/capybara/playwright/node.rb', line 843
def selected?
assert_element_not_stale {
@element.evaluate('el => !!el.selected')
}
end
|
#send_keys(*args) ⇒ Object
460
461
462
|
# File 'lib/capybara/playwright/node.rb', line 460
def send_keys(*args)
SendKeys.new(@element, args).execute
end
|
#set(value, **options) ⇒ Object
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
212
213
214
215
216
217
218
|
# File 'lib/capybara/playwright/node.rb', line 181
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
|
#shadow_root ⇒ Object
919
920
921
922
923
924
925
926
927
928
|
# File 'lib/capybara/playwright/node.rb', line 919
def shadow_root
ShadowRootNode.new(@driver, @page, @element)
end
|
#style(styles) ⇒ Object
173
174
175
176
177
|
# File 'lib/capybara/playwright/node.rb', line 173
def style(styles)
raise NotImplementedError
end
|
#tag_name ⇒ Object
795
796
797
|
# File 'lib/capybara/playwright/node.rb', line 795
def tag_name
@tag_name ||= @element.evaluate('e => e.tagName.toLowerCase()')
end
|
#trigger(event) ⇒ Object
915
916
917
|
# File 'lib/capybara/playwright/node.rb', line 915
def trigger(event)
@element.dispatch_event(event)
end
|
#unselect_option ⇒ Object
350
351
352
353
354
355
356
357
358
|
# File 'lib/capybara/playwright/node.rb', line 350
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
159
160
161
162
163
164
165
166
167
168
169
170
171
|
# File 'lib/capybara/playwright/node.rb', line 159
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
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
|
# File 'lib/capybara/playwright/node.rb', line 799
def visible?
assert_element_not_stale {
@element.evaluate(<<~JAVASCRIPT)
function(el) {
if (el.tagName == 'AREA'){
const map_name = document.evaluate('./ancestor::map/@name', el, null, XPathResult.STRING_TYPE, null).stringValue;
el = document.querySelector(`img[usemap='#${map_name}']`);
if (!el){
return false;
}
}
var forced_visible = false;
while (el) {
const style = window.getComputedStyle(el);
if (style.visibility == 'visible')
forced_visible = true;
if ((style.display == 'none') ||
((style.visibility == 'hidden') && !forced_visible) ||
(parseFloat(style.opacity) == 0)) {
return false;
}
var parent = el.parentElement;
if (parent && (parent.tagName == 'DETAILS') && !parent.open && (el.tagName != 'SUMMARY')) {
return false;
}
el = parent;
}
return true;
}
JAVASCRIPT
}
end
|
#visible_text ⇒ Object
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
# File 'lib/capybara/playwright/node.rb', line 122
def visible_text
assert_element_not_stale {
return '' unless visible?
text = @element.evaluate(<<~JAVASCRIPT)
function(el){
if (el.nodeName == 'TEXTAREA'){
return el.textContent;
} else if (el instanceof SVGElement) {
return el.textContent;
} else {
return el.innerText;
}
}
JAVASCRIPT
text.to_s.scrub.gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
.gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
.gsub(/\n+/, "\n")
.tr("\u00a0", ' ')
}
end
|