mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(text selector): ignore non-leading quote when parsing (#13170)
Previously, any unpaired quote in the text selector "escaped" everything till the end of the selector string, and so any subsequent chained selectors, including ">>" separator were ignored. An example of misbehaving selector: `text=19" >> nth=1`. Now, when text selector contains a non-leading quote, selector parser does not assume it should escape ">>" separator and correctly tokenizes all selectors from the chain. Note that this behavior is a workaround for the fact that our text selectors is somewhat poorly defined in this area. That said, this workaround seems to be safe enough. It still does not work for unpaired leading quotes like this: `text="19 >> nth=1`.
This commit is contained in:
parent
705a994f18
commit
a8d4a8aa52
@ -173,6 +173,13 @@ function parseSelectorString(selector: string): ParsedSelectorStrings {
|
||||
return result;
|
||||
}
|
||||
|
||||
const shouldIgnoreTextSelectorQuote = () => {
|
||||
const prefix = selector.substring(start, index);
|
||||
const match = prefix.match(/^\s*text\s*=(.*)$/);
|
||||
// Must be a text selector with some text before the quote.
|
||||
return !!match && !!match[1];
|
||||
};
|
||||
|
||||
while (index < selector.length) {
|
||||
const c = selector[index];
|
||||
if (c === '\\' && index + 1 < selector.length) {
|
||||
@ -180,7 +187,7 @@ function parseSelectorString(selector: string): ParsedSelectorStrings {
|
||||
} else if (c === quote) {
|
||||
quote = undefined;
|
||||
index++;
|
||||
} else if (!quote && (c === '"' || c === '\'' || c === '`')) {
|
||||
} else if (!quote && (c === '"' || c === '\'' || c === '`') && !shouldIgnoreTextSelectorQuote()) {
|
||||
quote = c;
|
||||
index++;
|
||||
} else if (!quote && c === '>' && selector[index + 1] === '>') {
|
||||
|
@ -303,6 +303,7 @@ it('should be case sensitive if quotes are specified', async ({ page }) => {
|
||||
await page.setContent(`<div>yo</div><div>ya</div><div>\nye </div>`);
|
||||
expect(await page.$eval(`text=yA`, e => e.outerHTML)).toBe('<div>ya</div>');
|
||||
expect(await page.$(`text="yA"`)).toBe(null);
|
||||
expect(await page.$(`text= "ya"`)).toBe(null);
|
||||
});
|
||||
|
||||
it('should search for a substring without quotes', async ({ page }) => {
|
||||
@ -411,3 +412,30 @@ it('should work with leading and trailing spaces', async ({ page }) => {
|
||||
await expect(page.locator('text=Add widget')).toBeVisible();
|
||||
await expect(page.locator('text= Add widget ')).toBeVisible();
|
||||
});
|
||||
|
||||
it('should work with unpaired quotes when not at the start', async ({ page }) => {
|
||||
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/12719' });
|
||||
await page.setContent(`
|
||||
<div>hello"world<span>yay</span></div>
|
||||
<div>hello'world<span>nay</span></div>
|
||||
<div>hello\`world<span>oh</span></div>
|
||||
<div>hello\`world<span>oh2</span></div>
|
||||
`);
|
||||
expect(await page.$eval('text=lo" >> span', e => e.outerHTML)).toBe('<span>yay</span>');
|
||||
expect(await page.$eval(' text=lo" >> span', e => e.outerHTML)).toBe('<span>yay</span>');
|
||||
expect(await page.$eval('text =lo" >> span', e => e.outerHTML)).toBe('<span>yay</span>');
|
||||
expect(await page.$eval('text= lo" >> span', e => e.outerHTML)).toBe('<span>yay</span>');
|
||||
expect(await page.$eval(' text = lo" >> span', e => e.outerHTML)).toBe('<span>yay</span>');
|
||||
expect(await page.$eval('text=o"wor >> span', e => e.outerHTML)).toBe('<span>yay</span>');
|
||||
|
||||
expect(await page.$eval(`text=lo'wor >> span`, e => e.outerHTML)).toBe('<span>nay</span>');
|
||||
expect(await page.$eval(`text=o' >> span`, e => e.outerHTML)).toBe('<span>nay</span>');
|
||||
|
||||
expect(await page.$eval(`text=ello\`wor >> span`, e => e.outerHTML)).toBe('<span>oh</span>');
|
||||
await expect(page.locator(`text=ello\`wor`).locator('span').first()).toHaveText('oh');
|
||||
await expect(page.locator(`text=ello\`wor`).locator('span').nth(1)).toHaveText('oh2');
|
||||
|
||||
expect(await page.$(`text='wor >> span`)).toBe(null);
|
||||
expect(await page.$(`text=" >> span`)).toBe(null);
|
||||
expect(await page.$(`text=\` >> span`)).toBe(null);
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user