feat: add executablePath to InstalledBrowser (#10594)

This commit is contained in:
Alex Rudenko 2023-07-20 10:53:15 +02:00 committed by GitHub
parent 5a411ca629
commit 87522e778a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 134 additions and 59 deletions

View File

@ -8,15 +8,17 @@ sidebar_label: install
```typescript ```typescript
export declare function install( export declare function install(
options: InstallOptions options: InstallOptions & {
unpack?: true;
}
): Promise<InstalledBrowser>; ): Promise<InstalledBrowser>;
``` ```
## Parameters ## Parameters
| Parameter | Type | Description | | Parameter | Type | Description |
| --------- | ---------------------------------------------- | ----------- | | --------- | ----------------------------------------------------------------------- | ----------- |
| options | [InstallOptions](./browsers.installoptions.md) | | | options | [InstallOptions](./browsers.installoptions.md) &amp; { unpack?: true; } | |
**Returns:** **Returns:**

View File

@ -0,0 +1,25 @@
---
sidebar_label: install_1
---
# install() function
#### Signature:
```typescript
export declare function install(
options: InstallOptions & {
unpack: false;
}
): Promise<string>;
```
## Parameters
| Parameter | Type | Description |
| --------- | ----------------------------------------------------------------------- | ----------- |
| options | [InstallOptions](./browsers.installoptions.md) &amp; { unpack: false; } | |
**Returns:**
Promise&lt;string&gt;

View File

@ -2,19 +2,24 @@
sidebar_label: InstalledBrowser sidebar_label: InstalledBrowser
--- ---
# InstalledBrowser interface # InstalledBrowser class
#### Signature: #### Signature:
```typescript ```typescript
export interface InstalledBrowser export declare class InstalledBrowser
``` ```
## Remarks
The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `InstalledBrowser` class.
## Properties ## Properties
| Property | Modifiers | Type | Description | Default | | Property | Modifiers | Type | Description |
| -------- | --------- | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | -------------- | --------------------- | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| browser | | [Browser](./browsers.browser.md) | | | | browser | | [Browser](./browsers.browser.md) | |
| buildId | | string | | | | buildId | | string | |
| path | | string | Path to the root of the installation folder. Use [computeExecutablePath()](./browsers.computeexecutablepath.md) to get the path to the executable binary. | | | executablePath | <code>readonly</code> | string | |
| platform | | [BrowserPlatform](./browsers.browserplatform.md) | | | | path | <code>readonly</code> | string | Path to the root of the installation folder. Use [computeExecutablePath()](./browsers.computeexecutablepath.md) to get the path to the executable binary. |
| platform | | [BrowserPlatform](./browsers.browserplatform.md) | |

View File

@ -33,11 +33,12 @@ The programmatic API allows installing and launching browsers from your code. Se
## Classes ## Classes
| Class | Description | | Class | Description |
| ------------------------------------------ | ----------- | | -------------------------------------------------- | ----------- |
| [CLI](./browsers.cli.md) | | | [CLI](./browsers.cli.md) | |
| [Process](./browsers.process.md) | | | [InstalledBrowser](./browsers.installedbrowser.md) | |
| [TimeoutError](./browsers.timeouterror.md) | | | [Process](./browsers.process.md) | |
| [TimeoutError](./browsers.timeouterror.md) | |
## Enumerations ## Enumerations
@ -58,6 +59,7 @@ The programmatic API allows installing and launching browsers from your code. Se
| [detectBrowserPlatform()](./browsers.detectbrowserplatform.md) | | | [detectBrowserPlatform()](./browsers.detectbrowserplatform.md) | |
| [getInstalledBrowsers(options)](./browsers.getinstalledbrowsers.md) | Returns metadata about browsers installed in the cache directory. | | [getInstalledBrowsers(options)](./browsers.getinstalledbrowsers.md) | Returns metadata about browsers installed in the cache directory. |
| [install(options)](./browsers.install.md) | | | [install(options)](./browsers.install.md) | |
| [install(options)](./browsers.install_1.md) | |
| [launch(opts)](./browsers.launch.md) | | | [launch(opts)](./browsers.launch.md) | |
| [makeProgressCallback(browser, buildId)](./browsers.makeprogresscallback.md) | | | [makeProgressCallback(browser, buildId)](./browsers.makeprogresscallback.md) | |
| [resolveBuildId(browser, platform, tag)](./browsers.resolvebuildid.md) | | | [resolveBuildId(browser, platform, tag)](./browsers.resolvebuildid.md) | |
@ -68,7 +70,6 @@ The programmatic API allows installing and launching browsers from your code. Se
| Interface | Description | | Interface | Description |
| ------------------------------------------------------------------------ | ----------- | | ------------------------------------------------------------------------ | ----------- |
| [GetInstalledBrowsersOptions](./browsers.getinstalledbrowsersoptions.md) | | | [GetInstalledBrowsersOptions](./browsers.getinstalledbrowsersoptions.md) | |
| [InstalledBrowser](./browsers.installedbrowser.md) | |
| [InstallOptions](./browsers.installoptions.md) | | | [InstallOptions](./browsers.installoptions.md) | |
| [LaunchOptions](./browsers.launchoptions.md) | | | [LaunchOptions](./browsers.launchoptions.md) | |
| [Options](./browsers.options.md) | | | [Options](./browsers.options.md) | |

View File

@ -18,19 +18,53 @@ import fs from 'fs';
import path from 'path'; import path from 'path';
import {Browser, BrowserPlatform} from './browser-data/browser-data.js'; import {Browser, BrowserPlatform} from './browser-data/browser-data.js';
import {computeExecutablePath} from './launch.js';
/** /**
* @public * @public
*/ */
export interface InstalledBrowser { export class InstalledBrowser {
browser: Browser;
buildId: string;
platform: BrowserPlatform;
#cache: Cache;
/**
* @internal
*/
constructor(
cache: Cache,
browser: Browser,
buildId: string,
platform: BrowserPlatform
) {
this.#cache = cache;
this.browser = browser;
this.buildId = buildId;
this.platform = platform;
}
/** /**
* Path to the root of the installation folder. Use * Path to the root of the installation folder. Use
* {@link computeExecutablePath} to get the path to the executable binary. * {@link computeExecutablePath} to get the path to the executable binary.
*/ */
path: string; get path(): string {
browser: Browser; return this.#cache.installationDir(
buildId: string; this.browser,
platform: BrowserPlatform; this.platform,
this.buildId
);
}
get executablePath(): string {
return computeExecutablePath({
cacheDir: this.#cache.rootDir,
platform: this.platform,
browser: this.browser,
buildId: this.buildId,
});
}
} }
/** /**
@ -54,6 +88,13 @@ export class Cache {
this.#rootDir = rootDir; this.#rootDir = rootDir;
} }
/**
* @internal
*/
get rootDir(): string {
return this.#rootDir;
}
browserRoot(browser: Browser): string { browserRoot(browser: Browser): string {
return path.join(this.#rootDir, browser); return path.join(this.#rootDir, browser);
} }
@ -106,14 +147,14 @@ export class Cache {
if (!result) { if (!result) {
return null; return null;
} }
return { return new InstalledBrowser(
path: path.join(this.browserRoot(browser), file), this,
browser, browser,
platform: result.platform, result.buildId,
buildId: result.buildId, result.platform as BrowserPlatform
}; );
}) })
.filter((item): item is InstalledBrowser => { .filter((item: InstalledBrowser | null): item is InstalledBrowser => {
return item !== null; return item !== null;
}); });
}); });

