/
node.rb
138 lines (118 loc) · 3.35 KB
/
node.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
class Capybara::RackTest::Node < Capybara::Driver::Node
def text
Capybara::Helpers.normalize_whitespace(unnormalized_text)
end
def [](name)
string_node[name]
end
def value
string_node.value
end
def set(value)
if (Array === value) && !self[:multiple]
raise ArgumentError.new "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}"
end
if tag_name == 'input' and type == 'radio'
other_radios_xpath = XPath.generate { |x| x.anywhere(:input)[x.attr(:name).equals(self[:name])] }.to_s
driver.dom.xpath(other_radios_xpath).each { |node| node.remove_attribute("checked") }
native['checked'] = 'checked'
elsif tag_name == 'input' and type == 'checkbox'
if value && !native['checked']
native['checked'] = 'checked'
elsif !value && native['checked']
native.remove_attribute('checked')
end
elsif tag_name == 'input'
if (type == 'text' || type == 'password') && self[:maxlength] &&
!self[:maxlength].empty?
# Browser behavior for maxlength="0" is inconsistent, so we stick with
# Firefox, allowing no input
value = value[0...self[:maxlength].to_i]
end
if Array === value #Assert multiple attribute is present
value.each do |v|
new_native = native.clone
new_native.remove_attribute('value')
native.add_next_sibling(new_native)
new_native['value'] = v.to_s
end
native.remove
else
native['value'] = value.to_s
end
elsif tag_name == "textarea"
native.content = value.to_s
end
end
def select_option
if select_node['multiple'] != 'multiple'
select_node.find(".//option[@selected]").each { |node| node.native.remove_attribute("selected") }
end
native["selected"] = 'selected'
end
def unselect_option
if select_node['multiple'] != 'multiple'
raise Capybara::UnselectNotAllowed, "Cannot unselect option from single select box."
end
native.remove_attribute('selected')
end
def click
if tag_name == 'a'
method = self["data-method"] if driver.options[:respect_data_method]
method ||= :get
driver.follow(method, self[:href].to_s)
elsif (tag_name == 'input' and %w(submit image).include?(type)) or
((tag_name == 'button') and type.nil? or type == "submit")
Capybara::RackTest::Form.new(driver, form).submit(self)
end
end
def tag_name
native.node_name
end
def visible?
string_node.visible?
end
def checked?
string_node.checked?
end
def selected?
string_node.selected?
end
def path
native.path
end
def find(locator)
native.xpath(locator).map { |n| self.class.new(driver, n) }
end
def ==(other)
native == other.native
end
protected
def unnormalized_text
if !visible?
''
elsif native.text?
native.text
elsif native.element?
native.children.map do |child|
Capybara::RackTest::Node.new(driver, child).unnormalized_text
end.join
else
''
end
end
private
def string_node
@string_node ||= Capybara::Node::Simple.new(native)
end
# a reference to the select node if this is an option node
def select_node
find('./ancestor::select').first
end
def type
native[:type]
end
def form
native.ancestors('form').first
end
end