Skip to content

Commit afb9bb1

Browse files
authored
Merge pull request #230 from rubycdp/bugfix/issue#229-node-select-picks-option-with-empty-value-instead-provided-value
2 parents 8e13c8e + e87c910 commit afb9bb1

File tree

5 files changed

+64
-24
lines changed

5 files changed

+64
-24
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ a block with this page, after which the page is closed.
1313
- `Ferrum::Browser` supports new option `:proxy` https://github.com/rubycdp/ferrum#proxy
1414
- `Ferrum::Network::Response#params` attr_reader added
1515
- `Ferrum::Node`
16-
- `#selected` check selected option
17-
- `#select` select option
16+
- `#selected` checks selected options. Returns an array of `Ferrum::Node` that's selected.
17+
- `#select` selects options by passed attribute, default: `:value`.
1818
- `#computed_style` returns hash of computed styles
1919
- `Ferrum::JavaScriptError#stack_trace` attr_reader
2020
- Windows support

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,9 +1098,23 @@ frame.at_css("//a[text() = 'Log in']") # => Node
10981098
#### property
10991099
#### attribute
11001100
#### evaluate
1101-
#### selected : `Array`
1101+
#### selected : `Array<Node>`
11021102
#### select
11031103

1104+
(chainable) Selects options by passed attribute.
1105+
1106+
```ruby
1107+
browser.at_xpath("//*[select]").select(["1"]) # => Node (select)
1108+
browser.at_xpath("//*[select]").select(["text"], by: :text) # => Node (select)
1109+
```
1110+
1111+
Accept string, array or strings:
1112+
```ruby
1113+
browser.at_xpath("//*[select]").select("1")
1114+
browser.at_xpath("//*[select]").select("1", "2")
1115+
browser.at_xpath("//*[select]").select(["1", "2"])
1116+
```
1117+
11041118

11051119
## Thread safety ##
11061120

lib/ferrum/node.rb

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,33 +136,30 @@ def selected
136136
if (element.nodeName.toLowerCase() !== 'select') {
137137
throw new Error('Element is not a <select> element.');
138138
}
139-
return Array.from(element).filter(option => option.selected).map((option) => option.text);
139+
return Array.from(element).filter(option => option.selected);
140140
}
141141
JS
142142
page.evaluate_func(function, self)
143143
end
144144

