fix: parse empty options in <select> (#8489)

This commit is contained in:
jrandolf 2022-06-09 13:27:34 +02:00 committed by GitHub
parent f64ec2051b
commit b30f3f44cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 30 deletions

View File

@ -766,7 +766,7 @@ export class ElementHandle<
* one is taken into account. * one is taken into account.
*/ */
async select(...values: string[]): Promise<string[]> { async select(...values: string[]): Promise<string[]> {
for (const value of values) for (const value of values) {
assert( assert(
helper.isString(value), helper.isString(value),
'Values must be strings. Found value "' + 'Values must be strings. Found value "' +
@ -775,26 +775,38 @@ export class ElementHandle<
typeof value + typeof value +
'"' '"'
); );
}
return this.evaluate<(element: Element, values: string[]) => string[]>( return this.evaluate((element: Element, vals: string[]): string[] => {
(element, values) => { const values = new Set(vals);
if (!(element instanceof HTMLSelectElement)) if (!(element instanceof HTMLSelectElement)) {
throw new Error('Element is not a <select> element.'); throw new Error('Element is not a <select> element.');
}
const options = Array.from(element.options); const selectedValues = new Set<string>();
element.value = ''; if (!element.multiple) {
for (const option of options) { for (const option of element.options) {
option.selected = values.includes(option.value); option.selected = false;
if (option.selected && !element.multiple) break; }
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('input', { bubbles: true }));
element.dispatchEvent(new Event('change', { bubbles: true })); element.dispatchEvent(new Event('change', { bubbles: true }));
return options return [...selectedValues.values()];
.filter((option) => option.selected) }, values);
.map((option) => option.value);
},
values
);
} }
/** /**

View File

@ -5,6 +5,7 @@
</head> </head>
<body> <body>
<select> <select>
<option value="">Empty</option>
<option value="black">Black</option> <option value="black">Black</option>
<option value="blue">Blue</option> <option value="blue">Blue</option>
<option value="brown">Brown</option> <option value="brown">Brown</option>

View File

@ -1887,12 +1887,13 @@ describe('Page', function () {
await page.select('select', 'blue', 'black', 'magenta'); await page.select('select', 'blue', 'black', 'magenta');
await page.select('select'); await page.select('select');
expect( expect(
await page.$eval('select', (select: HTMLSelectElement) => await page.$eval(
Array.from(select.options).every( 'select',
(option: HTMLOptionElement) => !option.selected (select: HTMLSelectElement) =>
Array.from(select.options).filter((option) => option.selected)[0]
.value
) )
) ).toEqual('');
).toEqual(true);
}); });
it('should throw if passed in non-strings', async () => { it('should throw if passed in non-strings', async () => {
const { page } = getTestState(); const { page } = getTestState();