mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: restore to.have.url matching via injected script (#35027)
This commit is contained in:
parent
02a63fe9e8
commit
d6a4c1cda4
@ -1423,7 +1423,6 @@ export class InjectedScript {
|
|||||||
} else if (expression === 'to.have.title') {
|
} else if (expression === 'to.have.title') {
|
||||||
received = this.document.title;
|
received = this.document.title;
|
||||||
} else if (expression === 'to.have.url') {
|
} else if (expression === 'to.have.url') {
|
||||||
// Note: this is used by all language ports except for javascript.
|
|
||||||
received = this.document.location.href;
|
received = this.document.location.href;
|
||||||
} else if (expression === 'to.have.value') {
|
} else if (expression === 'to.have.value') {
|
||||||
element = this.retarget(element, 'follow-label')!;
|
element = this.retarget(element, 'follow-label')!;
|
||||||
|
|||||||
@ -14,13 +14,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isRegExp, isString, isTextualMimeType, pollAgainstDeadline, serializeExpectedTextValues } from 'playwright-core/lib/utils';
|
import { constructURLBasedOnBaseURL, isRegExp, isString, isTextualMimeType, pollAgainstDeadline, serializeExpectedTextValues } from 'playwright-core/lib/utils';
|
||||||
import { colors } from 'playwright-core/lib/utils';
|
import { colors } from 'playwright-core/lib/utils';
|
||||||
|
|
||||||
import { callLogText, expectTypes } from '../util';
|
import { callLogText, expectTypes } from '../util';
|
||||||
import { toBeTruthy } from './toBeTruthy';
|
import { toBeTruthy } from './toBeTruthy';
|
||||||
import { toEqual } from './toEqual';
|
import { toEqual } from './toEqual';
|
||||||
import { toHaveURL as toHaveURLExternal } from './toHaveURL';
|
import { toHaveURLWithPredicate } from './toHaveURL';
|
||||||
import { toMatchText } from './toMatchText';
|
import { toMatchText } from './toMatchText';
|
||||||
import { takeFirst } from '../common/config';
|
import { takeFirst } from '../common/config';
|
||||||
import { currentTestInfo } from '../common/globals';
|
import { currentTestInfo } from '../common/globals';
|
||||||
@ -391,7 +391,17 @@ export function toHaveURL(
|
|||||||
expected: string | RegExp | ((url: URL) => boolean),
|
expected: string | RegExp | ((url: URL) => boolean),
|
||||||
options?: { ignoreCase?: boolean; timeout?: number },
|
options?: { ignoreCase?: boolean; timeout?: number },
|
||||||
) {
|
) {
|
||||||
return toHaveURLExternal.call(this, page, expected, options);
|
// Ports don't support predicates. Keep separate server and client codepaths
|
||||||
|
if (typeof expected === 'function')
|
||||||
|
return toHaveURLWithPredicate.call(this, page, expected, options);
|
||||||
|
|
||||||
|
const baseURL = (page.context() as any)._options.baseURL;
|
||||||
|
expected = typeof expected === 'string' ? constructURLBasedOnBaseURL(baseURL, expected) : expected;
|
||||||
|
const locator = page.locator(':root') as LocatorEx;
|
||||||
|
return toMatchText.call(this, 'toHaveURL', locator, 'Locator', async (isNot, timeout) => {
|
||||||
|
const expectedText = serializeExpectedTextValues([expected], { ignoreCase: options?.ignoreCase });
|
||||||
|
return await locator._expect('to.have.url', { expectedText, isNot, timeout });
|
||||||
|
}, expected, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function toBeOK(
|
export async function toBeOK(
|
||||||
|
|||||||
@ -14,10 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { constructURLBasedOnBaseURL, urlMatches } from 'playwright-core/lib/utils';
|
import { urlMatches } from 'playwright-core/lib/utils';
|
||||||
import { colors } from 'playwright-core/lib/utils';
|
import { colors } from 'playwright-core/lib/utils';
|
||||||
|
|
||||||
import { printReceivedStringContainExpectedResult, printReceivedStringContainExpectedSubstring } from './expect';
|
import { printReceivedStringContainExpectedResult } from './expect';
|
||||||
import { matcherHint } from './matcherHint';
|
import { matcherHint } from './matcherHint';
|
||||||
import { EXPECTED_COLOR, printReceived } from '../common/expectBundle';
|
import { EXPECTED_COLOR, printReceived } from '../common/expectBundle';
|
||||||
|
|
||||||
@ -25,10 +25,10 @@ import type { MatcherResult } from './matcherHint';
|
|||||||
import type { ExpectMatcherState } from '../../types/test';
|
import type { ExpectMatcherState } from '../../types/test';
|
||||||
import type { Page } from 'playwright-core';
|
import type { Page } from 'playwright-core';
|
||||||
|
|
||||||
export async function toHaveURL(
|
export async function toHaveURLWithPredicate(
|
||||||
this: ExpectMatcherState,
|
this: ExpectMatcherState,
|
||||||
page: Page,
|
page: Page,
|
||||||
expected: string | RegExp | ((url: URL) => boolean),
|
expected: (url: URL) => boolean,
|
||||||
options?: { ignoreCase?: boolean; timeout?: number },
|
options?: { ignoreCase?: boolean; timeout?: number },
|
||||||
): Promise<MatcherResult<string | RegExp, string>> {
|
): Promise<MatcherResult<string | RegExp, string>> {
|
||||||
const matcherName = 'toHaveURL';
|
const matcherName = 'toHaveURL';
|
||||||
@ -38,11 +38,7 @@ export async function toHaveURL(
|
|||||||
promise: this.promise,
|
promise: this.promise,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (typeof expected !== 'function') {
|
||||||
!(typeof expected === 'string') &&
|
|
||||||
!(expected && 'test' in expected && typeof expected.test === 'function') &&
|
|
||||||
!(typeof expected === 'function')
|
|
||||||
) {
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
[
|
[
|
||||||
// Always display `expected` in expectation place
|
// Always display `expected` in expectation place
|
||||||
@ -68,9 +64,7 @@ export async function toHaveURL(
|
|||||||
urlMatches(
|
urlMatches(
|
||||||
baseURL?.toLocaleLowerCase(),
|
baseURL?.toLocaleLowerCase(),
|
||||||
lastCheckedURLString.toLocaleLowerCase(),
|
lastCheckedURLString.toLocaleLowerCase(),
|
||||||
typeof expected === 'string'
|
expected,
|
||||||
? expected.toLocaleLowerCase()
|
|
||||||
: expected,
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -98,9 +92,7 @@ export async function toHaveURL(
|
|||||||
this,
|
this,
|
||||||
matcherName,
|
matcherName,
|
||||||
expression,
|
expression,
|
||||||
typeof expected === 'string'
|
expected,
|
||||||
? constructURLBasedOnBaseURL(baseURL, expected)
|
|
||||||
: expected,
|
|
||||||
lastCheckedURLString,
|
lastCheckedURLString,
|
||||||
this.isNot,
|
this.isNot,
|
||||||
true,
|
true,
|
||||||
@ -115,7 +107,7 @@ function toHaveURLMessage(
|
|||||||
state: ExpectMatcherState,
|
state: ExpectMatcherState,
|
||||||
matcherName: string,
|
matcherName: string,
|
||||||
expression: string,
|
expression: string,
|
||||||
expected: string | RegExp | Function,
|
expected: Function,
|
||||||
received: string | undefined,
|
received: string | undefined,
|
||||||
pass: boolean,
|
pass: boolean,
|
||||||
didTimeout: boolean,
|
didTimeout: boolean,
|
||||||
@ -136,15 +128,9 @@ function toHaveURLMessage(
|
|||||||
printedReceived = `Received string: ${printReceived(receivedString)}`;
|
printedReceived = `Received string: ${printReceived(receivedString)}`;
|
||||||
} else {
|
} else {
|
||||||
if (pass) {
|
if (pass) {
|
||||||
if (typeof expected === 'string') {
|
|
||||||
printedExpected = `Expected string: not ${state.utils.printExpected(expected)}`;
|
|
||||||
const formattedReceived = printReceivedStringContainExpectedSubstring(receivedString, receivedString.indexOf(expected), expected.length);
|
|
||||||
printedReceived = `Received string: ${formattedReceived}`;
|
|
||||||
} else {
|
|
||||||
printedExpected = `Expected pattern: not ${state.utils.printExpected(expected)}`;
|
printedExpected = `Expected pattern: not ${state.utils.printExpected(expected)}`;
|
||||||
const formattedReceived = printReceivedStringContainExpectedResult(receivedString, typeof expected.exec === 'function' ? expected.exec(receivedString) : null);
|
const formattedReceived = printReceivedStringContainExpectedResult(receivedString, null);
|
||||||
printedReceived = `Received string: ${formattedReceived}`;
|
printedReceived = `Received string: ${formattedReceived}`;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const labelExpected = `Expected ${typeof expected === 'string' ? 'string' : 'pattern'}`;
|
const labelExpected = `Expected ${typeof expected === 'string' ? 'string' : 'pattern'}`;
|
||||||
printedDiff = state.utils.printDiffOrStringify(expected, receivedString, labelExpected, 'Received string', false);
|
printedDiff = state.utils.printDiffOrStringify(expected, receivedString, labelExpected, 'Received string', false);
|
||||||
|
|||||||
@ -244,7 +244,7 @@ test.describe('toHaveURL', () => {
|
|||||||
test('fail string', async ({ page }) => {
|
test('fail string', async ({ page }) => {
|
||||||
await page.goto('data:text/html,<div>A</div>');
|
await page.goto('data:text/html,<div>A</div>');
|
||||||
const error = await expect(page).toHaveURL('wrong', { timeout: 1000 }).catch(e => e);
|
const error = await expect(page).toHaveURL('wrong', { timeout: 1000 }).catch(e => e);
|
||||||
expect(stripVTControlCharacters(error.message)).toContain('Timed out 1000ms waiting for expect(page).toHaveURL(expected)');
|
expect(stripVTControlCharacters(error.message)).toContain('Timed out 1000ms waiting for expect(locator).toHaveURL(expected)');
|
||||||
expect(stripVTControlCharacters(error.message)).toContain('Expected string: "wrong"\nReceived string: "data:text/html,<div>A</div>"');
|
expect(stripVTControlCharacters(error.message)).toContain('Expected string: "wrong"\nReceived string: "data:text/html,<div>A</div>"');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -252,7 +252,7 @@ test.describe('toHaveURL', () => {
|
|||||||
await page.goto('data:text/html,<div>A</div>');
|
await page.goto('data:text/html,<div>A</div>');
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
const error = await expect(page).toHaveURL({}).catch(e => e);
|
const error = await expect(page).toHaveURL({}).catch(e => e);
|
||||||
expect(stripVTControlCharacters(error.message)).toContain('expect(page).toHaveURL(expected)\n\n\n\nMatcher error: expected value must be a string, regular expression, or predicate');
|
expect(stripVTControlCharacters(error.message)).toContain(`expect(locator(':root')).toHaveURL([object Object])`);
|
||||||
expect(stripVTControlCharacters(error.message)).toContain('Expected has type: object\nExpected has value: {}');
|
expect(stripVTControlCharacters(error.message)).toContain('Expected has type: object\nExpected has value: {}');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -548,7 +548,7 @@ test('should respect expect.timeout', async ({ runInlineTest }) => {
|
|||||||
test('timeout', async ({ page }) => {
|
test('timeout', async ({ page }) => {
|
||||||
await page.goto('data:text/html,<div>A</div>');
|
await page.goto('data:text/html,<div>A</div>');
|
||||||
const error = await expect(page).toHaveURL('data:text/html,<div>B</div>').catch(e => e);
|
const error = await expect(page).toHaveURL('data:text/html,<div>B</div>').catch(e => e);
|
||||||
expect(stripVTControlCharacters(error.message)).toContain('Timed out 1000ms waiting for expect(page).toHaveURL(expected)');
|
expect(stripVTControlCharacters(error.message)).toContain('Timed out 1000ms waiting for expect(locator).toHaveURL(expected)');
|
||||||
expect(error.message).toContain('data:text/html,<div>');
|
expect(error.message).toContain('data:text/html,<div>');
|
||||||
});
|
});
|
||||||
`,
|
`,
|
||||||
@ -566,7 +566,7 @@ test('should support toHaveURL predicate', async ({ runInlineTest }) => {
|
|||||||
|
|
||||||
test('predicate', async ({ page }) => {
|
test('predicate', async ({ page }) => {
|
||||||
await page.goto('data:text/html,<div>A</div>');
|
await page.goto('data:text/html,<div>A</div>');
|
||||||
const error = await expect(page).toHaveURL('data:text/html,<div>B</div>').catch(e => e);
|
const error = await expect(page).toHaveURL(url => url === 'data:text/html,<div>B</div>').catch(e => e);
|
||||||
expect(stripVTControlCharacters(error.message)).toContain('Timed out 1000ms waiting for expect(page).toHaveURL(expected)');
|
expect(stripVTControlCharacters(error.message)).toContain('Timed out 1000ms waiting for expect(page).toHaveURL(expected)');
|
||||||
expect(error.message).toContain('data:text/html,<div>');
|
expect(error.message).toContain('data:text/html,<div>');
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user