fix(selectors): text engine after capture matches scope (#4749)
This commit is contained in:
parent
35533b15c1
commit
9a0023cc03
|
|
@ -54,7 +54,7 @@ export function parseSelector(selector: string, customNames: Set<string>): Parse
|
|||
};
|
||||
}
|
||||
|
||||
const chain = (from: number, to: number): CSSComplexSelector => {
|
||||
const chain = (from: number, to: number, turnFirstTextIntoScope: boolean): CSSComplexSelector => {
|
||||
const result: CSSComplexSelector = { simples: [] };
|
||||
for (const part of v1.parts.slice(from, to)) {
|
||||
let name = part.name;
|
||||
|
|
@ -76,6 +76,8 @@ export function parseSelector(selector: string, customNames: Set<string>): Parse
|
|||
}
|
||||
} else if (name === 'text') {
|
||||
let simple = textSelectorToSimple(part.body);
|
||||
if (turnFirstTextIntoScope)
|
||||
simple.functions.push({ name: 'is', args: [ simpleToComplex(callWith('scope', [])), simpleToComplex({ css: '*', functions: [] }) ]});
|
||||
if (result.simples.length)
|
||||
result.simples[result.simples.length - 1].combinator = '>=';
|
||||
if (wrapInLight)
|
||||
|
|
@ -87,14 +89,16 @@ export function parseSelector(selector: string, customNames: Set<string>): Parse
|
|||
simple = callWith('light', [simpleToComplex(simple)]);
|
||||
result.simples.push({ selector: simple, combinator: '' });
|
||||
}
|
||||
if (name !== 'text')
|
||||
turnFirstTextIntoScope = false;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const capture = v1.capture === undefined ? v1.parts.length - 1 : v1.capture;
|
||||
const result = chain(0, capture + 1);
|
||||
const result = chain(0, capture + 1, false);
|
||||
if (capture + 1 < v1.parts.length) {
|
||||
const has = chain(capture + 1, v1.parts.length);
|
||||
const has = chain(capture + 1, v1.parts.length, true);
|
||||
const last = result.simples[result.simples.length - 1];
|
||||
last.selector.functions.push({ name: 'has', args: [has] });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,8 +120,8 @@ export class SelectorEvaluatorImpl implements SelectorEvaluator {
|
|||
|
||||
private _matchesSimple(element: Element, simple: CSSSimpleSelector, context: QueryContext): boolean {
|
||||
return this._cached<boolean>(this._cacheMatchesSimple, element, [simple, context], () => {
|
||||
const isScopeClause = simple.functions.some(f => f.name === 'scope');
|
||||
if (!isScopeClause && element === context.scope)
|
||||
const isPossiblyScopeClause = simple.functions.some(f => f.name === 'scope' || f.name === 'is');
|
||||
if (!isPossiblyScopeClause && element === context.scope)
|
||||
return false;
|
||||
if (simple.css && !this._matchesCSS(element, simple.css))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -348,6 +348,8 @@ it('should work with :is', async ({page, server}) => {
|
|||
expect(await page.$$eval(`css=:is(div, span)`, els => els.length)).toBe(7);
|
||||
expect(await page.$$eval(`css=section:is(section) div:is(section div)`, els => els.length)).toBe(3);
|
||||
expect(await page.$$eval(`css=:is(div, span) > *`, els => els.length)).toBe(6);
|
||||
expect(await page.$$eval(`css=#root1:has(:is(#root1))`, els => els.length)).toBe(0);
|
||||
expect(await page.$$eval(`css=#root1:has(:is(:scope, #root1))`, els => els.length)).toBe(1);
|
||||
});
|
||||
|
||||
it('should work with :has', async ({page, server}) => {
|
||||
|
|
|
|||
|
|
@ -227,3 +227,8 @@ it('should match root after >>', async ({page, server}) => {
|
|||
const element2 = await page.$('text=test >> text=test');
|
||||
expect(element2).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should match root after >> with *', async ({ page }) => {
|
||||
await page.setContent(`<button> hello world </button> <button> hellow <span> world </span> </button>`);
|
||||
expect(await page.$$eval('*css=button >> text=hello >> text=world', els => els.length)).toBe(2);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue