fix(selectors): make selectOptions work for labels (#4402)

This commit is contained in:
Yury Semikhatsky 2020-11-11 15:33:23 -08:00 committed by GitHub
parent 138680f93c
commit 5702eca1f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 10 deletions

View file

@ -227,14 +227,14 @@ export class InjectedScript {
} }
selectOptions(node: Node, optionsToSelect: (Node | { value?: string, label?: string, index?: number })[]): string[] | 'error:notconnected' | FatalDOMError { selectOptions(node: Node, optionsToSelect: (Node | { value?: string, label?: string, index?: number })[]): string[] | 'error:notconnected' | FatalDOMError {
if (node.nodeName.toLowerCase() !== 'select') const element = this.findLabelTarget(node as Element);
return 'error:notselect'; if (!element || !element.isConnected)
if (!node.isConnected)
return 'error:notconnected'; return 'error:notconnected';
const element = node as HTMLSelectElement; if (element.nodeName.toLowerCase() !== 'select')
return 'error:notselect';
const options = Array.from(element.options); const select = element as HTMLSelectElement;
element.value = undefined as any; const options = Array.from(select.options);
select.value = undefined as any;
for (let index = 0; index < options.length; index++) { for (let index = 0; index < options.length; index++) {
const option = options[index]; const option = options[index];
option.selected = optionsToSelect.some(optionToSelect => { option.selected = optionsToSelect.some(optionToSelect => {
@ -249,11 +249,11 @@ export class InjectedScript {
matches = matches && optionToSelect.index === index; matches = matches && optionToSelect.index === index;
return matches; return matches;
}); });
if (option.selected && !element.multiple) if (option.selected && !select.multiple)
break; break;
} }
element.dispatchEvent(new Event('input', { 'bubbles': true })); select.dispatchEvent(new Event('input', { 'bubbles': true }));
element.dispatchEvent(new Event('change', { 'bubbles': true })); select.dispatchEvent(new Event('change', { 'bubbles': true }));
return options.filter(option => option.selected).map(option => option.value); return options.filter(option => option.selected).map(option => option.value);
} }

View file

@ -98,6 +98,26 @@ it('should select multiple options with attributes', async ({page, server}) => {
expect(await page.evaluate(() => window['result'].onChange)).toEqual(['blue', 'gray', 'green']); expect(await page.evaluate(() => window['result'].onChange)).toEqual(['blue', 'gray', 'green']);
}); });
it('should select options with sibling label', async ({page, server}) => {
await page.setContent(`<label for=pet-select>Choose a pet</label>
<select id='pet-select'>
<option value='dog'>Dog</option>
<option value='cat'>Cat</option>
</select>`);
await page.selectOption('text=Choose a pet', 'cat');
expect(await page.$eval('select', select => select.options[select.selectedIndex].text)).toEqual('Cat');
});
it('should select options with outer label', async ({page, server}) => {
await page.setContent(`<label for=pet-select>Choose a pet
<select id='pet-select'>
<option value='dog'>Dog</option>
<option value='cat'>Cat</option>
</select></label>`);
await page.selectOption('text=Choose a pet', 'cat');
expect(await page.$eval('select', select => select.options[select.selectedIndex].text)).toEqual('Cat');
});
it('should respect event bubbling', async ({page, server}) => { it('should respect event bubbling', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/select.html'); await page.goto(server.PREFIX + '/input/select.html');
await page.selectOption('select', 'blue'); await page.selectOption('select', 'blue');