feat(text selector): concat sibling text nodes when calculating text (#1969)
Text that is split into multiple text nodes now matches.
This commit is contained in:
parent
b60c006c63
commit
7ecf252dd6
|
|
@ -86,21 +86,33 @@ function queryInternal(root: SelectorRoot, matcher: Matcher, shadow: boolean): E
|
|||
const shadowRoots: ShadowRoot[] = [];
|
||||
if (shadow && (root as Element).shadowRoot)
|
||||
shadowRoots.push((root as Element).shadowRoot!);
|
||||
while (walker.nextNode()) {
|
||||
const node = walker.currentNode;
|
||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
|
||||
let lastTextParent: Element | null = null;
|
||||
let lastText = '';
|
||||
while (true) {
|
||||
const node = walker.nextNode();
|
||||
|
||||
const textParent = (node && node.nodeType === Node.TEXT_NODE) ? node.parentElement : null;
|
||||
if (lastTextParent && textParent !== lastTextParent) {
|
||||
if (lastTextParent.nodeName !== 'SCRIPT' && lastTextParent.nodeName !== 'STYLE' && matcher(lastText))
|
||||
return lastTextParent;
|
||||
lastText = '';
|
||||
}
|
||||
lastTextParent = textParent;
|
||||
|
||||
if (!node)
|
||||
break;
|
||||
if (node.nodeType === Node.TEXT_NODE) {
|
||||
lastText += node.nodeValue;
|
||||
} else {
|
||||
const element = node as Element;
|
||||
if ((element instanceof HTMLInputElement) && (element.type === 'submit' || element.type === 'button') && matcher(element.value))
|
||||
return element;
|
||||
if (shadow && element.shadowRoot)
|
||||
shadowRoots.push(element.shadowRoot);
|
||||
} else {
|
||||
const element = node.parentElement;
|
||||
const text = node.nodeValue;
|
||||
if (element && element.nodeName !== 'SCRIPT' && element.nodeName !== 'STYLE' && text && matcher(text))
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
for (const shadowRoot of shadowRoots) {
|
||||
const element = queryInternal(shadowRoot, matcher, shadow);
|
||||
if (element)
|
||||
|
|
@ -114,21 +126,33 @@ function queryAllInternal(root: SelectorRoot, matcher: Matcher, shadow: boolean,
|
|||
const shadowRoots: ShadowRoot[] = [];
|
||||
if (shadow && (root as Element).shadowRoot)
|
||||
shadowRoots.push((root as Element).shadowRoot!);
|
||||
while (walker.nextNode()) {
|
||||
const node = walker.currentNode;
|
||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
|
||||
let lastTextParent: Element | null = null;
|
||||
let lastText = '';
|
||||
while (true) {
|
||||
const node = walker.nextNode();
|
||||
|
||||
const textParent = (node && node.nodeType === Node.TEXT_NODE) ? node.parentElement : null;
|
||||
if (lastTextParent && textParent !== lastTextParent) {
|
||||
if (lastTextParent.nodeName !== 'SCRIPT' && lastTextParent.nodeName !== 'STYLE' && matcher(lastText))
|
||||
result.push(lastTextParent);
|
||||
lastText = '';
|
||||
}
|
||||
lastTextParent = textParent;
|
||||
|
||||
if (!node)
|
||||
break;
|
||||
if (node.nodeType === Node.TEXT_NODE) {
|
||||
lastText += node.nodeValue;
|
||||
} else {
|
||||
const element = node as Element;
|
||||
if ((element instanceof HTMLInputElement) && (element.type === 'submit' || element.type === 'button') && matcher(element.value))
|
||||
result.push(element);
|
||||
if (shadow && element.shadowRoot)
|
||||
shadowRoots.push(element.shadowRoot);
|
||||
} else {
|
||||
const element = node.parentElement;
|
||||
const text = node.nodeValue;
|
||||
if (element && element.nodeName !== 'SCRIPT' && element.nodeName !== 'STYLE' && text && matcher(text))
|
||||
result.push(element);
|
||||
}
|
||||
}
|
||||
|
||||
for (const shadowRoot of shadowRoots)
|
||||
queryAllInternal(shadowRoot, matcher, shadow, result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -540,6 +540,26 @@ describe('text selector', () => {
|
|||
await page.setContent(`<div> ' </div><div> " </div>`);
|
||||
expect(await page.$eval(`text="`, e => e.outerHTML)).toBe('<div> " </div>');
|
||||
expect(await page.$eval(`text='`, e => e.outerHTML)).toBe('<div> \' </div>');
|
||||
|
||||
await page.setContent(`<div>a<br>b</div><div>a</div>`);
|
||||
expect(await page.$eval(`text=a`, e => e.outerHTML)).toBe('<div>a<br>b</div>');
|
||||
expect(await page.$eval(`text=b`, e => e.outerHTML)).toBe('<div>a<br>b</div>');
|
||||
expect(await page.$(`text=ab`)).toBe(null);
|
||||
expect(await page.$$eval(`text=a`, els => els.length)).toBe(2);
|
||||
expect(await page.$$eval(`text=b`, els => els.length)).toBe(1);
|
||||
expect(await page.$$eval(`text=ab`, els => els.length)).toBe(0);
|
||||
|
||||
await page.setContent(`<div></div><span></span>`);
|
||||
await page.$eval('div', div => {
|
||||
div.appendChild(document.createTextNode('hello'));
|
||||
div.appendChild(document.createTextNode('world'));
|
||||
});
|
||||
await page.$eval('span', span => {
|
||||
span.appendChild(document.createTextNode('hello'));
|
||||
span.appendChild(document.createTextNode('world'));
|
||||
});
|
||||
expect(await page.$eval(`text=lowo`, e => e.outerHTML)).toBe('<div>helloworld</div>');
|
||||
expect(await page.$$eval(`text=lowo`, els => els.map(e => e.outerHTML).join(''))).toBe('<div>helloworld</div><span>helloworld</span>');
|
||||
});
|
||||
|
||||
it('create', async ({page}) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue