diff --git a/packages/playwright-core/src/server/injected/selectorEvaluator.ts b/packages/playwright-core/src/server/injected/selectorEvaluator.ts index 66363a767f..2affe18b49 100644 --- a/packages/playwright-core/src/server/injected/selectorEvaluator.ts +++ b/packages/playwright-core/src/server/injected/selectorEvaluator.ts @@ -472,6 +472,8 @@ export function createLaxTextMatcher(text: string): TextMatcher { export function createStrictTextMatcher(text: string): TextMatcher { text = text.trim().replace(/\s+/g, ' '); return (elementText: ElementText) => { + if (!text && !elementText.immediate.length) + return true; return elementText.immediate.some(s => s.trim().replace(/\s+/g, ' ') === text); }; } diff --git a/tests/page/selectors-text.spec.ts b/tests/page/selectors-text.spec.ts index 901292d082..4320bffda7 100644 --- a/tests/page/selectors-text.spec.ts +++ b/tests/page/selectors-text.spec.ts @@ -129,6 +129,20 @@ it('should work with :text', async ({ page }) => { expect(error2.message).toContain(`"text" engine expects a single string`); }); +it('should support empty string', async ({ page }) => { + await page.setContent(`
ya
\nHELLO \n world
`); + expect(await page.$eval(`div:text-is("")`, e => e.outerHTML)).toBe('
'); + expect(await page.$$eval(`div:text-is("")`, els => els.length)).toBe(1); + expect(await page.$eval(`div:text("")`, e => e.outerHTML)).toBe('
'); + expect(await page.$$eval(`div:text("")`, els => els.length)).toBe(3); + expect(await page.$eval(`div >> text=""`, e => e.outerHTML)).toBe('
'); + expect(await page.$$eval(`div >> text=""`, els => els.length)).toBe(1); + expect(await page.$eval(`div >> text=/^$/`, e => e.outerHTML)).toBe('
'); + expect(await page.$$eval(`div >> text=/^$/`, els => els.length)).toBe(1); + expect(await page.$eval(`div:text-matches("")`, e => e.outerHTML)).toBe('
'); + expect(await page.$$eval(`div:text-matches("")`, els => els.length)).toBe(3); +}); + it('should work across nodes', async ({ page }) => { await page.setContent(`
Hello, world!
`);