mirror of
https://github.com/microsoft/playwright.git
synced 2025-01-02 08:07:34 +03:00
feat: easy download (#56)
This commit is contained in:
parent
46a46d8da1
commit
9f603c49fb
17
docs/api.md
17
docs/api.md
@ -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].
|
||||
|
31
install.js
31
install.js
@ -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`;
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
20
src/download.ts
Normal 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,
|
||||
};
|
@ -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 });
|
||||
}
|
||||
}
|
||||
|
@ -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';
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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';
|
||||
|
@ -7,7 +7,8 @@
|
||||
"lib": ["esnext", "dom"],
|
||||
"sourceMap": true,
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib"
|
||||
"outDir": "./lib",
|
||||
"strictBindCallApply": true
|
||||
},
|
||||
"compileOnSave": true,
|
||||
"include": ["src/**/*.ts"],
|
||||
|
Loading…
Reference in New Issue
Block a user