mirror of
https://github.com/microsoft/playwright.git
synced 2024-09-11 20:37:54 +03:00
fix(selector generator): do not reparent to invisible ancestor (#31590)
Fixes #31335.
This commit is contained in:
parent
4dfa55d1f1
commit
21c4531618
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { cssEscape, escapeForAttributeSelector, escapeForTextSelector, escapeRegExp, quoteCSSAttributeValue } from '../../utils/isomorphic/stringUtils';
|
import { cssEscape, escapeForAttributeSelector, escapeForTextSelector, escapeRegExp, quoteCSSAttributeValue } from '../../utils/isomorphic/stringUtils';
|
||||||
import { closestCrossShadow, isInsideScope, parentElementOrShadowHost } from './domUtils';
|
import { closestCrossShadow, isElementVisible, isInsideScope, parentElementOrShadowHost } from './domUtils';
|
||||||
import type { InjectedScript } from './injectedScript';
|
import type { InjectedScript } from './injectedScript';
|
||||||
import { getAriaRole, getElementAccessibleName, beginAriaCaches, endAriaCaches } from './roleUtils';
|
import { getAriaRole, getElementAccessibleName, beginAriaCaches, endAriaCaches } from './roleUtils';
|
||||||
import { elementText, getElementLabels } from './selectorUtils';
|
import { elementText, getElementLabels } from './selectorUtils';
|
||||||
@ -89,7 +89,12 @@ export function generateSelector(injectedScript: InjectedScript, targetElement:
|
|||||||
}
|
}
|
||||||
selectors = [joinTokens(targetTokens)];
|
selectors = [joinTokens(targetTokens)];
|
||||||
} else {
|
} else {
|
||||||
targetElement = closestCrossShadow(targetElement, 'button,select,input,[role=button],[role=checkbox],[role=radio],a,[role=link]', options.root) || targetElement;
|
// Note: this matches InjectedScript.retarget().
|
||||||
|
if (!targetElement.matches('input,textarea,select') && !(targetElement as any).isContentEditable) {
|
||||||
|
const interactiveParent = closestCrossShadow(targetElement, 'button,select,input,[role=button],[role=checkbox],[role=radio],a,[role=link]', options.root);
|
||||||
|
if (interactiveParent && isElementVisible(interactiveParent))
|
||||||
|
targetElement = interactiveParent;
|
||||||
|
}
|
||||||
if (options.multiple) {
|
if (options.multiple) {
|
||||||
const withText = generateSelectorFor(injectedScript, targetElement, options);
|
const withText = generateSelectorFor(injectedScript, targetElement, options);
|
||||||
const withoutText = generateSelectorFor(injectedScript, targetElement, { ...options, noText: true });
|
const withoutText = generateSelectorFor(injectedScript, targetElement, { ...options, noText: true });
|
||||||
|
@ -33,13 +33,22 @@ it.describe('selector generator', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should prefer button over inner span', async ({ page }) => {
|
it('should prefer button over inner span', async ({ page }) => {
|
||||||
await page.setContent(`<button id=clickme><span></span></button>`);
|
await page.setContent(`<button><span>text</span></button>`);
|
||||||
expect(await generate(page, 'button')).toBe('#clickme');
|
expect(await generate(page, 'span')).toBe('internal:role=button[name="text"i]');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should prefer role=button over inner span', async ({ page }) => {
|
it('should prefer role=button over inner span', async ({ page }) => {
|
||||||
await page.setContent(`<div role=button><span></span></div>`);
|
await page.setContent(`<div role=button><span>text</span></div>`);
|
||||||
expect(await generate(page, 'div')).toBe('internal:role=button');
|
expect(await generate(page, 'span')).toBe('internal:role=button[name="text"i]');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not prefer zero-sized button over inner span', async ({ page }) => {
|
||||||
|
await page.setContent(`
|
||||||
|
<button style="width:0;height:0;padding:0;border:0;overflow:visible;">
|
||||||
|
<span style="width:100px;height:100px;">text</span>
|
||||||
|
</button>
|
||||||
|
`);
|
||||||
|
expect(await generate(page, 'span')).toBe('internal:text="text"i');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate text and normalize whitespace', async ({ page }) => {
|
it('should generate text and normalize whitespace', async ({ page }) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user