fix(platform) instanceof bug between execution contexts of RegExp object (#1048)
First encountered at jest-playwright repo: https://github.com/mmarkelov/jest-playwright/issues/38 Solution based on: https://stackoverflow.com/questions/4339288/typeof-for-regexp#comment4724685_4339350
This commit is contained in:
parent
a6c3735b9d
commit
fdfec8eb2a
|
|
@ -98,6 +98,10 @@ class Helper {
|
||||||
return typeof obj === 'number' || obj instanceof Number;
|
return typeof obj === 'number' || obj instanceof Number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static isRegExp(obj: any): obj is RegExp {
|
||||||
|
return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';
|
||||||
|
}
|
||||||
|
|
||||||
static isObject(obj: any): obj is NonNullable<object> {
|
static isObject(obj: any): obj is NonNullable<object> {
|
||||||
return typeof obj === 'object' && obj !== null;
|
return typeof obj === 'object' && obj !== null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -358,7 +358,7 @@ export class Page extends platform.EventEmitter {
|
||||||
async waitForRequest(urlOrPredicate: string | RegExp | ((r: network.Request) => boolean), options: types.TimeoutOptions = {}): Promise<network.Request> {
|
async waitForRequest(urlOrPredicate: string | RegExp | ((r: network.Request) => boolean), options: types.TimeoutOptions = {}): Promise<network.Request> {
|
||||||
const { timeout = this._timeoutSettings.timeout() } = options;
|
const { timeout = this._timeoutSettings.timeout() } = options;
|
||||||
return helper.waitForEvent(this, Events.Page.Request, (request: network.Request) => {
|
return helper.waitForEvent(this, Events.Page.Request, (request: network.Request) => {
|
||||||
if (helper.isString(urlOrPredicate) || urlOrPredicate instanceof RegExp)
|
if (helper.isString(urlOrPredicate) || helper.isRegExp(urlOrPredicate))
|
||||||
return platform.urlMatches(request.url(), urlOrPredicate);
|
return platform.urlMatches(request.url(), urlOrPredicate);
|
||||||
return urlOrPredicate(request);
|
return urlOrPredicate(request);
|
||||||
}, timeout, this._disconnectedPromise);
|
}, timeout, this._disconnectedPromise);
|
||||||
|
|
@ -367,7 +367,7 @@ export class Page extends platform.EventEmitter {
|
||||||
async waitForResponse(urlOrPredicate: string | RegExp | ((r: network.Response) => boolean), options: types.TimeoutOptions = {}): Promise<network.Response> {
|
async waitForResponse(urlOrPredicate: string | RegExp | ((r: network.Response) => boolean), options: types.TimeoutOptions = {}): Promise<network.Response> {
|
||||||
const { timeout = this._timeoutSettings.timeout() } = options;
|
const { timeout = this._timeoutSettings.timeout() } = options;
|
||||||
return helper.waitForEvent(this, Events.Page.Response, (response: network.Response) => {
|
return helper.waitForEvent(this, Events.Page.Response, (response: network.Response) => {
|
||||||
if (helper.isString(urlOrPredicate) || urlOrPredicate instanceof RegExp)
|
if (helper.isString(urlOrPredicate) || helper.isRegExp(urlOrPredicate))
|
||||||
return platform.urlMatches(response.url(), urlOrPredicate);
|
return platform.urlMatches(response.url(), urlOrPredicate);
|
||||||
return urlOrPredicate(response);
|
return urlOrPredicate(response);
|
||||||
}, timeout, this._disconnectedPromise);
|
}, timeout, this._disconnectedPromise);
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ export function urlMatches(urlString: string, match: types.URLMatch | undefined)
|
||||||
return true;
|
return true;
|
||||||
if (helper.isString(match))
|
if (helper.isString(match))
|
||||||
match = helper.globToRegex(match);
|
match = helper.globToRegex(match);
|
||||||
if (match instanceof RegExp)
|
if (helper.isRegExp(match))
|
||||||
return match.test(urlString);
|
return match.test(urlString);
|
||||||
if (typeof match === 'string' && match === urlString)
|
if (typeof match === 'string' && match === urlString)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { helper } = require('../lib/helper');
|
const { helper } = require('../lib/helper');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
|
const vm = require('vm');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {PageTestSuite}
|
* @type {PageTestSuite}
|
||||||
|
|
@ -618,6 +619,28 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
|
||||||
expect(helper.globToRegex('**/*.{png,jpg,jpeg}').test('https://localhost:8080/c.css')).toBeFalsy();
|
expect(helper.globToRegex('**/*.{png,jpg,jpeg}').test('https://localhost:8080/c.css')).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('regexp', function() {
|
||||||
|
it('should work with regular expression passed from a different context', async({page, server}) => {
|
||||||
|
const ctx = vm.createContext();
|
||||||
|
const regexp = vm.runInContext('new RegExp("empty\\.html")', ctx);
|
||||||
|
|
||||||
|
await page.route(regexp, request => {
|
||||||
|
expect(request.url()).toContain('empty.html');
|
||||||
|
expect(request.headers()['user-agent']).toBeTruthy();
|
||||||
|
expect(request.method()).toBe('GET');
|
||||||
|
expect(request.postData()).toBe(undefined);
|
||||||
|
expect(request.isNavigationRequest()).toBe(true);
|
||||||
|
expect(request.resourceType()).toBe('document');
|
||||||
|
expect(request.frame() === page.mainFrame()).toBe(true);
|
||||||
|
expect(request.frame().url()).toBe('about:blank');
|
||||||
|
request.continue();
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await page.goto(server.EMPTY_PAGE);
|
||||||
|
expect(response.ok()).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const {waitEvent} = utils;
|
const {waitEvent} = utils;
|
||||||
|
const vm = require('vm');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {PageTestSuite}
|
* @type {PageTestSuite}
|
||||||
|
|
@ -309,6 +310,19 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF
|
||||||
]);
|
]);
|
||||||
expect(request.url()).toBe(server.PREFIX + '/digits/1.png');
|
expect(request.url()).toBe(server.PREFIX + '/digits/1.png');
|
||||||
});
|
});
|
||||||
|
it('should work with url match regular expression from a different context', async({page, server}) => {
|
||||||
|
const ctx = vm.createContext();
|
||||||
|
const regexp = vm.runInContext('new RegExp(/digits\\/\\d\\.png/)', ctx);
|
||||||
|
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
const [request] = await Promise.all([
|
||||||
|
page.waitForRequest(regexp),
|
||||||
|
page.evaluate(() => {
|
||||||
|
fetch('/digits/1.png');
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
expect(request.url()).toBe(server.PREFIX + '/digits/1.png');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Page.waitForResponse', function() {
|
describe('Page.waitForResponse', function() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue