mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(selectors): do not automatically enter shadow roots with >> (#1812)
Now that we have shadow-aware selector engines, this extra logic adds confusion and does not help to actually query the element.
This commit is contained in:
parent
f3451d9148
commit
56aa4c2e71
@ -56,7 +56,6 @@ class SelectorEvaluator {
|
|||||||
|
|
||||||
private _querySelectorRecursively(root: SelectorRoot, selector: types.ParsedSelector, index: number): Element | undefined {
|
private _querySelectorRecursively(root: SelectorRoot, selector: types.ParsedSelector, index: number): Element | undefined {
|
||||||
const current = selector[index];
|
const current = selector[index];
|
||||||
root = (root as Element).shadowRoot || root;
|
|
||||||
if (index === selector.length - 1)
|
if (index === selector.length - 1)
|
||||||
return this.engines.get(current.name)!.query(root, current.body);
|
return this.engines.get(current.name)!.query(root, current.body);
|
||||||
const all = this.engines.get(current.name)!.queryAll(root, current.body);
|
const all = this.engines.get(current.name)!.queryAll(root, current.body);
|
||||||
@ -74,7 +73,7 @@ class SelectorEvaluator {
|
|||||||
for (const { name, body } of selector) {
|
for (const { name, body } of selector) {
|
||||||
const newSet = new Set<Element>();
|
const newSet = new Set<Element>();
|
||||||
for (const prev of set) {
|
for (const prev of set) {
|
||||||
for (const next of this.engines.get(name)!.queryAll((prev as Element).shadowRoot || prev, body)) {
|
for (const next of this.engines.get(name)!.queryAll(prev, body)) {
|
||||||
if (newSet.has(next))
|
if (newSet.has(next))
|
||||||
continue;
|
continue;
|
||||||
newSet.add(next);
|
newSet.add(next);
|
||||||
|
|||||||
@ -103,22 +103,9 @@ describe('Page.$eval', function() {
|
|||||||
});
|
});
|
||||||
it('should support spaces with >> syntax', async({page, server}) => {
|
it('should support spaces with >> syntax', async({page, server}) => {
|
||||||
await page.goto(server.PREFIX + '/deep-shadow.html');
|
await page.goto(server.PREFIX + '/deep-shadow.html');
|
||||||
const text = await page.$eval(' css:light = div >>css:light=div>>css:light = span ', e => e.textContent);
|
const text = await page.$eval(' css = div >>css=div>>css = span ', e => e.textContent);
|
||||||
expect(text).toBe('Hello from root2');
|
expect(text).toBe('Hello from root2');
|
||||||
});
|
});
|
||||||
it('should enter shadow roots with >> syntax', async({page, server}) => {
|
|
||||||
await page.goto(server.PREFIX + '/deep-shadow.html');
|
|
||||||
const text1 = await page.$eval('css:light=div >> css:light=span', e => e.textContent);
|
|
||||||
expect(text1).toBe('Hello from root1');
|
|
||||||
const text2 = await page.$eval('css:light=div >> css:light=*:nth-child(2) >> css:light=span', e => e.textContent);
|
|
||||||
expect(text2).toBe('Hello from root2');
|
|
||||||
const nonExisting = await page.$('css:light=div div >> css:light=span');
|
|
||||||
expect(nonExisting).not.toBeTruthy();
|
|
||||||
const text3 = await page.$eval('css:light=section div >> css:light=span', e => e.textContent);
|
|
||||||
expect(text3).toBe('Hello from root1');
|
|
||||||
const text4 = await page.$eval('xpath=/html/body/section/div >> css:light=div >> css:light=span', e => e.textContent);
|
|
||||||
expect(text4).toBe('Hello from root2');
|
|
||||||
});
|
|
||||||
it('should not stop at first failure with >> syntax', async({page, server}) => {
|
it('should not stop at first failure with >> syntax', async({page, server}) => {
|
||||||
await page.setContent('<div><span>Next</span><button>Previous</button><button>Next</button></div>');
|
await page.setContent('<div><span>Next</span><button>Previous</button><button>Next</button></div>');
|
||||||
const html = await page.$eval('button >> "Next"', e => e.outerHTML);
|
const html = await page.$eval('button >> "Next"', e => e.outerHTML);
|
||||||
@ -152,11 +139,6 @@ describe('Page.$$eval', function() {
|
|||||||
const spansCount = await page.$$eval('css=div >> css=span', spans => spans.length);
|
const spansCount = await page.$$eval('css=div >> css=span', spans => spans.length);
|
||||||
expect(spansCount).toBe(3);
|
expect(spansCount).toBe(3);
|
||||||
});
|
});
|
||||||
it('should enter shadow roots with >> syntax', async({page, server}) => {
|
|
||||||
await page.goto(server.PREFIX + '/deep-shadow.html');
|
|
||||||
const spansCount = await page.$$eval('css:light=div >> css:light=div >> css:light=span', spans => spans.length);
|
|
||||||
expect(spansCount).toBe(3);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Page.$', function() {
|
describe('Page.$', function() {
|
||||||
@ -571,12 +553,13 @@ describe('css selector', () => {
|
|||||||
|
|
||||||
const root2 = await page.$(`css=div div`);
|
const root2 = await page.$(`css=div div`);
|
||||||
expect(await root2.$eval(`css=#target`, e => e.textContent)).toBe('Hello from root2');
|
expect(await root2.$eval(`css=#target`, e => e.textContent)).toBe('Hello from root2');
|
||||||
expect(await root2.$eval(`css:light=#target`, e => e.textContent)).toBe('Hello from root2');
|
expect(await root2.$(`css:light=#target`)).toBe(null);
|
||||||
|
const root2Shadow = await root2.evaluateHandle(r => r.shadowRoot);
|
||||||
|
expect(await root2Shadow.$eval(`css:light=#target`, e => e.textContent)).toBe('Hello from root2');
|
||||||
const root3 = (await page.$$(`css=div div`))[1];
|
const root3 = (await page.$$(`css=div div`))[1];
|
||||||
expect(await root3.$eval(`text=root3`, e => e.textContent)).toBe('Hello from root3');
|
expect(await root3.$eval(`text=root3`, e => e.textContent)).toBe('Hello from root3');
|
||||||
expect(await root3.$eval(`css=[attr*="value"]`, e => e.textContent)).toBe('Hello from root3 #2');
|
expect(await root3.$eval(`css=[attr*="value"]`, e => e.textContent)).toBe('Hello from root3 #2');
|
||||||
// TODO: the following should be null, but we implicitly enter shadow root.
|
expect(await root3.$(`css:light=[attr*="value"]`)).toBe(null);
|
||||||
expect(await root3.$(`css:light=[attr*="value"]`)).not.toBe(null);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user