145-
def select(*values)
145+
def select(*values, by: :value)
146146
tap do
147147
function = <<~JS
148-
function(element, values) {
148+
function(element, values, by) {
149149
if (element.nodeName.toLowerCase() !== 'select') {
150150
throw new Error('Element is not a <select> element.');
151151
}
152152
const options = Array.from(element.options);
153153
element.value = undefined;
154154
for (const option of options) {
155-
option.selected = values.includes(option.value);
155+
option.selected = values.some((value) => option[by] === value);
156156
if (option.selected && !element.multiple) break;
157157
}
158158
element.dispatchEvent(new Event('input', { bubbles: true }));
159159
element.dispatchEvent(new Event('change', { bubbles: true }));
160-
return options
161-
.filter((option) => option.selected)
162-
.map((option) => option.value);
163160
}
164161
JS
165-
page.evaluate_func(function, self, values.join(","))
162+
page.evaluate_func(function, self, values.flatten, by)
166163
end
167164
end
168165

spec/node_spec.rb

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,24 +89,24 @@ module Ferrum
8989
end
9090

9191
it "returns texts of selected options" do
92-
expect(browser.at_xpath("//*[@id='form_region']").selected).to eq(["Norway"])
92+
expect(browser.at_xpath("//*[@id='form_region']").selected.map(&:text)).to eq(["Norway"])
9393
end
9494

9595
context "when options exists but no selected option" do
9696
it "returns first option text as default value" do
97-
expect(browser.at_xpath("//*[@id='form_title']").selected).to eq(["Mrs"])
97+
expect(browser.at_xpath("//*[@id='form_title']").selected.map(&:text)).to eq(["Mrs"])
9898
end
9999
end
100100

101101
context "when no selected options" do
102102
it "returns empty array" do
103-
expect(browser.at_xpath("//*[@id='form_tendency']").selected).to eq([])
103+
expect(browser.at_xpath("//*[@id='form_tendency']").selected.map(&:text)).to eq([])
104104
end
105105
end
106106

107107
context "when selector is not <select>" do
108108
it "raises JavaScriptError with proper message" do
109-
expect { browser.at_xpath("//*[@id='customer_name']").selected }
109+
expect { browser.at_xpath("//*[@id='customer_name']").selected.map(&:text) }
110110
.to raise_exception(Ferrum::JavaScriptError, /Element is not a <select> element/)
111111
end
112112
end
@@ -118,13 +118,13 @@ module Ferrum
118118
end
119119

120120
it "picks option in select by match string argument" do
121-
expect(browser.at_xpath("//*[@id='form_title']").select("Miss").selected).to eq(["Miss"])
121+
expect(browser.at_xpath("//*[@id='form_title']").select("Miss").selected.map(&:text)).to eq(["Miss"])
122122
end
123123

124124
shared_examples "clears selected options with no exception" do |options|
125125
it "clears selected options with no exception" do
126-
expect(browser.at_xpath("//*[@id='form_title']").selected).to eq(["Mrs"])
127-
expect(browser.at_xpath("//*[@id='form_title']").select(options).selected).to eq([])
126+
expect(browser.at_xpath("//*[@id='form_title']").selected.map(&:text)).to eq(["Mrs"])
127+
expect(browser.at_xpath("//*[@id='form_title']").select(options).selected.map(&:text)).to eq([])
128128
end
129129
end
130130

@@ -142,18 +142,20 @@ module Ferrum
142142

143143
context "when one of option with provided texts does not exist" do
144144
it "picks only existed options with no exception" do
145-
expect(browser.at_xpath("//*[@id='form_title']").selected).to eq(["Mrs"])
146-
expect(browser.at_xpath("//*[@id='form_title']").select(%w[Mrs SQL]).selected).to eq(["Mrs"])
145+
expect(browser.at_xpath("//*[@id='form_title']").selected.map(&:text)).to eq(["Mrs"])
146+
expect(browser.at_xpath("//*[@id='form_title']").select(%w[Mrs SQL]).selected.map(&:text)).to eq(["Mrs"])
147147
end
148148
end
149149

150150
context "when select has multiple property" do
151151
it "picks options in select by match arguments as array" do
152-
expect(browser.at_xpath("//*[@id='form_languages']").select(%w[SQL Ruby]).selected).to eq(%w[Ruby SQL])
152+
expect(browser.at_xpath("//*[@id='form_languages']").select(%w[SQL Ruby]).selected.map(&:text))
153+
.to eq(%w[Ruby SQL])
153154
end
154155

155-
it "picks options in select by match arguments as string" do
156-
expect(browser.at_xpath("//*[@id='form_languages']").select("SQL, Ruby").selected).to eq(%w[Ruby SQL])
156+
it "picks options in select by match arguments as strings" do
157+
expect(browser.at_xpath("//*[@id='form_languages']").select("SQL", "Ruby").selected.map(&:text))
158+
.to eq(%w[Ruby SQL])
157159
end
158160
end
159161

@@ -166,7 +168,29 @@ module Ferrum
166168

167169
context "when provided texts of disabled option" do
168170
it "picks disabled option with no exception" do
169-
expect(browser.at_xpath("//*[@id='form_title']").select(["Other"]).selected).to eq(["Other"])
171+
expect(browser.at_xpath("//*[@id='form_title']").select(["Other"]).selected.map(&:text)).to eq(["Other"])
172+
end
173+
end
174+
175+
context "when option with text and value" do
176+
it "picks option in select by matched text" do
177+
expect(browser.at_xpath("//select[@id='form_locale']").select("Swedish", by: :text).selected.map(&:value))
178+
.to eq(["sv"])
179+
end
180+
end
181+
182+
context "when option with empty text/value" do
183+
it "picks option in select by match string argument" do
184+
expect(browser.at_xpath("//select[@id='empty_option']").select("AU").selected.map(&:value)).to eq(["AU"])
185+
end
186+
187+
it "picks empty option by match empty value argument" do
188+
expect(browser.at_xpath("//select[@id='empty_option']").select("").selected.map(&:value)).to eq([""])
189+
end
190+
191+
it "picks empty option by match empty text argument" do
192+
expect(browser.at_xpath("//select[@id='empty_option']").select("", by: :text).selected.map(&:text))
193+
.to eq([""])
170194
end
171195
end
172196
end

spec/support/views/form.erb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,3 +672,8 @@ New line after and before textarea tag
672672
<p>
673673
<input id="hidden_input" style="display: none"/>
674674
</p>
675+
676+
<select id="empty_option">
677+
<option value=""></option>
678+
<option value="AU">Australia</option>
679+
</select>

0 commit comments

Comments
 (0)