fix(inspector): fall back to custom executable path for UI (#6214)
This commit is contained in:
parent
8c1b994f58
commit
e4ae6503d7
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
|
|
@ -119,7 +119,7 @@ jobs:
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: node lib/cli/cli install-deps
|
- run: node lib/cli/cli install-deps
|
||||||
- run: bash packages/installation-tests/installation-tests.sh
|
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash packages/installation-tests/installation-tests.sh
|
||||||
|
|
||||||
headful_linux:
|
headful_linux:
|
||||||
name: "Headful Linux"
|
name: "Headful Linux"
|
||||||
|
|
|
||||||
26
packages/installation-tests/inspector-custom-executable.js
Normal file
26
packages/installation-tests/inspector-custom-executable.js
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
const playwright = require('playwright');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const browser = await playwright.chromium.launch({
|
||||||
|
executablePath: '/opt/google/chrome/chrome'
|
||||||
|
});
|
||||||
|
const context = await browser.newContext();
|
||||||
|
await context.newPage();
|
||||||
|
await browser.close();
|
||||||
|
console.log('SUCCESS');
|
||||||
|
})();
|
||||||
|
|
@ -39,6 +39,7 @@ mkdir -p "${TEST_ROOT}"
|
||||||
NODE_VERSION="$(node --version)"
|
NODE_VERSION="$(node --version)"
|
||||||
|
|
||||||
function copy_test_scripts {
|
function copy_test_scripts {
|
||||||
|
cp "${SCRIPTS_PATH}/inspector-custom-executable.js" .
|
||||||
cp "${SCRIPTS_PATH}/sanity.js" .
|
cp "${SCRIPTS_PATH}/sanity.js" .
|
||||||
cp "${SCRIPTS_PATH}/screencast.js" .
|
cp "${SCRIPTS_PATH}/screencast.js" .
|
||||||
cp "${SCRIPTS_PATH}/esm.mjs" .
|
cp "${SCRIPTS_PATH}/esm.mjs" .
|
||||||
|
|
@ -55,6 +56,7 @@ function run_tests {
|
||||||
test_screencast
|
test_screencast
|
||||||
test_typescript_types
|
test_typescript_types
|
||||||
test_skip_browser_download
|
test_skip_browser_download
|
||||||
|
test_skip_browser_download_inspect_with_custom_executable
|
||||||
test_playwright_global_installation_subsequent_installs
|
test_playwright_global_installation_subsequent_installs
|
||||||
test_playwright_should_work
|
test_playwright_should_work
|
||||||
test_playwright_should_work_with_relative_home_path
|
test_playwright_should_work_with_relative_home_path
|
||||||
|
|
@ -194,6 +196,32 @@ function test_skip_browser_download {
|
||||||
echo "${FUNCNAME[0]} success"
|
echo "${FUNCNAME[0]} success"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_skip_browser_download_inspect_with_custom_executable {
|
||||||
|
initialize_test "${FUNCNAME[0]}"
|
||||||
|
copy_test_scripts
|
||||||
|
|
||||||
|
OUTPUT=$(PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install ${PLAYWRIGHT_TGZ})
|
||||||
|
if [[ "${OUTPUT}" != *"Skipping browsers download because"* ]]; then
|
||||||
|
echo "missing log message that browsers download is skipped"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$(uname)" != "Linux" ]]; then
|
||||||
|
echo
|
||||||
|
echo "Skipping test on non-Linux platform"
|
||||||
|
echo
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
OUTPUT=$(PWDEBUG=1 node inspector-custom-executable.js)
|
||||||
|
if [[ "${OUTPUT}" != *"SUCCESS"* ]]; then
|
||||||
|
echo "missing log message that launch succeeded: ${OUTPUT}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${FUNCNAME[0]} success"
|
||||||
|
}
|
||||||
|
|
||||||
function test_playwright_should_work {
|
function test_playwright_should_work {
|
||||||
initialize_test "${FUNCNAME[0]}"
|
initialize_test "${FUNCNAME[0]}"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ export type BrowserOptions = PlaywrightOptions & {
|
||||||
headful?: boolean,
|
headful?: boolean,
|
||||||
persistent?: types.BrowserContextOptions, // Undefined means no persistent context.
|
persistent?: types.BrowserContextOptions, // Undefined means no persistent context.
|
||||||
browserProcess: BrowserProcess,
|
browserProcess: BrowserProcess,
|
||||||
|
customExecutablePath?: string;
|
||||||
proxy?: ProxySettings,
|
proxy?: ProxySettings,
|
||||||
protocolLogger: types.ProtocolLogger,
|
protocolLogger: types.ProtocolLogger,
|
||||||
browserLogsCollector: RecentLogsCollector,
|
browserLogsCollector: RecentLogsCollector,
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ export abstract class BrowserType extends SdkObject {
|
||||||
this._registry = playwrightOptions.registry;
|
this._registry = playwrightOptions.registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
executablePath(options?: types.LaunchOptions): string {
|
executablePath(channel?: types.BrowserChannel): string {
|
||||||
return this._registry.executablePath(this._name) || '';
|
return this._registry.executablePath(this._name) || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,6 +110,7 @@ export abstract class BrowserType extends SdkObject {
|
||||||
headful: !options.headless,
|
headful: !options.headless,
|
||||||
downloadsPath,
|
downloadsPath,
|
||||||
browserProcess,
|
browserProcess,
|
||||||
|
customExecutablePath: options.executablePath,
|
||||||
proxy: options.proxy,
|
proxy: options.proxy,
|
||||||
protocolLogger,
|
protocolLogger,
|
||||||
browserLogsCollector,
|
browserLogsCollector,
|
||||||
|
|
@ -166,7 +167,7 @@ export abstract class BrowserType extends SdkObject {
|
||||||
else
|
else
|
||||||
browserArguments.push(...this._defaultArgs(options, isPersistent, userDataDir));
|
browserArguments.push(...this._defaultArgs(options, isPersistent, userDataDir));
|
||||||
|
|
||||||
const executable = executablePath || this.executablePath(options);
|
const executable = executablePath || this.executablePath(options.channel);
|
||||||
if (!executable)
|
if (!executable)
|
||||||
throw new Error(`No executable path is specified. Pass "executablePath" option directly.`);
|
throw new Error(`No executable path is specified. Pass "executablePath" option directly.`);
|
||||||
if (!(await existsAsync(executable))) {
|
if (!(await existsAsync(executable))) {
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,10 @@ export class Chromium extends BrowserType {
|
||||||
this._devtools = this._createDevTools();
|
this._devtools = this._createDevTools();
|
||||||
}
|
}
|
||||||
|
|
||||||
executablePath(options?: types.LaunchOptions): string {
|
executablePath(channel?: types.BrowserChannel): string {
|
||||||
if (options?.channel)
|
if (channel)
|
||||||
return findChromiumChannel(options.channel);
|
return findChromiumChannel(channel);
|
||||||
return super.executablePath(options);
|
return super.executablePath(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
async connectOverCDP(metadata: CallMetadata, endpointURL: string, options: { slowMo?: number, sdkLanguage: string }, timeout?: number) {
|
async connectOverCDP(metadata: CallMetadata, endpointURL: string, options: { slowMo?: number, sdkLanguage: string }, timeout?: number) {
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,10 @@ import { internalCallMetadata } from '../../instrumentation';
|
||||||
import type { CallLog, EventData, Mode, Source } from './recorderTypes';
|
import type { CallLog, EventData, Mode, Source } from './recorderTypes';
|
||||||
import { BrowserContext } from '../../browserContext';
|
import { BrowserContext } from '../../browserContext';
|
||||||
import { isUnderTest } from '../../../utils/utils';
|
import { isUnderTest } from '../../../utils/utils';
|
||||||
|
import * as types from '../../types';
|
||||||
|
|
||||||
const readFileAsync = util.promisify(fs.readFile);
|
const readFileAsync = util.promisify(fs.readFile);
|
||||||
|
const existsAsync = (path: string): Promise<boolean> => new Promise(resolve => fs.stat(path, err => resolve(!err)));
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
|
|
@ -101,8 +103,17 @@ export class RecorderApp extends EventEmitter {
|
||||||
];
|
];
|
||||||
if (process.env.PWTEST_RECORDER_PORT)
|
if (process.env.PWTEST_RECORDER_PORT)
|
||||||
args.push(`--remote-debugging-port=${process.env.PWTEST_RECORDER_PORT}`);
|
args.push(`--remote-debugging-port=${process.env.PWTEST_RECORDER_PORT}`);
|
||||||
|
let channel: types.BrowserChannel | undefined;
|
||||||
|
let executablePath: string | undefined;
|
||||||
|
if (inspectedContext._browser.options.isChromium) {
|
||||||
|
channel = inspectedContext._browser.options.channel;
|
||||||
|
const defaultExecutablePath = recorderPlaywright.chromium.executablePath(channel);
|
||||||
|
if (!(await existsAsync(defaultExecutablePath)))
|
||||||
|
executablePath = inspectedContext._browser.options.customExecutablePath;
|
||||||
|
}
|
||||||
const context = await recorderPlaywright.chromium.launchPersistentContext(internalCallMetadata(), '', {
|
const context = await recorderPlaywright.chromium.launchPersistentContext(internalCallMetadata(), '', {
|
||||||
channel: inspectedContext._browser.options.channel,
|
channel,
|
||||||
|
executablePath,
|
||||||
sdkLanguage: inspectedContext._options.sdkLanguage,
|
sdkLanguage: inspectedContext._options.sdkLanguage,
|
||||||
args,
|
args,
|
||||||
noDefaultViewport: true,
|
noDefaultViewport: true,
|
||||||
|
|
|
||||||
|
|
@ -31,16 +31,16 @@ export class WebKit extends BrowserType {
|
||||||
super('webkit', playwrightOptions);
|
super('webkit', playwrightOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
executablePath(options?: types.LaunchOptions): string {
|
executablePath(channel?: types.BrowserChannel): string {
|
||||||
if (options?.channel) {
|
if (channel) {
|
||||||
let executablePath = undefined;
|
let executablePath = undefined;
|
||||||
if ((options.channel as any) === 'technology-preview')
|
if ((channel as any) === 'technology-preview')
|
||||||
executablePath = this._registry.executablePath('webkit-technology-preview');
|
executablePath = this._registry.executablePath('webkit-technology-preview');
|
||||||
assert(executablePath, `unsupported webkit channel "${options.channel}"`);
|
assert(executablePath, `unsupported webkit channel "${channel}"`);
|
||||||
assert(fs.existsSync(executablePath), `webkit channel "${options.channel}" is not installed. Try running 'npx playwright install webkit-technology-preview'`);
|
assert(fs.existsSync(executablePath), `webkit channel "${channel}" is not installed. Try running 'npx playwright install webkit-technology-preview'`);
|
||||||
return executablePath;
|
return executablePath;
|
||||||
}
|
}
|
||||||
return super.executablePath(options);
|
return super.executablePath(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
_connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<WKBrowser> {
|
_connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<WKBrowser> {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue