feat(selectors): always make xpath relative (#5252)

This makes `/foo` and `//foo` match starting with the scope,
not the document, by turning them into `./foo` and `.//foo`.
This commit is contained in:
Dmitry Gozman 2021-02-02 13:27:16 -08:00 committed by GitHub
parent e0f41bf1fd
commit 6c12f58058
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 0 deletions

View File

@ -18,6 +18,8 @@ import { SelectorEngine, SelectorRoot } from './selectorEngine';
export const XPathEngine: SelectorEngine = {
query(root: SelectorRoot, selector: string): Element | undefined {
if (selector.startsWith('/'))
selector = '.' + selector;
const document = root instanceof Document ? root : root.ownerDocument;
if (!document)
return;
@ -29,6 +31,8 @@ export const XPathEngine: SelectorEngine = {
},
queryAll(root: SelectorRoot, selector: string): Element[] {
if (selector.startsWith('/'))
selector = '.' + selector;
const result: Element[] = [];
const document = root instanceof Document ? root : root.ownerDocument;
if (!document)

View File

@ -184,3 +184,24 @@ it('should escape the scope with >>', async ({ page }) => {
await page.setContent(`<div><label>Test</label><input id='myinput'></div>`);
expect(await page.$eval(`label >> xpath=.. >> input`, e => e.id)).toBe('myinput');
});
it('xpath should be relative', async ({ page }) => {
await page.setContent(`
<span class="find-me" id=target1>1</span>
<div>
<span class="find-me" id=target2>2</span>
</div>
`);
expect(await page.$eval(`//*[@class="find-me"]`, e => e.id)).toBe('target1');
const div = await page.$('div');
expect(await div.$eval(`xpath=./*[@class="find-me"]`, e => e.id)).toBe('target2');
expect(await div.$eval(`xpath=.//*[@class="find-me"]`, e => e.id)).toBe('target2');
expect(await div.$eval(`//*[@class="find-me"]`, e => e.id)).toBe('target2');
expect(await div.$eval(`xpath=/*[@class="find-me"]`, e => e.id)).toBe('target2');
expect(await page.$eval(`div >> xpath=./*[@class="find-me"]`, e => e.id)).toBe('target2');
expect(await page.$eval(`div >> xpath=.//*[@class="find-me"]`, e => e.id)).toBe('target2');
expect(await page.$eval(`div >> //*[@class="find-me"]`, e => e.id)).toBe('target2');
expect(await page.$eval(`div >> xpath=/*[@class="find-me"]`, e => e.id)).toBe('target2');
});