Skip to content

Commit

Permalink
feat(Frame): introduce Frame.select
Browse files Browse the repository at this point in the history
This patch adds `Frame.select` method that does the same functionality as
former `Page.select`, but on a per-frame level.

The `Page.select` method becomes a shortcut for the ÷main frame's select.

Fixes puppeteer#1139
  • Loading branch information
suvratjain1995 authored and aslushnikov committed Nov 2, 2017
1 parent bc7f211 commit fede264
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 12 deletions.
18 changes: 17 additions & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
* [frame.isDetached()](#frameisdetached)
* [frame.name()](#framename)
* [frame.parentFrame()](#frameparentframe)
* [frame.select(selector, ...values)](#frameselectselector-values)
* [frame.title()](#frametitle)
* [frame.url()](#frameurl)
* [frame.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])](#framewaitforselectororfunctionortimeout-options-args)
Expand Down Expand Up @@ -932,13 +933,15 @@ Shortcut for [page.mainFrame().executionContext().queryObjects(prototypeHandle)]
- returns: <[Promise]<[Array]<[string]>>> Returns an array of option values that have been successfully selected.

Triggers a `change` and `input` event once all the provided options have been selected.
If there's no `<select>` element matching `selector`, the method throws an error.
If there's no `<select>` element matching `selector`, the method throws an error.

```js
page.select('select#colors', 'blue'); // single selection
page.select('select#colors', 'red', 'green', 'blue'); // multiple selections
```

Shortcut for [page.mainFrame.select()](#frameselectselector-values)

#### page.setContent(html, options)
- `html` <[string]> HTML markup to assign to the page.
- `options` <[Object]> Navigation parameters which might have the following properties:
Expand Down Expand Up @@ -1504,6 +1507,19 @@ If the name is empty, returns the id attribute instead.
#### frame.parentFrame()
- returns: <[Frame]> Returns parent frame, if any. Detached frames and main frames return `null`.

#### frame.select(selector, ...values)
- `selector` <[string]> A [selector] to query frame for
- `...values` <...[string]> Values of options to select. If the `<select>` has the `multiple` attribute, all values are considered, otherwise only the first one is taken into account.
- returns: <[Promise]<[string]>>

Triggers a `change` and `input` event once all the provided options have been selected.
If there's no `<select>` element matching `selector`, the method throws an error.

```js
frame.select('select#colors', 'blue'); // single selection
frame.select('select#colors', 'red', 'green', 'blue'); // multiple selections
```

#### frame.title()
- returns: <[Promise]<[string]>> Returns page's title.

Expand Down
20 changes: 20 additions & 0 deletions lib/FrameManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,26 @@ class Frame {
}
}

/**
* @param {string} selector
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
async select(selector, ...values){
return await this.$eval(selector, (element, values) => {
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);
element.dispatchEvent(new Event('input', { 'bubbles': true }));
element.dispatchEvent(new Event('change', { 'bubbles': true }));
return options.filter(option => option.selected).map(option => option.value);
}, values);
}

/**
* @param {(string|number|Function)} selectorOrFunctionOrTimeout
* @param {!Object=} options
Expand Down
12 changes: 1 addition & 11 deletions lib/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -784,17 +784,7 @@ class Page extends EventEmitter {
* @return {!Promise<!Array<string>>}
*/
async select(selector, ...values) {
return await this.$eval(selector, (element, values) => {
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);
element.dispatchEvent(new Event('input', { 'bubbles': true }));
element.dispatchEvent(new Event('change', { 'bubbles': true }));
return options.filter(option => option.selected).map(option => option.value);
}, values);
return this.mainFrame().select(selector, ...values);
}

/**
Expand Down

0 comments on commit fede264

Please sign in to comment.