mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-01 08:34:02 +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 { closestCrossShadow, isInsideScope, parentElementOrShadowHost } from './domUtils';
|
||||
import { closestCrossShadow, isElementVisible, isInsideScope, parentElementOrShadowHost } from './domUtils';
|
||||
import type { InjectedScript } from './injectedScript';
|
||||
import { getAriaRole, getElementAccessibleName, beginAriaCaches, endAriaCaches } from './roleUtils';
|
||||
import { elementText, getElementLabels } from './selectorUtils';
|
||||
@ -89,7 +89,12 @@ export function generateSelector(injectedScript: InjectedScript, targetElement:
|
||||
}
|
||||
selectors = [joinTokens(targetTokens)];
|
||||
} 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) {
|
||||
const withText = generateSelectorFor(injectedScript, targetElement, options);
|
||||
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 }) => {
|
||||
await page.setContent(`<button id=clickme><span></span></button>`);
|
||||
expect(await generate(page, 'button')).toBe('#clickme');
|
||||
await page.setContent(`<button><span>text</span></button>`);
|
||||
expect(await generate(page, 'span')).toBe('internal:role=button[name="text"i]');
|
||||
});
|
||||
|
||||
it('should prefer role=button over inner span', async ({ page }) => {
|
||||
await page.setContent(`<div role=button><span></span></div>`);
|
||||
expect(await generate(page, 'div')).toBe('internal:role=button');
|
||||
await page.setContent(`<div role=button><span>text</span></div>`);
|
||||
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 }) => {
|
||||
|
Loading…
Reference in New Issue
Block a user