mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-14 05:37:20 +03:00
fix(expect): toHaveText, toContainText and toHaveTitle normalize whitespace (#8929)
This commit is contained in:
parent
c58f34fb2e
commit
b8a46580dd
@ -15,12 +15,12 @@
|
||||
*/
|
||||
|
||||
import { Locator, Page } from '../../..';
|
||||
import { constructURLBasedOnBaseURL } from '../../utils/utils';
|
||||
import { constructURLBasedOnBaseURL, isString } from '../../utils/utils';
|
||||
import { currentTestInfo } from '../globals';
|
||||
import type { Expect } from '../types';
|
||||
import { toBeTruthy } from './toBeTruthy';
|
||||
import { toEqual } from './toEqual';
|
||||
import { toMatchText } from './toMatchText';
|
||||
import { normalizeWhiteSpace, toMatchText } from './toMatchText';
|
||||
|
||||
export function toBeChecked(
|
||||
this: ReturnType<Expect['getState']>,
|
||||
@ -118,7 +118,7 @@ export function toContainText(
|
||||
if (options?.useInnerText)
|
||||
return await locator.innerText({ timeout });
|
||||
return await locator.textContent() || '';
|
||||
}, expected, { ...options, matchSubstring: true });
|
||||
}, expected, { ...options, matchSubstring: true, normalizeWhiteSpace: true });
|
||||
}
|
||||
|
||||
export function toHaveAttribute(
|
||||
@ -202,20 +202,23 @@ export function toHaveText(
|
||||
this: ReturnType<Expect['getState']>,
|
||||
locator: Locator,
|
||||
expected: string | RegExp | (string | RegExp)[],
|
||||
options?: { timeout?: number, useInnerText?: boolean },
|
||||
options: { timeout?: number, useInnerText?: boolean } = {},
|
||||
) {
|
||||
if (Array.isArray(expected)) {
|
||||
const expectedArray = expected.map(e => isString(e) ? normalizeWhiteSpace(e) : e);
|
||||
return toEqual.call(this, 'toHaveText', locator, 'Locator', async () => {
|
||||
return locator.evaluateAll((ee, useInnerText) => {
|
||||
const texts = await locator.evaluateAll((ee, useInnerText) => {
|
||||
return ee.map(e => useInnerText ? (e as HTMLElement).innerText : e.textContent || '');
|
||||
}, options?.useInnerText);
|
||||
}, expected, options);
|
||||
// Normalize those values that have string expectations.
|
||||
return texts.map((s, index) => isString(expectedArray[index]) ? normalizeWhiteSpace(s) : s);
|
||||
}, expectedArray, options);
|
||||
} else {
|
||||
return toMatchText.call(this, 'toHaveText', locator, 'Locator', async timeout => {
|
||||
if (options?.useInnerText)
|
||||
return await locator.innerText({ timeout });
|
||||
return await locator.textContent() || '';
|
||||
}, expected, options);
|
||||
}, expected, { ...options, normalizeWhiteSpace: true });
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,11 +226,11 @@ export function toHaveTitle(
|
||||
this: ReturnType<Expect['getState']>,
|
||||
page: Page,
|
||||
expected: string | RegExp,
|
||||
options?: { timeout?: number },
|
||||
options: { timeout?: number } = {},
|
||||
) {
|
||||
return toMatchText.call(this, 'toHaveTitle', page, 'Page', async () => {
|
||||
return await page.title();
|
||||
}, expected, options);
|
||||
}, expected, { ...options, normalizeWhiteSpace: true });
|
||||
}
|
||||
|
||||
export function toHaveURL(
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
printReceivedStringContainExpectedResult,
|
||||
printReceivedStringContainExpectedSubstring
|
||||
} from 'expect/build/print';
|
||||
|
||||
import { isString } from '../../utils/utils';
|
||||
import { currentTestInfo } from '../globals';
|
||||
import type { Expect } from '../types';
|
||||
import { expectType, pollUntilDeadline } from '../util';
|
||||
@ -30,7 +30,7 @@ export async function toMatchText(
|
||||
receiverType: string,
|
||||
query: (timeout: number) => Promise<string>,
|
||||
expected: string | RegExp,
|
||||
options: { timeout?: number, matchSubstring?: boolean } = {},
|
||||
options: { timeout?: number, matchSubstring?: boolean, normalizeWhiteSpace?: boolean } = {},
|
||||
) {
|
||||
const testInfo = currentTestInfo();
|
||||
if (!testInfo)
|
||||
@ -59,9 +59,13 @@ export async function toMatchText(
|
||||
|
||||
let received: string;
|
||||
let pass = false;
|
||||
if (options.normalizeWhiteSpace && isString(expected))
|
||||
expected = normalizeWhiteSpace(expected);
|
||||
|
||||
await pollUntilDeadline(testInfo, async remainingTime => {
|
||||
received = await query(remainingTime);
|
||||
if (options.normalizeWhiteSpace && isString(expected))
|
||||
received = normalizeWhiteSpace(received);
|
||||
if (options.matchSubstring)
|
||||
pass = received.includes(expected as string);
|
||||
else if (typeof expected === 'string')
|
||||
@ -112,3 +116,7 @@ export async function toMatchText(
|
||||
|
||||
return { message, pass };
|
||||
}
|
||||
|
||||
export function normalizeWhiteSpace(s: string) {
|
||||
return s.trim().replace(/\s+/g, ' ');
|
||||
}
|
||||
|
@ -124,8 +124,8 @@ test('should support toHaveTitle', async ({ runInlineTest }) => {
|
||||
const { test } = pwt;
|
||||
|
||||
test('pass', async ({ page }) => {
|
||||
await page.setContent('<title>Hello</title>');
|
||||
await expect(page).toHaveTitle('Hello');
|
||||
await page.setContent('<title> Hello world</title>');
|
||||
await expect(page).toHaveTitle('Hello world');
|
||||
});
|
||||
|
||||
test('fail', async ({ page }) => {
|
||||
|
@ -22,9 +22,12 @@ test('should support toHaveText w/ regex', async ({ runInlineTest }) => {
|
||||
const { test } = pwt;
|
||||
|
||||
test('pass', async ({ page }) => {
|
||||
await page.setContent('<div id=node>Text content</div>');
|
||||
await page.setContent('<div id=node>Text content</div>');
|
||||
const locator = page.locator('#node');
|
||||
await expect(locator).toHaveText(/Text/);
|
||||
|
||||
// Should not normalize whitespace.
|
||||
await expect(locator).toHaveText(/Text content/);
|
||||
});
|
||||
|
||||
test('fail', async ({ page }) => {
|
||||
@ -50,15 +53,18 @@ test('should support toHaveText w/ text', async ({ runInlineTest }) => {
|
||||
const { test } = pwt;
|
||||
|
||||
test('pass', async ({ page }) => {
|
||||
await page.setContent('<div id=node>Text content</div>');
|
||||
await page.setContent('<div id=node><span></span>Text \\ncontent </div>');
|
||||
const locator = page.locator('#node');
|
||||
await expect(locator).toHaveText('Text content');
|
||||
// Should normalize whitespace.
|
||||
await expect(locator).toHaveText('Text content');
|
||||
});
|
||||
|
||||
test('pass contain', async ({ page }) => {
|
||||
await page.setContent('<div id=node>Text content</div>');
|
||||
const locator = page.locator('#node');
|
||||
await expect(locator).toContainText('Text');
|
||||
// Should normalize whitespace.
|
||||
await expect(locator).toContainText(' Text content\\n ');
|
||||
});
|
||||
|
||||
test('fail', async ({ page }) => {
|
||||
@ -84,9 +90,10 @@ test('should support toHaveText w/ array', async ({ runInlineTest }) => {
|
||||
const { test } = pwt;
|
||||
|
||||
test('pass', async ({ page }) => {
|
||||
await page.setContent('<div>Text 1</div><div>Text 2a</div>');
|
||||
await page.setContent('<div>Text \\n1</div><div>Text 2a</div>');
|
||||
const locator = page.locator('div');
|
||||
await expect(locator).toHaveText(['Text 1', /Text \\d+a/]);
|
||||
// Should only normalize whitespace in the first item.
|
||||
await expect(locator).toHaveText(['Text 1', /Text \\d+a/]);
|
||||
});
|
||||
|
||||
test('fail', async ({ page }) => {
|
||||
|
Loading…
Reference in New Issue
Block a user