feat(selectAll): allow selecting all in the inputs and in the plain dom (#1783)

This commit is contained in:
Pavel Feldman 2020-04-14 17:09:26 -07:00 committed by GitHub
parent b2c65db37e
commit da683b2752
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 101 additions and 21 deletions

View file

@ -1424,7 +1424,13 @@ The `format` options are:
Focuses the element, and then uses [`keyboard.down`](#keyboarddownkey) and [`keyboard.up`](#keyboardupkey).
`key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to generate the text for. A superset of the `key` values can be found [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Note that only those present on a typical full computer keyboard are supported. Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
`key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to generate the text for. A superset of the `key` values can be found [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Examples of the keys are:
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`, `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrayRight`, `ArrowUp`, etc.
Following modification shortcuts are also suported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective texts.
@ -2242,7 +2248,13 @@ If the name is empty, returns the id attribute instead.
- `timeout` <[number]> Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the [browserContext.setDefaultTimeout(timeout)](#browsercontextsetdefaulttimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods.
- returns: <[Promise]>
`key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to generate the text for. A superset of the `key` values can be found [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Note that only those present on a typical full computer keyboard are supported. Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
`key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to generate the text for. A superset of the `key` values can be found [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Examples of the keys are:
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`, `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrayRight`, `ArrowUp`, etc.
Following modification shortcuts are also suported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective texts.
@ -2517,6 +2529,7 @@ ElementHandle instances can be used as an argument in [`page.$eval()`](#pageeval
- [elementHandle.screenshot([options])](#elementhandlescreenshotoptions)
- [elementHandle.scrollIntoViewIfNeeded()](#elementhandlescrollintoviewifneeded)
- [elementHandle.selectOption(values[, options])](#elementhandleselectoptionvalues-options)
- [elementHandle.selectText()](#elementhandleselecttext)
- [elementHandle.setInputFiles(files[, options])](#elementhandlesetinputfilesfiles-options)
- [elementHandle.textContent()](#elementhandletextcontent)
- [elementHandle.toString()](#elementhandletostring)
@ -2736,7 +2749,13 @@ If the element is detached from DOM, the method throws an error.
Focuses the element, and then uses [`keyboard.down`](#keyboarddownkey) and [`keyboard.up`](#keyboardupkey).
`key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to generate the text for. A superset of the `key` values can be found [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Note that only those present on a typical full computer keyboard are supported. Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
`key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to generate the text for. A superset of the `key` values can be found [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Examples of the keys are:
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`, `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrayRight`, `ArrowUp`, etc.
Following modification shortcuts are also suported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective texts.
@ -2793,6 +2812,11 @@ handle.selectOption('red', 'green', 'blue');
handle.selectOption({ value: 'blue' }, { index: 2 }, 'red');
```
#### elementHandle.selectText()
- returns: <[Promise]> Promise which resolves when the element is successfully selected.
This method focuses the element and selects all its text content.
#### elementHandle.setInputFiles(files[, options])
- `files` <[string]|[Array]<[string]>|[Object]|[Array]<[Object]>>
- `name` <[string]> [File] name **required**
@ -3125,7 +3149,13 @@ await page.keyboard.press('Shift+A');
Dispatches a `keydown` event.
`key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to generate the text for. A superset of the `key` values can be found [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Note that only those present on a typical full computer keyboard are supported. Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
`key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to generate the text for. A superset of the `key` values can be found [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Examples of the keys are:
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`, `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrayRight`, `ArrowUp`, etc.
Following modification shortcuts are also suported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective texts.
@ -3153,7 +3183,13 @@ page.keyboard.insertText('嗨');
- `delay` <[number]> Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
- returns: <[Promise]>
`key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to generate the text for. A superset of the `key` values can be found [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Note that only those present on a typical full computer keyboard are supported. Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
`key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to generate the text for. A superset of the `key` values can be found [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Examples of the keys are:
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`, `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrayRight`, `ArrowUp`, etc.
Following modification shortcuts are also suported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective texts.

View file

@ -290,6 +290,12 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
}, deadline, options, true);
}
async selectText(): Promise<void> {
const error = await this._evaluateInUtility(({ injected, node }) => injected.selectText(node), {});
if (typeof error === 'string')
throw new Error(error);
}
async setInputFiles(files: string | types.FilePayload | string[] | types.FilePayload[], options?: types.NavigatingActionWaitOptions) {
const deadline = this._page._timeoutSettings.computeDeadline(options);
const multiple = await this._evaluateInUtility(({ node }) => {

View file

@ -183,33 +183,46 @@ class Injected {
element.dispatchEvent(new Event('change', { 'bubbles': true }));
return false; // We have already changed the value, no need to input it.
}
} else if (element.nodeName.toLowerCase() === 'textarea') {
const textarea = element as HTMLTextAreaElement;
if (textarea.disabled)
return 'Cannot fill a disabled textarea.';
if (textarea.readOnly)
return 'Cannot fill a readonly textarea.';
} else if (!element.isContentEditable) {
return 'Element is not an <input>, <textarea> or [contenteditable] element.';
}
return this.selectText(node);
}
selectText(node: Node) {
if (node.nodeType !== Node.ELEMENT_NODE)
return 'Node is not of type HTMLElement';
const element = node as HTMLElement;
if (!this.isVisible(element))
return 'Element is not visible';
if (element.nodeName.toLowerCase() === 'input') {
const input = element as HTMLInputElement;
input.select();
input.focus();
return true;
}
if (element.nodeName.toLowerCase() === 'textarea') {
const textarea = element as HTMLTextAreaElement;
if (textarea.disabled)
return 'Cannot fill a disabled textarea.';
if (textarea.readOnly)
return 'Cannot fill a readonly textarea.';
textarea.selectionStart = 0;
textarea.selectionEnd = textarea.value.length;
textarea.focus();
return true;
}
if (element.isContentEditable) {
const range = element.ownerDocument!.createRange();
range.selectNodeContents(element);
const selection = element.ownerDocument!.defaultView!.getSelection();
if (!selection)
return 'Element belongs to invisible iframe.';
selection.removeAllRanges();
selection.addRange(range);
element.focus();
return true;
}
return 'Element is not an <input>, <textarea> or [contenteditable] element.';
const range = element.ownerDocument!.createRange();
range.selectNodeContents(element);
const selection = element.ownerDocument!.defaultView!.getSelection();
if (!selection)
return 'Element belongs to invisible iframe.';
selection.removeAllRanges();
selection.addRange(range);
element.focus();
return true;
}
isCheckboxChecked(node: Node) {

View file

@ -7,6 +7,7 @@
<textarea spellcheck="false"></textarea>
<input></input>
<div contenteditable="true"></div>
<div class="plain">Plain div</div>
<script src='mouse-helper.js'></script>
<script>
window.result = '';

View file

@ -327,6 +327,30 @@ describe('ElementHandle.fill', function() {
});
});
describe('ElementHandle.selectText', function() {
it.fail(FFOX)('should select textarea', async({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const textarea = await page.$('textarea');
await textarea.evaluate(textarea => textarea.value = 'some value');
await textarea.selectText();
expect(await page.evaluate(() => window.getSelection().toString())).toBe('some value');
});
it.fail(FFOX)('should select input', async({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const input = await page.$('input');
await input.evaluate(input => input.value = 'some value');
await input.selectText();
expect(await page.evaluate(() => window.getSelection().toString())).toBe('some value');
});
it('should select plain div', async({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const div = await page.$('div.plain');
await div.selectText();
expect(await page.evaluate(() => window.getSelection().toString())).toBe('Plain div');
});
});
describe('ElementHandle convenience API', function() {
it('getAttribute should work', async({page, server}) => {
await page.goto(`${server.PREFIX}/dom.html`);