mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore: add BiDi for goto
navigation (#9795)
This commit is contained in:
parent
07391bbf5f
commit
175362c048
@ -34,9 +34,9 @@ The constructor for this class is marked as internal. Third-party code should no
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Modifiers | Type | Description |
|
||||
| ------------------------------------------- | --------------------- | ---------- | ----------------------------------------------------------------- |
|
||||
| [client](./puppeteer.httprequest.client.md) | <code>readonly</code> | CDPSession | Warning! Using this client can break Puppeteer. Use with caution. |
|
||||
| Property | Modifiers | Type | Description |
|
||||
| ------------------------------------------- | --------------------- | --------------------------------------- | ----------------------------------------------------------------- |
|
||||
| [client](./puppeteer.httprequest.client.md) | <code>readonly</code> | [CDPSession](./puppeteer.cdpsession.md) | Warning! Using this client can break Puppeteer. Use with caution. |
|
||||
|
||||
## Methods
|
||||
|
||||
|
13
package-lock.json
generated
13
package-lock.json
generated
@ -2625,8 +2625,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/chromium-bidi": {
|
||||
"version": "0.4.4",
|
||||
"license": "Apache-2.0",
|
||||
"version": "0.4.5",
|
||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.5.tgz",
|
||||
"integrity": "sha512-rkav9YzRfAshSTG3wNXF7P7yNiI29QAo1xBXElPoCoSQR5n20q3cOyVhDv6S7+GlF/CJ/emUxlQiR0xOPurkGg==",
|
||||
"dependencies": {
|
||||
"mitt": "3.0.0"
|
||||
},
|
||||
@ -9228,7 +9229,7 @@
|
||||
"version": "19.7.4",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"chromium-bidi": "0.4.4",
|
||||
"chromium-bidi": "0.4.5",
|
||||
"cross-fetch": "3.1.5",
|
||||
"debug": "4.3.4",
|
||||
"devtools-protocol": "0.0.1094867",
|
||||
@ -11025,7 +11026,9 @@
|
||||
"version": "1.1.4"
|
||||
},
|
||||
"chromium-bidi": {
|
||||
"version": "0.4.4",
|
||||
"version": "0.4.5",
|
||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.5.tgz",
|
||||
"integrity": "sha512-rkav9YzRfAshSTG3wNXF7P7yNiI29QAo1xBXElPoCoSQR5n20q3cOyVhDv6S7+GlF/CJ/emUxlQiR0xOPurkGg==",
|
||||
"requires": {
|
||||
"mitt": "3.0.0"
|
||||
}
|
||||
@ -13982,7 +13985,7 @@
|
||||
"puppeteer-core": {
|
||||
"version": "file:packages/puppeteer-core",
|
||||
"requires": {
|
||||
"chromium-bidi": "0.4.4",
|
||||
"chromium-bidi": "0.4.5",
|
||||
"cross-fetch": "3.1.5",
|
||||
"debug": "4.3.4",
|
||||
"devtools-protocol": "0.0.1094867",
|
||||
|
@ -131,7 +131,7 @@
|
||||
"author": "The Chromium Authors",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"chromium-bidi": "0.4.4",
|
||||
"chromium-bidi": "0.4.5",
|
||||
"cross-fetch": "3.1.5",
|
||||
"debug": "4.3.4",
|
||||
"devtools-protocol": "0.0.1094867",
|
||||
|
@ -14,12 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {Protocol} from 'devtools-protocol';
|
||||
import {ProtocolMapping} from 'devtools-protocol/types/protocol-mapping.js';
|
||||
|
||||
import {assert} from '../util/assert.js';
|
||||
|
||||
import {CDPSession} from './Connection.js';
|
||||
import {ProtocolError} from './Errors.js';
|
||||
import {EventEmitter} from './EventEmitter.js';
|
||||
import {Frame} from './Frame.js';
|
||||
import {HTTPResponse} from './HTTPResponse.js';
|
||||
import {debugError, isString} from './util.js';
|
||||
@ -74,13 +73,6 @@ export type ResourceType = Lowercase<Protocol.Network.ResourceType>;
|
||||
*/
|
||||
export const DEFAULT_INTERCEPT_RESOLUTION_PRIORITY = 0;
|
||||
|
||||
interface CDPSession extends EventEmitter {
|
||||
send<T extends keyof ProtocolMapping.Commands>(
|
||||
method: T,
|
||||
...paramArgs: ProtocolMapping.Commands[T]['paramsType']
|
||||
): Promise<ProtocolMapping.Commands[T]['returnType']>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an HTTP request sent by a page.
|
||||
* @remarks
|
||||
|
@ -14,10 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {Protocol} from 'devtools-protocol';
|
||||
import {ProtocolMapping} from 'devtools-protocol/types/protocol-mapping.js';
|
||||
|
||||
import {CDPSession} from './Connection.js';
|
||||
import {ProtocolError} from './Errors.js';
|
||||
import {EventEmitter} from './EventEmitter.js';
|
||||
import {Frame} from './Frame.js';
|
||||
import {HTTPRequest} from './HTTPRequest.js';
|
||||
import {SecurityDetails} from './SecurityDetails.js';
|
||||
@ -30,13 +29,6 @@ export interface RemoteAddress {
|
||||
port?: number;
|
||||
}
|
||||
|
||||
interface CDPSession extends EventEmitter {
|
||||
send<T extends keyof ProtocolMapping.Commands>(
|
||||
method: T,
|
||||
...paramArgs: ProtocolMapping.Commands[T]['paramsType']
|
||||
): Promise<ProtocolMapping.Commands[T]['returnType']>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The HTTPResponse class represents responses which are received by the
|
||||
* {@link Page} class.
|
||||
|
@ -822,7 +822,7 @@ export class CDPPage extends Page {
|
||||
}
|
||||
const textTokens = [];
|
||||
for (const arg of args) {
|
||||
const remoteObject = arg.remoteObject() as Protocol.Runtime.RemoteObject;
|
||||
const remoteObject = arg.remoteObject();
|
||||
if (remoteObject.objectId) {
|
||||
textTokens.push(arg.toString());
|
||||
} else {
|
||||
|
@ -52,6 +52,10 @@ interface Commands {
|
||||
params: Bidi.BrowsingContext.CloseParameters;
|
||||
returnType: Bidi.BrowsingContext.CloseResult;
|
||||
};
|
||||
'browsingContext.navigate': {
|
||||
params: Bidi.BrowsingContext.NavigateParameters;
|
||||
returnType: Bidi.BrowsingContext.NavigateResult;
|
||||
};
|
||||
|
||||
'session.new': {
|
||||
params: {capabilities?: Record<any, unknown>}; // TODO: Update Types in chromium bidi
|
||||
@ -148,17 +152,20 @@ export class Connection extends EventEmitter {
|
||||
if (callback.method === 'browsingContext.create') {
|
||||
this.#contexts.set(
|
||||
object.result.context,
|
||||
new Context(this, object.result.context)
|
||||
new Context(this, object.result)
|
||||
);
|
||||
}
|
||||
callback.resolve(object);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ('source' in object.params && !!object.params.source.context) {
|
||||
const context = this.#contexts.get(object.params.source.context);
|
||||
context?.emit(object.method, object.params);
|
||||
let context: Context | undefined;
|
||||
if ('context' in object.params) {
|
||||
context = this.#contexts.get(object.params.context);
|
||||
} else if ('source' in object.params && !!object.params.source.context) {
|
||||
context = this.#contexts.get(object.params.source.context);
|
||||
}
|
||||
context?.emit(object.method, object.params);
|
||||
|
||||
this.emit(object.method, object.params);
|
||||
}
|
||||
|
@ -16,8 +16,13 @@
|
||||
|
||||
import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||
|
||||
import {WaitForOptions} from '../../api/Page.js';
|
||||
import {assert} from '../../util/assert.js';
|
||||
import {stringifyFunction} from '../../util/Function.js';
|
||||
import {ProtocolError, TimeoutError} from '../Errors.js';
|
||||
import {EventEmitter} from '../EventEmitter.js';
|
||||
import {PuppeteerLifeCycleEvent} from '../LifecycleWatcher.js';
|
||||
import {TimeoutSettings} from '../TimeoutSettings.js';
|
||||
import {EvaluateFunc, HandleFor} from '../types.js';
|
||||
import {isString} from '../util.js';
|
||||
|
||||
@ -26,17 +31,31 @@ import {ElementHandle} from './ElementHandle.js';
|
||||
import {JSHandle} from './JSHandle.js';
|
||||
import {BidiSerializer} from './Serializer.js';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
const puppeteerToReadinessState = new Map<
|
||||
PuppeteerLifeCycleEvent,
|
||||
Bidi.BrowsingContext.ReadinessState
|
||||
>([
|
||||
['load', 'complete'],
|
||||
['domcontentloaded', 'interactive'],
|
||||
]);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class Context extends EventEmitter {
|
||||
#connection: Connection;
|
||||
#url: string;
|
||||
_contextId: string;
|
||||
_timeoutSettings = new TimeoutSettings();
|
||||
|
||||
constructor(connection: Connection, contextId: string) {
|
||||
constructor(connection: Connection, result: Bidi.BrowsingContext.Info) {
|
||||
super();
|
||||
this.#connection = connection;
|
||||
this._contextId = contextId;
|
||||
this._contextId = result.context;
|
||||
this.#url = result.url;
|
||||
}
|
||||
|
||||
get connection(): Connection {
|
||||
@ -124,6 +143,76 @@ export class Context extends EventEmitter {
|
||||
? BidiSerializer.deserialize(result.result)
|
||||
: getBidiHandle(this, result.result);
|
||||
}
|
||||
|
||||
async goto(
|
||||
url: string,
|
||||
options: WaitForOptions & {
|
||||
referer?: string | undefined;
|
||||
referrerPolicy?: string | undefined;
|
||||
} = {}
|
||||
): Promise<null> {
|
||||
const {waitUntil = 'load'} = options;
|
||||
|
||||
try {
|
||||
const response = await Promise.race([
|
||||
this.connection.send('browsingContext.navigate', {
|
||||
url: url,
|
||||
context: this.id,
|
||||
wait: getWaitUntil(waitUntil),
|
||||
}),
|
||||
new Promise((_, reject) => {
|
||||
const timeout =
|
||||
options.timeout ?? this._timeoutSettings.navigationTimeout();
|
||||
if (!timeout) {
|
||||
return;
|
||||
}
|
||||
const error = new TimeoutError(
|
||||
'Navigation timeout of ' + timeout + ' ms exceeded'
|
||||
);
|
||||
return setTimeout(() => {
|
||||
return reject(error);
|
||||
}, timeout);
|
||||
}),
|
||||
]);
|
||||
this.#url = (response as Bidi.BrowsingContext.NavigateResult).result.url;
|
||||
return null;
|
||||
} catch (error) {
|
||||
if (error instanceof ProtocolError) {
|
||||
error.message += ` at ${url}`;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
function getWaitUntil(
|
||||
event: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[]
|
||||
): Bidi.BrowsingContext.ReadinessState {
|
||||
if (Array.isArray(event) && event.length > 1) {
|
||||
throw new Error('BiDi support only single `waitUntil` argument');
|
||||
}
|
||||
const waitUntilSingle = Array.isArray(event)
|
||||
? (event.find(lifecycle => {
|
||||
return lifecycle === 'domcontentloaded' || lifecycle === 'load';
|
||||
}) as PuppeteerLifeCycleEvent)
|
||||
: event;
|
||||
|
||||
if (
|
||||
waitUntilSingle === 'networkidle0' ||
|
||||
waitUntilSingle === 'networkidle2'
|
||||
) {
|
||||
throw new Error(`BiDi does not support 'waitUntil' ${waitUntilSingle}`);
|
||||
}
|
||||
|
||||
assert(waitUntilSingle, `Invalid waitUntil option ${waitUntilSingle}`);
|
||||
|
||||
return puppeteerToReadinessState.get(
|
||||
waitUntilSingle
|
||||
) as Bidi.BrowsingContext.ReadinessState;
|
||||
}
|
||||
}
|
||||
|
||||
url(): string {
|
||||
return this.#url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,8 +16,13 @@
|
||||
|
||||
import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||
|
||||
import {Page as PageBase, PageEmittedEvents} from '../../api/Page.js';
|
||||
import {
|
||||
Page as PageBase,
|
||||
PageEmittedEvents,
|
||||
WaitForOptions,
|
||||
} from '../../api/Page.js';
|
||||
import {ConsoleMessage, ConsoleMessageLocation} from '../ConsoleMessage.js';
|
||||
import {HTTPResponse} from '../HTTPResponse.js';
|
||||
import {EvaluateFunc, HandleFor} from '../types.js';
|
||||
|
||||
import {Context, getBidiHandle} from './Context.js';
|
||||
@ -30,8 +35,11 @@ export class Page extends PageBase {
|
||||
#context: Context;
|
||||
#subscribedEvents = [
|
||||
'log.entryAdded',
|
||||
'browsingContext.load',
|
||||
] as Bidi.Session.SubscribeParameters['events'];
|
||||
|
||||
#boundOnLogEntryAdded = this.#onLogEntryAdded.bind(this);
|
||||
#boundOnLoaded = this.#onLoad.bind(this);
|
||||
|
||||
constructor(context: Context) {
|
||||
super();
|
||||
@ -43,6 +51,7 @@ export class Page extends PageBase {
|
||||
});
|
||||
|
||||
this.#context.on('log.entryAdded', this.#boundOnLogEntryAdded);
|
||||
this.#context.on('browsingContext.load', this.#boundOnLoaded);
|
||||
}
|
||||
|
||||
#onLogEntryAdded(event: Bidi.Log.LogEntry): void {
|
||||
@ -82,6 +91,10 @@ export class Page extends PageBase {
|
||||
}
|
||||
}
|
||||
|
||||
#onLoad(_event: Bidi.BrowsingContext.NavigationInfo): void {
|
||||
this.emit(PageEmittedEvents.Load);
|
||||
}
|
||||
|
||||
override async close(): Promise<void> {
|
||||
await this.#context.connection.send('session.unsubscribe', {
|
||||
events: this.#subscribedEvents,
|
||||
@ -93,6 +106,7 @@ export class Page extends PageBase {
|
||||
});
|
||||
|
||||
this.#context.off('log.entryAdded', this.#boundOnLogEntryAdded);
|
||||
this.#context.off('browsingContext.load', this.#boundOnLogEntryAdded);
|
||||
}
|
||||
|
||||
override async evaluateHandle<
|
||||
@ -114,6 +128,28 @@ export class Page extends PageBase {
|
||||
): Promise<Awaited<ReturnType<Func>>> {
|
||||
return this.#context.evaluate(pageFunction, ...args);
|
||||
}
|
||||
|
||||
override async goto(
|
||||
url: string,
|
||||
options?: WaitForOptions & {
|
||||
referer?: string | undefined;
|
||||
referrerPolicy?: string | undefined;
|
||||
}
|
||||
): Promise<HTTPResponse | null> {
|
||||
return this.#context.goto(url, options);
|
||||
}
|
||||
|
||||
override url(): string {
|
||||
return this.#context.url();
|
||||
}
|
||||
|
||||
override setDefaultNavigationTimeout(timeout: number): void {
|
||||
this.#context._timeoutSettings.setDefaultNavigationTimeout(timeout);
|
||||
}
|
||||
|
||||
override setDefaultTimeout(timeout: number): void {
|
||||
this.#context._timeoutSettings.setDefaultTimeout(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
function isConsoleLogEntry(
|
||||
|
@ -1817,6 +1817,12 @@
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[jshandle.spec] JSHandle Page.evaluateHandle should accept object handle as an argument",
|
||||
"platforms": ["darwin"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS", "FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work ARIA selectors",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -1840,5 +1846,227 @@
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec]",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should work with redirects",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should return response when page changes its URL after load",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should navigate to empty page with domcontentloaded",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should work when page calls history API in beforeunload",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should navigate to empty page with networkidle0",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should navigate to empty page with networkidle2",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should fail when navigating to bad SSL",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should work when navigating to valid url",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should work when navigating to data url",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should work when navigating to 404",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should not throw an error for a 404 response with an empty body",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should not throw an error for a 500 response with an empty body",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should return last response in redirect chain",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should wait for network idle to succeed navigation",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should navigate to dataURL and fire dataURL requests",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should navigate to URL with hash and fire requests without hash",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should work with self requesting page",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should send referer",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.waitForNavigation should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.waitForNavigation should work with both domcontentloaded and load",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.waitForNavigation should work with clicking on anchor links",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.waitForNavigation should work with history.pushState()",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.waitForNavigation should work with history.replaceState()",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.waitForNavigation should work with DOM history.back()/history.forward()",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.waitForNavigation should work when subframe issues window.stop()",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL", "TIMEOUT"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goBack should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goBack should work with HistoryAPI",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Frame.goto should navigate subframes",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Frame.goto should reject when frame detaches",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Frame.goto should return matching responses",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Frame.waitForNavigation should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Frame.waitForNavigation should fail when frame detaches",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.reload should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should fail when navigating to bad url",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation Page.goto should fail when navigating to bad SSL after redirects",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation \"after all\" hook in \"navigation\"",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "headless", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
}
|
||||
]
|
||||
|
@ -25,11 +25,12 @@ import {
|
||||
setupTestBrowserHooks,
|
||||
setupTestPageAndContextHooks,
|
||||
} from './mocha-utils.js';
|
||||
import utils from './utils.js';
|
||||
import {attachFrame, isFavicon, waitEvent} from './utils.js';
|
||||
|
||||
describe('navigation', function () {
|
||||
setupTestBrowserHooks();
|
||||
setupTestPageAndContextHooks();
|
||||
|
||||
describe('Page.goto', function () {
|
||||
it('should work', async () => {
|
||||
const {page, server} = getTestState();
|
||||
@ -361,10 +362,14 @@ describe('navigation', function () {
|
||||
server.waitForRequest('/fetch-request-a.js'),
|
||||
server.waitForRequest('/fetch-request-b.js'),
|
||||
server.waitForRequest('/fetch-request-c.js'),
|
||||
]);
|
||||
const secondFetchResourceRequested = server.waitForRequest(
|
||||
'/fetch-request-d.js'
|
||||
);
|
||||
]).catch(() => {
|
||||
// Ignore Error that arise from test server during hooks
|
||||
});
|
||||
const secondFetchResourceRequested = server
|
||||
.waitForRequest('/fetch-request-d.js')
|
||||
.catch(() => {
|
||||
// Ignore Error that arise from test server during hooks
|
||||
});
|
||||
|
||||
// Navigate to a page which loads immediately and then does a bunch of
|
||||
// requests via javascript's fetch method.
|
||||
@ -466,7 +471,7 @@ describe('navigation', function () {
|
||||
|
||||
const requests: HTTPRequest[] = [];
|
||||
page.on('request', request => {
|
||||
return !utils.isFavicon(request) && requests.push(request);
|
||||
return !isFavicon(request) && requests.push(request);
|
||||
});
|
||||
const dataURL = 'data:text/html,<div>yo</div>';
|
||||
const response = (await page.goto(dataURL))!;
|
||||
@ -479,7 +484,7 @@ describe('navigation', function () {
|
||||
|
||||
const requests: HTTPRequest[] = [];
|
||||
page.on('request', request => {
|
||||
return !utils.isFavicon(request) && requests.push(request);
|
||||
return !isFavicon(request) && requests.push(request);
|
||||
});
|
||||
const response = (await page.goto(server.EMPTY_PAGE + '#hash'))!;
|
||||
expect(response.status()).toBe(200);
|
||||
@ -509,13 +514,17 @@ describe('navigation', function () {
|
||||
it('should send referer', async () => {
|
||||
const {page, server} = getTestState();
|
||||
|
||||
const [request1, request2] = await Promise.all([
|
||||
const requests = Promise.all([
|
||||
server.waitForRequest('/grid.html'),
|
||||
server.waitForRequest('/digits/1.png'),
|
||||
page.goto(server.PREFIX + '/grid.html', {
|
||||
referer: 'http://google.com/',
|
||||
}),
|
||||
]);
|
||||
]).catch(() => {
|
||||
return [];
|
||||
});
|
||||
|
||||
const [request1, request2] = await requests;
|
||||
expect(request1.headers['referer']).toBe('http://google.com/');
|
||||
// Make sure subresources do not inherit referer.
|
||||
expect(request2.headers['referer']).toBe(server.PREFIX + '/grid.html');
|
||||
@ -530,7 +539,9 @@ describe('navigation', function () {
|
||||
page.goto(server.PREFIX + '/grid.html', {
|
||||
referrerPolicy: 'no-referer',
|
||||
}),
|
||||
]);
|
||||
]).catch(() => {
|
||||
return [];
|
||||
});
|
||||
expect(request1.headers['referer']).toBeUndefined();
|
||||
expect(request2.headers['referer']).toBe(server.PREFIX + '/grid.html');
|
||||
});
|
||||
@ -571,7 +582,7 @@ describe('navigation', function () {
|
||||
return (bothFired = true);
|
||||
});
|
||||
|
||||
await server.waitForRequest('/one-style.css');
|
||||
await server.waitForRequest('/one-style.css').catch(() => {});
|
||||
await domContentLoadedPromise;
|
||||
expect(bothFired).toBe(false);
|
||||
response.end();
|
||||
@ -659,7 +670,7 @@ describe('navigation', function () {
|
||||
const navigationPromise = page.goto(
|
||||
server.PREFIX + '/frames/one-frame.html'
|
||||
);
|
||||
const frame = await utils.waitEvent(page, 'frameattached');
|
||||
const frame = await waitEvent(page, 'frameattached');
|
||||
await new Promise<void>(fulfill => {
|
||||
page.on('framenavigated', f => {
|
||||
if (f === frame) {
|
||||
@ -737,7 +748,7 @@ describe('navigation', function () {
|
||||
.catch(error_ => {
|
||||
return error_;
|
||||
});
|
||||
await server.waitForRequest('/empty.html');
|
||||
await server.waitForRequest('/empty.html').catch(() => {});
|
||||
|
||||
await page.$eval('iframe', frame => {
|
||||
return frame.remove();
|
||||
@ -753,9 +764,9 @@ describe('navigation', function () {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
// Attach three frames.
|
||||
const frames = await Promise.all([
|
||||
utils.attachFrame(page, 'frame1', server.EMPTY_PAGE),
|
||||
utils.attachFrame(page, 'frame2', server.EMPTY_PAGE),
|
||||
utils.attachFrame(page, 'frame3', server.EMPTY_PAGE),
|
||||
attachFrame(page, 'frame1', server.EMPTY_PAGE),
|
||||
attachFrame(page, 'frame2', server.EMPTY_PAGE),
|
||||
attachFrame(page, 'frame3', server.EMPTY_PAGE),
|
||||
]);
|
||||
// Navigate all frames to the same URL.
|
||||
const serverResponses: ServerResponse[] = [];
|
||||
|
Loading…
Reference in New Issue
Block a user