fix(selectOption): allow passing null to unselect all (#2405)
This commit is contained in:
parent
24316ad261
commit
e3f34f6ae2
|
|
@ -1632,7 +1632,7 @@ Page routes take precedence over browser context routes (set up with [browserCon
|
|||
|
||||
#### page.selectOption(selector, values[, options])
|
||||
- `selector` <[string]> A selector to query page for. See [working with selectors](#working-with-selectors) for more details.
|
||||
- `values` <[string]|[ElementHandle]|[Array]<[string]>|[Object]|[Array]<[ElementHandle]>|[Array]<[Object]>> Options to select. If the `<select>` has the `multiple` attribute, all matching options are selected, otherwise only the first option matching one of the passed options is selected. String values are equivalent to `{value:'string'}`. Option is considered matching if all specified properties match.
|
||||
- `values` <null|[string]|[ElementHandle]|[Array]<[string]>|[Object]|[Array]<[ElementHandle]>|[Array]<[Object]>> Options to select. If the `<select>` has the `multiple` attribute, all matching options are selected, otherwise only the first option matching one of the passed options is selected. String values are equivalent to `{value:'string'}`. Option is considered matching if all specified properties match.
|
||||
- `value` <[string]> Matches by `option.value`.
|
||||
- `label` <[string]> Matches by `option.label`.
|
||||
- `index` <[number]> Matches by the index.
|
||||
|
|
@ -2421,7 +2421,7 @@ Shortcuts such as `key: "Control+o"` or `key: "Control+Shift+T"` are supported a
|
|||
|
||||
#### frame.selectOption(selector, values[, options])
|
||||
- `selector` <[string]> A selector to query frame for. See [working with selectors](#working-with-selectors) for more details.
|
||||
- `values` <[string]|[ElementHandle]|[Array]<[string]>|[Object]|[Array]<[ElementHandle]>|[Array]<[Object]>> Options to select. If the `<select>` has the `multiple` attribute, all matching options are selected, otherwise only the first option matching one of the passed options is selected. String values are equivalent to `{value:'string'}`. Option is considered matching if all specified properties match.
|
||||
- `values` <null|[string]|[ElementHandle]|[Array]<[string]>|[Object]|[Array]<[ElementHandle]>|[Array]<[Object]>> Options to select. If the `<select>` has the `multiple` attribute, all matching options are selected, otherwise only the first option matching one of the passed options is selected. String values are equivalent to `{value:'string'}`. Option is considered matching if all specified properties match.
|
||||
- `value` <[string]> Matches by `option.value`.
|
||||
- `label` <[string]> Matches by `option.label`.
|
||||
- `index` <[number]> Matches by the index.
|
||||
|
|
@ -2926,7 +2926,7 @@ Throws when ```elementHandle``` does not point to an element [connected](https:/
|
|||
> **NOTE** If javascript is disabled, element is scrolled into view even when already completely visible.
|
||||
|
||||
#### elementHandle.selectOption(values[, options])
|
||||
- `values` <[string]|[ElementHandle]|[Array]<[string]>|[Object]|[Array]<[ElementHandle]>|[Array]<[Object]>> Options to select. If the `<select>` has the `multiple` attribute, all matching options are selected, otherwise only the first option matching one of the passed options is selected. String values are equivalent to `{value:'string'}`. Option is considered matching if all specified properties match.
|
||||
- `values` <null|[string]|[ElementHandle]|[Array]<[string]>|[Object]|[Array]<[ElementHandle]>|[Array]<[Object]>> Options to select. If the `<select>` has the `multiple` attribute, all matching options are selected, otherwise only the first option matching one of the passed options is selected. String values are equivalent to `{value:'string'}`. Option is considered matching if all specified properties match.
|
||||
- `value` <[string]> Matches by `option.value`.
|
||||
- `label` <[string]> Matches by `option.label`.
|
||||
- `index` <[number]> Matches by the index.
|
||||
|
|
|
|||
|
|
@ -344,18 +344,21 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
|
|||
return this._retryPointerAction(progress, point => this._page.mouse.dblclick(point.x, point.y, options), options);
|
||||
}
|
||||
|
||||
async selectOption(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[], options: types.NavigatingActionWaitOptions = {}): Promise<string[]> {
|
||||
async selectOption(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise<string[]> {
|
||||
return runAbortableTask(progress => this._selectOption(progress, values, options), this._page._logger, this._page._timeoutSettings.timeout(options));
|
||||
}
|
||||
|
||||
async _selectOption(progress: Progress, values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[], options: types.NavigatingActionWaitOptions): Promise<string[]> {
|
||||
async _selectOption(progress: Progress, values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions): Promise<string[]> {
|
||||
let vals: string[] | ElementHandle[] | types.SelectOption[];
|
||||
if (!Array.isArray(values))
|
||||
if (values === null)
|
||||
vals = [];
|
||||
else if (!Array.isArray(values))
|
||||
vals = [ values ] as (string[] | ElementHandle[] | types.SelectOption[]);
|
||||
else
|
||||
vals = values;
|
||||
const selectOptions = (vals as any).map((value: any) => typeof value === 'object' ? value : { value });
|
||||
for (const option of selectOptions) {
|
||||
assert(option !== null, 'Value items must not be null');
|
||||
if (option instanceof ElementHandle)
|
||||
continue;
|
||||
if (option.value !== undefined)
|
||||
|
|
|
|||
|
|
@ -765,7 +765,7 @@ export class Frame {
|
|||
await this._retryWithSelectorIfNotConnected(selector, options, (progress, handle) => handle._hover(progress, options));
|
||||
}
|
||||
|
||||
async selectOption(selector: string, values: string | dom.ElementHandle | types.SelectOption | string[] | dom.ElementHandle[] | types.SelectOption[], options: types.NavigatingActionWaitOptions = {}): Promise<string[]> {
|
||||
async selectOption(selector: string, values: string | dom.ElementHandle | types.SelectOption | string[] | dom.ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise<string[]> {
|
||||
return this._retryWithSelectorIfNotConnected(selector, options, (progress, handle) => handle._selectOption(progress, values, options));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ export class Page extends ExtendedEventEmitter {
|
|||
return this.mainFrame().hover(selector, options);
|
||||
}
|
||||
|
||||
async selectOption(selector: string, values: string | dom.ElementHandle | types.SelectOption | string[] | dom.ElementHandle[] | types.SelectOption[], options?: types.NavigatingActionWaitOptions): Promise<string[]> {
|
||||
async selectOption(selector: string, values: string | dom.ElementHandle | types.SelectOption | string[] | dom.ElementHandle[] | types.SelectOption[] | null, options?: types.NavigatingActionWaitOptions): Promise<string[]> {
|
||||
return this.mainFrame().selectOption(selector, values, options);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -953,6 +953,21 @@ describe('Page.selectOption', function() {
|
|||
const result = await page.selectOption('select', []);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
it('should not allow null items',async({page, server}) => {
|
||||
await page.goto(server.PREFIX + '/input/select.html');
|
||||
await page.evaluate(() => makeMultiple());
|
||||
let error = null
|
||||
await page.selectOption('select', ['blue', null, 'black','magenta']).catch(e => error = e);
|
||||
expect(error.message).toContain('Value items must not be null');
|
||||
});
|
||||
it('should unselect with null',async({page, server}) => {
|
||||
await page.goto(server.PREFIX + '/input/select.html');
|
||||
await page.evaluate(() => makeMultiple());
|
||||
const result = await page.selectOption('select', ['blue', 'black','magenta']);
|
||||
expect(result.reduce((accumulator,current) => ['blue', 'black', 'magenta'].includes(current) && accumulator, true)).toEqual(true);
|
||||
await page.selectOption('select', null);
|
||||
expect(await page.$eval('select', select => Array.from(select.options).every(option => !option.selected))).toEqual(true);
|
||||
});
|
||||
it('should deselect all options when passed no values for a multiple select',async({page, server}) => {
|
||||
await page.goto(server.PREFIX + '/input/select.html');
|
||||
await page.evaluate(() => makeMultiple());
|
||||
|
|
|
|||
Loading…
Reference in a new issue