feat(inputValue): allow on labels, retarget (#10666)

This commit is contained in:
Pavel Feldman 2021-12-02 10:31:06 -08:00 committed by GitHub
parent 15b92e3f62
commit 2ac9c08d0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 27 additions and 6 deletions

View file

@ -199,10 +199,10 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
async inputValue(): Promise<string> {
return throwRetargetableDOMError(await this.evaluateInUtility(([injected, node]) => {
if (node.nodeType !== Node.ELEMENT_NODE || (node.nodeName !== 'INPUT' && node.nodeName !== 'TEXTAREA' && node.nodeName !== 'SELECT'))
const element = injected.retarget(node, 'follow-label');
if (!element || (element.nodeName !== 'INPUT' && element.nodeName !== 'TEXTAREA' && element.nodeName !== 'SELECT'))
throw injected.createStacklessError('Node is not an <input>, <textarea> or <select> element');
const element = node as unknown as (HTMLInputElement | HTMLTextAreaElement);
return { value: element.value };
return { value: (element as HTMLInputElement | HTMLTextAreaElement).value };
}, undefined)).value;
}

View file

@ -1117,8 +1117,9 @@ export class Frame extends SdkObject {
}
async inputValue(metadata: CallMetadata, selector: string, options: types.TimeoutOptions & types.StrictOptions = {}): Promise<string> {
return this._scheduleRerunnableTask(metadata, selector, (progress, element) => {
if (element.nodeName !== 'INPUT' && element.nodeName !== 'TEXTAREA' && element.nodeName !== 'SELECT')
return this._scheduleRerunnableTask(metadata, selector, (progress, node) => {
const element = progress.injectedScript.retarget(node, 'follow-label');
if (!element || (element.nodeName !== 'INPUT' && element.nodeName !== 'TEXTAREA' && element.nodeName !== 'SELECT'))
throw progress.injectedScript.createStacklessError('Node is not an <input>, <textarea> or <select> element');
return (element as any).value;
}, undefined, options);

View file

@ -954,6 +954,7 @@ export class InjectedScript {
} else if (expression === 'to.have.url') {
received = document.location.href;
} else if (expression === 'to.have.value') {
element = this.retarget(element, 'follow-label')!;
if (element.nodeName !== 'INPUT' && element.nodeName !== 'TEXTAREA' && element.nodeName !== 'SELECT')
throw this.createStacklessError('Not an input element');
received = (element as any).value;

View file

@ -58,6 +58,13 @@ it('inputValue should work', async ({ page, server }) => {
expect(await handle2.inputValue().catch(e => e.message)).toContain('Node is not an <input>, <textarea> or <select> element');
});
it('inputValue should work on label', async ({ page, server }) => {
await page.setContent(`<label><input type=text></input></label>`);
await page.fill('input', 'foo');
const handle = await page.$('label');
expect(await handle.inputValue()).toBe('foo');
});
it('innerHTML should work', async ({ page, server }) => {
await page.goto(`${server.PREFIX}/dom.html`);
const handle = await page.$('#outer');

View file

@ -58,6 +58,12 @@ it('inputValue should work', async ({ page, server }) => {
expect(await locator2.inputValue().catch(e => e.message)).toContain('Node is not an <input>, <textarea> or <select> element');
});
it('inputValue should work on label', async ({ page, server }) => {
await page.setContent(`<label><input type=text></input></label>`);
await page.fill('input', 'foo');
expect(await page.locator('label').inputValue()).toBe('foo');
});
it('innerHTML should work', async ({ page, server }) => {
await page.goto(`${server.PREFIX}/dom.html`);
const locator = page.locator('#outer');

View file

@ -341,9 +341,15 @@ test('should support toHaveValue', async ({ runInlineTest }) => {
await locator.fill('Text content');
await expect(locator).toHaveValue('Text content');
});
test('pass on label', async ({ page }) => {
await page.setContent('<label><input></input></label>');
await page.locator('label input').fill('Text content');
await expect(page.locator('label')).toHaveValue('Text content');
});
`,
}, { workers: 1 });
expect(result.passed).toBe(1);
expect(result.passed).toBe(2);
expect(result.exitCode).toBe(0);
});