View File

@ -100,9 +100,15 @@ export interface InstallOptions {
/** /**
* @public * @public
*/ */
export function install(
options: InstallOptions & {unpack?: true}
): Promise<InstalledBrowser>;
export function install(
options: InstallOptions & {unpack: false}
): Promise<string>;
export async function install( export async function install(
options: InstallOptions options: InstallOptions
): Promise<InstalledBrowser> { ): Promise<InstalledBrowser | string> {
options.platform ??= detectBrowserPlatform(); options.platform ??= detectBrowserPlatform();
options.unpack ??= true; options.unpack ??= true;
if (!options.platform) { if (!options.platform) {
@ -118,8 +124,8 @@ export async function install(
); );
const fileName = url.toString().split('/').pop(); const fileName = url.toString().split('/').pop();
assert(fileName, `A malformed download URL was found: ${url}.`); assert(fileName, `A malformed download URL was found: ${url}.`);
const structure = new Cache(options.cacheDir); const cache = new Cache(options.cacheDir);
const browserRoot = structure.browserRoot(options.browser); const browserRoot = cache.browserRoot(options.browser);
const archivePath = path.join(browserRoot, fileName); const archivePath = path.join(browserRoot, fileName);
if (!existsSync(browserRoot)) { if (!existsSync(browserRoot)) {
await mkdir(browserRoot, {recursive: true}); await mkdir(browserRoot, {recursive: true});
@ -127,37 +133,27 @@ export async function install(
if (!options.unpack) { if (!options.unpack) {
if (existsSync(archivePath)) { if (existsSync(archivePath)) {
return { return archivePath;
path: archivePath,
browser: options.browser,
platform: options.platform,
buildId: options.buildId,
};
} }
debugInstall(`Downloading binary from ${url}`); debugInstall(`Downloading binary from ${url}`);
debugTime('download'); debugTime('download');
await downloadFile(url, archivePath, options.downloadProgressCallback); await downloadFile(url, archivePath, options.downloadProgressCallback);
debugTimeEnd('download'); debugTimeEnd('download');
return { return archivePath;
path: archivePath,
browser: options.browser,
platform: options.platform,
buildId: options.buildId,
};
} }
const outputPath = structure.installationDir( const outputPath = cache.installationDir(
options.browser, options.browser,
options.platform, options.platform,
options.buildId options.buildId
); );
if (existsSync(outputPath)) { if (existsSync(outputPath)) {
return { return new InstalledBrowser(
path: outputPath, cache,
browser: options.browser, options.browser,
platform: options.platform, options.buildId,
buildId: options.buildId, options.platform
}; );
} }
try { try {
debugInstall(`Downloading binary from ${url}`); debugInstall(`Downloading binary from ${url}`);
@ -180,12 +176,12 @@ export async function install(
await unlink(archivePath); await unlink(archivePath);
} }
} }
return { return new InstalledBrowser(
path: outputPath, cache,
browser: options.browser, options.browser,
platform: options.platform, options.buildId,
buildId: options.buildId, options.platform
}; );
} }
/** /**

View File

@ -104,6 +104,10 @@ describe('Chrome install', () => {
const cache = new Cache(tmpDir); const cache = new Cache(tmpDir);
const installed = cache.getInstalledBrowsers(); const installed = cache.getInstalledBrowsers();
assert.deepStrictEqual(browser, installed[0]); assert.deepStrictEqual(browser, installed[0]);
assert.deepStrictEqual(
browser!.executablePath,
installed[0]?.executablePath
);
}); });
it('throws on invalid URL', async function () { it('throws on invalid URL', async function () {

View File

@ -98,5 +98,6 @@ describe('ChromeDriver install', () => {
}); });
assert.strictEqual(browser.path, expectedOutputPath); assert.strictEqual(browser.path, expectedOutputPath);
assert.ok(fs.existsSync(expectedOutputPath)); assert.ok(fs.existsSync(expectedOutputPath));
assert.ok(fs.existsSync(browser.executablePath));
}); });
}); });

View File

@ -59,7 +59,7 @@ for (const version of Object.keys(versions)) {
continue; continue;
} }
const result = await install({ const archivePath = await install({
browser, browser,
buildId, buildId,
platform, platform,
@ -70,7 +70,7 @@ for (const version of Object.keys(versions)) {
fs.mkdirSync(path.dirname(targetPath), { fs.mkdirSync(path.dirname(targetPath), {
recursive: true, recursive: true,
}); });
fs.copyFileSync(result.path, targetPath); fs.copyFileSync(archivePath, targetPath);
} }
} }