Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: parse empty options in <select> #232

Merged
merged 1 commit into from
Jun 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions lib/puppeteer/element_handle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -384,22 +384,35 @@ def select(*values)
end

fn = <<~JAVASCRIPT
(element, values) => {
(element, vals) => {
const values = new Set(vals);
if (element.nodeName.toLowerCase() !== 'select') {
throw new Error('Element is not a <select> element.');
}

const options = Array.from(element.options);
element.value = undefined;
for (const option of options) {
option.selected = values.includes(option.value);
if (option.selected && !element.multiple) {
break;
const selectedValues = new Set();
if (!element.multiple) {
for (const option of element.options) {
option.selected = false;
}
for (const option of element.options) {
if (values.has(option.value)) {
option.selected = true;
selectedValues.add(option.value);
break;
}
}
} else {
for (const option of element.options) {
option.selected = values.has(option.value);
if (option.selected) {
selectedValues.add(option.value);
}
}
}
element.dispatchEvent(new Event('input', { bubbles: true }));
element.dispatchEvent(new Event('change', { bubbles: true }));
return options.filter(option => option.selected).map(option => option.value);
return [...selectedValues.values()];
}
JAVASCRIPT
evaluate(fn, values)
Expand Down
1 change: 1 addition & 0 deletions spec/assets/input/select.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
</head>
<body>
<select>
<option value="">Empty</option>
<option value="black">Black</option>
<option value="blue">Blue</option>
<option value="brown">Brown</option>
Expand Down
35 changes: 14 additions & 21 deletions spec/integration/page_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1455,13 +1455,11 @@ def check_metrics(page_metrics)
# );
# expect(result.length).toEqual(1);
# });
# it('should return [] on no values', async () => {
# const { page, server } = getTestState();

# await page.goto(server.PREFIX + '/input/select.html');
# const result = await page.select('select');
# expect(result).toEqual([]);
# });
it 'should return [] on no values', sinatra: true do
page.goto("#{server_prefix}/input/select.html")
result = page.select('select')
expect(result).to eq([])
end
# it('should deselect all options when passed no values for a multiple select', async () => {
# const { page, server } = getTestState();

Expand All @@ -1477,20 +1475,15 @@ def check_metrics(page_metrics)
# )
# ).toEqual(true);
# });
# it('should deselect all options when passed no values for a select without multiple', async () => {
# const { page, server } = getTestState();

# await page.goto(server.PREFIX + '/input/select.html');
# await page.select('select', 'blue', 'black', 'magenta');
# await page.select('select');
# expect(
# await page.$eval('select', (select: HTMLSelectElement) =>
# Array.from(select.options).every(
# (option: HTMLOptionElement) => !option.selected
# )
# )
# ).toEqual(true);
# });
it 'should deselect all options when passed no values for a select without multiple', sinatra: true do
page.goto("#{server_prefix}/input/select.html")
page.select('select', 'blue', 'black', 'magenta')
page.select('select')
first_selected = page.eval_on_selector('select', <<~JAVASCRIPT)
(select) => Array.from(select.options).filter((option) => option.selected)[0].value
JAVASCRIPT
expect(first_selected).to eq('')
end
# it('should throw if passed in non-strings', async () => {
# const { page } = getTestState();

Expand Down