diff --git a/src/dom.ts b/src/dom.ts
index 1efbe3e855..e27572f5e9 100644
--- a/src/dom.ts
+++ b/src/dom.ts
@@ -511,7 +511,9 @@ function normalizeSelector(selector: string): string {
const eqIndex = selector.indexOf('=');
if (eqIndex !== -1 && selector.substring(0, eqIndex).trim().match(/^[a-zA-Z_0-9-]+$/))
return selector;
- if (selector.startsWith('//'))
+ // If selector starts with '//' or '//' prefixed with multiple opening
+ // parenthesis, consider xpath. @see https://github.com/microsoft/playwright/issues/817
+ if (/^\(*\/\//.test(selector))
return 'xpath=' + selector;
if (selector.startsWith('"'))
return 'text=' + selector;
diff --git a/test/queryselector.spec.js b/test/queryselector.spec.js
index 54c6e60712..38a3de150c 100644
--- a/test/queryselector.spec.js
+++ b/test/queryselector.spec.js
@@ -177,6 +177,11 @@ module.exports.describe = function({testRunner, expect, selectors, FFOX, CHROMIU
const element = await page.$('//html/body/section');
expect(element).toBeTruthy();
});
+ it('should auto-detect xpath selector with starting parenthesis', async({page, server}) => {
+ await page.setContent('');
+ const element = await page.$('(//section)[1]');
+ expect(element).toBeTruthy();
+ });
it('should auto-detect text selector', async({page, server}) => {
await page.setContent('');
const element = await page.$('"test"');