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') {
 | 
			
		||||
        received = this.document.title;
 | 
			
		||||
      } else if (expression === 'to.have.url') {
 | 
			
		||||
        // Note: this is used by all language ports except for javascript.
 | 
			
		||||
        received = this.document.location.href;
 | 
			
		||||
      } else if (expression === 'to.have.value') {
 | 
			
		||||
        element = this.retarget(element, 'follow-label')!;
 | 
			
		||||
 | 
			
		||||
@ -14,13 +14,13 @@
 | 
			
		||||
 * 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 { callLogText, expectTypes } from '../util';
 | 
			
		||||
import { toBeTruthy } from './toBeTruthy';
 | 
			
		||||
import { toEqual } from './toEqual';
 | 
			
		||||
import { toHaveURL as toHaveURLExternal } from './toHaveURL';
 | 
			
		||||
import { toHaveURLWithPredicate } from './toHaveURL';
 | 
			
		||||
import { toMatchText } from './toMatchText';
 | 
			
		||||
import { takeFirst } from '../common/config';
 | 
			
		||||
import { currentTestInfo } from '../common/globals';
 | 
			
		||||
@ -391,7 +391,17 @@ export function toHaveURL(
 | 
			
		||||
  expected: string | RegExp | ((url: URL) => boolean),
 | 
			
		||||
  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(
 | 
			
		||||
 | 
			
		||||
@ -14,10 +14,10 @@
 | 
			
		||||
 * 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 { printReceivedStringContainExpectedResult, printReceivedStringContainExpectedSubstring } from './expect';
 | 
			
		||||
import { printReceivedStringContainExpectedResult } from './expect';
 | 
			
		||||
import {  matcherHint } from './matcherHint';
 | 
			
		||||
import { EXPECTED_COLOR, printReceived } from '../common/expectBundle';
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,10 @@ import type { MatcherResult } from './matcherHint';
 | 
			
		||||
import type { ExpectMatcherState } from '../../types/test';
 | 
			
		||||
import type { Page } from 'playwright-core';
 | 
			
		||||
 | 
			
		||||
export async function toHaveURL(
 | 
			
		||||
export async function toHaveURLWithPredicate(
 | 
			
		||||
  this: ExpectMatcherState,
 | 
			
		||||
  page: Page,
 | 
			
		||||
  expected: string | RegExp | ((url: URL) => boolean),
 | 
			
		||||
  expected: (url: URL) => boolean,
 | 
			
		||||
  options?: { ignoreCase?: boolean; timeout?: number },
 | 
			
		||||
): Promise<MatcherResult<string | RegExp, string>> {
 | 
			
		||||
  const matcherName = 'toHaveURL';
 | 
			
		||||
@ -38,11 +38,7 @@ export async function toHaveURL(
 | 
			
		||||
    promise: this.promise,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  if (
 | 
			
		||||
    !(typeof expected === 'string') &&
 | 
			
		||||
    !(expected && 'test' in expected && typeof expected.test === 'function') &&
 | 
			
		||||
    !(typeof expected === 'function')
 | 
			
		||||
  ) {
 | 
			
		||||
  if (typeof expected !== 'function') {
 | 
			
		||||
    throw new Error(
 | 
			
		||||
        [
 | 
			
		||||
          // Always display `expected` in expectation place
 | 
			
		||||
@ -68,9 +64,7 @@ export async function toHaveURL(
 | 
			
		||||
              urlMatches(
 | 
			
		||||
                  baseURL?.toLocaleLowerCase(),
 | 
			
		||||
                  lastCheckedURLString.toLocaleLowerCase(),
 | 
			
		||||
                  typeof expected === 'string'
 | 
			
		||||
                    ? expected.toLocaleLowerCase()
 | 
			
		||||
                    : expected,
 | 
			
		||||
                  expected,
 | 
			
		||||
              )
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
@ -98,9 +92,7 @@ export async function toHaveURL(
 | 
			
		||||
          this,
 | 
			
		||||
          matcherName,
 | 
			
		||||
          expression,
 | 
			
		||||
          typeof expected === 'string'
 | 
			
		||||
            ? constructURLBasedOnBaseURL(baseURL, expected)
 | 
			
		||||
            : expected,
 | 
			
		||||
          expected,
 | 
			
		||||
          lastCheckedURLString,
 | 
			
		||||
          this.isNot,
 | 
			
		||||
          true,
 | 
			
		||||
@ -115,7 +107,7 @@ function toHaveURLMessage(
 | 
			
		||||
  state: ExpectMatcherState,
 | 
			
		||||
  matcherName: string,
 | 
			
		||||
  expression: string,
 | 
			
		||||
  expected: string | RegExp | Function,
 | 
			
		||||
  expected: Function,
 | 
			
		||||
  received: string | undefined,
 | 
			
		||||
  pass: boolean,
 | 
			
		||||
  didTimeout: boolean,
 | 
			
		||||
@ -136,15 +128,9 @@ function toHaveURLMessage(
 | 
			
		||||
    printedReceived = `Received string: ${printReceived(receivedString)}`;
 | 
			
		||||
  } else {
 | 
			
		||||
    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)}`;
 | 
			
		||||
        const formattedReceived = printReceivedStringContainExpectedResult(receivedString, typeof expected.exec === 'function' ? expected.exec(receivedString) : null);
 | 
			
		||||
      const formattedReceived = printReceivedStringContainExpectedResult(receivedString, null);
 | 
			
		||||
      printedReceived = `Received string: ${formattedReceived}`;
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      const labelExpected = `Expected ${typeof expected === 'string' ? 'string' : 'pattern'}`;
 | 
			
		||||
      printedDiff = state.utils.printDiffOrStringify(expected, receivedString, labelExpected, 'Received string', false);
 | 
			
		||||
 | 
			
		||||
@ -244,7 +244,7 @@ test.describe('toHaveURL', () => {
 | 
			
		||||
  test('fail string', async ({ page }) => {
 | 
			
		||||
    await page.goto('data:text/html,<div>A</div>');
 | 
			
		||||
    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>"');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@ -252,7 +252,7 @@ test.describe('toHaveURL', () => {
 | 
			
		||||
    await page.goto('data:text/html,<div>A</div>');
 | 
			
		||||
    // @ts-expect-error
 | 
			
		||||
    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: {}');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -548,7 +548,7 @@ test('should respect expect.timeout', async ({ runInlineTest }) => {
 | 
			
		||||
      test('timeout', async ({ page }) => {
 | 
			
		||||
        await page.goto('data:text/html,<div>A</div>');
 | 
			
		||||
        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>');
 | 
			
		||||
      });
 | 
			
		||||
      `,
 | 
			
		||||
@ -566,7 +566,7 @@ test('should support toHaveURL predicate', async ({ runInlineTest }) => {
 | 
			
		||||
 | 
			
		||||
      test('predicate', async ({ page }) => {
 | 
			
		||||
        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(error.message).toContain('data:text/html,<div>');
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user