feat: easy download (#56)

This commit is contained in:
Joel Einbinder 2019-12-04 17:58:38 -08:00 committed by GitHub
parent 46a46d8da1
commit 9f603c49fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 65 additions and 32 deletions

View File

@ -16,6 +16,7 @@
* [playwright.createBrowserFetcher([options])](#playwrightcreatebrowserfetcheroptions)
* [playwright.defaultArgs([options])](#playwrightdefaultargsoptions)
* [playwright.devices](#playwrightdevices)
* [playwright.downloadBrowser([options])](#playwrightdownloadbrowseroptions)
* [playwright.errors](#playwrighterrors)
* [playwright.executablePath()](#playwrightexecutablepath)
* [playwright.launch([options])](#playwrightlaunchoptions)
@ -431,6 +432,22 @@ const iPhone = playwright.devices['iPhone 6'];
> **NOTE** The old way (Playwright versions <= v1.14.0) devices can be obtained with `require('playwright/DeviceDescriptors')`.
#### playwright.downloadBrowser([options])
- `options` <[Object]>
- `onProgress` <[function]([number], [number])> A function that will be called with two arguments:
- `downloadedBytes` <[number]> how many bytes have been downloaded
- `totalBytes` <[number]> how large is the total download.
- returns: <[Promise]<[Object]>> Resolves with revision information when the revision is downloaded and extracted
- `revision` <[string]> the revision the info was created from
- `folderPath` <[string]> path to the extracted revision folder
- `executablePath` <[string]> path to the revision executable
- `url` <[string]> URL this revision can be downloaded from
- `local` <[boolean]> whether the revision is locally available on disk
Downloads the default browser that Playwright controls. The browser is usually around 100mb.
> **NOTE** Depending on your terminal, the progress bar might not appear.
#### playwright.errors
- returns: <[Object]>
- `TimeoutError` <[function]> A class of [TimeoutError].

View File

@ -22,48 +22,32 @@ try {
stdio: 'ignore'
});
} catch (e) {
console.warn('Build failed');
}
(async function() {
const {generateWebKitProtocol, generateFirefoxProtocol, generateChromeProtocol} = require('./utils/protocol-types-generator/') ;
try {
const chromeRevision = await downloadBrowser('chromium', require('./chromium').createBrowserFetcher());
const chromeRevision = await downloadBrowser('chromium', require('./chromium'));
await generateChromeProtocol(chromeRevision);
} catch (e) {
console.warn(e.message);
}
try {
const firefoxRevision = await downloadBrowser('firefox', require('./firefox').createBrowserFetcher());
const firefoxRevision = await downloadBrowser('firefox', require('./firefox'));
await generateFirefoxProtocol(firefoxRevision);
} catch (e) {
console.warn(e.message);
}
try {
const webkitRevision = await downloadBrowser('webkit', require('./webkit').createBrowserFetcher());
const webkitRevision = await downloadBrowser('webkit', require('./webkit'));
await generateWebKitProtocol(webkitRevision);
} catch (e) {
console.warn(e.message);
}
})();
function getRevision(browser) {
if (browser === 'chromium')
return require('./package.json').playwright.chromium_revision;
if (browser === 'firefox')
return require('./package.json').playwright.firefox_revision;
if (browser === 'webkit')
return require('./package.json').playwright.webkit_revision;
}
async function downloadBrowser(browser, browserFetcher) {
const revision = getRevision(browser);
const revisionInfo = browserFetcher.revisionInfo(revision);
// Do nothing if the revision is already downloaded.
if (revisionInfo.local)
return revisionInfo;
async function downloadBrowser(browser, playwright) {
let progressBar = null;
let lastDownloadedBytes = 0;
function onProgress(downloadedBytes, totalBytes) {
@ -81,8 +65,12 @@ async function downloadBrowser(browser, browserFetcher) {
progressBar.tick(delta);
}
await browserFetcher.download(revisionInfo.revision, onProgress);
const revisionInfo = await playwright.downloadBrowser({onProgress});
// Do nothing if the revision is already downloaded.
if (revisionInfo.local)
return revisionInfo;
logPolitely(`${browser} downloaded to ${revisionInfo.folderPath}`);
const browserFetcher = playwright.createBrowserFetcher();
const localRevisions = await browserFetcher.localRevisions();
// Remove previous chromium revisions.
const cleanupOldVersions = localRevisions.filter(revision => revision !== revisionInfo.revision).map(revision => browserFetcher.remove(revision));
@ -94,7 +82,6 @@ async function downloadBrowser(browser, browserFetcher) {
return revisionInfo;
}
function toMegabytes(bytes) {
const mb = bytes / 1024 / 1024;
return `${Math.round(mb * 10) / 10} Mb`;

View File

@ -37,7 +37,6 @@
"extract-zip": "^1.6.6",
"https-proxy-agent": "^3.0.0",
"mime": "^2.0.3",
"progress": "^2.0.1",
"proxy-from-env": "^1.0.0",
"rimraf": "^2.6.1",
"ws": "^6.1.0"
@ -61,6 +60,7 @@
"node-stream-zip": "^1.8.2",
"pixelmatch": "^4.0.2",
"pngjs": "^3.3.3",
"progress": "^2.0.1",
"text-diff": "^1.0.1",
"ts-loader": "^6.1.2",
"typescript": "3.6.3",

View File

@ -39,7 +39,7 @@ export class LifecycleWatcher {
private _newDocumentNavigationCompleteCallback: () => void;
private _timeoutPromise: Promise<Error>;
private _terminationPromise: Promise<Error | null>;
private _terminationCallback: () => void;
private _terminationCallback: (err: Error | null) => void;
private _maximumTimer: NodeJS.Timer;
private _hasSameDocumentNavigation: boolean;

View File

@ -20,14 +20,17 @@ import { ConnectionTransport } from '../ConnectionTransport';
import { DeviceDescriptors } from '../DeviceDescriptors';
import * as Errors from '../Errors';
import { Launcher, LauncherBrowserOptions, LauncherChromeArgOptions, LauncherLaunchOptions } from './Launcher';
import {download, RevisionInfo} from '../download';
export class Playwright {
private _projectRoot: string;
private _launcher: Launcher;
downloadBrowser: (options?: { onProgress?: (downloadedBytes: number, totalBytes: number) => void; }) => Promise<RevisionInfo>;
constructor(projectRoot: string, preferredRevision: string) {
this._projectRoot = projectRoot;
this._launcher = new Launcher(projectRoot, preferredRevision);
this.downloadBrowser = download.bind(null, this.createBrowserFetcher(), preferredRevision, 'Chromium');
}
launch(options: (LauncherLaunchOptions & LauncherChromeArgOptions & LauncherBrowserOptions) | undefined): Promise<Browser> {
@ -60,7 +63,7 @@ export class Playwright {
return this._launcher.defaultArgs(options);
}
createBrowserFetcher(options: BrowserFetcherOptions | undefined): BrowserFetcher {
createBrowserFetcher(options?: BrowserFetcherOptions | undefined): BrowserFetcher {
return new BrowserFetcher(this._projectRoot, options);
}
}

20
src/download.ts Normal file
View File

@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
export async function download(
browserFetcher:
import('./chromium/BrowserFetcher').BrowserFetcher |
import('./firefox/BrowserFetcher').BrowserFetcher |
import('./webkit/BrowserFetcher').BrowserFetcher,
revision: string,
browserName: string,
{onProgress}: {onProgress?: (downloadedBytes: number, totalBytes: number) => void} = {}) : Promise<RevisionInfo> {
return await browserFetcher.download(revision, onProgress);
}
export type RevisionInfo = {
folderPath: string,
executablePath: string,
url: string,
local: boolean,
revision: string,
};

View File

@ -20,14 +20,17 @@ import { ConnectionTransport } from '../ConnectionTransport';
import { DeviceDescriptors } from '../DeviceDescriptors';
import * as Errors from '../Errors';
import { Launcher } from './Launcher';
import {download, RevisionInfo} from '../download';
export class Playwright {
private _projectRoot: string;
private _launcher: Launcher;
downloadBrowser: (options?: { onProgress?: (downloadedBytes: number, totalBytes: number) => void; }) => Promise<RevisionInfo>;
constructor(projectRoot: string, preferredRevision: string) {
this._projectRoot = projectRoot;
this._launcher = new Launcher(projectRoot, preferredRevision);
this.downloadBrowser = download.bind(null, this.createBrowserFetcher(), preferredRevision, 'Chromium');
}
launch(options: any): Promise<Browser> {
@ -60,7 +63,7 @@ export class Playwright {
return this._launcher.defaultArgs(options);
}
createBrowserFetcher(options: any | undefined): BrowserFetcher {
createBrowserFetcher(options?: any | undefined): BrowserFetcher {
return new BrowserFetcher(this._projectRoot, { browser: 'firefox', ...options });
}
}

View File

@ -20,7 +20,6 @@ import { EventEmitter } from 'events';
import { assert, helper, RegisteredListener } from '../helper';
import { filterCookies, NetworkCookie, rewriteCookies, SetNetworkCookieParam } from '../network';
import { Connection } from './Connection';
import { Events } from './events';
import { Page, Viewport } from './Page';
import { Target } from './Target';
import { TaskQueue } from './TaskQueue';

View File

@ -90,7 +90,7 @@ export class NetworkManager extends EventEmitter {
});
}
_onRequestWillBeSent(event: Protocol.Network.requestWillBeSentPayload, interceptionId: string | null) {
_onRequestWillBeSent(event: Protocol.Network.requestWillBeSentPayload) {
let redirectChain: network.Request[] = [];
if (event.redirectResponse) {
const request = this._requestIdToRequest.get(event.requestId);
@ -101,7 +101,7 @@ export class NetworkManager extends EventEmitter {
}
}
const frame = event.frameId && this._frameManager ? this._frameManager.frame(event.frameId) : null;
const request = new InterceptableRequest(frame, interceptionId, event, redirectChain);
const request = new InterceptableRequest(frame, undefined, event, redirectChain);
this._requestIdToRequest.set(event.requestId, request);
this.emit(NetworkManagerEvents.Request, request.request);
}

View File

@ -19,14 +19,17 @@ import { BrowserFetcher, BrowserFetcherOptions } from './BrowserFetcher';
import { DeviceDescriptors } from '../DeviceDescriptors';
import * as Errors from '../Errors';
import { Launcher, LauncherLaunchOptions } from './Launcher';
import { download, RevisionInfo } from '../download';
export class Playwright {
private _projectRoot: string;
private _launcher: Launcher;
downloadBrowser: (options?: { onProgress?: (downloadedBytes: number, totalBytes: number) => void; }) => Promise<RevisionInfo>;
constructor(projectRoot: string, preferredRevision: string) {
this._projectRoot = projectRoot;
this._launcher = new Launcher(projectRoot, preferredRevision);
this.downloadBrowser = download.bind(null, this.createBrowserFetcher(), preferredRevision, 'WebKit');
}
launch(options: (LauncherLaunchOptions) | undefined): Promise<Browser> {
@ -52,7 +55,7 @@ export class Playwright {
return this._launcher.defaultArgs(options);
}
createBrowserFetcher(options: BrowserFetcherOptions | undefined): BrowserFetcher {
createBrowserFetcher(options?: BrowserFetcherOptions | undefined): BrowserFetcher {
return new BrowserFetcher(this._projectRoot, options);
}
}

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { helper, RegisteredListener } from '../helper';
import { RegisteredListener } from '../helper';
import { Browser, BrowserContext } from './Browser';
import { Page } from './Page';
import { Protocol } from './protocol';

View File

@ -7,7 +7,8 @@
"lib": ["esnext", "dom"],
"sourceMap": true,
"rootDir": "./src",
"outDir": "./lib"
"outDir": "./lib",
"strictBindCallApply": true
},
"compileOnSave": true,
"include": ["src/**/*.ts"],