diff --git a/packages/playwright-core/src/utils/isomorphic/stringUtils.ts b/packages/playwright-core/src/utils/isomorphic/stringUtils.ts index ed81c9a0335ee..7bdfe178d7b3b 100644 --- a/packages/playwright-core/src/utils/isomorphic/stringUtils.ts +++ b/packages/playwright-core/src/utils/isomorphic/stringUtils.ts @@ -83,7 +83,7 @@ export function cacheNormalizedWhitespaces() { export function normalizeWhiteSpace(text: string): string { let result = normalizedWhitespaceCache?.get(text); if (result === undefined) { - result = text.replace(/\u200b/g, '').trim().replace(/\s+/g, ' '); + result = text.replace(/\u200b/g, '').replace(/ /g, ' ').trim().replace(/\s+/g, ' '); normalizedWhitespaceCache?.set(text, result); } return result; diff --git a/packages/playwright/src/matchers/matchers.ts b/packages/playwright/src/matchers/matchers.ts index 8a8089e91e20f..acf4c5bcc89af 100644 --- a/packages/playwright/src/matchers/matchers.ts +++ b/packages/playwright/src/matchers/matchers.ts @@ -337,7 +337,7 @@ export function toHaveValue( options?: { timeout?: number }, ) { return toMatchText.call(this, 'toHaveValue', locator, 'Locator', async (isNot, timeout) => { - const expectedText = serializeExpectedTextValues([expected]); + const expectedText = serializeExpectedTextValues([expected], { normalizeWhiteSpace: true }); return await locator._expect('to.have.value', { expectedText, isNot, timeout }); }, expected, options); } diff --git a/tests/page/expect-to-have-value.spec.ts b/tests/page/expect-to-have-value.spec.ts index 0518eac725fff..0fe70aeec7b72 100644 --- a/tests/page/expect-to-have-value.spec.ts +++ b/tests/page/expect-to-have-value.spec.ts @@ -45,6 +45,13 @@ test('should support failure', async ({ page }) => { expect(stripAnsi(error.message)).toContain('"Text content"'); }); +test('should normalize whitespace', async ({ page }) => { + await page.setContent(''); + const locator = page.locator('#node'); + await locator.fill('foo bar\nbaz'); + await expect(locator).toHaveValue('foo bar baz'); +}); + test.describe('toHaveValues with multi-select', () => { test('works with text', async ({ page }) => { await page.setContent(`