chore: remove unused non-rpc code, test options, infra, bots (#3444)
This commit is contained in:
parent
176227549d
commit
9b52ca8676
11
.github/workflows/tests.yml
vendored
11
.github/workflows/tests.yml
vendored
|
|
@ -177,13 +177,12 @@ jobs:
|
|||
name: headful-${{ matrix.browser }}-linux-testrun.log
|
||||
path: testrun.log
|
||||
|
||||
rpc_linux:
|
||||
name: "RPC Linux"
|
||||
wire_linux:
|
||||
name: "Wire Linux"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
browser: [chromium, firefox, webkit]
|
||||
transport: [wire, none]
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
@ -204,14 +203,14 @@ jobs:
|
|||
BROWSER: ${{ matrix.browser }}
|
||||
DEBUG: "pw:*,-pw:wrapped*,-pw:test*"
|
||||
DEBUG_FILE: "testrun.log"
|
||||
PWCHANNEL: ${{ matrix.transport }}
|
||||
PWWIRE: true
|
||||
- uses: actions/upload-artifact@v1
|
||||
if: failure()
|
||||
with:
|
||||
name: rpc-${{ matrix.transport }}-${{ matrix.browser }}-linux-output
|
||||
name: wire-${{ matrix.browser }}-linux-output
|
||||
path: test/output-${{ matrix.browser }}
|
||||
- uses: actions/upload-artifact@v1
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: rpc-${{ matrix.transport }}-${{ matrix.browser }}-linux-testrun.log
|
||||
name: wire-${{ matrix.browser }}-linux-testrun.log
|
||||
path: testrun.log
|
||||
|
|
|
|||
|
|
@ -17,9 +17,8 @@
|
|||
"tsc": "tsc -p .",
|
||||
"tsc-installer": "tsc -p ./src/install/tsconfig.json",
|
||||
"doc": "node utils/doclint/cli.js",
|
||||
"doc-no-channel": "node utils/doclint/cli.js --no-channel",
|
||||
"test-infra": "node test/runner utils/doclint/check_public_api/test/test.js && node test/runner utils/doclint/preprocessor/test.js",
|
||||
"lint": "npm run eslint && npm run tsc && npm run doc && npm run doc-no-channel && npm run check-deps && npm run generate-channels && npm run test-types && npm run test-infra",
|
||||
"lint": "npm run eslint && npm run tsc && npm run doc && npm run check-deps && npm run generate-channels && npm run test-types && npm run test-infra",
|
||||
"clean": "rimraf lib && rimraf types",
|
||||
"prepare": "node install-from-github.js",
|
||||
"build": "node utils/runWebpack.js --mode='development' && tsc -p . && npm run generate-types",
|
||||
|
|
|
|||
|
|
@ -16,13 +16,11 @@
|
|||
|
||||
import { ChildProcess } from 'child_process';
|
||||
import { EventEmitter } from 'events';
|
||||
import { WebSocketServer } from './webSocketServer';
|
||||
|
||||
export class BrowserServer extends EventEmitter {
|
||||
private _process: ChildProcess;
|
||||
private _gracefullyClose: () => Promise<void>;
|
||||
private _kill: () => Promise<void>;
|
||||
_webSocketServer: WebSocketServer | null = null;
|
||||
|
||||
constructor(process: ChildProcess, gracefullyClose: () => Promise<void>, kill: () => Promise<void>) {
|
||||
super();
|
||||
|
|
@ -35,10 +33,6 @@ export class BrowserServer extends EventEmitter {
|
|||
return this._process;
|
||||
}
|
||||
|
||||
wsEndpoint(): string {
|
||||
return this._webSocketServer ? this._webSocketServer.wsEndpoint : '';
|
||||
}
|
||||
|
||||
async kill(): Promise<void> {
|
||||
await this._kill();
|
||||
}
|
||||
|
|
@ -47,11 +41,6 @@ export class BrowserServer extends EventEmitter {
|
|||
await this._gracefullyClose();
|
||||
}
|
||||
|
||||
async _checkLeaks(): Promise<void> {
|
||||
if (this._webSocketServer)
|
||||
await this._webSocketServer.checkLeaks();
|
||||
}
|
||||
|
||||
async _closeOrKill(timeout: number): Promise<void> {
|
||||
let timer: NodeJS.Timer;
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import * as util from 'util';
|
|||
import { BrowserContext, verifyProxySettings, validateBrowserContextOptions } from '../browserContext';
|
||||
import { BrowserServer } from './browserServer';
|
||||
import * as browserPaths from '../install/browserPaths';
|
||||
import { Loggers, Logger } from '../logger';
|
||||
import { Loggers } from '../logger';
|
||||
import { ConnectionTransport, WebSocketTransport } from '../transport';
|
||||
import { BrowserBase, BrowserOptions, Browser } from '../browser';
|
||||
import { assert, helper } from '../helper';
|
||||
|
|
@ -31,13 +31,11 @@ import { PipeTransport } from './pipeTransport';
|
|||
import { Progress, runAbortableTask } from '../progress';
|
||||
import * as types from '../types';
|
||||
import { TimeoutSettings } from '../timeoutSettings';
|
||||
import { WebSocketServer } from './webSocketServer';
|
||||
import { LoggerSink } from '../loggerSink';
|
||||
import { validateHostRequirements } from './validateDependencies';
|
||||
|
||||
type FirefoxPrefsOptions = { firefoxUserPrefs?: { [key: string]: string | number | boolean } };
|
||||
type LaunchOptions = types.LaunchOptions & { logger?: LoggerSink };
|
||||
type ConnectOptions = types.ConnectOptions & { logger?: LoggerSink };
|
||||
|
||||
|
||||
export type LaunchNonPersistentOptions = LaunchOptions & FirefoxPrefsOptions;
|
||||
|
|
@ -50,7 +48,6 @@ export interface BrowserType {
|
|||
launch(options?: LaunchNonPersistentOptions): Promise<Browser>;
|
||||
launchServer(options?: LaunchServerOptions): Promise<BrowserServer>;
|
||||
launchPersistentContext(userDataDir: string, options?: LaunchPersistentOptions): Promise<BrowserContext>;
|
||||
connect(options: ConnectOptions): Promise<Browser>;
|
||||
}
|
||||
|
||||
const mkdirAsync = util.promisify(fs.mkdir);
|
||||
|
|
@ -134,26 +131,12 @@ export abstract class BrowserTypeBase implements BrowserType {
|
|||
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launchServer`. Use `browserType.launchPersistentContext` instead');
|
||||
options = validateLaunchOptions(options);
|
||||
const loggers = new Loggers(options.logger);
|
||||
const { port = 0 } = options;
|
||||
return runAbortableTask(async progress => {
|
||||
const { browserServer, transport } = await this._launchServer(progress, options, false, loggers);
|
||||
browserServer._webSocketServer = this._startWebSocketServer(transport, loggers.browser, port);
|
||||
const { browserServer } = await this._launchServer(progress, options, false, loggers);
|
||||
return browserServer;
|
||||
}, loggers.browser, TimeoutSettings.timeout(options), 'browserType.launchServer');
|
||||
}
|
||||
|
||||
async connect(options: ConnectOptions): Promise<Browser> {
|
||||
const loggers = new Loggers(options.logger);
|
||||
return runAbortableTask(async progress => {
|
||||
const transport = await WebSocketTransport.connect(progress, options.wsEndpoint);
|
||||
progress.cleanupWhenAborted(() => transport.closeAndWait());
|
||||
if ((options as any).__testHookBeforeCreateBrowser)
|
||||
await (options as any).__testHookBeforeCreateBrowser();
|
||||
const browser = await this._connectToTransport(transport, { name: this._name, slowMo: options.slowMo, loggers });
|
||||
return browser;
|
||||
}, loggers.browser, TimeoutSettings.timeout(options), 'browserType.connect');
|
||||
}
|
||||
|
||||
private async _launchServer(progress: Progress, options: LaunchServerOptions, isPersistent: boolean, loggers: Loggers, userDataDir?: string): Promise<{ browserServer: BrowserServer, downloadsPath: string, transport: ConnectionTransport }> {
|
||||
const {
|
||||
ignoreDefaultArgs = false,
|
||||
|
|
@ -247,7 +230,6 @@ export abstract class BrowserTypeBase implements BrowserType {
|
|||
|
||||
abstract _defaultArgs(options: types.LaunchOptionsBase, isPersistent: boolean, userDataDir: string): string[];
|
||||
abstract _connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<BrowserBase>;
|
||||
abstract _startWebSocketServer(transport: ConnectionTransport, logger: Logger, port: number): WebSocketServer;
|
||||
abstract _amendEnvironment(env: Env, userDataDir: string, executable: string, browserArguments: string[]): Env;
|
||||
abstract _amendArguments(browserArguments: string[]): string[];
|
||||
abstract _rewriteStartupError(error: Error, prefix: string): Error;
|
||||
|
|
|
|||
|
|
@ -19,17 +19,14 @@ import * as path from 'path';
|
|||
import * as os from 'os';
|
||||
import { getFromENV, logPolitely, helper } from '../helper';
|
||||
import { CRBrowser } from '../chromium/crBrowser';
|
||||
import * as ws from 'ws';
|
||||
import { Env } from './processLauncher';
|
||||
import { kBrowserCloseMessageId } from '../chromium/crConnection';
|
||||
import { rewriteErrorMessage } from '../utils/stackTrace';
|
||||
import { BrowserTypeBase } from './browserType';
|
||||
import { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../transport';
|
||||
import { Logger } from '../logger';
|
||||
import { ConnectionTransport, ProtocolRequest } from '../transport';
|
||||
import { BrowserDescriptor } from '../install/browserPaths';
|
||||
import { CRDevTools } from '../chromium/crDevTools';
|
||||
import { BrowserOptions } from '../browser';
|
||||
import { WebSocketServer } from './webSocketServer';
|
||||
import { LaunchOptionsBase } from '../types';
|
||||
|
||||
export class Chromium extends BrowserTypeBase {
|
||||
|
|
@ -105,10 +102,6 @@ export class Chromium extends BrowserTypeBase {
|
|||
transport.send(message);
|
||||
}
|
||||
|
||||
_startWebSocketServer(transport: ConnectionTransport, logger: Logger, port: number): WebSocketServer {
|
||||
return startWebSocketServer(transport, logger, port);
|
||||
}
|
||||
|
||||
_defaultArgs(options: LaunchOptionsBase, isPersistent: boolean, userDataDir: string): string[] {
|
||||
const { args = [], proxy } = options;
|
||||
const userDataDirArg = args.find(arg => arg.startsWith('--user-data-dir'));
|
||||
|
|
@ -158,136 +151,6 @@ export class Chromium extends BrowserTypeBase {
|
|||
}
|
||||
}
|
||||
|
||||
type SessionData = {
|
||||
socket: ws,
|
||||
children: Set<string>,
|
||||
isBrowserSession: boolean,
|
||||
parent?: string,
|
||||
};
|
||||
|
||||
function startWebSocketServer(transport: ConnectionTransport, logger: Logger, port: number): WebSocketServer {
|
||||
const awaitingBrowserTarget = new Map<number, ws>();
|
||||
const sessionToData = new Map<string, SessionData>();
|
||||
const socketToBrowserSession = new Map<ws, { sessionId?: string, queue?: ProtocolRequest[] }>();
|
||||
|
||||
function addSession(sessionId: string, socket: ws, parentSessionId?: string) {
|
||||
sessionToData.set(sessionId, {
|
||||
socket,
|
||||
children: new Set(),
|
||||
isBrowserSession: !parentSessionId,
|
||||
parent: parentSessionId,
|
||||
});
|
||||
if (parentSessionId)
|
||||
sessionToData.get(parentSessionId)!.children.add(sessionId);
|
||||
}
|
||||
|
||||
function removeSession(sessionId: string) {
|
||||
const data = sessionToData.get(sessionId)!;
|
||||
for (const child of data.children)
|
||||
removeSession(child);
|
||||
if (data.parent)
|
||||
sessionToData.get(data.parent)!.children.delete(sessionId);
|
||||
sessionToData.delete(sessionId);
|
||||
}
|
||||
|
||||
const server = new WebSocketServer(transport, logger, port, {
|
||||
onBrowserResponse(seqNum: number, source: ws, message: ProtocolResponse) {
|
||||
if (awaitingBrowserTarget.has(seqNum)) {
|
||||
const freshSocket = awaitingBrowserTarget.get(seqNum)!;
|
||||
awaitingBrowserTarget.delete(seqNum);
|
||||
|
||||
const sessionId = message.result.sessionId;
|
||||
if (freshSocket.readyState !== ws.CLOSED && freshSocket.readyState !== ws.CLOSING) {
|
||||
const { queue } = socketToBrowserSession.get(freshSocket)!;
|
||||
for (const item of queue!) {
|
||||
item.sessionId = sessionId;
|
||||
server.sendMessageToBrowser(item, source);
|
||||
}
|
||||
socketToBrowserSession.set(freshSocket, { sessionId });
|
||||
addSession(sessionId, freshSocket);
|
||||
} else {
|
||||
server.sendMessageToBrowserOneWay('Target.detachFromTarget', { sessionId });
|
||||
socketToBrowserSession.delete(freshSocket);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.id === -1)
|
||||
return;
|
||||
|
||||
// At this point everything we care about has sessionId.
|
||||
if (!message.sessionId)
|
||||
return;
|
||||
|
||||
const data = sessionToData.get(message.sessionId);
|
||||
if (data && data.socket.readyState !== ws.CLOSING) {
|
||||
if (data.isBrowserSession)
|
||||
delete message.sessionId;
|
||||
data.socket.send(JSON.stringify(message));
|
||||
}
|
||||
},
|
||||
|
||||
onBrowserNotification(message: ProtocolResponse) {
|
||||
// At this point everything we care about has sessionId.
|
||||
if (!message.sessionId)
|
||||
return;
|
||||
|
||||
const data = sessionToData.get(message.sessionId);
|
||||
if (data && data.socket.readyState !== ws.CLOSING) {
|
||||
if (message.method === 'Target.attachedToTarget')
|
||||
addSession(message.params.sessionId, data.socket, message.sessionId);
|
||||
if (message.method === 'Target.detachedFromTarget')
|
||||
removeSession(message.params.sessionId);
|
||||
// Strip session ids from the browser sessions.
|
||||
if (data.isBrowserSession)
|
||||
delete message.sessionId;
|
||||
data.socket.send(JSON.stringify(message));
|
||||
}
|
||||
},
|
||||
|
||||
onClientAttached(socket: ws) {
|
||||
socketToBrowserSession.set(socket, { queue: [] });
|
||||
|
||||
const seqNum = server.sendMessageToBrowser({
|
||||
id: -1, // Proxy-initiated request.
|
||||
method: 'Target.attachToBrowserTarget',
|
||||
params: {}
|
||||
}, socket);
|
||||
awaitingBrowserTarget.set(seqNum, socket);
|
||||
},
|
||||
|
||||
onClientRequest(socket: ws, message: ProtocolRequest) {
|
||||
// If message has sessionId, pass through.
|
||||
if (message.sessionId) {
|
||||
server.sendMessageToBrowser(message, socket);
|
||||
return;
|
||||
}
|
||||
|
||||
// If message has no sessionId, look it up.
|
||||
const session = socketToBrowserSession.get(socket)!;
|
||||
if (session.sessionId) {
|
||||
// We have it, use it.
|
||||
message.sessionId = session.sessionId;
|
||||
server.sendMessageToBrowser(message, socket);
|
||||
return;
|
||||
}
|
||||
// Pending session id, queue the message.
|
||||
session.queue!.push(message);
|
||||
},
|
||||
|
||||
onClientDetached(socket: ws) {
|
||||
const session = socketToBrowserSession.get(socket);
|
||||
if (!session || !session.sessionId)
|
||||
return;
|
||||
removeSession(session.sessionId);
|
||||
socketToBrowserSession.delete(socket);
|
||||
server.sendMessageToBrowserOneWay('Target.detachFromTarget', { sessionId: session.sessionId });
|
||||
}
|
||||
});
|
||||
return server;
|
||||
}
|
||||
|
||||
|
||||
const DEFAULT_ARGS = [
|
||||
'--disable-background-networking',
|
||||
'--enable-features=NetworkService,NetworkServiceInProcess',
|
||||
|
|
|
|||
|
|
@ -18,16 +18,13 @@
|
|||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as ws from 'ws';
|
||||
import { FFBrowser } from '../firefox/ffBrowser';
|
||||
import { kBrowserCloseMessageId } from '../firefox/ffConnection';
|
||||
import { BrowserTypeBase, LaunchNonPersistentOptions } from './browserType';
|
||||
import { Env } from './processLauncher';
|
||||
import { ConnectionTransport, ProtocolResponse, ProtocolRequest } from '../transport';
|
||||
import { Logger } from '../logger';
|
||||
import { ConnectionTransport } from '../transport';
|
||||
import { BrowserOptions } from '../browser';
|
||||
import { BrowserDescriptor } from '../install/browserPaths';
|
||||
import { WebSocketServer } from './webSocketServer';
|
||||
|
||||
export class Firefox extends BrowserTypeBase {
|
||||
constructor(packagePath: string, browser: BrowserDescriptor) {
|
||||
|
|
@ -60,10 +57,6 @@ export class Firefox extends BrowserTypeBase {
|
|||
transport.send(message);
|
||||
}
|
||||
|
||||
_startWebSocketServer(transport: ConnectionTransport, logger: Logger, port: number): WebSocketServer {
|
||||
return startWebSocketServer(transport, logger, port);
|
||||
}
|
||||
|
||||
_defaultArgs(options: LaunchNonPersistentOptions, isPersistent: boolean, userDataDir: string): string[] {
|
||||
const { args = [], devtools, headless } = options;
|
||||
if (devtools)
|
||||
|
|
@ -97,100 +90,3 @@ export class Firefox extends BrowserTypeBase {
|
|||
return firefoxArguments;
|
||||
}
|
||||
}
|
||||
|
||||
type SessionData = {
|
||||
socket: ws,
|
||||
};
|
||||
|
||||
function startWebSocketServer(transport: ConnectionTransport, logger: Logger, port: number): WebSocketServer {
|
||||
const pendingBrowserContextCreations = new Set<number>();
|
||||
const pendingBrowserContextDeletions = new Map<number, string>();
|
||||
const browserContextIds = new Map<string, ws>();
|
||||
const sessionToData = new Map<string, SessionData>();
|
||||
|
||||
function removeSession(sessionId: string): SessionData | undefined {
|
||||
const data = sessionToData.get(sessionId);
|
||||
if (!data)
|
||||
return;
|
||||
sessionToData.delete(sessionId);
|
||||
return data;
|
||||
}
|
||||
|
||||
const server = new WebSocketServer(transport, logger, port, {
|
||||
onBrowserResponse(seqNum: number, source: ws, message: ProtocolResponse) {
|
||||
// Process command response.
|
||||
if (source.readyState === ws.CLOSING || source.readyState === ws.CLOSED) {
|
||||
if (pendingBrowserContextCreations.has(seqNum))
|
||||
server.sendMessageToBrowserOneWay('Browser.removeBrowserContext', { browserContextId: message.result.browserContextId });
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingBrowserContextCreations.has(seqNum)) {
|
||||
// Browser.createBrowserContext response -> establish context attribution.
|
||||
browserContextIds.set(message.result.browserContextId, source);
|
||||
pendingBrowserContextCreations.delete(seqNum);
|
||||
}
|
||||
|
||||
const deletedContextId = pendingBrowserContextDeletions.get(seqNum);
|
||||
if (deletedContextId) {
|
||||
// Browser.removeBrowserContext response -> remove context attribution.
|
||||
browserContextIds.delete(deletedContextId);
|
||||
pendingBrowserContextDeletions.delete(seqNum);
|
||||
}
|
||||
|
||||
source.send(JSON.stringify(message));
|
||||
return;
|
||||
},
|
||||
|
||||
onBrowserNotification(message: ProtocolResponse) {
|
||||
// Process notification response.
|
||||
const { method, params, sessionId } = message;
|
||||
if (sessionId) {
|
||||
const data = sessionToData.get(sessionId);
|
||||
if (!data || data.socket.readyState === ws.CLOSING) {
|
||||
// Drop unattributed messages on the floor.
|
||||
return;
|
||||
}
|
||||
data.socket.send(JSON.stringify(message));
|
||||
return;
|
||||
}
|
||||
if (method === 'Browser.attachedToTarget') {
|
||||
const socket = browserContextIds.get(params.targetInfo.browserContextId);
|
||||
if (!socket || socket.readyState === ws.CLOSING) {
|
||||
// Drop unattributed messages on the floor.
|
||||
return;
|
||||
}
|
||||
sessionToData.set(params.sessionId, { socket });
|
||||
socket.send(JSON.stringify(message));
|
||||
return;
|
||||
}
|
||||
if (method === 'Browser.detachedFromTarget') {
|
||||
const data = removeSession(params.sessionId);
|
||||
if (data && data.socket.readyState !== ws.CLOSING)
|
||||
data.socket.send(JSON.stringify(message));
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
onClientAttached() {},
|
||||
|
||||
onClientRequest(socket: ws, message: ProtocolRequest) {
|
||||
const { method, params } = message;
|
||||
const seqNum = server.sendMessageToBrowser(message, socket);
|
||||
if (method === 'Browser.createBrowserContext')
|
||||
pendingBrowserContextCreations.add(seqNum);
|
||||
if (method === 'Browser.removeBrowserContext')
|
||||
pendingBrowserContextDeletions.set(seqNum, params.browserContextId);
|
||||
},
|
||||
|
||||
onClientDetached(socket: ws) {
|
||||
for (const [browserContextId, s] of browserContextIds) {
|
||||
if (s === socket) {
|
||||
server.sendMessageToBrowserOneWay('Browser.removeBrowserContext', { browserContextId });
|
||||
browserContextIds.delete(browserContextId);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return server;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,139 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { IncomingMessage } from 'http';
|
||||
import * as ws from 'ws';
|
||||
import { helper } from '../helper';
|
||||
import { logError, Logger } from '../logger';
|
||||
import { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../transport';
|
||||
|
||||
export interface WebSocketServerDelegate {
|
||||
onClientAttached(socket: ws): void;
|
||||
onClientRequest(socket: ws, message: ProtocolRequest): void;
|
||||
onClientDetached(socket: ws): void;
|
||||
onBrowserNotification(message: ProtocolResponse): void;
|
||||
onBrowserResponse(seqNum: number, source: ws, message: ProtocolResponse): void;
|
||||
}
|
||||
|
||||
export class WebSocketServer {
|
||||
private _transport: ConnectionTransport;
|
||||
private _logger: Logger;
|
||||
private _server: ws.Server;
|
||||
private _guid: string;
|
||||
readonly wsEndpoint: string;
|
||||
private _bindings: (Map<any, any> | Set<any>)[] = [];
|
||||
private _lastSeqNum = 0;
|
||||
private _delegate: WebSocketServerDelegate;
|
||||
private _sockets = new Set<ws>();
|
||||
private _pendingRequests = new Map<number, { message: ProtocolRequest, source: ws | null }>();
|
||||
|
||||
constructor(transport: ConnectionTransport, logger: Logger, port: number, delegate: WebSocketServerDelegate) {
|
||||
this._guid = helper.guid();
|
||||
this._transport = transport;
|
||||
this._logger = logger;
|
||||
this._server = new ws.Server({ port });
|
||||
this._delegate = delegate;
|
||||
transport.onmessage = message => this._browserMessage(message);
|
||||
transport.onclose = () => this._browserClosed();
|
||||
this._server.on('connection', (socket: ws, req) => this._clientAttached(socket, req));
|
||||
const address = this._server.address();
|
||||
this.wsEndpoint = typeof address === 'string' ? `${address}/${this._guid}` : `ws://127.0.0.1:${address.port}/${this._guid}`;
|
||||
}
|
||||
|
||||
addBindings(bindings: (Map<any, any>|Set<any>)[]) {
|
||||
this._bindings.push(...bindings);
|
||||
}
|
||||
|
||||
sendMessageToBrowser(message: ProtocolRequest, source: ws): number {
|
||||
const seqNum = ++this._lastSeqNum;
|
||||
this._pendingRequests.set(seqNum, { message, source });
|
||||
this._transport.send({ ...message, id: seqNum });
|
||||
return seqNum;
|
||||
}
|
||||
|
||||
sendMessageToBrowserOneWay(method: string, params: any) {
|
||||
this._transport.send({ id: ++this._lastSeqNum, method, params });
|
||||
}
|
||||
|
||||
close() {
|
||||
this._server.close();
|
||||
}
|
||||
|
||||
private _browserMessage(message: ProtocolResponse) {
|
||||
const seqNum = message.id;
|
||||
if (typeof seqNum === 'number') {
|
||||
const request = this._pendingRequests.get(seqNum);
|
||||
if (!request)
|
||||
return;
|
||||
this._pendingRequests.delete(seqNum);
|
||||
message.id = request.message.id;
|
||||
if (request.source)
|
||||
this._delegate.onBrowserResponse(seqNum, request.source, message);
|
||||
} else {
|
||||
this._delegate.onBrowserNotification(message);
|
||||
}
|
||||
}
|
||||
|
||||
private _browserClosed() {
|
||||
this._transport.onmessage = undefined;
|
||||
this._transport.onclose = undefined;
|
||||
for (const socket of this._sockets) {
|
||||
socket.removeAllListeners('close');
|
||||
socket.close(undefined, 'Browser disconnected');
|
||||
}
|
||||
this._server.close();
|
||||
}
|
||||
|
||||
private _clientAttached(socket: ws, req: IncomingMessage) {
|
||||
if (req.url !== '/' + this._guid) {
|
||||
socket.close();
|
||||
return;
|
||||
}
|
||||
|
||||
this._sockets.add(socket);
|
||||
this._delegate.onClientAttached(socket);
|
||||
socket.on('message', (message: string) => {
|
||||
const parsedMessage = JSON.parse(Buffer.from(message).toString()) as ProtocolRequest;
|
||||
this._delegate.onClientRequest(socket, parsedMessage);
|
||||
});
|
||||
socket.on('error', logError(this._logger));
|
||||
socket.on('close', () => {
|
||||
this._delegate.onClientDetached(socket);
|
||||
this._sockets.delete(socket);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async checkLeaks() {
|
||||
let counter = 0;
|
||||
return new Promise((fulfill, reject) => {
|
||||
const check = () => {
|
||||
const filtered = this._bindings.filter(entry => entry.size);
|
||||
if (!filtered.length) {
|
||||
fulfill();
|
||||
return;
|
||||
}
|
||||
|
||||
if (++counter >= 50) {
|
||||
reject(new Error('Web socket leak ' + filtered.map(entry => [...entry.keys()].join(':')).join('|')));
|
||||
return;
|
||||
}
|
||||
setTimeout(check, 100);
|
||||
};
|
||||
check();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -20,13 +20,9 @@ import { Env } from './processLauncher';
|
|||
import * as path from 'path';
|
||||
import { kBrowserCloseMessageId } from '../webkit/wkConnection';
|
||||
import { BrowserTypeBase } from './browserType';
|
||||
import { ConnectionTransport, ProtocolResponse, ProtocolRequest } from '../transport';
|
||||
import * as ws from 'ws';
|
||||
import { Logger } from '../logger';
|
||||
import { ConnectionTransport } from '../transport';
|
||||
import { BrowserOptions } from '../browser';
|
||||
import { BrowserDescriptor } from '../install/browserPaths';
|
||||
import { WebSocketServer } from './webSocketServer';
|
||||
import { assert } from '../helper';
|
||||
import { LaunchOptionsBase } from '../types';
|
||||
|
||||
export class WebKit extends BrowserTypeBase {
|
||||
|
|
@ -54,10 +50,6 @@ export class WebKit extends BrowserTypeBase {
|
|||
transport.send({method: 'Playwright.close', params: {}, id: kBrowserCloseMessageId});
|
||||
}
|
||||
|
||||
_startWebSocketServer(transport: ConnectionTransport, logger: Logger, port: number): WebSocketServer {
|
||||
return startWebSocketServer(transport, logger, port);
|
||||
}
|
||||
|
||||
_defaultArgs(options: LaunchOptionsBase, isPersistent: boolean, userDataDir: string): string[] {
|
||||
const { args = [], proxy, devtools, headless } = options;
|
||||
if (devtools)
|
||||
|
|
@ -95,70 +87,3 @@ export class WebKit extends BrowserTypeBase {
|
|||
return webkitArguments;
|
||||
}
|
||||
}
|
||||
|
||||
function startWebSocketServer(transport: ConnectionTransport, logger: Logger, port: number): WebSocketServer {
|
||||
const pendingBrowserContextCreations = new Set<number>();
|
||||
const pendingBrowserContextDeletions = new Map<number, string>();
|
||||
const browserContextIds = new Map<string, ws>();
|
||||
|
||||
const server = new WebSocketServer(transport, logger, port, {
|
||||
onBrowserResponse(seqNum: number, source: ws, message: ProtocolResponse) {
|
||||
if (source.readyState === ws.CLOSED || source.readyState === ws.CLOSING) {
|
||||
if (pendingBrowserContextCreations.has(seqNum))
|
||||
server.sendMessageToBrowserOneWay('Playwright.deleteContext', { browserContextId: message.result.browserContextId });
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingBrowserContextCreations.has(seqNum)) {
|
||||
// Browser.createContext response -> establish context attribution.
|
||||
browserContextIds.set(message.result.browserContextId, source);
|
||||
pendingBrowserContextCreations.delete(seqNum);
|
||||
}
|
||||
|
||||
const deletedContextId = pendingBrowserContextDeletions.get(seqNum);
|
||||
if (deletedContextId) {
|
||||
// Browser.deleteContext response -> remove context attribution.
|
||||
browserContextIds.delete(deletedContextId);
|
||||
pendingBrowserContextDeletions.delete(seqNum);
|
||||
}
|
||||
|
||||
source.send(JSON.stringify(message));
|
||||
return;
|
||||
},
|
||||
|
||||
onBrowserNotification(message: ProtocolResponse) {
|
||||
// Process notification response.
|
||||
const { params, browserContextId } = message;
|
||||
const contextId = browserContextId || params.browserContextId;
|
||||
assert(contextId);
|
||||
const socket = browserContextIds.get(contextId);
|
||||
if (!socket || socket.readyState === ws.CLOSING) {
|
||||
// Drop unattributed messages on the floor.
|
||||
return;
|
||||
}
|
||||
socket.send(JSON.stringify(message));
|
||||
},
|
||||
|
||||
onClientAttached(socket: ws) {
|
||||
},
|
||||
|
||||
onClientRequest(socket: ws, message: ProtocolRequest) {
|
||||
const { method, params } = message;
|
||||
const seqNum = server.sendMessageToBrowser(message, socket);
|
||||
if (method === 'Playwright.createContext')
|
||||
pendingBrowserContextCreations.add(seqNum);
|
||||
if (method === 'Playwright.deleteContext')
|
||||
pendingBrowserContextDeletions.set(seqNum, params.browserContextId);
|
||||
},
|
||||
|
||||
onClientDetached(socket: ws) {
|
||||
for (const [browserContextId, s] of browserContextIds) {
|
||||
if (s === socket) {
|
||||
server.sendMessageToBrowserOneWay('Playwright.deleteContext', { browserContextId });
|
||||
browserContextIds.delete(browserContextId);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return server;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -308,12 +308,6 @@ export type LaunchOptionsBase = {
|
|||
export type LaunchOptions = LaunchOptionsBase & { slowMo?: number };
|
||||
export type LaunchServerOptions = LaunchOptionsBase & { port?: number };
|
||||
|
||||
export type ConnectOptions = {
|
||||
wsEndpoint: string,
|
||||
slowMo?: number,
|
||||
timeout?: number,
|
||||
};
|
||||
|
||||
export type SerializedAXNode = {
|
||||
role: string,
|
||||
name: string,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import utils from './utils';
|
||||
|
||||
const {USES_HOOKS} = testOptions;
|
||||
const {WIRE} = testOptions;
|
||||
|
||||
it('should await navigation when clicking anchor', async({page, server}) => {
|
||||
const messages = [];
|
||||
|
|
@ -204,7 +204,7 @@ it('should work with goto following click', async({page, server}) => {
|
|||
await page.goto(server.EMPTY_PAGE);
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should report navigation in the log when clicking anchor', async({page, server}) => {
|
||||
it.skip(WIRE)('should report navigation in the log when clicking anchor', async({page, server}) => {
|
||||
await page.setContent(`<a href="${server.PREFIX + '/frames/one-frame.html'}">click me</a>`);
|
||||
const __testHookAfterPointerAction = () => new Promise(f => setTimeout(f, 6000));
|
||||
const error = await page.click('a', { timeout: 5000, __testHookAfterPointerAction } as any).catch(e => e);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ declare global {
|
|||
page: Page;
|
||||
httpsServer: TestServer;
|
||||
browserServer: BrowserServer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerWorkerFixture('parallelIndex', async ({}, test) => {
|
||||
|
|
@ -93,7 +93,7 @@ registerWorkerFixture('defaultBrowserOptions', async({}, test) => {
|
|||
|
||||
registerWorkerFixture('playwright', async({parallelIndex}, test) => {
|
||||
const {coverage, uninstall} = installCoverageHooks(browserName);
|
||||
if (process.env.PWCHANNEL === 'wire') {
|
||||
if (process.env.PWWIRE) {
|
||||
const connection = new Connection();
|
||||
const spawnedProcess = childProcess.fork(path.join(__dirname, '..', 'lib', 'rpc', 'server'), [], {
|
||||
stdio: 'pipe',
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, MAC, CHANNEL, HEADLESS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, MAC, HEADLESS} = testOptions;
|
||||
const {devices} = require('..');
|
||||
|
||||
it('expose binding should work', async({browser}) => {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
import './base.fixture';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, MAC, CHANNEL, HEADLESS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, MAC, HEADLESS} = testOptions;
|
||||
const {devices} = require('..');
|
||||
|
||||
it('should have url', async({browser, server}) => {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, MAC, CHANNEL, HEADLESS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, MAC, HEADLESS} = testOptions;
|
||||
const {devices} = require('..');
|
||||
|
||||
it('should intercept', async({browser, server}) => {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, MAC, CHANNEL, HEADLESS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, MAC, HEADLESS} = testOptions;
|
||||
const {devices} = require('..');
|
||||
|
||||
it('should work', async({browser, server}) => {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('browserType.executablePath should work', async({browserType}) => {
|
||||
const executablePath = browserType.executablePath();
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it.skip(USES_HOOKS).slow()('should be able to reconnect to a browser', async({browserType, defaultBrowserOptions, server}) => {
|
||||
it.skip(WIRE).slow()('should be able to reconnect to a browser', async({browserType, defaultBrowserOptions, server}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
{
|
||||
const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
|
|
@ -38,7 +38,7 @@ it.skip(USES_HOOKS).slow()('should be able to reconnect to a browser', async({br
|
|||
await browserServer.close();
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS).fail(CHROMIUM && WIN).slow()('should handle exceptions during connect', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE).fail(CHROMIUM && WIN).slow()('should handle exceptions during connect', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const __testHookBeforeCreateBrowser = () => { throw new Error('Dummy') };
|
||||
const error = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint(), __testHookBeforeCreateBrowser } as any).catch(e => e);
|
||||
|
|
@ -46,7 +46,7 @@ it.skip(USES_HOOKS).fail(CHROMIUM && WIN).slow()('should handle exceptions durin
|
|||
expect(error.message).toContain('Dummy');
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should set the browser connected state', async ({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should set the browser connected state', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
expect(remote.isConnected()).toBe(true);
|
||||
|
|
@ -55,7 +55,7 @@ it.skip(USES_HOOKS)('should set the browser connected state', async ({browserTyp
|
|||
await browserServer.close();
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should throw when used after isConnected returns false', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should throw when used after isConnected returns false', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const page = await remote.newPage();
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it.skip(USES_HOOKS)('should work', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should work', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const browserContext = await browser.newContext();
|
||||
|
|
@ -34,7 +34,7 @@ it.skip(USES_HOOKS)('should work', async({browserType, defaultBrowserOptions}) =
|
|||
await browserServer.close();
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should fire "disconnected" when closing the server', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should fire "disconnected" when closing the server', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const disconnectedEventPromise = new Promise(resolve => browser.once('disconnected', resolve));
|
||||
|
|
@ -46,7 +46,7 @@ it.skip(USES_HOOKS)('should fire "disconnected" when closing the server', async(
|
|||
]);
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should fire "close" event during kill', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should fire "close" event during kill', async({browserType, defaultBrowserOptions}) => {
|
||||
const order = [];
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const closedPromise = new Promise(f => browserServer.on('close', () => {
|
||||
|
|
@ -60,13 +60,13 @@ it.skip(USES_HOOKS)('should fire "close" event during kill', async({browserType,
|
|||
expect(order).toEqual(['closed', 'killed']);
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should return child_process instance', async ({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should return child_process instance', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
expect(browserServer.process().pid).toBeGreaterThan(0);
|
||||
await browserServer.close();
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should fire close event', async ({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should fire close event', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const [result] = await Promise.all([
|
||||
new Promise(f => (browserServer as any).on('close', (exitCode, signal) => f({ exitCode, signal }))),
|
||||
|
|
@ -76,7 +76,7 @@ it.skip(USES_HOOKS)('should fire close event', async ({browserType, defaultBrows
|
|||
expect(result['signal']).toBe(null);
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should reject navigation when browser closes', async({browserType, defaultBrowserOptions, server}) => {
|
||||
it.skip(WIRE)('should reject navigation when browser closes', async({browserType, defaultBrowserOptions, server}) => {
|
||||
server.setRoute('/one-style.css', () => {});
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
|
|
@ -89,7 +89,7 @@ it.skip(USES_HOOKS)('should reject navigation when browser closes', async({brows
|
|||
await browserServer.close();
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should reject waitForSelector when browser closes', async({browserType, defaultBrowserOptions, server}) => {
|
||||
it.skip(WIRE)('should reject waitForSelector when browser closes', async({browserType, defaultBrowserOptions, server}) => {
|
||||
server.setRoute('/empty.html', () => {});
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
|
|
@ -105,7 +105,7 @@ it.skip(USES_HOOKS)('should reject waitForSelector when browser closes', async({
|
|||
await browserServer.close();
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should throw if used after disconnect', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should throw if used after disconnect', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const page = await remote.newPage();
|
||||
|
|
@ -115,7 +115,7 @@ it.skip(USES_HOOKS)('should throw if used after disconnect', async({browserType,
|
|||
await browserServer.close();
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should emit close events on pages and contexts', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should emit close events on pages and contexts', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const context = await remote.newContext();
|
||||
|
|
@ -129,7 +129,7 @@ it.skip(USES_HOOKS)('should emit close events on pages and contexts', async({bro
|
|||
expect(pageClosed).toBeTruthy();
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should terminate network waiters', async({browserType, defaultBrowserOptions, server}) => {
|
||||
it.skip(WIRE)('should terminate network waiters', async({browserType, defaultBrowserOptions, server}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const newPage = await remote.newPage();
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('should reject all promises when browser is closed', async({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch(defaultBrowserOptions);
|
||||
|
|
@ -61,7 +61,7 @@ it('should reject if executable path is invalid', async({browserType, defaultBro
|
|||
expect(waitError.message).toContain('Failed to launch');
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should handle timeout', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should handle timeout', async({browserType, defaultBrowserOptions}) => {
|
||||
const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) };
|
||||
const error = await browserType.launch(options).catch(e => e);
|
||||
expect(error.message).toContain(`browserType.launch: Timeout 5000ms exceeded.`);
|
||||
|
|
@ -69,14 +69,14 @@ it.skip(USES_HOOKS)('should handle timeout', async({browserType, defaultBrowserO
|
|||
expect(error.message).toContain(`[browser] <launched> pid=`);
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should handle exception', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should handle exception', async({browserType, defaultBrowserOptions}) => {
|
||||
const e = new Error('Dummy');
|
||||
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 };
|
||||
const error = await browserType.launch(options).catch(e => e);
|
||||
expect(error.message).toContain('Dummy');
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should report launch log', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should report launch log', async({browserType, defaultBrowserOptions}) => {
|
||||
const e = new Error('Dummy');
|
||||
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 };
|
||||
const error = await browserType.launch(options).catch(e => e);
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@ import './base.fixture';
|
|||
|
||||
import utils from './utils';
|
||||
import { ChromiumBrowser } from '..';
|
||||
const { FFOX, CHROMIUM, WEBKIT, WIN, CHANNEL } = testOptions;
|
||||
const { FFOX, CHROMIUM, WEBKIT, WIN } = testOptions;
|
||||
|
||||
it.skip(!CHANNEL)('should work', async({browser}) => {
|
||||
it('should work', async({browser}) => {
|
||||
expect(!!browser['_connection']).toBeTruthy();
|
||||
});
|
||||
|
||||
it.skip(!CHANNEL)('should scope context handles', async({browserType, browser, server}) => {
|
||||
it('should scope context handles', async({browserType, browser, server}) => {
|
||||
const GOLDEN_PRECONDITION = {
|
||||
_guid: '',
|
||||
objects: [
|
||||
|
|
@ -68,7 +68,7 @@ it.skip(!CHANNEL)('should scope context handles', async({browserType, browser, s
|
|||
await expectScopeState(browser, GOLDEN_PRECONDITION);
|
||||
});
|
||||
|
||||
it.skip(!CHANNEL || !CHROMIUM)('should scope CDPSession handles', async({browserType, browser, server}) => {
|
||||
it.skip(!CHROMIUM)('should scope CDPSession handles', async({browserType, browser, server}) => {
|
||||
const GOLDEN_PRECONDITION = {
|
||||
_guid: '',
|
||||
objects: [
|
||||
|
|
@ -105,7 +105,7 @@ it.skip(!CHANNEL || !CHROMIUM)('should scope CDPSession handles', async({browser
|
|||
await expectScopeState(browserType, GOLDEN_PRECONDITION);
|
||||
});
|
||||
|
||||
it.skip(!CHANNEL)('should scope browser handles', async({browserType, defaultBrowserOptions}) => {
|
||||
it('should scope browser handles', async({browserType, defaultBrowserOptions}) => {
|
||||
const GOLDEN_PRECONDITION = {
|
||||
_guid: '',
|
||||
objects: [
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
import '../base.fixture';
|
||||
import { ChromiumBrowserContext } from '../..';
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT} = testOptions;
|
||||
|
||||
it.skip(!CHROMIUM)('should create a worker from a service worker', async({page, server, context}) => {
|
||||
const [worker] = await Promise.all([
|
||||
|
|
|
|||
|
|
@ -19,23 +19,23 @@ import path from 'path';
|
|||
import utils from '../utils';
|
||||
import { ChromiumBrowser, ChromiumBrowserContext } from '../..';
|
||||
const {makeUserDataDir, removeUserDataDir} = utils;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it.skip(USES_HOOKS || !CHROMIUM)('should throw with remote-debugging-pipe argument', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE || !CHROMIUM)('should throw with remote-debugging-pipe argument', async({browserType, defaultBrowserOptions}) => {
|
||||
const options = Object.assign({}, defaultBrowserOptions);
|
||||
options.args = ['--remote-debugging-pipe'].concat(options.args || []);
|
||||
const error = await browserType.launchServer(options).catch(e => e);
|
||||
expect(error.message).toContain('Playwright manages remote debugging connection itself');
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS || !CHROMIUM)('should not throw with remote-debugging-port argument', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE || !CHROMIUM)('should not throw with remote-debugging-port argument', async({browserType, defaultBrowserOptions}) => {
|
||||
const options = Object.assign({}, defaultBrowserOptions);
|
||||
options.args = ['--remote-debugging-port=0'].concat(options.args || []);
|
||||
const browser = await browserType.launchServer(options);
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM || USES_HOOKS || WIN)('should open devtools when "devtools: true" option is given', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(!CHROMIUM || WIRE || WIN)('should open devtools when "devtools: true" option is given', async({browserType, defaultBrowserOptions}) => {
|
||||
let devtoolsCallback;
|
||||
const devtoolsPromise = new Promise(f => devtoolsCallback = f);
|
||||
const __testHookForDevTools = devtools => devtools.__testHookOnBinding = parsed => {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
import '../base.fixture';
|
||||
import { Page, Browser, BrowserContext } from '../..';
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT} = testOptions;
|
||||
|
||||
declare global {
|
||||
interface FixtureState {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
import '../base.fixture';
|
||||
import { ChromiumBrowserContext, ChromiumBrowser } from "../../types/types";
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE} = testOptions;
|
||||
|
||||
it.skip(!CHROMIUM)('should work', async function({page}) {
|
||||
const client = await (page.context() as ChromiumBrowserContext).newCDPSession(page);
|
||||
|
|
@ -73,7 +73,7 @@ it.skip(!CHROMIUM)('should be able to detach session', async function({page}) {
|
|||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
expect(error.message).toContain(CHANNEL ? 'Target browser or context has been closed' : 'Session closed.');
|
||||
expect(error.message).toContain('Target browser or context has been closed');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should throw nice errors', async function({page}) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import '../base.fixture';
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { ChromiumBrowser } from '../..';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT} = testOptions;
|
||||
declare global {
|
||||
interface FixtureState {
|
||||
outputFile: string;
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {USES_HOOKS} = testOptions;
|
||||
const {WIRE} = testOptions;
|
||||
|
||||
it.skip(USES_HOOKS)('should avoid side effects after timeout', async({page, server}) => {
|
||||
it.skip(WIRE)('should avoid side effects after timeout', async({page, server}) => {
|
||||
await page.goto(server.PREFIX + '/input/button.html');
|
||||
const error = await page.click('button', { timeout: 2000, __testHookBeforePointerAction: () => new Promise(f => setTimeout(f, 2500))} as any).catch(e => e);
|
||||
await page.waitForTimeout(5000); // Give it some time to click after the test hook is done waiting.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {USES_HOOKS} = testOptions;
|
||||
const {WIRE} = testOptions;
|
||||
|
||||
it('should timeout waiting for display:none to be gone', async({page, server}) => {
|
||||
await page.goto(server.PREFIX + '/input/button.html');
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {USES_HOOKS} = testOptions;
|
||||
const {WIRE} = testOptions;
|
||||
|
||||
it.skip(USES_HOOKS)('should fail when element jumps during hit testing', async({page, server}) => {
|
||||
it.skip(WIRE)('should fail when element jumps during hit testing', async({page, server}) => {
|
||||
await page.setContent('<button>Click me</button>');
|
||||
let clicked = false;
|
||||
const handle = await page.$('button');
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, HEADLESS, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, HEADLESS, WIRE} = testOptions;
|
||||
|
||||
async function giveItAChanceToClick(page) {
|
||||
for (let i = 0; i < 5; i++)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import utils from './utils';
|
|||
import os from 'os';
|
||||
import { BrowserType, Browser, BrowserContext, Page } from '..';
|
||||
const {removeFolderAsync, mkdtempAsync, removeUserDataDir, makeUserDataDir} = utils;
|
||||
const {FFOX, MAC, CHROMIUM, WEBKIT, WIN, USES_HOOKS} = testOptions;
|
||||
const {FFOX, MAC, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
declare global {
|
||||
interface FixtureState {
|
||||
|
|
@ -352,7 +352,7 @@ it.skip(FFOX)('should throw if page argument is passed', async ({browserType, de
|
|||
expect(error.message).toContain('can not specify page');
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should have passed URL when launching with ignoreDefaultArgs: true', async ({browserType, defaultBrowserOptions, server, userDataDir, toImpl}) => {
|
||||
it.skip(WIRE)('should have passed URL when launching with ignoreDefaultArgs: true', async ({browserType, defaultBrowserOptions, server, userDataDir, toImpl}) => {
|
||||
const args = toImpl(browserType)._defaultArgs(defaultBrowserOptions, 'persistent', userDataDir, 0).filter(a => a !== 'about:blank');
|
||||
const options = {
|
||||
...defaultBrowserOptions,
|
||||
|
|
@ -368,13 +368,13 @@ it.skip(USES_HOOKS)('should have passed URL when launching with ignoreDefaultArg
|
|||
await browserContext.close();
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should handle timeout', async({browserType, defaultBrowserOptions, userDataDir}) => {
|
||||
it.skip(WIRE)('should handle timeout', async({browserType, defaultBrowserOptions, userDataDir}) => {
|
||||
const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) };
|
||||
const error = await browserType.launchPersistentContext(userDataDir, options).catch(e => e);
|
||||
expect(error.message).toContain(`browserType.launchPersistentContext: Timeout 5000ms exceeded.`);
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should handle exception', async({browserType, defaultBrowserOptions, userDataDir}) => {
|
||||
it.skip(WIRE)('should handle exception', async({browserType, defaultBrowserOptions, userDataDir}) => {
|
||||
const e = new Error('Dummy');
|
||||
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; } };
|
||||
const error = await browserType.launchPersistentContext(userDataDir, options).catch(e => e);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
import './base.fixture';
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT} = testOptions;
|
||||
|
||||
it('should fire', async({page, server}) => {
|
||||
page.on('dialog', dialog => {
|
||||
|
|
@ -63,24 +63,6 @@ it('should dismiss the confirm prompt', async({page, server}) => {
|
|||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it.fail(CHANNEL)('should log prompt actions', async({browser}) => {
|
||||
const messages = [];
|
||||
const context = await browser.newContext({
|
||||
logger: {
|
||||
isEnabled: () => true,
|
||||
log: (name, severity, message) => messages.push(message),
|
||||
}
|
||||
});
|
||||
const page = await context.newPage();
|
||||
const promise = page.evaluate(() => confirm('01234567890123456789012345678901234567890123456789012345678901234567890123456789'));
|
||||
const dialog = await page.waitForEvent('dialog');
|
||||
expect(messages.join()).toContain('confirm "0123456789012345678901234567890123456789012345678…" was shown');
|
||||
await dialog.accept('123');
|
||||
await promise;
|
||||
expect(messages.join()).toContain('confirm "0123456789012345678901234567890123456789012345678…" was accepted');
|
||||
await context.close();
|
||||
});
|
||||
|
||||
it.fail(WEBKIT)('should be able to close context with open alert', async({browser}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('should dispatch click event', async({page, server}) => {
|
||||
await page.goto(server.PREFIX + '/input/button.html');
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import path from 'path';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE} = testOptions;
|
||||
|
||||
it('should work', async({page, server}) => {
|
||||
await page.setContent('<html><body><div class="tweet"><div class="like">100</div><div class="retweets">10</div></div></body></html>');
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import path from 'path';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE} = testOptions;
|
||||
|
||||
it('should query existing element', async({page, server}) => {
|
||||
await page.goto(server.PREFIX + '/playground.html');
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, USES_HOOKS, HEADLESS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE, HEADLESS} = testOptions;
|
||||
import {PNG} from 'pngjs';
|
||||
|
||||
// Firefox headful produces a different image.
|
||||
|
|
@ -283,7 +283,7 @@ it.skip(ffheadful)('should restore default viewport after fullPage screenshot',
|
|||
await context.close();
|
||||
});
|
||||
|
||||
it.skip(ffheadful || USES_HOOKS)('should restore viewport after page screenshot and exception', async({ browser, server }) => {
|
||||
it.skip(ffheadful || WIRE)('should restore viewport after page screenshot and exception', async({ browser, server }) => {
|
||||
const context = await browser.newContext({ viewport: { width: 350, height: 360 } });
|
||||
const page = await context.newPage();
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
|
|
@ -294,7 +294,7 @@ it.skip(ffheadful || USES_HOOKS)('should restore viewport after page screenshot
|
|||
await context.close();
|
||||
});
|
||||
|
||||
it.skip(ffheadful || USES_HOOKS)('should restore viewport after page screenshot and timeout', async({ browser, server }) => {
|
||||
it.skip(ffheadful || WIRE)('should restore viewport after page screenshot and timeout', async({ browser, server }) => {
|
||||
const context = await browser.newContext({ viewport: { width: 350, height: 360 } });
|
||||
const page = await context.newPage();
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
|
|
@ -338,7 +338,7 @@ it.skip(ffheadful)('should take element screenshot when default viewport is null
|
|||
await context.close();
|
||||
});
|
||||
|
||||
it.skip(ffheadful || USES_HOOKS)('should restore viewport after element screenshot and exception', async({server, browser}) => {
|
||||
it.skip(ffheadful || WIRE)('should restore viewport after element screenshot and exception', async({server, browser}) => {
|
||||
const context = await browser.newContext({ viewport: { width: 350, height: 360 } });
|
||||
const page = await context.newPage();
|
||||
await page.setContent(`<div style="width:600px;height:600px;"></div>`);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import path from 'path';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE} = testOptions;
|
||||
|
||||
it('should work with css selector', async({page, server}) => {
|
||||
await page.setContent('<div>hello</div><div>beautiful</div><div>world!</div>');
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import path from 'path';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE} = testOptions;
|
||||
|
||||
it('should work with css selector', async({page, server}) => {
|
||||
await page.setContent('<section id="testAttribute">43543</section>');
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import utils from './utils';
|
||||
import path from 'path';
|
||||
const { FFOX, CHROMIUM, WEBKIT, USES_HOOKS } = testOptions;
|
||||
const { FFOX, CHROMIUM, WEBKIT, WIRE } = testOptions;
|
||||
|
||||
it('should have different execution contexts', async ({ page, server }) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
|
|
@ -44,7 +44,7 @@ function expectContexts(pageImpl, count) {
|
|||
expect(pageImpl._delegate._contextIdToContext.size).toBe(count);
|
||||
}
|
||||
|
||||
it.skip(USES_HOOKS)('should dispose context on navigation', async ({ page, server, toImpl }) => {
|
||||
it.skip(WIRE)('should dispose context on navigation', async ({ page, server, toImpl }) => {
|
||||
await page.goto(server.PREFIX + '/frames/one-frame.html');
|
||||
expect(page.frames().length).toBe(2);
|
||||
expectContexts(toImpl(page), 4);
|
||||
|
|
@ -52,7 +52,7 @@ it.skip(USES_HOOKS)('should dispose context on navigation', async ({ page, serve
|
|||
expectContexts(toImpl(page), 2);
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should dispose context on cross-origin navigation', async ({ page, server, toImpl }) => {
|
||||
it.skip(WIRE)('should dispose context on cross-origin navigation', async ({ page, server, toImpl }) => {
|
||||
await page.goto(server.PREFIX + '/frames/one-frame.html');
|
||||
expect(page.frames().length).toBe(2);
|
||||
expectContexts(toImpl(page), 4);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('should require top-level Errors', async({playwright}) => {
|
||||
const Errors = require(path.join(utils.projectRoot(), '/lib/errors.js'));
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import './base.fixture';
|
|||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT} = testOptions;
|
||||
|
||||
it('should log', async({browserType, defaultBrowserOptions}) => {
|
||||
const log = [];
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@
|
|||
*/
|
||||
import './base.fixture';
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE} = testOptions;
|
||||
|
||||
it.skip(USES_HOOKS)('should work across sessions', async ({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should work across sessions', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const browser1 = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
expect(browser1.contexts().length).toBe(0);
|
||||
|
|
@ -38,7 +38,7 @@ it.skip(USES_HOOKS)('should work across sessions', async ({browserType, defaultB
|
|||
await browserServer.close();
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS).slow()('should be emitted when: browser gets closed, disconnected or underlying websocket gets closed', async ({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE).slow()('should be emitted when: browser gets closed, disconnected or underlying websocket gets closed', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const originalBrowser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const wsEndpoint = browserServer.wsEndpoint();
|
||||
|
|
@ -72,7 +72,7 @@ it.skip(USES_HOOKS).slow()('should be emitted when: browser gets closed, disconn
|
|||
expect(disconnectedRemote2).toBe(1);
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should be able to connect multiple times to the same browser', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should be able to connect multiple times to the same browser', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const browser1 = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const browser2 = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
|
|
@ -86,7 +86,7 @@ it.skip(USES_HOOKS)('should be able to connect multiple times to the same browse
|
|||
await browserServer.close();
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should not be able to close remote browser', async({browserType, defaultBrowserOptions}) => {
|
||||
it.skip(WIRE)('should not be able to close remote browser', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
{
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import utils from './utils';
|
||||
import path from 'path';
|
||||
const { FFOX, CHROMIUM, WEBKIT, USES_HOOKS } = testOptions;
|
||||
const { FFOX, CHROMIUM, WEBKIT, WIRE } = testOptions;
|
||||
|
||||
it('should evaluate before anything else on the page', async ({ page, server }) => {
|
||||
await page.addInitScript(function () {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import util from 'util';
|
||||
import vm from 'vm';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('should throw an error if no options are provided', async({page, server}) => {
|
||||
let error = null;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import util from 'util';
|
||||
import vm from 'vm';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('should throw an error if no options are provided', async({page, server}) => {
|
||||
let error = null;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import util from 'util';
|
||||
import vm from 'vm';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('should reject all promises when page is closed', async({context}) => {
|
||||
const newPage = await context.newPage();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
import './base.fixture';
|
||||
|
||||
const {WEBKIT, USES_HOOKS, FFOX} = testOptions;
|
||||
const {WEBKIT, WIRE, FFOX} = testOptions;
|
||||
|
||||
it('should work', async ({ page, server }) => {
|
||||
const result = await page.evaluate(() => 7 * 3);
|
||||
|
|
@ -434,8 +434,8 @@ it('should not throw an error when evaluation does a synchronous navigation and
|
|||
expect(result).toBe(undefined);
|
||||
});
|
||||
|
||||
it.fail(USES_HOOKS)('should transfer 100Mb of data from page to node.js', async ({ page }) => {
|
||||
// This does not use hooks, but is slow in wire channel.
|
||||
it.fail(WIRE)('should transfer 100Mb of data from page to node.js', async ({ page }) => {
|
||||
// This is too slow with wire.
|
||||
const a = await page.evaluate(() => Array(100 * 1024 * 1024 + 1).join('a'));
|
||||
expect(a.length).toBe(100 * 1024 * 1024);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import util from 'util';
|
||||
import vm from 'vm';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('should work', async({page, server}) => {
|
||||
let message = null;
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import util from 'util';
|
||||
import vm from 'vm';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
const CRASH_FAIL = (FFOX && WIN) || USES_HOOKS;
|
||||
const CRASH_FAIL = (FFOX && WIN) || WIRE;
|
||||
// Firefox Win: it just doesn't crash sometimes.
|
||||
function crash(pageImpl) {
|
||||
if (CHROMIUM)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import './base.fixture';
|
||||
|
||||
import path from 'path';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('should fire', async({page, server}) => {
|
||||
const [error] = await Promise.all([
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import util from 'util';
|
||||
import vm from 'vm';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('exposeBinding should work', async({browser}) => {
|
||||
const context = await browser.newContext();
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import util from 'util';
|
||||
import vm from 'vm';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
async function giveItAChanceToFill(page) {
|
||||
for (let i = 0; i < 5; i++)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, USES_HOOKS, HEADLESS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE, HEADLESS} = testOptions;
|
||||
import {PNG} from 'pngjs';
|
||||
|
||||
// Firefox headful produces a different image.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import util from 'util';
|
||||
import vm from 'vm';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('should select single option', async({page, server}) => {
|
||||
await page.goto(server.PREFIX + '/input/select.html');
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import util from 'util';
|
||||
import vm from 'vm';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
const expectedOutput = '<html><head></head><body><div>hello</div></body></html>';
|
||||
it('should work', async({page, server}) => {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import util from 'util';
|
||||
import vm from 'vm';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('should work', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import './base.fixture';
|
|||
import path from 'path';
|
||||
import util from 'util';
|
||||
import vm from 'vm';
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, WIRE} = testOptions;
|
||||
|
||||
it('should work', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import path from 'path';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE} = testOptions;
|
||||
|
||||
it('should query existing element with css selector', async({page, server}) => {
|
||||
await page.setContent('<section>test</section>');
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@ testOptions.WIN = platform === 'win32';
|
|||
testOptions.CHROMIUM = browserName === 'chromium';
|
||||
testOptions.FFOX = browserName === 'firefox';
|
||||
testOptions.WEBKIT = browserName === 'webkit';
|
||||
testOptions.USES_HOOKS = process.env.PWCHANNEL === 'wire';
|
||||
testOptions.CHANNEL = process.env.PWCHANNEL !== 'none';
|
||||
testOptions.WIRE = process.env.PWWIRE;
|
||||
testOptions.HEADLESS = !!valueFromEnv('HEADLESS', true);
|
||||
testOptions.ASSETS_DIR = path.join(__dirname, '..', 'assets');
|
||||
testOptions.GOLDEN_DIR = path.join(__dirname, '..', 'golden-' + browserName);
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ const path = require('path');
|
|||
const url = require('url');
|
||||
const {mkdtempAsync, removeFolderAsync} = require('./utils');
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, MAC, LINUX, WIN, HEADLESS, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, MAC, LINUX, WIN, HEADLESS, WIRE} = testOptions;
|
||||
|
||||
declare global {
|
||||
interface FixtureState {
|
||||
persistentDirectory: string;
|
||||
videoPlayer: VideoPlayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerFixture('persistentDirectory', async ({}, test) => {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import path from 'path';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE} = testOptions;
|
||||
|
||||
it('should work for open shadow roots', async({page, server}) => {
|
||||
await page.goto(server.PREFIX + '/deep-shadow.html');
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import path from 'path';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE} = testOptions;
|
||||
|
||||
it('should work for open shadow roots', async({page, server}) => {
|
||||
await page.goto(server.PREFIX + '/deep-shadow.html');
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import path from 'path';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE} = testOptions;
|
||||
|
||||
it('should work', async ({playwright, page}) => {
|
||||
const createTagSelector = () => ({
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import './base.fixture';
|
|||
|
||||
import path from 'path';
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIRE} = testOptions;
|
||||
|
||||
it('query', async ({page}) => {
|
||||
await page.setContent(`<div>yo</div><div>ya</div><div>\nye </div>`);
|
||||
|
|
|
|||
3
test/types.d.ts
vendored
3
test/types.d.ts
vendored
|
|
@ -55,8 +55,7 @@ declare const testOptions: {
|
|||
LINUX: boolean;
|
||||
WIN: boolean;
|
||||
HEADLESS: boolean;
|
||||
USES_HOOKS: boolean;
|
||||
CHANNEL: boolean;
|
||||
WIRE: boolean;
|
||||
ASSETS_DIR: string;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT} = testOptions;
|
||||
|
||||
it('should timeout', async({page, server}) => {
|
||||
const startTime = Date.now();
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import './base.fixture';
|
||||
|
||||
import utils from './utils';
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
|
||||
const {FFOX, CHROMIUM, WEBKIT} = testOptions;
|
||||
|
||||
async function giveItTimeToLog(frame) {
|
||||
await frame.evaluate(() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f))));
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ const ts = require('typescript');
|
|||
const path = require('path');
|
||||
const Documentation = require('./Documentation');
|
||||
const EventEmitter = require('events');
|
||||
module.exports = { checkSources, expandPrefix };
|
||||
module.exports = { checkSources };
|
||||
|
||||
/**
|
||||
* @param {!Array<!import('../Source')>} sources
|
||||
|
|
@ -101,13 +101,12 @@ function checkSources(sources) {
|
|||
}
|
||||
if (className && !excludeClasses.has(className) && !fileName.endsWith('/protocol.ts')) {
|
||||
excludeClasses.add(className);
|
||||
const renamed = expandPrefix(className);
|
||||
classes.push(serializeClass(renamed, symbol, node));
|
||||
inheritance.set(renamed, parentClasses(node).map(expandPrefix));
|
||||
classes.push(serializeClass(className, symbol, node));
|
||||
inheritance.set(className, parentClasses(node));
|
||||
}
|
||||
}
|
||||
if (fileName.endsWith('/api.ts') && ts.isExportSpecifier(node))
|
||||
apiClassNames.add(expandPrefix((node.propertyName || node.name).text));
|
||||
apiClassNames.add((node.propertyName || node.name).text);
|
||||
ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
|
|
@ -215,10 +214,10 @@ function checkSources(sources) {
|
|||
innerTypeNames.push(innerType.name);
|
||||
}
|
||||
if (innerTypeNames.length === 0 || (innerTypeNames.length === 1 && innerTypeNames[0] === 'void'))
|
||||
return new Documentation.Type(expandPrefix(type.symbol.name));
|
||||
return new Documentation.Type(`${expandPrefix(type.symbol.name)}<${innerTypeNames.join(', ')}>`, properties);
|
||||
return new Documentation.Type(type.symbol.name);
|
||||
return new Documentation.Type(`${type.symbol.name}<${innerTypeNames.join(', ')}>`, properties);
|
||||
}
|
||||
return new Documentation.Type(expandPrefix(typeName), []);
|
||||
return new Documentation.Type(typeName, []);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -305,15 +304,3 @@ function checkSources(sources) {
|
|||
return props;
|
||||
}
|
||||
}
|
||||
|
||||
function expandPrefix(name) {
|
||||
if (name === 'CRSession')
|
||||
return 'CDPSession';
|
||||
if (name.startsWith('CR'))
|
||||
return 'Chromium' + name.substring(2);
|
||||
if (name.startsWith('FF'))
|
||||
return 'Firefox' + name.substring(2);
|
||||
if (name.startsWith('WK'))
|
||||
return 'WebKit' + name.substring(2);
|
||||
return name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,9 +36,6 @@ run();
|
|||
async function run() {
|
||||
const startTime = Date.now();
|
||||
const onlyBrowserVersions = process.argv.includes('--only-browser-versions');
|
||||
const noChannel = process.argv.includes('--no-channel');
|
||||
if (noChannel)
|
||||
console.warn(`${YELLOW_COLOR}NOTE: checking documentation against //src${RESET_COLOR}`);
|
||||
|
||||
/** @type {!Array<!Message>} */
|
||||
const messages = [];
|
||||
|
|
@ -69,13 +66,7 @@ async function run() {
|
|||
const browser = await playwright.chromium.launch();
|
||||
const page = await browser.newPage();
|
||||
const checkPublicAPI = require('./check_public_api');
|
||||
let jsSources;
|
||||
if (noChannel) {
|
||||
const rpcDir = path.join(PROJECT_DIR, 'src', 'rpc');
|
||||
jsSources = await Source.readdir(path.join(PROJECT_DIR, 'src'), '', [rpcDir]);
|
||||
} else {
|
||||
jsSources = await Source.readdir(path.join(PROJECT_DIR, 'src', 'rpc', 'client'), '', []);
|
||||
}
|
||||
const jsSources = await Source.readdir(path.join(PROJECT_DIR, 'src', 'rpc', 'client'), '', []);
|
||||
messages.push(...await checkPublicAPI(page, [api], jsSources));
|
||||
await browser.close();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue