chore(stable): throw user-friendly message when ffmpeg is missing (#5865)
This commit is contained in:
parent
141583c79f
commit
2367039a2c
|
|
@ -36,7 +36,7 @@ import { CRBrowserContext } from './crBrowser';
|
||||||
import * as types from '../types';
|
import * as types from '../types';
|
||||||
import { ConsoleMessage } from '../console';
|
import { ConsoleMessage } from '../console';
|
||||||
import { rewriteErrorMessage } from '../../utils/stackTrace';
|
import { rewriteErrorMessage } from '../../utils/stackTrace';
|
||||||
import { assert, headersArrayToObject, createGuid } from '../../utils/utils';
|
import { assert, headersArrayToObject, createGuid, canAccessFile } from '../../utils/utils';
|
||||||
import { VideoRecorder } from './videoRecorder';
|
import { VideoRecorder } from './videoRecorder';
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -816,6 +816,22 @@ class FrameSession {
|
||||||
const ffmpegPath = this._crPage._browserContext._browser.options.registry.executablePath('ffmpeg');
|
const ffmpegPath = this._crPage._browserContext._browser.options.registry.executablePath('ffmpeg');
|
||||||
if (!ffmpegPath)
|
if (!ffmpegPath)
|
||||||
throw new Error('ffmpeg executable was not found');
|
throw new Error('ffmpeg executable was not found');
|
||||||
|
if (!canAccessFile(ffmpegPath)) {
|
||||||
|
let message: string = '';
|
||||||
|
switch (this._page._browserContext._options.sdkLanguage) {
|
||||||
|
case 'python': message = 'playwright install ffmpeg'; break;
|
||||||
|
case 'python-async': message = 'playwright install ffmpeg'; break;
|
||||||
|
case 'javascript': message = 'npx playwright install ffmpeg'; break;
|
||||||
|
case 'java': message = 'mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="install ffmpeg"'; break;
|
||||||
|
}
|
||||||
|
throw new Error(`
|
||||||
|
============================================================
|
||||||
|
Please install ffmpeg in order to record video.
|
||||||
|
|
||||||
|
$ ${message}
|
||||||
|
============================================================
|
||||||
|
`);
|
||||||
|
}
|
||||||
this._videoRecorder = await VideoRecorder.launch(this._crPage._page, ffmpegPath, options);
|
this._videoRecorder = await VideoRecorder.launch(this._crPage._page, ffmpegPath, options);
|
||||||
this._screencastId = screencastId;
|
this._screencastId = screencastId;
|
||||||
const gotFirstFrame = new Promise(f => this._client.once('Page.screencastFrame', f));
|
const gotFirstFrame = new Promise(f => this._client.once('Page.screencastFrame', f));
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { canAccessFile } from '../../utils/utils';
|
||||||
|
|
||||||
function darwin(channel: string): string | undefined {
|
function darwin(channel: string): string | undefined {
|
||||||
switch (channel) {
|
switch (channel) {
|
||||||
|
|
@ -60,24 +60,12 @@ function win32(channel: string): string | undefined {
|
||||||
let result: string | undefined;
|
let result: string | undefined;
|
||||||
prefixes.forEach(prefix => {
|
prefixes.forEach(prefix => {
|
||||||
const chromePath = path.join(prefix, suffix!);
|
const chromePath = path.join(prefix, suffix!);
|
||||||
if (canAccess(chromePath))
|
if (canAccessFile(chromePath))
|
||||||
result = chromePath;
|
result = chromePath;
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function canAccess(file: string) {
|
|
||||||
if (!file)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs.accessSync(file);
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function findChromiumChannel(channel: string): string {
|
export function findChromiumChannel(channel: string): string {
|
||||||
let result: string | undefined;
|
let result: string | undefined;
|
||||||
if (process.platform === 'linux')
|
if (process.platform === 'linux')
|
||||||
|
|
@ -90,7 +78,7 @@ export function findChromiumChannel(channel: string): string {
|
||||||
if (!result)
|
if (!result)
|
||||||
throw new Error(`Chromium distribution '${channel}' is not supported on ${process.platform}`);
|
throw new Error(`Chromium distribution '${channel}' is not supported on ${process.platform}`);
|
||||||
|
|
||||||
if (canAccess(result))
|
if (canAccessFile(result))
|
||||||
return result;
|
return result;
|
||||||
throw new Error(`Chromium distribution was not found: ${channel}`);
|
throw new Error(`Chromium distribution was not found: ${channel}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ export async function launchProcess(options: LaunchProcessOptions): Promise<Laun
|
||||||
let failed: (e: Error) => void;
|
let failed: (e: Error) => void;
|
||||||
const failedPromise = new Promise<Error>((f, r) => failed = f);
|
const failedPromise = new Promise<Error>((f, r) => failed = f);
|
||||||
spawnedProcess.once('error', error => {
|
spawnedProcess.once('error', error => {
|
||||||
failed(new Error('Failed to launch browser: ' + error));
|
failed(new Error('Failed to launch: ' + error));
|
||||||
});
|
});
|
||||||
return cleanup().then(() => failedPromise).then(e => Promise.reject(e));
|
return cleanup().then(() => failedPromise).then(e => Promise.reject(e));
|
||||||
}
|
}
|
||||||
|
|
@ -164,7 +164,7 @@ export async function launchProcess(options: LaunchProcessOptions): Promise<Laun
|
||||||
// Force kill the browser.
|
// Force kill the browser.
|
||||||
try {
|
try {
|
||||||
if (process.platform === 'win32')
|
if (process.platform === 'win32')
|
||||||
childProcess.execSync(`taskkill /pid ${spawnedProcess.pid} /T /F`);
|
childProcess.execSync(`taskkill /pid ${spawnedProcess.pid} /T /F`, { stdio: 'ignore' });
|
||||||
else
|
else
|
||||||
process.kill(-spawnedProcess.pid, 'SIGKILL');
|
process.kill(-spawnedProcess.pid, 'SIGKILL');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -158,3 +158,15 @@ export async function removeFolders(dirs: string[]) {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function canAccessFile(file: string) {
|
||||||
|
if (!file)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.accessSync(file);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,9 @@ it('should restore state from userDataDir', (test, { browserName }) => {
|
||||||
await browserContext3.close();
|
await browserContext3.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should restore cookies from userDataDir', (test, { browserName }) => {
|
it('should restore cookies from userDataDir', (test, { platform, browserChannel }) => {
|
||||||
test.slow();
|
test.slow();
|
||||||
|
test.fixme(platform === 'win32' && browserChannel === 'chrome');
|
||||||
}, async ({browserType, browserOptions, server, createUserDataDir}) => {
|
}, async ({browserType, browserOptions, server, createUserDataDir}) => {
|
||||||
const userDataDir = await createUserDataDir();
|
const userDataDir = await createUserDataDir();
|
||||||
const browserContext = await browserType.launchPersistentContext(userDataDir, browserOptions);
|
const browserContext = await browserType.launchPersistentContext(userDataDir, browserOptions);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue