mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat(urlmatch): support url matching in waitForNavigation (#300)
This commit is contained in:
parent
1c2b6444e9
commit
3669dad243
@ -42,6 +42,8 @@ export type NavigateOptions = {
|
||||
waitUntil?: LifecycleEvent | LifecycleEvent[],
|
||||
};
|
||||
|
||||
export type WaitForNavigationOptions = NavigateOptions & types.URLMatch;
|
||||
|
||||
export type GotoOptions = NavigateOptions & {
|
||||
referer?: string,
|
||||
};
|
||||
@ -284,13 +286,11 @@ export class Frame {
|
||||
this._parentFrame._childFrames.add(this);
|
||||
}
|
||||
|
||||
async goto(url: string, options: GotoOptions = {}): Promise<network.Response | null> {
|
||||
const {
|
||||
referer = (this._page._state.extraHTTPHeaders || {})['referer'],
|
||||
waitUntil = (['load'] as LifecycleEvent[]),
|
||||
timeout = this._page._timeoutSettings.navigationTimeout(),
|
||||
} = options;
|
||||
const watcher = new LifecycleWatcher(this, waitUntil, timeout);
|
||||
async goto(url: string, options?: GotoOptions): Promise<network.Response | null> {
|
||||
let referer = (this._page._state.extraHTTPHeaders || {})['referer'];
|
||||
if (options && options.referer !== undefined)
|
||||
referer = options.referer;
|
||||
const watcher = new LifecycleWatcher(this, options, false /* supportUrlMatch */);
|
||||
|
||||
let navigateResult: GotoResult;
|
||||
const navigate = async () => {
|
||||
@ -323,12 +323,8 @@ export class Frame {
|
||||
return watcher.navigationResponse();
|
||||
}
|
||||
|
||||
async waitForNavigation(options: NavigateOptions = {}): Promise<network.Response | null> {
|
||||
const {
|
||||
waitUntil = (['load'] as LifecycleEvent[]),
|
||||
timeout = this._page._timeoutSettings.navigationTimeout(),
|
||||
} = options;
|
||||
const watcher = new LifecycleWatcher(this, waitUntil, timeout);
|
||||
async waitForNavigation(options?: WaitForNavigationOptions): Promise<network.Response | null> {
|
||||
const watcher = new LifecycleWatcher(this, options, true /* supportUrlMatch */);
|
||||
const error = await Promise.race([
|
||||
watcher.timeoutOrTerminationPromise,
|
||||
watcher.sameDocumentNavigationPromise,
|
||||
@ -430,11 +426,7 @@ export class Frame {
|
||||
});
|
||||
}
|
||||
|
||||
async setContent(html: string, options: NavigateOptions = {}): Promise<void> {
|
||||
const {
|
||||
waitUntil = (['load'] as LifecycleEvent[]),
|
||||
timeout = this._page._timeoutSettings.navigationTimeout(),
|
||||
} = options;
|
||||
async setContent(html: string, options?: NavigateOptions): Promise<void> {
|
||||
const context = await this._utilityContext();
|
||||
if (this._page._delegate.needsLifecycleResetOnSetContent())
|
||||
this._firedLifecycleEvents.clear();
|
||||
@ -443,7 +435,7 @@ export class Frame {
|
||||
document.write(html);
|
||||
document.close();
|
||||
}, html);
|
||||
const watcher = new LifecycleWatcher(this, waitUntil, timeout);
|
||||
const watcher = new LifecycleWatcher(this, options, false /* supportUrlMatch */);
|
||||
const error = await Promise.race([
|
||||
watcher.timeoutOrTerminationPromise,
|
||||
watcher.lifecyclePromise,
|
||||
@ -869,14 +861,22 @@ class LifecycleWatcher {
|
||||
private _hasSameDocumentNavigation: boolean;
|
||||
private _targetUrl?: string;
|
||||
private _expectedDocumentId?: string;
|
||||
private _urlMatch?: types.URLMatch;
|
||||
|
||||
constructor(frame: Frame, waitUntil: LifecycleEvent | LifecycleEvent[], timeout: number) {
|
||||
if (Array.isArray(waitUntil))
|
||||
waitUntil = waitUntil.slice();
|
||||
else if (typeof waitUntil === 'string')
|
||||
constructor(frame: Frame, options: WaitForNavigationOptions | undefined, supportUrlMatch: boolean) {
|
||||
options = options || {};
|
||||
let {
|
||||
waitUntil = (['load'] as LifecycleEvent[]),
|
||||
timeout = frame._page._timeoutSettings.navigationTimeout()
|
||||
} = options;
|
||||
if (!Array.isArray(waitUntil))
|
||||
waitUntil = [waitUntil];
|
||||
if (waitUntil.some(e => !kLifecycleEvents.has(e)))
|
||||
throw new Error('Unsupported waitUntil option');
|
||||
for (const event of waitUntil) {
|
||||
if (!kLifecycleEvents.has(event))
|
||||
throw new Error(`Unsupported waitUntil option ${String(event)}`);
|
||||
}
|
||||
if (supportUrlMatch)
|
||||
this._urlMatch = options;
|
||||
this._expectedLifecycle = waitUntil.slice();
|
||||
this._frame = frame;
|
||||
this.sameDocumentNavigationPromise = new Promise(f => this._sameDocumentNavigationCompleteCallback = f);
|
||||
@ -892,7 +892,12 @@ class LifecycleWatcher {
|
||||
this._checkLifecycleComplete();
|
||||
}
|
||||
|
||||
private _urlMatches(urlString: string): boolean {
|
||||
return !this._urlMatch || helper.urlMatches(urlString, this._urlMatch);
|
||||
}
|
||||
|
||||
setExpectedDocumentId(documentId: string, url: string) {
|
||||
assert(!this._urlMatch, 'Should not have url match when expecting a particular navigation');
|
||||
this._expectedDocumentId = documentId;
|
||||
this._targetUrl = url;
|
||||
if (this._navigationRequest && this._navigationRequest._documentId !== documentId)
|
||||
@ -916,7 +921,7 @@ class LifecycleWatcher {
|
||||
|
||||
_onNavigationRequest(frame: Frame, request: network.Request) {
|
||||
assert(request._documentId);
|
||||
if (frame !== this._frame)
|
||||
if (frame !== this._frame || !this._urlMatches(request.url()))
|
||||
return;
|
||||
if (this._expectedDocumentId === undefined || this._expectedDocumentId === request._documentId) {
|
||||
this._navigationRequest = request;
|
||||
@ -926,7 +931,7 @@ class LifecycleWatcher {
|
||||
}
|
||||
|
||||
_onCommittedNewDocumentNavigation(frame: Frame) {
|
||||
if (frame === this._frame && this._expectedDocumentId === undefined) {
|
||||
if (frame === this._frame && this._expectedDocumentId === undefined && this._urlMatches(frame.url())) {
|
||||
this._expectedDocumentId = frame._lastDocumentId;
|
||||
this._targetUrl = frame.url();
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ export class Page extends EventEmitter {
|
||||
return waitPromise;
|
||||
}
|
||||
|
||||
waitForNavigation(options?: frames.NavigateOptions): Promise<network.Response | null> {
|
||||
async waitForNavigation(options?: frames.WaitForNavigationOptions): Promise<network.Response | null> {
|
||||
return this.mainFrame().waitForNavigation(options);
|
||||
}
|
||||
|
||||
|
@ -582,6 +582,40 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROME
|
||||
navigationPromise
|
||||
]);
|
||||
});
|
||||
it('should work with url match', async({page, server}) => {
|
||||
let response1 = null;
|
||||
const response1Promise = page.waitForNavigation({ url: /one-style\.html/ }).then(response => response1 = response);
|
||||
let response2 = null;
|
||||
const response2Promise = page.waitForNavigation({ pathname: '/frame.html' }).then(response => response2 = response);
|
||||
let response3 = null;
|
||||
const response3Promise = page.waitForNavigation({ searchParams: { 'foo': 'bar' }, strictSearchParams: true }).then(response => response3 = response);
|
||||
expect(response1).toBe(null);
|
||||
expect(response2).toBe(null);
|
||||
expect(response3).toBe(null);
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
expect(response1).toBe(null);
|
||||
expect(response2).toBe(null);
|
||||
expect(response3).toBe(null);
|
||||
await page.goto(server.PREFIX + '/frame.html');
|
||||
expect(response1).toBe(null);
|
||||
await response2Promise;
|
||||
expect(response2).not.toBe(null);
|
||||
expect(response3).toBe(null);
|
||||
await page.goto(server.PREFIX + '/one-style.html');
|
||||
await response1Promise;
|
||||
expect(response1).not.toBe(null);
|
||||
expect(response2).not.toBe(null);
|
||||
expect(response3).toBe(null);
|
||||
await page.goto(server.PREFIX + '/frame.html?foo=bar');
|
||||
await response3Promise;
|
||||
expect(response1).not.toBe(null);
|
||||
expect(response2).not.toBe(null);
|
||||
expect(response3).not.toBe(null);
|
||||
await page.goto(server.PREFIX + '/empty.html');
|
||||
expect(response1.url()).toBe(server.PREFIX + '/one-style.html');
|
||||
expect(response2.url()).toBe(server.PREFIX + '/frame.html');
|
||||
expect(response3.url()).toBe(server.PREFIX + '/frame.html?foo=bar');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Page.goBack', function() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user